Skip to content

Instantly share code, notes, and snippets.

@jclosure
Created May 30, 2016 17:58
Show Gist options
  • Select an option

  • Save jclosure/971840ab3483c2755bd2d91e2144255f to your computer and use it in GitHub Desktop.

Select an option

Save jclosure/971840ab3483c2755bd2d91e2144255f to your computer and use it in GitHub Desktop.
trace, log, log_current_line, and interact functions for python
"""The ucb module contains functions specific to 61A at UC Berkeley."""
import code
import functools
import inspect
import re
import sys
def main(fn):
"""Call fn with command line arguments. Used as a decorator.
The main decorator marks the function that starts a program. For example,
@main
def my_run_function():
# function body
Use this instead of the typical __name__ == "__main__" predicate.
"""
if inspect.stack()[1][0].f_locals['__name__'] == '__main__':
args = sys.argv[1:] # Discard the script name from command line
fn(*args) # Call the main function
PREFIX = ''
def trace(fn):
"""A decorator that prints a function's name, its arguments, and its return
values each time the function is called. For example,
@trace
def compute_something(x, y):
# function body
"""
@functools.wraps(fn)
def wrapped(*args, **kwds):
global PREFIX
reprs = [repr(e) for e in args]
reprs += [repr(k) + '=' + repr(v) for k, v in kwds.items()]
log('{0}({1})'.format(fn.__name__, ', '.join(reprs)) + ':')
PREFIX += ' '
try:
result = fn(*args, **kwds)
PREFIX = PREFIX[:-4]
except Exception as e:
log(fn.__name__ + ' exited via exception')
PREFIX = PREFIX[:-4]
raise
# Here, print out the return value.
log('{0}({1}) -> {2}'.format(fn.__name__, ', '.join(reprs), result))
return result
return wrapped
def log(message):
"""Print an indented message (used with trace)."""
if type(message) is not str:
message = str(message)
print(PREFIX + re.sub('\n', '\n' + PREFIX, message))
def log_current_line():
"""Print information about the current line of code."""
frame = inspect.stack()[1]
log('Current line: File "{f[1]}", line {f[2]}, in {f[3]}'.format(f=frame))
def interact():
"""Start an interactive interpreter session in the current environment.
On Unix:
<Control>-D exits the interactive session and returns to normal execution.
In Windows:
<Control>-z <Enter> exists the interactive session and returns to normal
execution.
"""
# use exception trick to pick up the current frame
try:
raise None
except:
frame = sys.exc_info()[2].tb_frame.f_back
# evaluate commands in current namespace
namespace = frame.f_globals.copy()
namespace.update(frame.f_locals)
cur_frame = inspect.stack()[1]
banner = 'Interacting at File "{0}", line {1} \n'
banner += ' Unix: <Control>-D continues the program; \n'
banner += ' Windows: <Control>-z <Enter> continues the program; \n'
banner += ' exit() exits the program'
code.interact(banner.format(cur_frame[1], cur_frame[2]), None, namespace)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment