-
Notifications
You must be signed in to change notification settings - Fork 4
/
ucb.py
102 lines (82 loc) · 2.99 KB
/
ucb.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
"""The ucb module contains functions specific to 61A at UC Berkeley."""
import code
import functools
import inspect
import re
import signal
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
return fn
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(msg=None):
"""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)
# exit on interrupt
def handler(signum, frame):
print()
exit(0)
signal.signal(signal.SIGINT, handler)
if not msg:
_, filename, line, _, _, _ = inspect.stack()[1]
msg = 'Interacting at File "{0}", line {1} \n'.format(filename, line)
msg += ' Unix: <Control>-D continues the program; \n'
msg += ' Windows: <Control>-Z <Enter> continues the program; \n'
msg += ' exit() or <Control>-C exits the program'
code.interact(msg, None, namespace)