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://github.com/python/cpython/blob/2.7/Lib/logging/__init__.py#
(stack_info=False, stacklevel=1)
| 81 | |
| 82 | |
| 83 | def find_caller(stack_info=False, stacklevel=1): |
| 84 | """ |
| 85 | Find the stack frame of the caller so that we can note the source file name, line number and |
| 86 | function name. |
| 87 | |
| 88 | Note: This is based on logging/__init__.py:findCaller and modified so it takes into account |
| 89 | this file: |
| 90 | https://github.com/python/cpython/blob/2.7/Lib/logging/__init__.py#L1240-L1259 |
| 91 | |
| 92 | The Python 3.x implementation adds in a new argument `stack_info` and `stacklevel` |
| 93 | and expects a 4-element tuple to be returned, rather than a 3-element tuple in |
| 94 | the python 2 implementation. |
| 95 | We derived our implementation from the Python 3.9 source code here: |
| 96 | https://github.com/python/cpython/blob/3.9/Lib/logging/__init__.py#L1502-L1536 |
| 97 | |
| 98 | We've made the appropriate changes so that we're python 2 and python 3 compatible depending |
| 99 | on what runtine we're working in. |
| 100 | """ |
| 101 | if six.PY2: |
| 102 | rv = "(unknown file)", 0, "(unknown function)" |
| 103 | else: |
| 104 | # python 3, has extra tuple element at the end for stack information |
| 105 | rv = "(unknown file)", 0, "(unknown function)", None |
| 106 | |
| 107 | try: |
| 108 | f = logging.currentframe() |
| 109 | # On some versions of IronPython, currentframe() returns None if |
| 110 | # IronPython isn't run with -X:Frames. |
| 111 | if f is not None: |
| 112 | f = f.f_back |
| 113 | orig_f = f |
| 114 | while f and stacklevel > 1: |
| 115 | f = f.f_back |
| 116 | stacklevel -= 1 |
| 117 | if not f: |
| 118 | f = orig_f |
| 119 | |
| 120 | while hasattr(f, "f_code"): |
| 121 | co = f.f_code |
| 122 | filename = os.path.normcase(co.co_filename) |
| 123 | if filename in (_srcfile, logging._srcfile): # This line is modified. |
| 124 | f = f.f_back |
| 125 | continue |
| 126 | |
| 127 | if six.PY2: |
| 128 | rv = (filename, f.f_lineno, co.co_name) |
| 129 | else: |
| 130 | # python 3, new stack_info processing and extra tuple return value |
| 131 | sinfo = None |
| 132 | if stack_info: |
| 133 | sio = io.StringIO() |
| 134 | sio.write("Stack (most recent call last):\n") |
| 135 | traceback.print_stack(f, file=sio) |
| 136 | sinfo = sio.getvalue() |
| 137 | if sinfo[-1] == "\n": |
| 138 | sinfo = sinfo[:-1] |
| 139 | sio.close() |
| 140 | rv = (filename, f.f_lineno, co.co_name, sinfo) |