1+ import bdb
2+ import sys
3+
4+ MAX_LINES = 10000 # maximum lines run across all files
5+
6+ class BranchFinder (bdb .Bdb ):
7+ def __init__ (self ):
8+ bdb .Bdb .__init__ (self )
9+ self .branches = []
10+ self .prevline = None
11+ self .lines_left = MAX_LINES
12+
13+ def user_line (self , frame ):
14+ """This function is called when we stop or break at this line."""
15+ # This is so awful but it works
16+ # Only care about lines in the string executed
17+ self .lines_left -= 1
18+ if self .lines_left <= 0 :
19+ self .set_quit ()
20+ if "<string>" not in str (frame .f_code ):
21+ return
22+ if self .prevline and frame .f_lineno != self .prevline + 1 :
23+ self .branches .append ((self .prevline , frame .f_lineno ))
24+ self .prevline = frame .f_lineno
25+
26+ def runscript (self , script_str ):
27+ self .set_step ()
28+ try :
29+ self .run (script_str )
30+ except Exception , e : # catch all exceptions, and reraise them with more web-friendly message
31+ # Janky janky way to get exception name. Please don't break?
32+ name = str (type (e )).split ("'" )[1 ]
33+ return "%s raised on line %d: %s" % (name , self .prevline , e )
34+ return self .branches
35+
36+ # runs arbitrary code!
37+ # (please don't break me :( )
38+ def exec_script_str (script_str ):
39+ runner = BranchFinder ()
40+ return runner .runscript (script_str )
41+
42+ if __name__ == '__main__' :
43+ with open (sys .argv [1 ]) as f :
44+ print exec_script_str (f .read ())
0 commit comments