diff --git a/edb.py b/edb.py new file mode 100644 index 0000000..4630b67 --- /dev/null +++ b/edb.py @@ -0,0 +1,96 @@ +import bdb, os, re, sys, time, traceback + +class Edb(bdb.Bdb): + run_ = 0 + def interaction(self, frame, t): + pass + def user_call(self, frame, args): + name = frame.f_code.co_name or "" + print "call", name, args + sys.stdin.readline() + self.set_continue() # continue + + def user_line(self, frame): + if self.run_: + self.run_ = 0 + self.set_trace() # start tracing + else: + # arrived at breakpoint + name = frame.f_code.co_name or "" + filename = self.canonic(frame.f_code.co_filename) + print "break at", filename, frame.f_lineno, "in", name + print "continue..." + sys.stdin.readline() + self.set_continue() # continue to next breakpoint + + def user_return(self, frame, value): + name = frame.f_code.co_name or "" + print "return from", name, value + print "continue..." + sys.stdin.readline() + self.set_continue() # continue + + def user_exception(self, frame, exception): + name = frame.f_code.co_name or "" + print "exception in", name, exception + print "continue..." + sys.stdin.readline() + self.set_continue() # continue + + def _runscript(self, filename): + # Start with fresh empty copy of globals and locals and tell the script + # that it's being run as __main__ to avoid scripts being able to access + # the pdb.py namespace. + globals_ = {"__name__" : "__main__"} + locals_ = globals_ + + # When bdb sets tracing, a number of call and line events happens + # BEFORE debugger even reaches user's code (and the exact sequence of + # events depends on python version). So we take special measures to + # avoid stopping before we reach the main script (see user_line and + # user_call for details). + self._wait_for_mainpyfile = 1 + self.mainpyfile = self.canonic(filename) + self._user_requested_quit = 0 + statement = 'execfile( "%s")' % filename + self.run(statement, globals=globals_, locals=locals_) + +def main(): + if not sys.argv[1:]: + print "usage: edb.py scriptfile [arg] ..." + sys.exit(2) + + mainpyfile = sys.argv[1] # Get script filename + if not os.path.exists(mainpyfile): + print 'Error:', mainpyfile, 'does not exist' + sys.exit(1) + + del sys.argv[0] + + # Replace pdb's dir with script's dir in front of module search path. + sys.path[0] = os.path.dirname(mainpyfile) + + edb = Edb() + while 1: + try: + edb._runscript(mainpyfile) + if edb._user_requested_quit: + break + print "The program finished and will be restarted" + except SystemExit: + # In most cases SystemExit does not warrant a post-mortem session. + print "The program exited via sys.exit(). Exit status:", + print sys.exc_info()[1] + except: + traceback.print_exc() + print "Uncaught exception. Entering post mortem debugging" + #print "Running 'cont' or 'step' will restart the program" + t = sys.exc_info()[2] + while t.tb_next is not None: + t = t.tb_next + edb.interaction(t.tb_frame,t) + print "Post mortem debugger finished. The "+mainpyfile+" will be restarted" + +# When invoked as main program, invoke the debugger on a script +if __name__=='__main__': + main()