Created
May 30, 2016 17:58
-
-
Save jclosure/971840ab3483c2755bd2d91e2144255f to your computer and use it in GitHub Desktop.
trace, log, log_current_line, and interact functions for python
This file contains hidden or 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
| """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