1*cda5da8dSAndroid Build Coastguard Worker"""Debugger basics""" 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard Workerimport fnmatch 4*cda5da8dSAndroid Build Coastguard Workerimport sys 5*cda5da8dSAndroid Build Coastguard Workerimport os 6*cda5da8dSAndroid Build Coastguard Workerfrom inspect import CO_GENERATOR, CO_COROUTINE, CO_ASYNC_GENERATOR 7*cda5da8dSAndroid Build Coastguard Worker 8*cda5da8dSAndroid Build Coastguard Worker__all__ = ["BdbQuit", "Bdb", "Breakpoint"] 9*cda5da8dSAndroid Build Coastguard Worker 10*cda5da8dSAndroid Build Coastguard WorkerGENERATOR_AND_COROUTINE_FLAGS = CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR 11*cda5da8dSAndroid Build Coastguard Worker 12*cda5da8dSAndroid Build Coastguard Worker 13*cda5da8dSAndroid Build Coastguard Workerclass BdbQuit(Exception): 14*cda5da8dSAndroid Build Coastguard Worker """Exception to give up completely.""" 15*cda5da8dSAndroid Build Coastguard Worker 16*cda5da8dSAndroid Build Coastguard Worker 17*cda5da8dSAndroid Build Coastguard Workerclass Bdb: 18*cda5da8dSAndroid Build Coastguard Worker """Generic Python debugger base class. 19*cda5da8dSAndroid Build Coastguard Worker 20*cda5da8dSAndroid Build Coastguard Worker This class takes care of details of the trace facility; 21*cda5da8dSAndroid Build Coastguard Worker a derived class should implement user interaction. 22*cda5da8dSAndroid Build Coastguard Worker The standard debugger class (pdb.Pdb) is an example. 23*cda5da8dSAndroid Build Coastguard Worker 24*cda5da8dSAndroid Build Coastguard Worker The optional skip argument must be an iterable of glob-style 25*cda5da8dSAndroid Build Coastguard Worker module name patterns. The debugger will not step into frames 26*cda5da8dSAndroid Build Coastguard Worker that originate in a module that matches one of these patterns. 27*cda5da8dSAndroid Build Coastguard Worker Whether a frame is considered to originate in a certain module 28*cda5da8dSAndroid Build Coastguard Worker is determined by the __name__ in the frame globals. 29*cda5da8dSAndroid Build Coastguard Worker """ 30*cda5da8dSAndroid Build Coastguard Worker 31*cda5da8dSAndroid Build Coastguard Worker def __init__(self, skip=None): 32*cda5da8dSAndroid Build Coastguard Worker self.skip = set(skip) if skip else None 33*cda5da8dSAndroid Build Coastguard Worker self.breaks = {} 34*cda5da8dSAndroid Build Coastguard Worker self.fncache = {} 35*cda5da8dSAndroid Build Coastguard Worker self.frame_returning = None 36*cda5da8dSAndroid Build Coastguard Worker 37*cda5da8dSAndroid Build Coastguard Worker self._load_breaks() 38*cda5da8dSAndroid Build Coastguard Worker 39*cda5da8dSAndroid Build Coastguard Worker def canonic(self, filename): 40*cda5da8dSAndroid Build Coastguard Worker """Return canonical form of filename. 41*cda5da8dSAndroid Build Coastguard Worker 42*cda5da8dSAndroid Build Coastguard Worker For real filenames, the canonical form is a case-normalized (on 43*cda5da8dSAndroid Build Coastguard Worker case insensitive filesystems) absolute path. 'Filenames' with 44*cda5da8dSAndroid Build Coastguard Worker angle brackets, such as "<stdin>", generated in interactive 45*cda5da8dSAndroid Build Coastguard Worker mode, are returned unchanged. 46*cda5da8dSAndroid Build Coastguard Worker """ 47*cda5da8dSAndroid Build Coastguard Worker if filename == "<" + filename[1:-1] + ">": 48*cda5da8dSAndroid Build Coastguard Worker return filename 49*cda5da8dSAndroid Build Coastguard Worker canonic = self.fncache.get(filename) 50*cda5da8dSAndroid Build Coastguard Worker if not canonic: 51*cda5da8dSAndroid Build Coastguard Worker canonic = os.path.abspath(filename) 52*cda5da8dSAndroid Build Coastguard Worker canonic = os.path.normcase(canonic) 53*cda5da8dSAndroid Build Coastguard Worker self.fncache[filename] = canonic 54*cda5da8dSAndroid Build Coastguard Worker return canonic 55*cda5da8dSAndroid Build Coastguard Worker 56*cda5da8dSAndroid Build Coastguard Worker def reset(self): 57*cda5da8dSAndroid Build Coastguard Worker """Set values of attributes as ready to start debugging.""" 58*cda5da8dSAndroid Build Coastguard Worker import linecache 59*cda5da8dSAndroid Build Coastguard Worker linecache.checkcache() 60*cda5da8dSAndroid Build Coastguard Worker self.botframe = None 61*cda5da8dSAndroid Build Coastguard Worker self._set_stopinfo(None, None) 62*cda5da8dSAndroid Build Coastguard Worker 63*cda5da8dSAndroid Build Coastguard Worker def trace_dispatch(self, frame, event, arg): 64*cda5da8dSAndroid Build Coastguard Worker """Dispatch a trace function for debugged frames based on the event. 65*cda5da8dSAndroid Build Coastguard Worker 66*cda5da8dSAndroid Build Coastguard Worker This function is installed as the trace function for debugged 67*cda5da8dSAndroid Build Coastguard Worker frames. Its return value is the new trace function, which is 68*cda5da8dSAndroid Build Coastguard Worker usually itself. The default implementation decides how to 69*cda5da8dSAndroid Build Coastguard Worker dispatch a frame, depending on the type of event (passed in as a 70*cda5da8dSAndroid Build Coastguard Worker string) that is about to be executed. 71*cda5da8dSAndroid Build Coastguard Worker 72*cda5da8dSAndroid Build Coastguard Worker The event can be one of the following: 73*cda5da8dSAndroid Build Coastguard Worker line: A new line of code is going to be executed. 74*cda5da8dSAndroid Build Coastguard Worker call: A function is about to be called or another code block 75*cda5da8dSAndroid Build Coastguard Worker is entered. 76*cda5da8dSAndroid Build Coastguard Worker return: A function or other code block is about to return. 77*cda5da8dSAndroid Build Coastguard Worker exception: An exception has occurred. 78*cda5da8dSAndroid Build Coastguard Worker c_call: A C function is about to be called. 79*cda5da8dSAndroid Build Coastguard Worker c_return: A C function has returned. 80*cda5da8dSAndroid Build Coastguard Worker c_exception: A C function has raised an exception. 81*cda5da8dSAndroid Build Coastguard Worker 82*cda5da8dSAndroid Build Coastguard Worker For the Python events, specialized functions (see the dispatch_*() 83*cda5da8dSAndroid Build Coastguard Worker methods) are called. For the C events, no action is taken. 84*cda5da8dSAndroid Build Coastguard Worker 85*cda5da8dSAndroid Build Coastguard Worker The arg parameter depends on the previous event. 86*cda5da8dSAndroid Build Coastguard Worker """ 87*cda5da8dSAndroid Build Coastguard Worker if self.quitting: 88*cda5da8dSAndroid Build Coastguard Worker return # None 89*cda5da8dSAndroid Build Coastguard Worker if event == 'line': 90*cda5da8dSAndroid Build Coastguard Worker return self.dispatch_line(frame) 91*cda5da8dSAndroid Build Coastguard Worker if event == 'call': 92*cda5da8dSAndroid Build Coastguard Worker return self.dispatch_call(frame, arg) 93*cda5da8dSAndroid Build Coastguard Worker if event == 'return': 94*cda5da8dSAndroid Build Coastguard Worker return self.dispatch_return(frame, arg) 95*cda5da8dSAndroid Build Coastguard Worker if event == 'exception': 96*cda5da8dSAndroid Build Coastguard Worker return self.dispatch_exception(frame, arg) 97*cda5da8dSAndroid Build Coastguard Worker if event == 'c_call': 98*cda5da8dSAndroid Build Coastguard Worker return self.trace_dispatch 99*cda5da8dSAndroid Build Coastguard Worker if event == 'c_exception': 100*cda5da8dSAndroid Build Coastguard Worker return self.trace_dispatch 101*cda5da8dSAndroid Build Coastguard Worker if event == 'c_return': 102*cda5da8dSAndroid Build Coastguard Worker return self.trace_dispatch 103*cda5da8dSAndroid Build Coastguard Worker print('bdb.Bdb.dispatch: unknown debugging event:', repr(event)) 104*cda5da8dSAndroid Build Coastguard Worker return self.trace_dispatch 105*cda5da8dSAndroid Build Coastguard Worker 106*cda5da8dSAndroid Build Coastguard Worker def dispatch_line(self, frame): 107*cda5da8dSAndroid Build Coastguard Worker """Invoke user function and return trace function for line event. 108*cda5da8dSAndroid Build Coastguard Worker 109*cda5da8dSAndroid Build Coastguard Worker If the debugger stops on the current line, invoke 110*cda5da8dSAndroid Build Coastguard Worker self.user_line(). Raise BdbQuit if self.quitting is set. 111*cda5da8dSAndroid Build Coastguard Worker Return self.trace_dispatch to continue tracing in this scope. 112*cda5da8dSAndroid Build Coastguard Worker """ 113*cda5da8dSAndroid Build Coastguard Worker if self.stop_here(frame) or self.break_here(frame): 114*cda5da8dSAndroid Build Coastguard Worker self.user_line(frame) 115*cda5da8dSAndroid Build Coastguard Worker if self.quitting: raise BdbQuit 116*cda5da8dSAndroid Build Coastguard Worker return self.trace_dispatch 117*cda5da8dSAndroid Build Coastguard Worker 118*cda5da8dSAndroid Build Coastguard Worker def dispatch_call(self, frame, arg): 119*cda5da8dSAndroid Build Coastguard Worker """Invoke user function and return trace function for call event. 120*cda5da8dSAndroid Build Coastguard Worker 121*cda5da8dSAndroid Build Coastguard Worker If the debugger stops on this function call, invoke 122*cda5da8dSAndroid Build Coastguard Worker self.user_call(). Raise BdbQuit if self.quitting is set. 123*cda5da8dSAndroid Build Coastguard Worker Return self.trace_dispatch to continue tracing in this scope. 124*cda5da8dSAndroid Build Coastguard Worker """ 125*cda5da8dSAndroid Build Coastguard Worker # XXX 'arg' is no longer used 126*cda5da8dSAndroid Build Coastguard Worker if self.botframe is None: 127*cda5da8dSAndroid Build Coastguard Worker # First call of dispatch since reset() 128*cda5da8dSAndroid Build Coastguard Worker self.botframe = frame.f_back # (CT) Note that this may also be None! 129*cda5da8dSAndroid Build Coastguard Worker return self.trace_dispatch 130*cda5da8dSAndroid Build Coastguard Worker if not (self.stop_here(frame) or self.break_anywhere(frame)): 131*cda5da8dSAndroid Build Coastguard Worker # No need to trace this function 132*cda5da8dSAndroid Build Coastguard Worker return # None 133*cda5da8dSAndroid Build Coastguard Worker # Ignore call events in generator except when stepping. 134*cda5da8dSAndroid Build Coastguard Worker if self.stopframe and frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS: 135*cda5da8dSAndroid Build Coastguard Worker return self.trace_dispatch 136*cda5da8dSAndroid Build Coastguard Worker self.user_call(frame, arg) 137*cda5da8dSAndroid Build Coastguard Worker if self.quitting: raise BdbQuit 138*cda5da8dSAndroid Build Coastguard Worker return self.trace_dispatch 139*cda5da8dSAndroid Build Coastguard Worker 140*cda5da8dSAndroid Build Coastguard Worker def dispatch_return(self, frame, arg): 141*cda5da8dSAndroid Build Coastguard Worker """Invoke user function and return trace function for return event. 142*cda5da8dSAndroid Build Coastguard Worker 143*cda5da8dSAndroid Build Coastguard Worker If the debugger stops on this function return, invoke 144*cda5da8dSAndroid Build Coastguard Worker self.user_return(). Raise BdbQuit if self.quitting is set. 145*cda5da8dSAndroid Build Coastguard Worker Return self.trace_dispatch to continue tracing in this scope. 146*cda5da8dSAndroid Build Coastguard Worker """ 147*cda5da8dSAndroid Build Coastguard Worker if self.stop_here(frame) or frame == self.returnframe: 148*cda5da8dSAndroid Build Coastguard Worker # Ignore return events in generator except when stepping. 149*cda5da8dSAndroid Build Coastguard Worker if self.stopframe and frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS: 150*cda5da8dSAndroid Build Coastguard Worker return self.trace_dispatch 151*cda5da8dSAndroid Build Coastguard Worker try: 152*cda5da8dSAndroid Build Coastguard Worker self.frame_returning = frame 153*cda5da8dSAndroid Build Coastguard Worker self.user_return(frame, arg) 154*cda5da8dSAndroid Build Coastguard Worker finally: 155*cda5da8dSAndroid Build Coastguard Worker self.frame_returning = None 156*cda5da8dSAndroid Build Coastguard Worker if self.quitting: raise BdbQuit 157*cda5da8dSAndroid Build Coastguard Worker # The user issued a 'next' or 'until' command. 158*cda5da8dSAndroid Build Coastguard Worker if self.stopframe is frame and self.stoplineno != -1: 159*cda5da8dSAndroid Build Coastguard Worker self._set_stopinfo(None, None) 160*cda5da8dSAndroid Build Coastguard Worker return self.trace_dispatch 161*cda5da8dSAndroid Build Coastguard Worker 162*cda5da8dSAndroid Build Coastguard Worker def dispatch_exception(self, frame, arg): 163*cda5da8dSAndroid Build Coastguard Worker """Invoke user function and return trace function for exception event. 164*cda5da8dSAndroid Build Coastguard Worker 165*cda5da8dSAndroid Build Coastguard Worker If the debugger stops on this exception, invoke 166*cda5da8dSAndroid Build Coastguard Worker self.user_exception(). Raise BdbQuit if self.quitting is set. 167*cda5da8dSAndroid Build Coastguard Worker Return self.trace_dispatch to continue tracing in this scope. 168*cda5da8dSAndroid Build Coastguard Worker """ 169*cda5da8dSAndroid Build Coastguard Worker if self.stop_here(frame): 170*cda5da8dSAndroid Build Coastguard Worker # When stepping with next/until/return in a generator frame, skip 171*cda5da8dSAndroid Build Coastguard Worker # the internal StopIteration exception (with no traceback) 172*cda5da8dSAndroid Build Coastguard Worker # triggered by a subiterator run with the 'yield from' statement. 173*cda5da8dSAndroid Build Coastguard Worker if not (frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS 174*cda5da8dSAndroid Build Coastguard Worker and arg[0] is StopIteration and arg[2] is None): 175*cda5da8dSAndroid Build Coastguard Worker self.user_exception(frame, arg) 176*cda5da8dSAndroid Build Coastguard Worker if self.quitting: raise BdbQuit 177*cda5da8dSAndroid Build Coastguard Worker # Stop at the StopIteration or GeneratorExit exception when the user 178*cda5da8dSAndroid Build Coastguard Worker # has set stopframe in a generator by issuing a return command, or a 179*cda5da8dSAndroid Build Coastguard Worker # next/until command at the last statement in the generator before the 180*cda5da8dSAndroid Build Coastguard Worker # exception. 181*cda5da8dSAndroid Build Coastguard Worker elif (self.stopframe and frame is not self.stopframe 182*cda5da8dSAndroid Build Coastguard Worker and self.stopframe.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS 183*cda5da8dSAndroid Build Coastguard Worker and arg[0] in (StopIteration, GeneratorExit)): 184*cda5da8dSAndroid Build Coastguard Worker self.user_exception(frame, arg) 185*cda5da8dSAndroid Build Coastguard Worker if self.quitting: raise BdbQuit 186*cda5da8dSAndroid Build Coastguard Worker 187*cda5da8dSAndroid Build Coastguard Worker return self.trace_dispatch 188*cda5da8dSAndroid Build Coastguard Worker 189*cda5da8dSAndroid Build Coastguard Worker # Normally derived classes don't override the following 190*cda5da8dSAndroid Build Coastguard Worker # methods, but they may if they want to redefine the 191*cda5da8dSAndroid Build Coastguard Worker # definition of stopping and breakpoints. 192*cda5da8dSAndroid Build Coastguard Worker 193*cda5da8dSAndroid Build Coastguard Worker def is_skipped_module(self, module_name): 194*cda5da8dSAndroid Build Coastguard Worker "Return True if module_name matches any skip pattern." 195*cda5da8dSAndroid Build Coastguard Worker if module_name is None: # some modules do not have names 196*cda5da8dSAndroid Build Coastguard Worker return False 197*cda5da8dSAndroid Build Coastguard Worker for pattern in self.skip: 198*cda5da8dSAndroid Build Coastguard Worker if fnmatch.fnmatch(module_name, pattern): 199*cda5da8dSAndroid Build Coastguard Worker return True 200*cda5da8dSAndroid Build Coastguard Worker return False 201*cda5da8dSAndroid Build Coastguard Worker 202*cda5da8dSAndroid Build Coastguard Worker def stop_here(self, frame): 203*cda5da8dSAndroid Build Coastguard Worker "Return True if frame is below the starting frame in the stack." 204*cda5da8dSAndroid Build Coastguard Worker # (CT) stopframe may now also be None, see dispatch_call. 205*cda5da8dSAndroid Build Coastguard Worker # (CT) the former test for None is therefore removed from here. 206*cda5da8dSAndroid Build Coastguard Worker if self.skip and \ 207*cda5da8dSAndroid Build Coastguard Worker self.is_skipped_module(frame.f_globals.get('__name__')): 208*cda5da8dSAndroid Build Coastguard Worker return False 209*cda5da8dSAndroid Build Coastguard Worker if frame is self.stopframe: 210*cda5da8dSAndroid Build Coastguard Worker if self.stoplineno == -1: 211*cda5da8dSAndroid Build Coastguard Worker return False 212*cda5da8dSAndroid Build Coastguard Worker return frame.f_lineno >= self.stoplineno 213*cda5da8dSAndroid Build Coastguard Worker if not self.stopframe: 214*cda5da8dSAndroid Build Coastguard Worker return True 215*cda5da8dSAndroid Build Coastguard Worker return False 216*cda5da8dSAndroid Build Coastguard Worker 217*cda5da8dSAndroid Build Coastguard Worker def break_here(self, frame): 218*cda5da8dSAndroid Build Coastguard Worker """Return True if there is an effective breakpoint for this line. 219*cda5da8dSAndroid Build Coastguard Worker 220*cda5da8dSAndroid Build Coastguard Worker Check for line or function breakpoint and if in effect. 221*cda5da8dSAndroid Build Coastguard Worker Delete temporary breakpoints if effective() says to. 222*cda5da8dSAndroid Build Coastguard Worker """ 223*cda5da8dSAndroid Build Coastguard Worker filename = self.canonic(frame.f_code.co_filename) 224*cda5da8dSAndroid Build Coastguard Worker if filename not in self.breaks: 225*cda5da8dSAndroid Build Coastguard Worker return False 226*cda5da8dSAndroid Build Coastguard Worker lineno = frame.f_lineno 227*cda5da8dSAndroid Build Coastguard Worker if lineno not in self.breaks[filename]: 228*cda5da8dSAndroid Build Coastguard Worker # The line itself has no breakpoint, but maybe the line is the 229*cda5da8dSAndroid Build Coastguard Worker # first line of a function with breakpoint set by function name. 230*cda5da8dSAndroid Build Coastguard Worker lineno = frame.f_code.co_firstlineno 231*cda5da8dSAndroid Build Coastguard Worker if lineno not in self.breaks[filename]: 232*cda5da8dSAndroid Build Coastguard Worker return False 233*cda5da8dSAndroid Build Coastguard Worker 234*cda5da8dSAndroid Build Coastguard Worker # flag says ok to delete temp. bp 235*cda5da8dSAndroid Build Coastguard Worker (bp, flag) = effective(filename, lineno, frame) 236*cda5da8dSAndroid Build Coastguard Worker if bp: 237*cda5da8dSAndroid Build Coastguard Worker self.currentbp = bp.number 238*cda5da8dSAndroid Build Coastguard Worker if (flag and bp.temporary): 239*cda5da8dSAndroid Build Coastguard Worker self.do_clear(str(bp.number)) 240*cda5da8dSAndroid Build Coastguard Worker return True 241*cda5da8dSAndroid Build Coastguard Worker else: 242*cda5da8dSAndroid Build Coastguard Worker return False 243*cda5da8dSAndroid Build Coastguard Worker 244*cda5da8dSAndroid Build Coastguard Worker def do_clear(self, arg): 245*cda5da8dSAndroid Build Coastguard Worker """Remove temporary breakpoint. 246*cda5da8dSAndroid Build Coastguard Worker 247*cda5da8dSAndroid Build Coastguard Worker Must implement in derived classes or get NotImplementedError. 248*cda5da8dSAndroid Build Coastguard Worker """ 249*cda5da8dSAndroid Build Coastguard Worker raise NotImplementedError("subclass of bdb must implement do_clear()") 250*cda5da8dSAndroid Build Coastguard Worker 251*cda5da8dSAndroid Build Coastguard Worker def break_anywhere(self, frame): 252*cda5da8dSAndroid Build Coastguard Worker """Return True if there is any breakpoint for frame's filename. 253*cda5da8dSAndroid Build Coastguard Worker """ 254*cda5da8dSAndroid Build Coastguard Worker return self.canonic(frame.f_code.co_filename) in self.breaks 255*cda5da8dSAndroid Build Coastguard Worker 256*cda5da8dSAndroid Build Coastguard Worker # Derived classes should override the user_* methods 257*cda5da8dSAndroid Build Coastguard Worker # to gain control. 258*cda5da8dSAndroid Build Coastguard Worker 259*cda5da8dSAndroid Build Coastguard Worker def user_call(self, frame, argument_list): 260*cda5da8dSAndroid Build Coastguard Worker """Called if we might stop in a function.""" 261*cda5da8dSAndroid Build Coastguard Worker pass 262*cda5da8dSAndroid Build Coastguard Worker 263*cda5da8dSAndroid Build Coastguard Worker def user_line(self, frame): 264*cda5da8dSAndroid Build Coastguard Worker """Called when we stop or break at a line.""" 265*cda5da8dSAndroid Build Coastguard Worker pass 266*cda5da8dSAndroid Build Coastguard Worker 267*cda5da8dSAndroid Build Coastguard Worker def user_return(self, frame, return_value): 268*cda5da8dSAndroid Build Coastguard Worker """Called when a return trap is set here.""" 269*cda5da8dSAndroid Build Coastguard Worker pass 270*cda5da8dSAndroid Build Coastguard Worker 271*cda5da8dSAndroid Build Coastguard Worker def user_exception(self, frame, exc_info): 272*cda5da8dSAndroid Build Coastguard Worker """Called when we stop on an exception.""" 273*cda5da8dSAndroid Build Coastguard Worker pass 274*cda5da8dSAndroid Build Coastguard Worker 275*cda5da8dSAndroid Build Coastguard Worker def _set_stopinfo(self, stopframe, returnframe, stoplineno=0): 276*cda5da8dSAndroid Build Coastguard Worker """Set the attributes for stopping. 277*cda5da8dSAndroid Build Coastguard Worker 278*cda5da8dSAndroid Build Coastguard Worker If stoplineno is greater than or equal to 0, then stop at line 279*cda5da8dSAndroid Build Coastguard Worker greater than or equal to the stopline. If stoplineno is -1, then 280*cda5da8dSAndroid Build Coastguard Worker don't stop at all. 281*cda5da8dSAndroid Build Coastguard Worker """ 282*cda5da8dSAndroid Build Coastguard Worker self.stopframe = stopframe 283*cda5da8dSAndroid Build Coastguard Worker self.returnframe = returnframe 284*cda5da8dSAndroid Build Coastguard Worker self.quitting = False 285*cda5da8dSAndroid Build Coastguard Worker # stoplineno >= 0 means: stop at line >= the stoplineno 286*cda5da8dSAndroid Build Coastguard Worker # stoplineno -1 means: don't stop at all 287*cda5da8dSAndroid Build Coastguard Worker self.stoplineno = stoplineno 288*cda5da8dSAndroid Build Coastguard Worker 289*cda5da8dSAndroid Build Coastguard Worker # Derived classes and clients can call the following methods 290*cda5da8dSAndroid Build Coastguard Worker # to affect the stepping state. 291*cda5da8dSAndroid Build Coastguard Worker 292*cda5da8dSAndroid Build Coastguard Worker def set_until(self, frame, lineno=None): 293*cda5da8dSAndroid Build Coastguard Worker """Stop when the line with the lineno greater than the current one is 294*cda5da8dSAndroid Build Coastguard Worker reached or when returning from current frame.""" 295*cda5da8dSAndroid Build Coastguard Worker # the name "until" is borrowed from gdb 296*cda5da8dSAndroid Build Coastguard Worker if lineno is None: 297*cda5da8dSAndroid Build Coastguard Worker lineno = frame.f_lineno + 1 298*cda5da8dSAndroid Build Coastguard Worker self._set_stopinfo(frame, frame, lineno) 299*cda5da8dSAndroid Build Coastguard Worker 300*cda5da8dSAndroid Build Coastguard Worker def set_step(self): 301*cda5da8dSAndroid Build Coastguard Worker """Stop after one line of code.""" 302*cda5da8dSAndroid Build Coastguard Worker # Issue #13183: pdb skips frames after hitting a breakpoint and running 303*cda5da8dSAndroid Build Coastguard Worker # step commands. 304*cda5da8dSAndroid Build Coastguard Worker # Restore the trace function in the caller (that may not have been set 305*cda5da8dSAndroid Build Coastguard Worker # for performance reasons) when returning from the current frame. 306*cda5da8dSAndroid Build Coastguard Worker if self.frame_returning: 307*cda5da8dSAndroid Build Coastguard Worker caller_frame = self.frame_returning.f_back 308*cda5da8dSAndroid Build Coastguard Worker if caller_frame and not caller_frame.f_trace: 309*cda5da8dSAndroid Build Coastguard Worker caller_frame.f_trace = self.trace_dispatch 310*cda5da8dSAndroid Build Coastguard Worker self._set_stopinfo(None, None) 311*cda5da8dSAndroid Build Coastguard Worker 312*cda5da8dSAndroid Build Coastguard Worker def set_next(self, frame): 313*cda5da8dSAndroid Build Coastguard Worker """Stop on the next line in or below the given frame.""" 314*cda5da8dSAndroid Build Coastguard Worker self._set_stopinfo(frame, None) 315*cda5da8dSAndroid Build Coastguard Worker 316*cda5da8dSAndroid Build Coastguard Worker def set_return(self, frame): 317*cda5da8dSAndroid Build Coastguard Worker """Stop when returning from the given frame.""" 318*cda5da8dSAndroid Build Coastguard Worker if frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS: 319*cda5da8dSAndroid Build Coastguard Worker self._set_stopinfo(frame, None, -1) 320*cda5da8dSAndroid Build Coastguard Worker else: 321*cda5da8dSAndroid Build Coastguard Worker self._set_stopinfo(frame.f_back, frame) 322*cda5da8dSAndroid Build Coastguard Worker 323*cda5da8dSAndroid Build Coastguard Worker def set_trace(self, frame=None): 324*cda5da8dSAndroid Build Coastguard Worker """Start debugging from frame. 325*cda5da8dSAndroid Build Coastguard Worker 326*cda5da8dSAndroid Build Coastguard Worker If frame is not specified, debugging starts from caller's frame. 327*cda5da8dSAndroid Build Coastguard Worker """ 328*cda5da8dSAndroid Build Coastguard Worker if frame is None: 329*cda5da8dSAndroid Build Coastguard Worker frame = sys._getframe().f_back 330*cda5da8dSAndroid Build Coastguard Worker self.reset() 331*cda5da8dSAndroid Build Coastguard Worker while frame: 332*cda5da8dSAndroid Build Coastguard Worker frame.f_trace = self.trace_dispatch 333*cda5da8dSAndroid Build Coastguard Worker self.botframe = frame 334*cda5da8dSAndroid Build Coastguard Worker frame = frame.f_back 335*cda5da8dSAndroid Build Coastguard Worker self.set_step() 336*cda5da8dSAndroid Build Coastguard Worker sys.settrace(self.trace_dispatch) 337*cda5da8dSAndroid Build Coastguard Worker 338*cda5da8dSAndroid Build Coastguard Worker def set_continue(self): 339*cda5da8dSAndroid Build Coastguard Worker """Stop only at breakpoints or when finished. 340*cda5da8dSAndroid Build Coastguard Worker 341*cda5da8dSAndroid Build Coastguard Worker If there are no breakpoints, set the system trace function to None. 342*cda5da8dSAndroid Build Coastguard Worker """ 343*cda5da8dSAndroid Build Coastguard Worker # Don't stop except at breakpoints or when finished 344*cda5da8dSAndroid Build Coastguard Worker self._set_stopinfo(self.botframe, None, -1) 345*cda5da8dSAndroid Build Coastguard Worker if not self.breaks: 346*cda5da8dSAndroid Build Coastguard Worker # no breakpoints; run without debugger overhead 347*cda5da8dSAndroid Build Coastguard Worker sys.settrace(None) 348*cda5da8dSAndroid Build Coastguard Worker frame = sys._getframe().f_back 349*cda5da8dSAndroid Build Coastguard Worker while frame and frame is not self.botframe: 350*cda5da8dSAndroid Build Coastguard Worker del frame.f_trace 351*cda5da8dSAndroid Build Coastguard Worker frame = frame.f_back 352*cda5da8dSAndroid Build Coastguard Worker 353*cda5da8dSAndroid Build Coastguard Worker def set_quit(self): 354*cda5da8dSAndroid Build Coastguard Worker """Set quitting attribute to True. 355*cda5da8dSAndroid Build Coastguard Worker 356*cda5da8dSAndroid Build Coastguard Worker Raises BdbQuit exception in the next call to a dispatch_*() method. 357*cda5da8dSAndroid Build Coastguard Worker """ 358*cda5da8dSAndroid Build Coastguard Worker self.stopframe = self.botframe 359*cda5da8dSAndroid Build Coastguard Worker self.returnframe = None 360*cda5da8dSAndroid Build Coastguard Worker self.quitting = True 361*cda5da8dSAndroid Build Coastguard Worker sys.settrace(None) 362*cda5da8dSAndroid Build Coastguard Worker 363*cda5da8dSAndroid Build Coastguard Worker # Derived classes and clients can call the following methods 364*cda5da8dSAndroid Build Coastguard Worker # to manipulate breakpoints. These methods return an 365*cda5da8dSAndroid Build Coastguard Worker # error message if something went wrong, None if all is well. 366*cda5da8dSAndroid Build Coastguard Worker # Set_break prints out the breakpoint line and file:lineno. 367*cda5da8dSAndroid Build Coastguard Worker # Call self.get_*break*() to see the breakpoints or better 368*cda5da8dSAndroid Build Coastguard Worker # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint(). 369*cda5da8dSAndroid Build Coastguard Worker 370*cda5da8dSAndroid Build Coastguard Worker def _add_to_breaks(self, filename, lineno): 371*cda5da8dSAndroid Build Coastguard Worker """Add breakpoint to breaks, if not already there.""" 372*cda5da8dSAndroid Build Coastguard Worker bp_linenos = self.breaks.setdefault(filename, []) 373*cda5da8dSAndroid Build Coastguard Worker if lineno not in bp_linenos: 374*cda5da8dSAndroid Build Coastguard Worker bp_linenos.append(lineno) 375*cda5da8dSAndroid Build Coastguard Worker 376*cda5da8dSAndroid Build Coastguard Worker def set_break(self, filename, lineno, temporary=False, cond=None, 377*cda5da8dSAndroid Build Coastguard Worker funcname=None): 378*cda5da8dSAndroid Build Coastguard Worker """Set a new breakpoint for filename:lineno. 379*cda5da8dSAndroid Build Coastguard Worker 380*cda5da8dSAndroid Build Coastguard Worker If lineno doesn't exist for the filename, return an error message. 381*cda5da8dSAndroid Build Coastguard Worker The filename should be in canonical form. 382*cda5da8dSAndroid Build Coastguard Worker """ 383*cda5da8dSAndroid Build Coastguard Worker filename = self.canonic(filename) 384*cda5da8dSAndroid Build Coastguard Worker import linecache # Import as late as possible 385*cda5da8dSAndroid Build Coastguard Worker line = linecache.getline(filename, lineno) 386*cda5da8dSAndroid Build Coastguard Worker if not line: 387*cda5da8dSAndroid Build Coastguard Worker return 'Line %s:%d does not exist' % (filename, lineno) 388*cda5da8dSAndroid Build Coastguard Worker self._add_to_breaks(filename, lineno) 389*cda5da8dSAndroid Build Coastguard Worker bp = Breakpoint(filename, lineno, temporary, cond, funcname) 390*cda5da8dSAndroid Build Coastguard Worker return None 391*cda5da8dSAndroid Build Coastguard Worker 392*cda5da8dSAndroid Build Coastguard Worker def _load_breaks(self): 393*cda5da8dSAndroid Build Coastguard Worker """Apply all breakpoints (set in other instances) to this one. 394*cda5da8dSAndroid Build Coastguard Worker 395*cda5da8dSAndroid Build Coastguard Worker Populates this instance's breaks list from the Breakpoint class's 396*cda5da8dSAndroid Build Coastguard Worker list, which can have breakpoints set by another Bdb instance. This 397*cda5da8dSAndroid Build Coastguard Worker is necessary for interactive sessions to keep the breakpoints 398*cda5da8dSAndroid Build Coastguard Worker active across multiple calls to run(). 399*cda5da8dSAndroid Build Coastguard Worker """ 400*cda5da8dSAndroid Build Coastguard Worker for (filename, lineno) in Breakpoint.bplist.keys(): 401*cda5da8dSAndroid Build Coastguard Worker self._add_to_breaks(filename, lineno) 402*cda5da8dSAndroid Build Coastguard Worker 403*cda5da8dSAndroid Build Coastguard Worker def _prune_breaks(self, filename, lineno): 404*cda5da8dSAndroid Build Coastguard Worker """Prune breakpoints for filename:lineno. 405*cda5da8dSAndroid Build Coastguard Worker 406*cda5da8dSAndroid Build Coastguard Worker A list of breakpoints is maintained in the Bdb instance and in 407*cda5da8dSAndroid Build Coastguard Worker the Breakpoint class. If a breakpoint in the Bdb instance no 408*cda5da8dSAndroid Build Coastguard Worker longer exists in the Breakpoint class, then it's removed from the 409*cda5da8dSAndroid Build Coastguard Worker Bdb instance. 410*cda5da8dSAndroid Build Coastguard Worker """ 411*cda5da8dSAndroid Build Coastguard Worker if (filename, lineno) not in Breakpoint.bplist: 412*cda5da8dSAndroid Build Coastguard Worker self.breaks[filename].remove(lineno) 413*cda5da8dSAndroid Build Coastguard Worker if not self.breaks[filename]: 414*cda5da8dSAndroid Build Coastguard Worker del self.breaks[filename] 415*cda5da8dSAndroid Build Coastguard Worker 416*cda5da8dSAndroid Build Coastguard Worker def clear_break(self, filename, lineno): 417*cda5da8dSAndroid Build Coastguard Worker """Delete breakpoints for filename:lineno. 418*cda5da8dSAndroid Build Coastguard Worker 419*cda5da8dSAndroid Build Coastguard Worker If no breakpoints were set, return an error message. 420*cda5da8dSAndroid Build Coastguard Worker """ 421*cda5da8dSAndroid Build Coastguard Worker filename = self.canonic(filename) 422*cda5da8dSAndroid Build Coastguard Worker if filename not in self.breaks: 423*cda5da8dSAndroid Build Coastguard Worker return 'There are no breakpoints in %s' % filename 424*cda5da8dSAndroid Build Coastguard Worker if lineno not in self.breaks[filename]: 425*cda5da8dSAndroid Build Coastguard Worker return 'There is no breakpoint at %s:%d' % (filename, lineno) 426*cda5da8dSAndroid Build Coastguard Worker # If there's only one bp in the list for that file,line 427*cda5da8dSAndroid Build Coastguard Worker # pair, then remove the breaks entry 428*cda5da8dSAndroid Build Coastguard Worker for bp in Breakpoint.bplist[filename, lineno][:]: 429*cda5da8dSAndroid Build Coastguard Worker bp.deleteMe() 430*cda5da8dSAndroid Build Coastguard Worker self._prune_breaks(filename, lineno) 431*cda5da8dSAndroid Build Coastguard Worker return None 432*cda5da8dSAndroid Build Coastguard Worker 433*cda5da8dSAndroid Build Coastguard Worker def clear_bpbynumber(self, arg): 434*cda5da8dSAndroid Build Coastguard Worker """Delete a breakpoint by its index in Breakpoint.bpbynumber. 435*cda5da8dSAndroid Build Coastguard Worker 436*cda5da8dSAndroid Build Coastguard Worker If arg is invalid, return an error message. 437*cda5da8dSAndroid Build Coastguard Worker """ 438*cda5da8dSAndroid Build Coastguard Worker try: 439*cda5da8dSAndroid Build Coastguard Worker bp = self.get_bpbynumber(arg) 440*cda5da8dSAndroid Build Coastguard Worker except ValueError as err: 441*cda5da8dSAndroid Build Coastguard Worker return str(err) 442*cda5da8dSAndroid Build Coastguard Worker bp.deleteMe() 443*cda5da8dSAndroid Build Coastguard Worker self._prune_breaks(bp.file, bp.line) 444*cda5da8dSAndroid Build Coastguard Worker return None 445*cda5da8dSAndroid Build Coastguard Worker 446*cda5da8dSAndroid Build Coastguard Worker def clear_all_file_breaks(self, filename): 447*cda5da8dSAndroid Build Coastguard Worker """Delete all breakpoints in filename. 448*cda5da8dSAndroid Build Coastguard Worker 449*cda5da8dSAndroid Build Coastguard Worker If none were set, return an error message. 450*cda5da8dSAndroid Build Coastguard Worker """ 451*cda5da8dSAndroid Build Coastguard Worker filename = self.canonic(filename) 452*cda5da8dSAndroid Build Coastguard Worker if filename not in self.breaks: 453*cda5da8dSAndroid Build Coastguard Worker return 'There are no breakpoints in %s' % filename 454*cda5da8dSAndroid Build Coastguard Worker for line in self.breaks[filename]: 455*cda5da8dSAndroid Build Coastguard Worker blist = Breakpoint.bplist[filename, line] 456*cda5da8dSAndroid Build Coastguard Worker for bp in blist: 457*cda5da8dSAndroid Build Coastguard Worker bp.deleteMe() 458*cda5da8dSAndroid Build Coastguard Worker del self.breaks[filename] 459*cda5da8dSAndroid Build Coastguard Worker return None 460*cda5da8dSAndroid Build Coastguard Worker 461*cda5da8dSAndroid Build Coastguard Worker def clear_all_breaks(self): 462*cda5da8dSAndroid Build Coastguard Worker """Delete all existing breakpoints. 463*cda5da8dSAndroid Build Coastguard Worker 464*cda5da8dSAndroid Build Coastguard Worker If none were set, return an error message. 465*cda5da8dSAndroid Build Coastguard Worker """ 466*cda5da8dSAndroid Build Coastguard Worker if not self.breaks: 467*cda5da8dSAndroid Build Coastguard Worker return 'There are no breakpoints' 468*cda5da8dSAndroid Build Coastguard Worker for bp in Breakpoint.bpbynumber: 469*cda5da8dSAndroid Build Coastguard Worker if bp: 470*cda5da8dSAndroid Build Coastguard Worker bp.deleteMe() 471*cda5da8dSAndroid Build Coastguard Worker self.breaks = {} 472*cda5da8dSAndroid Build Coastguard Worker return None 473*cda5da8dSAndroid Build Coastguard Worker 474*cda5da8dSAndroid Build Coastguard Worker def get_bpbynumber(self, arg): 475*cda5da8dSAndroid Build Coastguard Worker """Return a breakpoint by its index in Breakpoint.bybpnumber. 476*cda5da8dSAndroid Build Coastguard Worker 477*cda5da8dSAndroid Build Coastguard Worker For invalid arg values or if the breakpoint doesn't exist, 478*cda5da8dSAndroid Build Coastguard Worker raise a ValueError. 479*cda5da8dSAndroid Build Coastguard Worker """ 480*cda5da8dSAndroid Build Coastguard Worker if not arg: 481*cda5da8dSAndroid Build Coastguard Worker raise ValueError('Breakpoint number expected') 482*cda5da8dSAndroid Build Coastguard Worker try: 483*cda5da8dSAndroid Build Coastguard Worker number = int(arg) 484*cda5da8dSAndroid Build Coastguard Worker except ValueError: 485*cda5da8dSAndroid Build Coastguard Worker raise ValueError('Non-numeric breakpoint number %s' % arg) from None 486*cda5da8dSAndroid Build Coastguard Worker try: 487*cda5da8dSAndroid Build Coastguard Worker bp = Breakpoint.bpbynumber[number] 488*cda5da8dSAndroid Build Coastguard Worker except IndexError: 489*cda5da8dSAndroid Build Coastguard Worker raise ValueError('Breakpoint number %d out of range' % number) from None 490*cda5da8dSAndroid Build Coastguard Worker if bp is None: 491*cda5da8dSAndroid Build Coastguard Worker raise ValueError('Breakpoint %d already deleted' % number) 492*cda5da8dSAndroid Build Coastguard Worker return bp 493*cda5da8dSAndroid Build Coastguard Worker 494*cda5da8dSAndroid Build Coastguard Worker def get_break(self, filename, lineno): 495*cda5da8dSAndroid Build Coastguard Worker """Return True if there is a breakpoint for filename:lineno.""" 496*cda5da8dSAndroid Build Coastguard Worker filename = self.canonic(filename) 497*cda5da8dSAndroid Build Coastguard Worker return filename in self.breaks and \ 498*cda5da8dSAndroid Build Coastguard Worker lineno in self.breaks[filename] 499*cda5da8dSAndroid Build Coastguard Worker 500*cda5da8dSAndroid Build Coastguard Worker def get_breaks(self, filename, lineno): 501*cda5da8dSAndroid Build Coastguard Worker """Return all breakpoints for filename:lineno. 502*cda5da8dSAndroid Build Coastguard Worker 503*cda5da8dSAndroid Build Coastguard Worker If no breakpoints are set, return an empty list. 504*cda5da8dSAndroid Build Coastguard Worker """ 505*cda5da8dSAndroid Build Coastguard Worker filename = self.canonic(filename) 506*cda5da8dSAndroid Build Coastguard Worker return filename in self.breaks and \ 507*cda5da8dSAndroid Build Coastguard Worker lineno in self.breaks[filename] and \ 508*cda5da8dSAndroid Build Coastguard Worker Breakpoint.bplist[filename, lineno] or [] 509*cda5da8dSAndroid Build Coastguard Worker 510*cda5da8dSAndroid Build Coastguard Worker def get_file_breaks(self, filename): 511*cda5da8dSAndroid Build Coastguard Worker """Return all lines with breakpoints for filename. 512*cda5da8dSAndroid Build Coastguard Worker 513*cda5da8dSAndroid Build Coastguard Worker If no breakpoints are set, return an empty list. 514*cda5da8dSAndroid Build Coastguard Worker """ 515*cda5da8dSAndroid Build Coastguard Worker filename = self.canonic(filename) 516*cda5da8dSAndroid Build Coastguard Worker if filename in self.breaks: 517*cda5da8dSAndroid Build Coastguard Worker return self.breaks[filename] 518*cda5da8dSAndroid Build Coastguard Worker else: 519*cda5da8dSAndroid Build Coastguard Worker return [] 520*cda5da8dSAndroid Build Coastguard Worker 521*cda5da8dSAndroid Build Coastguard Worker def get_all_breaks(self): 522*cda5da8dSAndroid Build Coastguard Worker """Return all breakpoints that are set.""" 523*cda5da8dSAndroid Build Coastguard Worker return self.breaks 524*cda5da8dSAndroid Build Coastguard Worker 525*cda5da8dSAndroid Build Coastguard Worker # Derived classes and clients can call the following method 526*cda5da8dSAndroid Build Coastguard Worker # to get a data structure representing a stack trace. 527*cda5da8dSAndroid Build Coastguard Worker 528*cda5da8dSAndroid Build Coastguard Worker def get_stack(self, f, t): 529*cda5da8dSAndroid Build Coastguard Worker """Return a list of (frame, lineno) in a stack trace and a size. 530*cda5da8dSAndroid Build Coastguard Worker 531*cda5da8dSAndroid Build Coastguard Worker List starts with original calling frame, if there is one. 532*cda5da8dSAndroid Build Coastguard Worker Size may be number of frames above or below f. 533*cda5da8dSAndroid Build Coastguard Worker """ 534*cda5da8dSAndroid Build Coastguard Worker stack = [] 535*cda5da8dSAndroid Build Coastguard Worker if t and t.tb_frame is f: 536*cda5da8dSAndroid Build Coastguard Worker t = t.tb_next 537*cda5da8dSAndroid Build Coastguard Worker while f is not None: 538*cda5da8dSAndroid Build Coastguard Worker stack.append((f, f.f_lineno)) 539*cda5da8dSAndroid Build Coastguard Worker if f is self.botframe: 540*cda5da8dSAndroid Build Coastguard Worker break 541*cda5da8dSAndroid Build Coastguard Worker f = f.f_back 542*cda5da8dSAndroid Build Coastguard Worker stack.reverse() 543*cda5da8dSAndroid Build Coastguard Worker i = max(0, len(stack) - 1) 544*cda5da8dSAndroid Build Coastguard Worker while t is not None: 545*cda5da8dSAndroid Build Coastguard Worker stack.append((t.tb_frame, t.tb_lineno)) 546*cda5da8dSAndroid Build Coastguard Worker t = t.tb_next 547*cda5da8dSAndroid Build Coastguard Worker if f is None: 548*cda5da8dSAndroid Build Coastguard Worker i = max(0, len(stack) - 1) 549*cda5da8dSAndroid Build Coastguard Worker return stack, i 550*cda5da8dSAndroid Build Coastguard Worker 551*cda5da8dSAndroid Build Coastguard Worker def format_stack_entry(self, frame_lineno, lprefix=': '): 552*cda5da8dSAndroid Build Coastguard Worker """Return a string with information about a stack entry. 553*cda5da8dSAndroid Build Coastguard Worker 554*cda5da8dSAndroid Build Coastguard Worker The stack entry frame_lineno is a (frame, lineno) tuple. The 555*cda5da8dSAndroid Build Coastguard Worker return string contains the canonical filename, the function name 556*cda5da8dSAndroid Build Coastguard Worker or '<lambda>', the input arguments, the return value, and the 557*cda5da8dSAndroid Build Coastguard Worker line of code (if it exists). 558*cda5da8dSAndroid Build Coastguard Worker 559*cda5da8dSAndroid Build Coastguard Worker """ 560*cda5da8dSAndroid Build Coastguard Worker import linecache, reprlib 561*cda5da8dSAndroid Build Coastguard Worker frame, lineno = frame_lineno 562*cda5da8dSAndroid Build Coastguard Worker filename = self.canonic(frame.f_code.co_filename) 563*cda5da8dSAndroid Build Coastguard Worker s = '%s(%r)' % (filename, lineno) 564*cda5da8dSAndroid Build Coastguard Worker if frame.f_code.co_name: 565*cda5da8dSAndroid Build Coastguard Worker s += frame.f_code.co_name 566*cda5da8dSAndroid Build Coastguard Worker else: 567*cda5da8dSAndroid Build Coastguard Worker s += "<lambda>" 568*cda5da8dSAndroid Build Coastguard Worker s += '()' 569*cda5da8dSAndroid Build Coastguard Worker if '__return__' in frame.f_locals: 570*cda5da8dSAndroid Build Coastguard Worker rv = frame.f_locals['__return__'] 571*cda5da8dSAndroid Build Coastguard Worker s += '->' 572*cda5da8dSAndroid Build Coastguard Worker s += reprlib.repr(rv) 573*cda5da8dSAndroid Build Coastguard Worker if lineno is not None: 574*cda5da8dSAndroid Build Coastguard Worker line = linecache.getline(filename, lineno, frame.f_globals) 575*cda5da8dSAndroid Build Coastguard Worker if line: 576*cda5da8dSAndroid Build Coastguard Worker s += lprefix + line.strip() 577*cda5da8dSAndroid Build Coastguard Worker else: 578*cda5da8dSAndroid Build Coastguard Worker s += f'{lprefix}Warning: lineno is None' 579*cda5da8dSAndroid Build Coastguard Worker return s 580*cda5da8dSAndroid Build Coastguard Worker 581*cda5da8dSAndroid Build Coastguard Worker # The following methods can be called by clients to use 582*cda5da8dSAndroid Build Coastguard Worker # a debugger to debug a statement or an expression. 583*cda5da8dSAndroid Build Coastguard Worker # Both can be given as a string, or a code object. 584*cda5da8dSAndroid Build Coastguard Worker 585*cda5da8dSAndroid Build Coastguard Worker def run(self, cmd, globals=None, locals=None): 586*cda5da8dSAndroid Build Coastguard Worker """Debug a statement executed via the exec() function. 587*cda5da8dSAndroid Build Coastguard Worker 588*cda5da8dSAndroid Build Coastguard Worker globals defaults to __main__.dict; locals defaults to globals. 589*cda5da8dSAndroid Build Coastguard Worker """ 590*cda5da8dSAndroid Build Coastguard Worker if globals is None: 591*cda5da8dSAndroid Build Coastguard Worker import __main__ 592*cda5da8dSAndroid Build Coastguard Worker globals = __main__.__dict__ 593*cda5da8dSAndroid Build Coastguard Worker if locals is None: 594*cda5da8dSAndroid Build Coastguard Worker locals = globals 595*cda5da8dSAndroid Build Coastguard Worker self.reset() 596*cda5da8dSAndroid Build Coastguard Worker if isinstance(cmd, str): 597*cda5da8dSAndroid Build Coastguard Worker cmd = compile(cmd, "<string>", "exec") 598*cda5da8dSAndroid Build Coastguard Worker sys.settrace(self.trace_dispatch) 599*cda5da8dSAndroid Build Coastguard Worker try: 600*cda5da8dSAndroid Build Coastguard Worker exec(cmd, globals, locals) 601*cda5da8dSAndroid Build Coastguard Worker except BdbQuit: 602*cda5da8dSAndroid Build Coastguard Worker pass 603*cda5da8dSAndroid Build Coastguard Worker finally: 604*cda5da8dSAndroid Build Coastguard Worker self.quitting = True 605*cda5da8dSAndroid Build Coastguard Worker sys.settrace(None) 606*cda5da8dSAndroid Build Coastguard Worker 607*cda5da8dSAndroid Build Coastguard Worker def runeval(self, expr, globals=None, locals=None): 608*cda5da8dSAndroid Build Coastguard Worker """Debug an expression executed via the eval() function. 609*cda5da8dSAndroid Build Coastguard Worker 610*cda5da8dSAndroid Build Coastguard Worker globals defaults to __main__.dict; locals defaults to globals. 611*cda5da8dSAndroid Build Coastguard Worker """ 612*cda5da8dSAndroid Build Coastguard Worker if globals is None: 613*cda5da8dSAndroid Build Coastguard Worker import __main__ 614*cda5da8dSAndroid Build Coastguard Worker globals = __main__.__dict__ 615*cda5da8dSAndroid Build Coastguard Worker if locals is None: 616*cda5da8dSAndroid Build Coastguard Worker locals = globals 617*cda5da8dSAndroid Build Coastguard Worker self.reset() 618*cda5da8dSAndroid Build Coastguard Worker sys.settrace(self.trace_dispatch) 619*cda5da8dSAndroid Build Coastguard Worker try: 620*cda5da8dSAndroid Build Coastguard Worker return eval(expr, globals, locals) 621*cda5da8dSAndroid Build Coastguard Worker except BdbQuit: 622*cda5da8dSAndroid Build Coastguard Worker pass 623*cda5da8dSAndroid Build Coastguard Worker finally: 624*cda5da8dSAndroid Build Coastguard Worker self.quitting = True 625*cda5da8dSAndroid Build Coastguard Worker sys.settrace(None) 626*cda5da8dSAndroid Build Coastguard Worker 627*cda5da8dSAndroid Build Coastguard Worker def runctx(self, cmd, globals, locals): 628*cda5da8dSAndroid Build Coastguard Worker """For backwards-compatibility. Defers to run().""" 629*cda5da8dSAndroid Build Coastguard Worker # B/W compatibility 630*cda5da8dSAndroid Build Coastguard Worker self.run(cmd, globals, locals) 631*cda5da8dSAndroid Build Coastguard Worker 632*cda5da8dSAndroid Build Coastguard Worker # This method is more useful to debug a single function call. 633*cda5da8dSAndroid Build Coastguard Worker 634*cda5da8dSAndroid Build Coastguard Worker def runcall(self, func, /, *args, **kwds): 635*cda5da8dSAndroid Build Coastguard Worker """Debug a single function call. 636*cda5da8dSAndroid Build Coastguard Worker 637*cda5da8dSAndroid Build Coastguard Worker Return the result of the function call. 638*cda5da8dSAndroid Build Coastguard Worker """ 639*cda5da8dSAndroid Build Coastguard Worker self.reset() 640*cda5da8dSAndroid Build Coastguard Worker sys.settrace(self.trace_dispatch) 641*cda5da8dSAndroid Build Coastguard Worker res = None 642*cda5da8dSAndroid Build Coastguard Worker try: 643*cda5da8dSAndroid Build Coastguard Worker res = func(*args, **kwds) 644*cda5da8dSAndroid Build Coastguard Worker except BdbQuit: 645*cda5da8dSAndroid Build Coastguard Worker pass 646*cda5da8dSAndroid Build Coastguard Worker finally: 647*cda5da8dSAndroid Build Coastguard Worker self.quitting = True 648*cda5da8dSAndroid Build Coastguard Worker sys.settrace(None) 649*cda5da8dSAndroid Build Coastguard Worker return res 650*cda5da8dSAndroid Build Coastguard Worker 651*cda5da8dSAndroid Build Coastguard Worker 652*cda5da8dSAndroid Build Coastguard Workerdef set_trace(): 653*cda5da8dSAndroid Build Coastguard Worker """Start debugging with a Bdb instance from the caller's frame.""" 654*cda5da8dSAndroid Build Coastguard Worker Bdb().set_trace() 655*cda5da8dSAndroid Build Coastguard Worker 656*cda5da8dSAndroid Build Coastguard Worker 657*cda5da8dSAndroid Build Coastguard Workerclass Breakpoint: 658*cda5da8dSAndroid Build Coastguard Worker """Breakpoint class. 659*cda5da8dSAndroid Build Coastguard Worker 660*cda5da8dSAndroid Build Coastguard Worker Implements temporary breakpoints, ignore counts, disabling and 661*cda5da8dSAndroid Build Coastguard Worker (re)-enabling, and conditionals. 662*cda5da8dSAndroid Build Coastguard Worker 663*cda5da8dSAndroid Build Coastguard Worker Breakpoints are indexed by number through bpbynumber and by 664*cda5da8dSAndroid Build Coastguard Worker the (file, line) tuple using bplist. The former points to a 665*cda5da8dSAndroid Build Coastguard Worker single instance of class Breakpoint. The latter points to a 666*cda5da8dSAndroid Build Coastguard Worker list of such instances since there may be more than one 667*cda5da8dSAndroid Build Coastguard Worker breakpoint per line. 668*cda5da8dSAndroid Build Coastguard Worker 669*cda5da8dSAndroid Build Coastguard Worker When creating a breakpoint, its associated filename should be 670*cda5da8dSAndroid Build Coastguard Worker in canonical form. If funcname is defined, a breakpoint hit will be 671*cda5da8dSAndroid Build Coastguard Worker counted when the first line of that function is executed. A 672*cda5da8dSAndroid Build Coastguard Worker conditional breakpoint always counts a hit. 673*cda5da8dSAndroid Build Coastguard Worker """ 674*cda5da8dSAndroid Build Coastguard Worker 675*cda5da8dSAndroid Build Coastguard Worker # XXX Keeping state in the class is a mistake -- this means 676*cda5da8dSAndroid Build Coastguard Worker # you cannot have more than one active Bdb instance. 677*cda5da8dSAndroid Build Coastguard Worker 678*cda5da8dSAndroid Build Coastguard Worker next = 1 # Next bp to be assigned 679*cda5da8dSAndroid Build Coastguard Worker bplist = {} # indexed by (file, lineno) tuple 680*cda5da8dSAndroid Build Coastguard Worker bpbynumber = [None] # Each entry is None or an instance of Bpt 681*cda5da8dSAndroid Build Coastguard Worker # index 0 is unused, except for marking an 682*cda5da8dSAndroid Build Coastguard Worker # effective break .... see effective() 683*cda5da8dSAndroid Build Coastguard Worker 684*cda5da8dSAndroid Build Coastguard Worker def __init__(self, file, line, temporary=False, cond=None, funcname=None): 685*cda5da8dSAndroid Build Coastguard Worker self.funcname = funcname 686*cda5da8dSAndroid Build Coastguard Worker # Needed if funcname is not None. 687*cda5da8dSAndroid Build Coastguard Worker self.func_first_executable_line = None 688*cda5da8dSAndroid Build Coastguard Worker self.file = file # This better be in canonical form! 689*cda5da8dSAndroid Build Coastguard Worker self.line = line 690*cda5da8dSAndroid Build Coastguard Worker self.temporary = temporary 691*cda5da8dSAndroid Build Coastguard Worker self.cond = cond 692*cda5da8dSAndroid Build Coastguard Worker self.enabled = True 693*cda5da8dSAndroid Build Coastguard Worker self.ignore = 0 694*cda5da8dSAndroid Build Coastguard Worker self.hits = 0 695*cda5da8dSAndroid Build Coastguard Worker self.number = Breakpoint.next 696*cda5da8dSAndroid Build Coastguard Worker Breakpoint.next += 1 697*cda5da8dSAndroid Build Coastguard Worker # Build the two lists 698*cda5da8dSAndroid Build Coastguard Worker self.bpbynumber.append(self) 699*cda5da8dSAndroid Build Coastguard Worker if (file, line) in self.bplist: 700*cda5da8dSAndroid Build Coastguard Worker self.bplist[file, line].append(self) 701*cda5da8dSAndroid Build Coastguard Worker else: 702*cda5da8dSAndroid Build Coastguard Worker self.bplist[file, line] = [self] 703*cda5da8dSAndroid Build Coastguard Worker 704*cda5da8dSAndroid Build Coastguard Worker @staticmethod 705*cda5da8dSAndroid Build Coastguard Worker def clearBreakpoints(): 706*cda5da8dSAndroid Build Coastguard Worker Breakpoint.next = 1 707*cda5da8dSAndroid Build Coastguard Worker Breakpoint.bplist = {} 708*cda5da8dSAndroid Build Coastguard Worker Breakpoint.bpbynumber = [None] 709*cda5da8dSAndroid Build Coastguard Worker 710*cda5da8dSAndroid Build Coastguard Worker def deleteMe(self): 711*cda5da8dSAndroid Build Coastguard Worker """Delete the breakpoint from the list associated to a file:line. 712*cda5da8dSAndroid Build Coastguard Worker 713*cda5da8dSAndroid Build Coastguard Worker If it is the last breakpoint in that position, it also deletes 714*cda5da8dSAndroid Build Coastguard Worker the entry for the file:line. 715*cda5da8dSAndroid Build Coastguard Worker """ 716*cda5da8dSAndroid Build Coastguard Worker 717*cda5da8dSAndroid Build Coastguard Worker index = (self.file, self.line) 718*cda5da8dSAndroid Build Coastguard Worker self.bpbynumber[self.number] = None # No longer in list 719*cda5da8dSAndroid Build Coastguard Worker self.bplist[index].remove(self) 720*cda5da8dSAndroid Build Coastguard Worker if not self.bplist[index]: 721*cda5da8dSAndroid Build Coastguard Worker # No more bp for this f:l combo 722*cda5da8dSAndroid Build Coastguard Worker del self.bplist[index] 723*cda5da8dSAndroid Build Coastguard Worker 724*cda5da8dSAndroid Build Coastguard Worker def enable(self): 725*cda5da8dSAndroid Build Coastguard Worker """Mark the breakpoint as enabled.""" 726*cda5da8dSAndroid Build Coastguard Worker self.enabled = True 727*cda5da8dSAndroid Build Coastguard Worker 728*cda5da8dSAndroid Build Coastguard Worker def disable(self): 729*cda5da8dSAndroid Build Coastguard Worker """Mark the breakpoint as disabled.""" 730*cda5da8dSAndroid Build Coastguard Worker self.enabled = False 731*cda5da8dSAndroid Build Coastguard Worker 732*cda5da8dSAndroid Build Coastguard Worker def bpprint(self, out=None): 733*cda5da8dSAndroid Build Coastguard Worker """Print the output of bpformat(). 734*cda5da8dSAndroid Build Coastguard Worker 735*cda5da8dSAndroid Build Coastguard Worker The optional out argument directs where the output is sent 736*cda5da8dSAndroid Build Coastguard Worker and defaults to standard output. 737*cda5da8dSAndroid Build Coastguard Worker """ 738*cda5da8dSAndroid Build Coastguard Worker if out is None: 739*cda5da8dSAndroid Build Coastguard Worker out = sys.stdout 740*cda5da8dSAndroid Build Coastguard Worker print(self.bpformat(), file=out) 741*cda5da8dSAndroid Build Coastguard Worker 742*cda5da8dSAndroid Build Coastguard Worker def bpformat(self): 743*cda5da8dSAndroid Build Coastguard Worker """Return a string with information about the breakpoint. 744*cda5da8dSAndroid Build Coastguard Worker 745*cda5da8dSAndroid Build Coastguard Worker The information includes the breakpoint number, temporary 746*cda5da8dSAndroid Build Coastguard Worker status, file:line position, break condition, number of times to 747*cda5da8dSAndroid Build Coastguard Worker ignore, and number of times hit. 748*cda5da8dSAndroid Build Coastguard Worker 749*cda5da8dSAndroid Build Coastguard Worker """ 750*cda5da8dSAndroid Build Coastguard Worker if self.temporary: 751*cda5da8dSAndroid Build Coastguard Worker disp = 'del ' 752*cda5da8dSAndroid Build Coastguard Worker else: 753*cda5da8dSAndroid Build Coastguard Worker disp = 'keep ' 754*cda5da8dSAndroid Build Coastguard Worker if self.enabled: 755*cda5da8dSAndroid Build Coastguard Worker disp = disp + 'yes ' 756*cda5da8dSAndroid Build Coastguard Worker else: 757*cda5da8dSAndroid Build Coastguard Worker disp = disp + 'no ' 758*cda5da8dSAndroid Build Coastguard Worker ret = '%-4dbreakpoint %s at %s:%d' % (self.number, disp, 759*cda5da8dSAndroid Build Coastguard Worker self.file, self.line) 760*cda5da8dSAndroid Build Coastguard Worker if self.cond: 761*cda5da8dSAndroid Build Coastguard Worker ret += '\n\tstop only if %s' % (self.cond,) 762*cda5da8dSAndroid Build Coastguard Worker if self.ignore: 763*cda5da8dSAndroid Build Coastguard Worker ret += '\n\tignore next %d hits' % (self.ignore,) 764*cda5da8dSAndroid Build Coastguard Worker if self.hits: 765*cda5da8dSAndroid Build Coastguard Worker if self.hits > 1: 766*cda5da8dSAndroid Build Coastguard Worker ss = 's' 767*cda5da8dSAndroid Build Coastguard Worker else: 768*cda5da8dSAndroid Build Coastguard Worker ss = '' 769*cda5da8dSAndroid Build Coastguard Worker ret += '\n\tbreakpoint already hit %d time%s' % (self.hits, ss) 770*cda5da8dSAndroid Build Coastguard Worker return ret 771*cda5da8dSAndroid Build Coastguard Worker 772*cda5da8dSAndroid Build Coastguard Worker def __str__(self): 773*cda5da8dSAndroid Build Coastguard Worker "Return a condensed description of the breakpoint." 774*cda5da8dSAndroid Build Coastguard Worker return 'breakpoint %s at %s:%s' % (self.number, self.file, self.line) 775*cda5da8dSAndroid Build Coastguard Worker 776*cda5da8dSAndroid Build Coastguard Worker# -----------end of Breakpoint class---------- 777*cda5da8dSAndroid Build Coastguard Worker 778*cda5da8dSAndroid Build Coastguard Worker 779*cda5da8dSAndroid Build Coastguard Workerdef checkfuncname(b, frame): 780*cda5da8dSAndroid Build Coastguard Worker """Return True if break should happen here. 781*cda5da8dSAndroid Build Coastguard Worker 782*cda5da8dSAndroid Build Coastguard Worker Whether a break should happen depends on the way that b (the breakpoint) 783*cda5da8dSAndroid Build Coastguard Worker was set. If it was set via line number, check if b.line is the same as 784*cda5da8dSAndroid Build Coastguard Worker the one in the frame. If it was set via function name, check if this is 785*cda5da8dSAndroid Build Coastguard Worker the right function and if it is on the first executable line. 786*cda5da8dSAndroid Build Coastguard Worker """ 787*cda5da8dSAndroid Build Coastguard Worker if not b.funcname: 788*cda5da8dSAndroid Build Coastguard Worker # Breakpoint was set via line number. 789*cda5da8dSAndroid Build Coastguard Worker if b.line != frame.f_lineno: 790*cda5da8dSAndroid Build Coastguard Worker # Breakpoint was set at a line with a def statement and the function 791*cda5da8dSAndroid Build Coastguard Worker # defined is called: don't break. 792*cda5da8dSAndroid Build Coastguard Worker return False 793*cda5da8dSAndroid Build Coastguard Worker return True 794*cda5da8dSAndroid Build Coastguard Worker 795*cda5da8dSAndroid Build Coastguard Worker # Breakpoint set via function name. 796*cda5da8dSAndroid Build Coastguard Worker if frame.f_code.co_name != b.funcname: 797*cda5da8dSAndroid Build Coastguard Worker # It's not a function call, but rather execution of def statement. 798*cda5da8dSAndroid Build Coastguard Worker return False 799*cda5da8dSAndroid Build Coastguard Worker 800*cda5da8dSAndroid Build Coastguard Worker # We are in the right frame. 801*cda5da8dSAndroid Build Coastguard Worker if not b.func_first_executable_line: 802*cda5da8dSAndroid Build Coastguard Worker # The function is entered for the 1st time. 803*cda5da8dSAndroid Build Coastguard Worker b.func_first_executable_line = frame.f_lineno 804*cda5da8dSAndroid Build Coastguard Worker 805*cda5da8dSAndroid Build Coastguard Worker if b.func_first_executable_line != frame.f_lineno: 806*cda5da8dSAndroid Build Coastguard Worker # But we are not at the first line number: don't break. 807*cda5da8dSAndroid Build Coastguard Worker return False 808*cda5da8dSAndroid Build Coastguard Worker return True 809*cda5da8dSAndroid Build Coastguard Worker 810*cda5da8dSAndroid Build Coastguard Worker 811*cda5da8dSAndroid Build Coastguard Workerdef effective(file, line, frame): 812*cda5da8dSAndroid Build Coastguard Worker """Return (active breakpoint, delete temporary flag) or (None, None) as 813*cda5da8dSAndroid Build Coastguard Worker breakpoint to act upon. 814*cda5da8dSAndroid Build Coastguard Worker 815*cda5da8dSAndroid Build Coastguard Worker The "active breakpoint" is the first entry in bplist[line, file] (which 816*cda5da8dSAndroid Build Coastguard Worker must exist) that is enabled, for which checkfuncname is True, and that 817*cda5da8dSAndroid Build Coastguard Worker has neither a False condition nor a positive ignore count. The flag, 818*cda5da8dSAndroid Build Coastguard Worker meaning that a temporary breakpoint should be deleted, is False only 819*cda5da8dSAndroid Build Coastguard Worker when the condiion cannot be evaluated (in which case, ignore count is 820*cda5da8dSAndroid Build Coastguard Worker ignored). 821*cda5da8dSAndroid Build Coastguard Worker 822*cda5da8dSAndroid Build Coastguard Worker If no such entry exists, then (None, None) is returned. 823*cda5da8dSAndroid Build Coastguard Worker """ 824*cda5da8dSAndroid Build Coastguard Worker possibles = Breakpoint.bplist[file, line] 825*cda5da8dSAndroid Build Coastguard Worker for b in possibles: 826*cda5da8dSAndroid Build Coastguard Worker if not b.enabled: 827*cda5da8dSAndroid Build Coastguard Worker continue 828*cda5da8dSAndroid Build Coastguard Worker if not checkfuncname(b, frame): 829*cda5da8dSAndroid Build Coastguard Worker continue 830*cda5da8dSAndroid Build Coastguard Worker # Count every hit when bp is enabled 831*cda5da8dSAndroid Build Coastguard Worker b.hits += 1 832*cda5da8dSAndroid Build Coastguard Worker if not b.cond: 833*cda5da8dSAndroid Build Coastguard Worker # If unconditional, and ignoring go on to next, else break 834*cda5da8dSAndroid Build Coastguard Worker if b.ignore > 0: 835*cda5da8dSAndroid Build Coastguard Worker b.ignore -= 1 836*cda5da8dSAndroid Build Coastguard Worker continue 837*cda5da8dSAndroid Build Coastguard Worker else: 838*cda5da8dSAndroid Build Coastguard Worker # breakpoint and marker that it's ok to delete if temporary 839*cda5da8dSAndroid Build Coastguard Worker return (b, True) 840*cda5da8dSAndroid Build Coastguard Worker else: 841*cda5da8dSAndroid Build Coastguard Worker # Conditional bp. 842*cda5da8dSAndroid Build Coastguard Worker # Ignore count applies only to those bpt hits where the 843*cda5da8dSAndroid Build Coastguard Worker # condition evaluates to true. 844*cda5da8dSAndroid Build Coastguard Worker try: 845*cda5da8dSAndroid Build Coastguard Worker val = eval(b.cond, frame.f_globals, frame.f_locals) 846*cda5da8dSAndroid Build Coastguard Worker if val: 847*cda5da8dSAndroid Build Coastguard Worker if b.ignore > 0: 848*cda5da8dSAndroid Build Coastguard Worker b.ignore -= 1 849*cda5da8dSAndroid Build Coastguard Worker # continue 850*cda5da8dSAndroid Build Coastguard Worker else: 851*cda5da8dSAndroid Build Coastguard Worker return (b, True) 852*cda5da8dSAndroid Build Coastguard Worker # else: 853*cda5da8dSAndroid Build Coastguard Worker # continue 854*cda5da8dSAndroid Build Coastguard Worker except: 855*cda5da8dSAndroid Build Coastguard Worker # if eval fails, most conservative thing is to stop on 856*cda5da8dSAndroid Build Coastguard Worker # breakpoint regardless of ignore count. Don't delete 857*cda5da8dSAndroid Build Coastguard Worker # temporary, as another hint to user. 858*cda5da8dSAndroid Build Coastguard Worker return (b, False) 859*cda5da8dSAndroid Build Coastguard Worker return (None, None) 860*cda5da8dSAndroid Build Coastguard Worker 861*cda5da8dSAndroid Build Coastguard Worker 862*cda5da8dSAndroid Build Coastguard Worker# -------------------- testing -------------------- 863*cda5da8dSAndroid Build Coastguard Worker 864*cda5da8dSAndroid Build Coastguard Workerclass Tdb(Bdb): 865*cda5da8dSAndroid Build Coastguard Worker def user_call(self, frame, args): 866*cda5da8dSAndroid Build Coastguard Worker name = frame.f_code.co_name 867*cda5da8dSAndroid Build Coastguard Worker if not name: name = '???' 868*cda5da8dSAndroid Build Coastguard Worker print('+++ call', name, args) 869*cda5da8dSAndroid Build Coastguard Worker def user_line(self, frame): 870*cda5da8dSAndroid Build Coastguard Worker import linecache 871*cda5da8dSAndroid Build Coastguard Worker name = frame.f_code.co_name 872*cda5da8dSAndroid Build Coastguard Worker if not name: name = '???' 873*cda5da8dSAndroid Build Coastguard Worker fn = self.canonic(frame.f_code.co_filename) 874*cda5da8dSAndroid Build Coastguard Worker line = linecache.getline(fn, frame.f_lineno, frame.f_globals) 875*cda5da8dSAndroid Build Coastguard Worker print('+++', fn, frame.f_lineno, name, ':', line.strip()) 876*cda5da8dSAndroid Build Coastguard Worker def user_return(self, frame, retval): 877*cda5da8dSAndroid Build Coastguard Worker print('+++ return', retval) 878*cda5da8dSAndroid Build Coastguard Worker def user_exception(self, frame, exc_stuff): 879*cda5da8dSAndroid Build Coastguard Worker print('+++ exception', exc_stuff) 880*cda5da8dSAndroid Build Coastguard Worker self.set_continue() 881*cda5da8dSAndroid Build Coastguard Worker 882*cda5da8dSAndroid Build Coastguard Workerdef foo(n): 883*cda5da8dSAndroid Build Coastguard Worker print('foo(', n, ')') 884*cda5da8dSAndroid Build Coastguard Worker x = bar(n*10) 885*cda5da8dSAndroid Build Coastguard Worker print('bar returned', x) 886*cda5da8dSAndroid Build Coastguard Worker 887*cda5da8dSAndroid Build Coastguard Workerdef bar(a): 888*cda5da8dSAndroid Build Coastguard Worker print('bar(', a, ')') 889*cda5da8dSAndroid Build Coastguard Worker return a/2 890*cda5da8dSAndroid Build Coastguard Worker 891*cda5da8dSAndroid Build Coastguard Workerdef test(): 892*cda5da8dSAndroid Build Coastguard Worker t = Tdb() 893*cda5da8dSAndroid Build Coastguard Worker t.run('import bdb; bdb.foo(10)') 894