Created
October 25, 2019 21:43
-
-
Save pirogoeth/b646b93d865bdf3b00e5ad2d3f12fb77 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
import inspect | |
def get_caller(): | |
""" Inspects the call stack to determine the path of a caller. | |
Returns a string representing the full path to the caller. | |
""" | |
# If we want to get the "caller" of a function, from this context we | |
# must go backwards by two layers. The first frame is the current frame. | |
# The second frame would be the function that calls get_caller(). | |
# The third frame is the frame we want to know the identity of. | |
# The named tuple, Traceback, looks like this: | |
# Traceback(filename, lineno, function, code_context, index) | |
frame = inspect.currentframe() | |
# Get a list of frames up to two outside of the current frame1. | |
callstack = inspect.getouterframes(frame, 2) | |
# callstack is [Traceback(...), ...] | |
# Grab the outermost frame | |
caller = callstack[2][0] | |
# Pull the Traceback tuple for the current frame. | |
callerinfo = inspect.getframeinfo(caller) | |
# Determine if the function is a bound method. | |
if 'self' in caller.f_locals: | |
# Since the caller is a bound method, extract the 'self' reference | |
# from the locals, then pull the class name from the instance class. | |
caller_class = caller.f_locals["self"].__class__.__name__ | |
else: | |
# There is no object this method is bound to -- it is a module | |
# function. | |
caller_class = None | |
# Get the FQN of the module that the calling frame belongs to. | |
caller_module = inspect.getmodule(caller).__name__ | |
# callerinfo is Traceback(...) | |
caller_name = callerinfo[2] | |
# Check the determined caller class. | |
if caller_class: | |
# If there is a caller class, prepend it to the caller name. | |
caller_string = f"{caller_class}.{caller_name}" | |
else: | |
# The caller string is just the caller name by itself. | |
caller_string = caller_name | |
# Check if we know the caller module. | |
if caller_module: | |
caller_string = f"{caller_module}.{caller_string}" | |
if caller.f_lineno: | |
caller_string = f"{caller_string}:{caller.f_lineno}" | |
return caller_string |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment