Skip to content

Instantly share code, notes, and snippets.

@jtratner
Last active December 18, 2015 10:39
Show Gist options
  • Save jtratner/5770080 to your computer and use it in GitHub Desktop.
Save jtratner/5770080 to your computer and use it in GitHub Desktop.
Easy to slap-on trace function.
import inspect
import os
def trace(f, indent_level=[0]):
"""
slap this on a function as a decorator and
it'll show you what it's called with
and what it returns.
As an aside, if you put this on classes, be sure to
*not* put it on the __repr__ method. Otherwise you'll
end up in infinite recursion. ;)
I can no longer find the SO answer that
proposed setting up `indent_level` like this
but using a mutable list as storage for indent level
is a great idea. (and cribbed from a StackOverflow answer)
"""
_,_,line_number,_,_,_=\
inspect.getouterframes(inspect.currentframe())[1]
def wraps(*args, **kwargs):
res = None
ilevel = indent_level[0]
_,file_name,calling_line,_,_,_=\
inspect.getouterframes(inspect.currentframe())[1]
file_name = os.path.split(file_name)[-1]
called_by = "(called from %s:%d)" % (file_name, calling_line)
src = "%04d:%s> %s" % (line_number, "--"*ilevel, f.__name__)
ret = "%04d:<%s %s" % (line_number, "--"*ilevel, f.__name__)
try:
print("%s(%r, %r) %s" % (src, args, kwargs, called_by))
indent_level[0] += 1
res = f(*args, **kwargs)
print("%s (%r)" % (ret, res))
return res
except Exception as e:
print("%s EXCEPTION: %r %s" % (ret, e, called_by))
raise
finally:
indent_level[0] -= 1
wraps.__name__ = f.__name__
wraps.__doc__ = f.__doc__
return wraps
# if you want to quickly remove trace, just do
# trace=disabled -- yay!
def disabled(f): return f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment