Skip to content

Commit

Permalink
Merge pull request #5059 from StackStorm/hotfix/python3-logging-filename
Browse files Browse the repository at this point in the history
Fixed python 3 incompatibility in logging API implemenation of findCaller (v3.3 cherry pick)
  • Loading branch information
nmaludy authored Oct 15, 2020
2 parents e5bce50 + 10d3ccf commit 1689445
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 5 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ Fixed
where the ``find_caller()`` function introduced some new variables. (bug fix) #4923

Contributed by @Dahfizz9897
* Fixed another logging compatibility issue with the ``logging`` API in Python 3.
The return from the ``logging.findCaller()`` implementation now expects a 4-element
tuple. Also, in Python 3 there are new arguments that are passed in and needs to be
acted upon, specificall ``stack_info`` that determines the new 4th element in the returned
tuple. (bug fix) #5057

Contributed by Nick Maludy (@nmaludy Encore Technologies)

Removed
~~~~~~~
Expand Down
50 changes: 45 additions & 5 deletions st2common/st2common/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from __future__ import absolute_import

import io
import os
import sys
import logging
Expand Down Expand Up @@ -69,25 +70,64 @@
_srcfile = get_normalized_file_path(__file__)


def find_caller(*args, **kwargs):
def find_caller(stack_info=False, stacklevel=1):
"""
Find the stack frame of the caller so that we can note the source file name, line number and
function name.
Note: This is based on logging/__init__.py:findCaller and modified so it takes into account
this file - https://hg.python.org/cpython/file/2.7/Lib/logging/__init__.py#l1233
this file:
https://github.com/python/cpython/blob/2.7/Lib/logging/__init__.py#L1240-L1259
The Python 3.x implementation adds in a new argument `stack_info` and `stacklevel`
and expects a 4-element tuple to be returned, rather than a 3-element tuple in
the python 2 implementation.
We derived our implementation from the Python 3.9 source code here:
https://github.com/python/cpython/blob/3.9/Lib/logging/__init__.py#L1502-L1536
We've made the appropriate changes so that we're python 2 and python 3 compatible depending
on what runtine we're working in.
"""
rv = '(unknown file)', 0, '(unknown function)'
if six.PY2:
rv = '(unknown file)', 0, '(unknown function)'
else:
# python 3, has extra tuple element at the end for stack information
rv = '(unknown file)', 0, '(unknown function)', None

try:
f = logging.currentframe().f_back
f = logging.currentframe()
# On some versions of IronPython, currentframe() returns None if
# IronPython isn't run with -X:Frames.
if f is not None:
f = f.f_back
orig_f = f
while f and stacklevel > 1:
f = f.f_back
stacklevel -= 1
if not f:
f = orig_f

while hasattr(f, 'f_code'):
co = f.f_code
filename = os.path.normcase(co.co_filename)
if filename in (_srcfile, logging._srcfile): # This line is modified.
f = f.f_back
continue
rv = (filename, f.f_lineno, co.co_name)

if six.PY2:
rv = (filename, f.f_lineno, co.co_name)
else:
# python 3, new stack_info processing and extra tuple return value
sinfo = None
if stack_info:
sio = io.StringIO()
sio.write('Stack (most recent call last):\n')
traceback.print_stack(f, file=sio)
sinfo = sio.getvalue()
if sinfo[-1] == '\n':
sinfo = sinfo[:-1]
sio.close()
rv = (filename, f.f_lineno, co.co_name, sinfo)
break
except Exception:
pass
Expand Down

0 comments on commit 1689445

Please sign in to comment.