1#! /usr/bin/env python3 2 3""" 4The Python Debugger Pdb 5======================= 6 7To use the debugger in its simplest form: 8 9 >>> import pdb 10 >>> pdb.run('<a statement>') 11 12The debugger's prompt is '(Pdb) '. This will stop in the first 13function call in <a statement>. 14 15Alternatively, if a statement terminated with an unhandled exception, 16you can use pdb's post-mortem facility to inspect the contents of the 17traceback: 18 19 >>> <a statement> 20 <exception traceback> 21 >>> import pdb 22 >>> pdb.pm() 23 24The commands recognized by the debugger are listed in the next 25section. Most can be abbreviated as indicated; e.g., h(elp) means 26that 'help' can be typed as 'h' or 'help' (but not as 'he' or 'hel', 27nor as 'H' or 'Help' or 'HELP'). Optional arguments are enclosed in 28square brackets. Alternatives in the command syntax are separated 29by a vertical bar (|). 30 31A blank line repeats the previous command literally, except for 32'list', where it lists the next 11 lines. 33 34Commands that the debugger doesn't recognize are assumed to be Python 35statements and are executed in the context of the program being 36debugged. Python statements can also be prefixed with an exclamation 37point ('!'). This is a powerful way to inspect the program being 38debugged; it is even possible to change variables or call functions. 39When an exception occurs in such a statement, the exception name is 40printed but the debugger's state is not changed. 41 42The debugger supports aliases, which can save typing. And aliases can 43have parameters (see the alias help entry) which allows one a certain 44level of adaptability to the context under examination. 45 46Multiple commands may be entered on a single line, separated by the 47pair ';;'. No intelligence is applied to separating the commands; the 48input is split at the first ';;', even if it is in the middle of a 49quoted string. 50 51If a file ".pdbrc" exists in your home directory or in the current 52directory, it is read in and executed as if it had been typed at the 53debugger prompt. This is particularly useful for aliases. If both 54files exist, the one in the home directory is read first and aliases 55defined there can be overridden by the local file. This behavior can be 56disabled by passing the "readrc=False" argument to the Pdb constructor. 57 58Aside from aliases, the debugger is not directly programmable; but it 59is implemented as a class from which you can derive your own debugger 60class, which you can make as fancy as you like. 61 62 63Debugger commands 64================= 65 66""" 67# NOTE: the actual command documentation is collected from docstrings of the 68# commands and is appended to __doc__ after the class has been defined. 69 70import os 71import io 72import re 73import sys 74import cmd 75import bdb 76import dis 77import code 78import glob 79import token 80import types 81import codeop 82import pprint 83import signal 84import inspect 85import textwrap 86import tokenize 87import itertools 88import traceback 89import linecache 90import _colorize 91 92from contextlib import contextmanager 93from rlcompleter import Completer 94from types import CodeType 95 96 97class Restart(Exception): 98 """Causes a debugger to be restarted for the debugged python program.""" 99 pass 100 101__all__ = ["run", "pm", "Pdb", "runeval", "runctx", "runcall", "set_trace", 102 "post_mortem", "help"] 103 104 105def find_first_executable_line(code): 106 """ Try to find the first executable line of the code object. 107 108 Equivalently, find the line number of the instruction that's 109 after RESUME 110 111 Return code.co_firstlineno if no executable line is found. 112 """ 113 prev = None 114 for instr in dis.get_instructions(code): 115 if prev is not None and prev.opname == 'RESUME': 116 if instr.positions.lineno is not None: 117 return instr.positions.lineno 118 return code.co_firstlineno 119 prev = instr 120 return code.co_firstlineno 121 122def find_function(funcname, filename): 123 cre = re.compile(r'def\s+%s(\s*\[.+\])?\s*[(]' % re.escape(funcname)) 124 try: 125 fp = tokenize.open(filename) 126 except OSError: 127 lines = linecache.getlines(filename) 128 if not lines: 129 return None 130 fp = io.StringIO(''.join(lines)) 131 funcdef = "" 132 funcstart = None 133 # consumer of this info expects the first line to be 1 134 with fp: 135 for lineno, line in enumerate(fp, start=1): 136 if cre.match(line): 137 funcstart, funcdef = lineno, line 138 elif funcdef: 139 funcdef += line 140 141 if funcdef: 142 try: 143 code = compile(funcdef, filename, 'exec') 144 except SyntaxError: 145 continue 146 # We should always be able to find the code object here 147 funccode = next(c for c in code.co_consts if 148 isinstance(c, CodeType) and c.co_name == funcname) 149 lineno_offset = find_first_executable_line(funccode) 150 return funcname, filename, funcstart + lineno_offset - 1 151 return None 152 153def lasti2lineno(code, lasti): 154 linestarts = list(dis.findlinestarts(code)) 155 linestarts.reverse() 156 for i, lineno in linestarts: 157 if lasti >= i: 158 return lineno 159 return 0 160 161 162class _rstr(str): 163 """String that doesn't quote its repr.""" 164 def __repr__(self): 165 return self 166 167 168class _ExecutableTarget: 169 filename: str 170 code: CodeType | str 171 namespace: dict 172 173 174class _ScriptTarget(_ExecutableTarget): 175 def __init__(self, target): 176 self._target = os.path.realpath(target) 177 178 if not os.path.exists(self._target): 179 print(f'Error: {target} does not exist') 180 sys.exit(1) 181 if os.path.isdir(self._target): 182 print(f'Error: {target} is a directory') 183 sys.exit(1) 184 185 # If safe_path(-P) is not set, sys.path[0] is the directory 186 # of pdb, and we should replace it with the directory of the script 187 if not sys.flags.safe_path: 188 sys.path[0] = os.path.dirname(self._target) 189 190 def __repr__(self): 191 return self._target 192 193 @property 194 def filename(self): 195 return self._target 196 197 @property 198 def code(self): 199 # Open the file each time because the file may be modified 200 with io.open_code(self._target) as fp: 201 return f"exec(compile({fp.read()!r}, {self._target!r}, 'exec'))" 202 203 @property 204 def namespace(self): 205 return dict( 206 __name__='__main__', 207 __file__=self._target, 208 __builtins__=__builtins__, 209 __spec__=None, 210 ) 211 212 213class _ModuleTarget(_ExecutableTarget): 214 def __init__(self, target): 215 self._target = target 216 217 import runpy 218 try: 219 _, self._spec, self._code = runpy._get_module_details(self._target) 220 except ImportError as e: 221 print(f"ImportError: {e}") 222 sys.exit(1) 223 except Exception: 224 traceback.print_exc() 225 sys.exit(1) 226 227 def __repr__(self): 228 return self._target 229 230 @property 231 def filename(self): 232 return self._code.co_filename 233 234 @property 235 def code(self): 236 return self._code 237 238 @property 239 def namespace(self): 240 return dict( 241 __name__='__main__', 242 __file__=os.path.normcase(os.path.abspath(self.filename)), 243 __package__=self._spec.parent, 244 __loader__=self._spec.loader, 245 __spec__=self._spec, 246 __builtins__=__builtins__, 247 ) 248 249 250class _ZipTarget(_ExecutableTarget): 251 def __init__(self, target): 252 import runpy 253 254 self._target = os.path.realpath(target) 255 sys.path.insert(0, self._target) 256 try: 257 _, self._spec, self._code = runpy._get_main_module_details() 258 except ImportError as e: 259 print(f"ImportError: {e}") 260 sys.exit(1) 261 except Exception: 262 traceback.print_exc() 263 sys.exit(1) 264 265 def __repr__(self): 266 return self._target 267 268 @property 269 def filename(self): 270 return self._code.co_filename 271 272 @property 273 def code(self): 274 return self._code 275 276 @property 277 def namespace(self): 278 return dict( 279 __name__='__main__', 280 __file__=os.path.normcase(os.path.abspath(self.filename)), 281 __package__=self._spec.parent, 282 __loader__=self._spec.loader, 283 __spec__=self._spec, 284 __builtins__=__builtins__, 285 ) 286 287 288class _PdbInteractiveConsole(code.InteractiveConsole): 289 def __init__(self, ns, message): 290 self._message = message 291 super().__init__(locals=ns, local_exit=True) 292 293 def write(self, data): 294 self._message(data, end='') 295 296 297# Interaction prompt line will separate file and call info from code 298# text using value of line_prefix string. A newline and arrow may 299# be to your liking. You can set it once pdb is imported using the 300# command "pdb.line_prefix = '\n% '". 301# line_prefix = ': ' # Use this to get the old situation back 302line_prefix = '\n-> ' # Probably a better default 303 304 305 306class Pdb(bdb.Bdb, cmd.Cmd): 307 _previous_sigint_handler = None 308 309 # Limit the maximum depth of chained exceptions, we should be handling cycles, 310 # but in case there are recursions, we stop at 999. 311 MAX_CHAINED_EXCEPTION_DEPTH = 999 312 313 _file_mtime_table = {} 314 315 def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, 316 nosigint=False, readrc=True): 317 bdb.Bdb.__init__(self, skip=skip) 318 cmd.Cmd.__init__(self, completekey, stdin, stdout) 319 sys.audit("pdb.Pdb") 320 if stdout: 321 self.use_rawinput = 0 322 self.prompt = '(Pdb) ' 323 self.aliases = {} 324 self.displaying = {} 325 self.mainpyfile = '' 326 self._wait_for_mainpyfile = False 327 self.tb_lineno = {} 328 # Try to load readline if it exists 329 try: 330 import readline 331 # remove some common file name delimiters 332 readline.set_completer_delims(' \t\n`@#%^&*()=+[{]}\\|;:\'",<>?') 333 except ImportError: 334 pass 335 self.allow_kbdint = False 336 self.nosigint = nosigint 337 # Consider these characters as part of the command so when the users type 338 # c.a or c['a'], it won't be recognized as a c(ontinue) command 339 self.identchars = cmd.Cmd.identchars + '=.[](),"\'+-*/%@&|<>~^' 340 341 # Read ~/.pdbrc and ./.pdbrc 342 self.rcLines = [] 343 if readrc: 344 try: 345 with open(os.path.expanduser('~/.pdbrc'), encoding='utf-8') as rcFile: 346 self.rcLines.extend(rcFile) 347 except OSError: 348 pass 349 try: 350 with open(".pdbrc", encoding='utf-8') as rcFile: 351 self.rcLines.extend(rcFile) 352 except OSError: 353 pass 354 355 self.commands = {} # associates a command list to breakpoint numbers 356 self.commands_doprompt = {} # for each bp num, tells if the prompt 357 # must be disp. after execing the cmd list 358 self.commands_silent = {} # for each bp num, tells if the stack trace 359 # must be disp. after execing the cmd list 360 self.commands_defining = False # True while in the process of defining 361 # a command list 362 self.commands_bnum = None # The breakpoint number for which we are 363 # defining a list 364 365 self._chained_exceptions = tuple() 366 self._chained_exception_index = 0 367 368 def sigint_handler(self, signum, frame): 369 if self.allow_kbdint: 370 raise KeyboardInterrupt 371 self.message("\nProgram interrupted. (Use 'cont' to resume).") 372 self.set_step() 373 self.set_trace(frame) 374 375 def reset(self): 376 bdb.Bdb.reset(self) 377 self.forget() 378 379 def forget(self): 380 self.lineno = None 381 self.stack = [] 382 self.curindex = 0 383 if hasattr(self, 'curframe') and self.curframe: 384 self.curframe.f_globals.pop('__pdb_convenience_variables', None) 385 self.curframe = None 386 self.tb_lineno.clear() 387 388 def setup(self, f, tb): 389 self.forget() 390 self.stack, self.curindex = self.get_stack(f, tb) 391 while tb: 392 # when setting up post-mortem debugging with a traceback, save all 393 # the original line numbers to be displayed along the current line 394 # numbers (which can be different, e.g. due to finally clauses) 395 lineno = lasti2lineno(tb.tb_frame.f_code, tb.tb_lasti) 396 self.tb_lineno[tb.tb_frame] = lineno 397 tb = tb.tb_next 398 self.curframe = self.stack[self.curindex][0] 399 # The f_locals dictionary used to be updated from the actual frame 400 # locals whenever the .f_locals accessor was called, so it was 401 # cached here to ensure that modifications were not overwritten. While 402 # the caching is no longer required now that f_locals is a direct proxy 403 # on optimized frames, it's also harmless, so the code structure has 404 # been left unchanged. 405 self.curframe_locals = self.curframe.f_locals 406 self.set_convenience_variable(self.curframe, '_frame', self.curframe) 407 408 if self._chained_exceptions: 409 self.set_convenience_variable( 410 self.curframe, 411 '_exception', 412 self._chained_exceptions[self._chained_exception_index], 413 ) 414 415 if self.rcLines: 416 self.cmdqueue = [ 417 line for line in self.rcLines 418 if line.strip() and not line.strip().startswith("#") 419 ] 420 self.rcLines = [] 421 422 # Override Bdb methods 423 424 def user_call(self, frame, argument_list): 425 """This method is called when there is the remote possibility 426 that we ever need to stop in this function.""" 427 if self._wait_for_mainpyfile: 428 return 429 if self.stop_here(frame): 430 self.message('--Call--') 431 self.interaction(frame, None) 432 433 def user_line(self, frame): 434 """This function is called when we stop or break at this line.""" 435 if self._wait_for_mainpyfile: 436 if (self.mainpyfile != self.canonic(frame.f_code.co_filename)): 437 return 438 self._wait_for_mainpyfile = False 439 if self.trace_opcodes: 440 # GH-127321 441 # We want to avoid stopping at an opcode that does not have 442 # an associated line number because pdb does not like it 443 if frame.f_lineno is None: 444 self.set_stepinstr() 445 return 446 if self.bp_commands(frame): 447 self.interaction(frame, None) 448 449 user_opcode = user_line 450 451 def bp_commands(self, frame): 452 """Call every command that was set for the current active breakpoint 453 (if there is one). 454 455 Returns True if the normal interaction function must be called, 456 False otherwise.""" 457 # self.currentbp is set in bdb in Bdb.break_here if a breakpoint was hit 458 if getattr(self, "currentbp", False) and \ 459 self.currentbp in self.commands: 460 currentbp = self.currentbp 461 self.currentbp = 0 462 lastcmd_back = self.lastcmd 463 self.setup(frame, None) 464 for line in self.commands[currentbp]: 465 self.onecmd(line) 466 self.lastcmd = lastcmd_back 467 if not self.commands_silent[currentbp]: 468 self.print_stack_entry(self.stack[self.curindex]) 469 if self.commands_doprompt[currentbp]: 470 self._cmdloop() 471 self.forget() 472 return 473 return 1 474 475 def user_return(self, frame, return_value): 476 """This function is called when a return trap is set here.""" 477 if self._wait_for_mainpyfile: 478 return 479 frame.f_locals['__return__'] = return_value 480 self.set_convenience_variable(frame, '_retval', return_value) 481 self.message('--Return--') 482 self.interaction(frame, None) 483 484 def user_exception(self, frame, exc_info): 485 """This function is called if an exception occurs, 486 but only if we are to stop at or just below this level.""" 487 if self._wait_for_mainpyfile: 488 return 489 exc_type, exc_value, exc_traceback = exc_info 490 frame.f_locals['__exception__'] = exc_type, exc_value 491 self.set_convenience_variable(frame, '_exception', exc_value) 492 493 # An 'Internal StopIteration' exception is an exception debug event 494 # issued by the interpreter when handling a subgenerator run with 495 # 'yield from' or a generator controlled by a for loop. No exception has 496 # actually occurred in this case. The debugger uses this debug event to 497 # stop when the debuggee is returning from such generators. 498 prefix = 'Internal ' if (not exc_traceback 499 and exc_type is StopIteration) else '' 500 self.message('%s%s' % (prefix, self._format_exc(exc_value))) 501 self.interaction(frame, exc_traceback) 502 503 # General interaction function 504 def _cmdloop(self): 505 while True: 506 try: 507 # keyboard interrupts allow for an easy way to cancel 508 # the current command, so allow them during interactive input 509 self.allow_kbdint = True 510 self.cmdloop() 511 self.allow_kbdint = False 512 break 513 except KeyboardInterrupt: 514 self.message('--KeyboardInterrupt--') 515 516 def _validate_file_mtime(self): 517 """Check if the source file of the current frame has been modified since 518 the last time we saw it. If so, give a warning.""" 519 try: 520 filename = self.curframe.f_code.co_filename 521 mtime = os.path.getmtime(filename) 522 except Exception: 523 return 524 if (filename in self._file_mtime_table and 525 mtime != self._file_mtime_table[filename]): 526 self.message(f"*** WARNING: file '{filename}' was edited, " 527 "running stale code until the program is rerun") 528 self._file_mtime_table[filename] = mtime 529 530 # Called before loop, handles display expressions 531 # Set up convenience variable containers 532 def _show_display(self): 533 displaying = self.displaying.get(self.curframe) 534 if displaying: 535 for expr, oldvalue in displaying.items(): 536 newvalue = self._getval_except(expr) 537 # check for identity first; this prevents custom __eq__ to 538 # be called at every loop, and also prevents instances whose 539 # fields are changed to be displayed 540 if newvalue is not oldvalue and newvalue != oldvalue: 541 displaying[expr] = newvalue 542 self.message('display %s: %s [old: %s]' % 543 (expr, self._safe_repr(newvalue, expr), 544 self._safe_repr(oldvalue, expr))) 545 546 def _get_tb_and_exceptions(self, tb_or_exc): 547 """ 548 Given a tracecack or an exception, return a tuple of chained exceptions 549 and current traceback to inspect. 550 551 This will deal with selecting the right ``__cause__`` or ``__context__`` 552 as well as handling cycles, and return a flattened list of exceptions we 553 can jump to with do_exceptions. 554 555 """ 556 _exceptions = [] 557 if isinstance(tb_or_exc, BaseException): 558 traceback, current = tb_or_exc.__traceback__, tb_or_exc 559 560 while current is not None: 561 if current in _exceptions: 562 break 563 _exceptions.append(current) 564 if current.__cause__ is not None: 565 current = current.__cause__ 566 elif ( 567 current.__context__ is not None and not current.__suppress_context__ 568 ): 569 current = current.__context__ 570 571 if len(_exceptions) >= self.MAX_CHAINED_EXCEPTION_DEPTH: 572 self.message( 573 f"More than {self.MAX_CHAINED_EXCEPTION_DEPTH}" 574 " chained exceptions found, not all exceptions" 575 "will be browsable with `exceptions`." 576 ) 577 break 578 else: 579 traceback = tb_or_exc 580 return tuple(reversed(_exceptions)), traceback 581 582 @contextmanager 583 def _hold_exceptions(self, exceptions): 584 """ 585 Context manager to ensure proper cleaning of exceptions references 586 587 When given a chained exception instead of a traceback, 588 pdb may hold references to many objects which may leak memory. 589 590 We use this context manager to make sure everything is properly cleaned 591 592 """ 593 try: 594 self._chained_exceptions = exceptions 595 self._chained_exception_index = len(exceptions) - 1 596 yield 597 finally: 598 # we can't put those in forget as otherwise they would 599 # be cleared on exception change 600 self._chained_exceptions = tuple() 601 self._chained_exception_index = 0 602 603 def interaction(self, frame, tb_or_exc): 604 # Restore the previous signal handler at the Pdb prompt. 605 if Pdb._previous_sigint_handler: 606 try: 607 signal.signal(signal.SIGINT, Pdb._previous_sigint_handler) 608 except ValueError: # ValueError: signal only works in main thread 609 pass 610 else: 611 Pdb._previous_sigint_handler = None 612 613 _chained_exceptions, tb = self._get_tb_and_exceptions(tb_or_exc) 614 if isinstance(tb_or_exc, BaseException): 615 assert tb is not None, "main exception must have a traceback" 616 with self._hold_exceptions(_chained_exceptions): 617 self.setup(frame, tb) 618 # We should print the stack entry if and only if the user input 619 # is expected, and we should print it right before the user input. 620 # We achieve this by appending _pdbcmd_print_frame_status to the 621 # command queue. If cmdqueue is not exausted, the user input is 622 # not expected and we will not print the stack entry. 623 self.cmdqueue.append('_pdbcmd_print_frame_status') 624 self._cmdloop() 625 # If _pdbcmd_print_frame_status is not used, pop it out 626 if self.cmdqueue and self.cmdqueue[-1] == '_pdbcmd_print_frame_status': 627 self.cmdqueue.pop() 628 self.forget() 629 630 def displayhook(self, obj): 631 """Custom displayhook for the exec in default(), which prevents 632 assignment of the _ variable in the builtins. 633 """ 634 # reproduce the behavior of the standard displayhook, not printing None 635 if obj is not None: 636 self.message(repr(obj)) 637 638 @contextmanager 639 def _disable_command_completion(self): 640 completenames = self.completenames 641 try: 642 self.completenames = self.completedefault 643 yield 644 finally: 645 self.completenames = completenames 646 return 647 648 def _exec_in_closure(self, source, globals, locals): 649 """ Run source code in closure so code object created within source 650 can find variables in locals correctly 651 652 returns True if the source is executed, False otherwise 653 """ 654 655 # Determine if the source should be executed in closure. Only when the 656 # source compiled to multiple code objects, we should use this feature. 657 # Otherwise, we can just raise an exception and normal exec will be used. 658 659 code = compile(source, "<string>", "exec") 660 if not any(isinstance(const, CodeType) for const in code.co_consts): 661 return False 662 663 # locals could be a proxy which does not support pop 664 # copy it first to avoid modifying the original locals 665 locals_copy = dict(locals) 666 667 locals_copy["__pdb_eval__"] = { 668 "result": None, 669 "write_back": {} 670 } 671 672 # If the source is an expression, we need to print its value 673 try: 674 compile(source, "<string>", "eval") 675 except SyntaxError: 676 pass 677 else: 678 source = "__pdb_eval__['result'] = " + source 679 680 # Add write-back to update the locals 681 source = ("try:\n" + 682 textwrap.indent(source, " ") + "\n" + 683 "finally:\n" + 684 " __pdb_eval__['write_back'] = locals()") 685 686 # Build a closure source code with freevars from locals like: 687 # def __pdb_outer(): 688 # var = None 689 # def __pdb_scope(): # This is the code object we want to execute 690 # nonlocal var 691 # <source> 692 # return __pdb_scope.__code__ 693 source_with_closure = ("def __pdb_outer():\n" + 694 "\n".join(f" {var} = None" for var in locals_copy) + "\n" + 695 " def __pdb_scope():\n" + 696 "\n".join(f" nonlocal {var}" for var in locals_copy) + "\n" + 697 textwrap.indent(source, " ") + "\n" + 698 " return __pdb_scope.__code__" 699 ) 700 701 # Get the code object of __pdb_scope() 702 # The exec fills locals_copy with the __pdb_outer() function and we can call 703 # that to get the code object of __pdb_scope() 704 ns = {} 705 try: 706 exec(source_with_closure, {}, ns) 707 except Exception: 708 return False 709 code = ns["__pdb_outer"]() 710 711 cells = tuple(types.CellType(locals_copy.get(var)) for var in code.co_freevars) 712 713 try: 714 exec(code, globals, locals_copy, closure=cells) 715 except Exception: 716 return False 717 718 # get the data we need from the statement 719 pdb_eval = locals_copy["__pdb_eval__"] 720 721 # __pdb_eval__ should not be updated back to locals 722 pdb_eval["write_back"].pop("__pdb_eval__") 723 724 # Write all local variables back to locals 725 locals.update(pdb_eval["write_back"]) 726 eval_result = pdb_eval["result"] 727 if eval_result is not None: 728 print(repr(eval_result)) 729 730 return True 731 732 def default(self, line): 733 if line[:1] == '!': line = line[1:].strip() 734 locals = self.curframe_locals 735 globals = self.curframe.f_globals 736 try: 737 buffer = line 738 if (code := codeop.compile_command(line + '\n', '<stdin>', 'single')) is None: 739 # Multi-line mode 740 with self._disable_command_completion(): 741 buffer = line 742 continue_prompt = "... " 743 while (code := codeop.compile_command(buffer, '<stdin>', 'single')) is None: 744 if self.use_rawinput: 745 try: 746 line = input(continue_prompt) 747 except (EOFError, KeyboardInterrupt): 748 self.lastcmd = "" 749 print('\n') 750 return 751 else: 752 self.stdout.write(continue_prompt) 753 self.stdout.flush() 754 line = self.stdin.readline() 755 if not len(line): 756 self.lastcmd = "" 757 self.stdout.write('\n') 758 self.stdout.flush() 759 return 760 else: 761 line = line.rstrip('\r\n') 762 buffer += '\n' + line 763 self.lastcmd = buffer 764 save_stdout = sys.stdout 765 save_stdin = sys.stdin 766 save_displayhook = sys.displayhook 767 try: 768 sys.stdin = self.stdin 769 sys.stdout = self.stdout 770 sys.displayhook = self.displayhook 771 if not self._exec_in_closure(buffer, globals, locals): 772 exec(code, globals, locals) 773 finally: 774 sys.stdout = save_stdout 775 sys.stdin = save_stdin 776 sys.displayhook = save_displayhook 777 except: 778 self._error_exc() 779 780 def _replace_convenience_variables(self, line): 781 """Replace the convenience variables in 'line' with their values. 782 e.g. $foo is replaced by __pdb_convenience_variables["foo"]. 783 Note: such pattern in string literals will be skipped""" 784 785 if "$" not in line: 786 return line 787 788 dollar_start = dollar_end = -1 789 replace_variables = [] 790 try: 791 for t in tokenize.generate_tokens(io.StringIO(line).readline): 792 token_type, token_string, start, end, _ = t 793 if token_type == token.OP and token_string == '$': 794 dollar_start, dollar_end = start, end 795 elif start == dollar_end and token_type == token.NAME: 796 # line is a one-line command so we only care about column 797 replace_variables.append((dollar_start[1], end[1], token_string)) 798 except tokenize.TokenError: 799 return line 800 801 if not replace_variables: 802 return line 803 804 last_end = 0 805 line_pieces = [] 806 for start, end, name in replace_variables: 807 line_pieces.append(line[last_end:start] + f'__pdb_convenience_variables["{name}"]') 808 last_end = end 809 line_pieces.append(line[last_end:]) 810 811 return ''.join(line_pieces) 812 813 def precmd(self, line): 814 """Handle alias expansion and ';;' separator.""" 815 if not line.strip(): 816 return line 817 args = line.split() 818 while args[0] in self.aliases: 819 line = self.aliases[args[0]] 820 for idx in range(1, 10): 821 if f'%{idx}' in line: 822 if idx >= len(args): 823 self.error(f"Not enough arguments for alias '{args[0]}'") 824 # This is a no-op 825 return "!" 826 line = line.replace(f'%{idx}', args[idx]) 827 elif '%*' not in line: 828 if idx < len(args): 829 self.error(f"Too many arguments for alias '{args[0]}'") 830 # This is a no-op 831 return "!" 832 break 833 834 line = line.replace("%*", ' '.join(args[1:])) 835 args = line.split() 836 # split into ';;' separated commands 837 # unless it's an alias command 838 if args[0] != 'alias': 839 marker = line.find(';;') 840 if marker >= 0: 841 # queue up everything after marker 842 next = line[marker+2:].lstrip() 843 self.cmdqueue.insert(0, next) 844 line = line[:marker].rstrip() 845 846 # Replace all the convenience variables 847 line = self._replace_convenience_variables(line) 848 849 return line 850 851 def onecmd(self, line): 852 """Interpret the argument as though it had been typed in response 853 to the prompt. 854 855 Checks whether this line is typed at the normal prompt or in 856 a breakpoint command list definition. 857 """ 858 if not self.commands_defining: 859 self._validate_file_mtime() 860 if line.startswith('_pdbcmd'): 861 command, arg, line = self.parseline(line) 862 if hasattr(self, command): 863 return getattr(self, command)(arg) 864 return cmd.Cmd.onecmd(self, line) 865 else: 866 return self.handle_command_def(line) 867 868 def handle_command_def(self, line): 869 """Handles one command line during command list definition.""" 870 cmd, arg, line = self.parseline(line) 871 if not cmd: 872 return False 873 if cmd == 'silent': 874 self.commands_silent[self.commands_bnum] = True 875 return False # continue to handle other cmd def in the cmd list 876 elif cmd == 'end': 877 return True # end of cmd list 878 cmdlist = self.commands[self.commands_bnum] 879 if arg: 880 cmdlist.append(cmd+' '+arg) 881 else: 882 cmdlist.append(cmd) 883 # Determine if we must stop 884 try: 885 func = getattr(self, 'do_' + cmd) 886 except AttributeError: 887 func = self.default 888 # one of the resuming commands 889 if func.__name__ in self.commands_resuming: 890 self.commands_doprompt[self.commands_bnum] = False 891 return True 892 return False 893 894 # interface abstraction functions 895 896 def message(self, msg, end='\n'): 897 print(msg, end=end, file=self.stdout) 898 899 def error(self, msg): 900 print('***', msg, file=self.stdout) 901 902 # convenience variables 903 904 def set_convenience_variable(self, frame, name, value): 905 if '__pdb_convenience_variables' not in frame.f_globals: 906 frame.f_globals['__pdb_convenience_variables'] = {} 907 frame.f_globals['__pdb_convenience_variables'][name] = value 908 909 # Generic completion functions. Individual complete_foo methods can be 910 # assigned below to one of these functions. 911 912 def completenames(self, text, line, begidx, endidx): 913 # Overwrite completenames() of cmd so for the command completion, 914 # if no current command matches, check for expressions as well 915 commands = super().completenames(text, line, begidx, endidx) 916 for alias in self.aliases: 917 if alias.startswith(text): 918 commands.append(alias) 919 if commands: 920 return commands 921 else: 922 expressions = self._complete_expression(text, line, begidx, endidx) 923 if expressions: 924 return expressions 925 return self.completedefault(text, line, begidx, endidx) 926 927 def _complete_location(self, text, line, begidx, endidx): 928 # Complete a file/module/function location for break/tbreak/clear. 929 if line.strip().endswith((':', ',')): 930 # Here comes a line number or a condition which we can't complete. 931 return [] 932 # First, try to find matching functions (i.e. expressions). 933 try: 934 ret = self._complete_expression(text, line, begidx, endidx) 935 except Exception: 936 ret = [] 937 # Then, try to complete file names as well. 938 globs = glob.glob(glob.escape(text) + '*') 939 for fn in globs: 940 if os.path.isdir(fn): 941 ret.append(fn + '/') 942 elif os.path.isfile(fn) and fn.lower().endswith(('.py', '.pyw')): 943 ret.append(fn + ':') 944 return ret 945 946 def _complete_bpnumber(self, text, line, begidx, endidx): 947 # Complete a breakpoint number. (This would be more helpful if we could 948 # display additional info along with the completions, such as file/line 949 # of the breakpoint.) 950 return [str(i) for i, bp in enumerate(bdb.Breakpoint.bpbynumber) 951 if bp is not None and str(i).startswith(text)] 952 953 def _complete_expression(self, text, line, begidx, endidx): 954 # Complete an arbitrary expression. 955 if not self.curframe: 956 return [] 957 # Collect globals and locals. It is usually not really sensible to also 958 # complete builtins, and they clutter the namespace quite heavily, so we 959 # leave them out. 960 ns = {**self.curframe.f_globals, **self.curframe_locals} 961 if text.startswith("$"): 962 # Complete convenience variables 963 conv_vars = self.curframe.f_globals.get('__pdb_convenience_variables', {}) 964 return [f"${name}" for name in conv_vars if name.startswith(text[1:])] 965 if '.' in text: 966 # Walk an attribute chain up to the last part, similar to what 967 # rlcompleter does. This will bail if any of the parts are not 968 # simple attribute access, which is what we want. 969 dotted = text.split('.') 970 try: 971 obj = ns[dotted[0]] 972 for part in dotted[1:-1]: 973 obj = getattr(obj, part) 974 except (KeyError, AttributeError): 975 return [] 976 prefix = '.'.join(dotted[:-1]) + '.' 977 return [prefix + n for n in dir(obj) if n.startswith(dotted[-1])] 978 else: 979 # Complete a simple name. 980 return [n for n in ns.keys() if n.startswith(text)] 981 982 def completedefault(self, text, line, begidx, endidx): 983 if text.startswith("$"): 984 # Complete convenience variables 985 conv_vars = self.curframe.f_globals.get('__pdb_convenience_variables', {}) 986 return [f"${name}" for name in conv_vars if name.startswith(text[1:])] 987 988 # Use rlcompleter to do the completion 989 state = 0 990 matches = [] 991 completer = Completer(self.curframe.f_globals | self.curframe_locals) 992 while (match := completer.complete(text, state)) is not None: 993 matches.append(match) 994 state += 1 995 return matches 996 997 # Pdb meta commands, only intended to be used internally by pdb 998 999 def _pdbcmd_print_frame_status(self, arg): 1000 self.print_stack_entry(self.stack[self.curindex]) 1001 self._show_display() 1002 1003 # Command definitions, called by cmdloop() 1004 # The argument is the remaining string on the command line 1005 # Return true to exit from the command loop 1006 1007 def do_commands(self, arg): 1008 """(Pdb) commands [bpnumber] 1009 (com) ... 1010 (com) end 1011 (Pdb) 1012 1013 Specify a list of commands for breakpoint number bpnumber. 1014 The commands themselves are entered on the following lines. 1015 Type a line containing just 'end' to terminate the commands. 1016 The commands are executed when the breakpoint is hit. 1017 1018 To remove all commands from a breakpoint, type commands and 1019 follow it immediately with end; that is, give no commands. 1020 1021 With no bpnumber argument, commands refers to the last 1022 breakpoint set. 1023 1024 You can use breakpoint commands to start your program up 1025 again. Simply use the continue command, or step, or any other 1026 command that resumes execution. 1027 1028 Specifying any command resuming execution (currently continue, 1029 step, next, return, jump, quit and their abbreviations) 1030 terminates the command list (as if that command was 1031 immediately followed by end). This is because any time you 1032 resume execution (even with a simple next or step), you may 1033 encounter another breakpoint -- which could have its own 1034 command list, leading to ambiguities about which list to 1035 execute. 1036 1037 If you use the 'silent' command in the command list, the usual 1038 message about stopping at a breakpoint is not printed. This 1039 may be desirable for breakpoints that are to print a specific 1040 message and then continue. If none of the other commands 1041 print anything, you will see no sign that the breakpoint was 1042 reached. 1043 """ 1044 if not arg: 1045 bnum = len(bdb.Breakpoint.bpbynumber) - 1 1046 else: 1047 try: 1048 bnum = int(arg) 1049 except: 1050 self._print_invalid_arg(arg) 1051 return 1052 try: 1053 self.get_bpbynumber(bnum) 1054 except ValueError as err: 1055 self.error('cannot set commands: %s' % err) 1056 return 1057 1058 self.commands_bnum = bnum 1059 # Save old definitions for the case of a keyboard interrupt. 1060 if bnum in self.commands: 1061 old_command_defs = (self.commands[bnum], 1062 self.commands_doprompt[bnum], 1063 self.commands_silent[bnum]) 1064 else: 1065 old_command_defs = None 1066 self.commands[bnum] = [] 1067 self.commands_doprompt[bnum] = True 1068 self.commands_silent[bnum] = False 1069 1070 prompt_back = self.prompt 1071 self.prompt = '(com) ' 1072 self.commands_defining = True 1073 try: 1074 self.cmdloop() 1075 except KeyboardInterrupt: 1076 # Restore old definitions. 1077 if old_command_defs: 1078 self.commands[bnum] = old_command_defs[0] 1079 self.commands_doprompt[bnum] = old_command_defs[1] 1080 self.commands_silent[bnum] = old_command_defs[2] 1081 else: 1082 del self.commands[bnum] 1083 del self.commands_doprompt[bnum] 1084 del self.commands_silent[bnum] 1085 self.error('command definition aborted, old commands restored') 1086 finally: 1087 self.commands_defining = False 1088 self.prompt = prompt_back 1089 1090 complete_commands = _complete_bpnumber 1091 1092 def do_break(self, arg, temporary = 0): 1093 """b(reak) [ ([filename:]lineno | function) [, condition] ] 1094 1095 Without argument, list all breaks. 1096 1097 With a line number argument, set a break at this line in the 1098 current file. With a function name, set a break at the first 1099 executable line of that function. If a second argument is 1100 present, it is a string specifying an expression which must 1101 evaluate to true before the breakpoint is honored. 1102 1103 The line number may be prefixed with a filename and a colon, 1104 to specify a breakpoint in another file (probably one that 1105 hasn't been loaded yet). The file is searched for on 1106 sys.path; the .py suffix may be omitted. 1107 """ 1108 if not arg: 1109 if self.breaks: # There's at least one 1110 self.message("Num Type Disp Enb Where") 1111 for bp in bdb.Breakpoint.bpbynumber: 1112 if bp: 1113 self.message(bp.bpformat()) 1114 return 1115 # parse arguments; comma has lowest precedence 1116 # and cannot occur in filename 1117 filename = None 1118 lineno = None 1119 cond = None 1120 comma = arg.find(',') 1121 if comma > 0: 1122 # parse stuff after comma: "condition" 1123 cond = arg[comma+1:].lstrip() 1124 if err := self._compile_error_message(cond): 1125 self.error('Invalid condition %s: %r' % (cond, err)) 1126 return 1127 arg = arg[:comma].rstrip() 1128 # parse stuff before comma: [filename:]lineno | function 1129 colon = arg.rfind(':') 1130 funcname = None 1131 if colon >= 0: 1132 filename = arg[:colon].rstrip() 1133 f = self.lookupmodule(filename) 1134 if not f: 1135 self.error('%r not found from sys.path' % filename) 1136 return 1137 else: 1138 filename = f 1139 arg = arg[colon+1:].lstrip() 1140 try: 1141 lineno = int(arg) 1142 except ValueError: 1143 self.error('Bad lineno: %s' % arg) 1144 return 1145 else: 1146 # no colon; can be lineno or function 1147 try: 1148 lineno = int(arg) 1149 except ValueError: 1150 try: 1151 func = eval(arg, 1152 self.curframe.f_globals, 1153 self.curframe_locals) 1154 except: 1155 func = arg 1156 try: 1157 if hasattr(func, '__func__'): 1158 func = func.__func__ 1159 code = func.__code__ 1160 #use co_name to identify the bkpt (function names 1161 #could be aliased, but co_name is invariant) 1162 funcname = code.co_name 1163 lineno = find_first_executable_line(code) 1164 filename = code.co_filename 1165 except: 1166 # last thing to try 1167 (ok, filename, ln) = self.lineinfo(arg) 1168 if not ok: 1169 self.error('The specified object %r is not a function ' 1170 'or was not found along sys.path.' % arg) 1171 return 1172 funcname = ok # ok contains a function name 1173 lineno = int(ln) 1174 if not filename: 1175 filename = self.defaultFile() 1176 # Check for reasonable breakpoint 1177 line = self.checkline(filename, lineno) 1178 if line: 1179 # now set the break point 1180 err = self.set_break(filename, line, temporary, cond, funcname) 1181 if err: 1182 self.error(err) 1183 else: 1184 bp = self.get_breaks(filename, line)[-1] 1185 self.message("Breakpoint %d at %s:%d" % 1186 (bp.number, bp.file, bp.line)) 1187 1188 # To be overridden in derived debuggers 1189 def defaultFile(self): 1190 """Produce a reasonable default.""" 1191 filename = self.curframe.f_code.co_filename 1192 if filename == '<string>' and self.mainpyfile: 1193 filename = self.mainpyfile 1194 return filename 1195 1196 do_b = do_break 1197 1198 complete_break = _complete_location 1199 complete_b = _complete_location 1200 1201 def do_tbreak(self, arg): 1202 """tbreak [ ([filename:]lineno | function) [, condition] ] 1203 1204 Same arguments as break, but sets a temporary breakpoint: it 1205 is automatically deleted when first hit. 1206 """ 1207 self.do_break(arg, 1) 1208 1209 complete_tbreak = _complete_location 1210 1211 def lineinfo(self, identifier): 1212 failed = (None, None, None) 1213 # Input is identifier, may be in single quotes 1214 idstring = identifier.split("'") 1215 if len(idstring) == 1: 1216 # not in single quotes 1217 id = idstring[0].strip() 1218 elif len(idstring) == 3: 1219 # quoted 1220 id = idstring[1].strip() 1221 else: 1222 return failed 1223 if id == '': return failed 1224 parts = id.split('.') 1225 # Protection for derived debuggers 1226 if parts[0] == 'self': 1227 del parts[0] 1228 if len(parts) == 0: 1229 return failed 1230 # Best first guess at file to look at 1231 fname = self.defaultFile() 1232 if len(parts) == 1: 1233 item = parts[0] 1234 else: 1235 # More than one part. 1236 # First is module, second is method/class 1237 f = self.lookupmodule(parts[0]) 1238 if f: 1239 fname = f 1240 item = parts[1] 1241 answer = find_function(item, self.canonic(fname)) 1242 return answer or failed 1243 1244 def checkline(self, filename, lineno): 1245 """Check whether specified line seems to be executable. 1246 1247 Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank 1248 line or EOF). Warning: testing is not comprehensive. 1249 """ 1250 # this method should be callable before starting debugging, so default 1251 # to "no globals" if there is no current frame 1252 frame = getattr(self, 'curframe', None) 1253 globs = frame.f_globals if frame else None 1254 line = linecache.getline(filename, lineno, globs) 1255 if not line: 1256 self.message('End of file') 1257 return 0 1258 line = line.strip() 1259 # Don't allow setting breakpoint at a blank line 1260 if (not line or (line[0] == '#') or 1261 (line[:3] == '"""') or line[:3] == "'''"): 1262 self.error('Blank or comment') 1263 return 0 1264 return lineno 1265 1266 def do_enable(self, arg): 1267 """enable bpnumber [bpnumber ...] 1268 1269 Enables the breakpoints given as a space separated list of 1270 breakpoint numbers. 1271 """ 1272 args = arg.split() 1273 for i in args: 1274 try: 1275 bp = self.get_bpbynumber(i) 1276 except ValueError as err: 1277 self.error(err) 1278 else: 1279 bp.enable() 1280 self.message('Enabled %s' % bp) 1281 1282 complete_enable = _complete_bpnumber 1283 1284 def do_disable(self, arg): 1285 """disable bpnumber [bpnumber ...] 1286 1287 Disables the breakpoints given as a space separated list of 1288 breakpoint numbers. Disabling a breakpoint means it cannot 1289 cause the program to stop execution, but unlike clearing a 1290 breakpoint, it remains in the list of breakpoints and can be 1291 (re-)enabled. 1292 """ 1293 args = arg.split() 1294 for i in args: 1295 try: 1296 bp = self.get_bpbynumber(i) 1297 except ValueError as err: 1298 self.error(err) 1299 else: 1300 bp.disable() 1301 self.message('Disabled %s' % bp) 1302 1303 complete_disable = _complete_bpnumber 1304 1305 def do_condition(self, arg): 1306 """condition bpnumber [condition] 1307 1308 Set a new condition for the breakpoint, an expression which 1309 must evaluate to true before the breakpoint is honored. If 1310 condition is absent, any existing condition is removed; i.e., 1311 the breakpoint is made unconditional. 1312 """ 1313 args = arg.split(' ', 1) 1314 try: 1315 cond = args[1] 1316 if err := self._compile_error_message(cond): 1317 self.error('Invalid condition %s: %r' % (cond, err)) 1318 return 1319 except IndexError: 1320 cond = None 1321 try: 1322 bp = self.get_bpbynumber(args[0].strip()) 1323 except IndexError: 1324 self.error('Breakpoint number expected') 1325 except ValueError as err: 1326 self.error(err) 1327 else: 1328 bp.cond = cond 1329 if not cond: 1330 self.message('Breakpoint %d is now unconditional.' % bp.number) 1331 else: 1332 self.message('New condition set for breakpoint %d.' % bp.number) 1333 1334 complete_condition = _complete_bpnumber 1335 1336 def do_ignore(self, arg): 1337 """ignore bpnumber [count] 1338 1339 Set the ignore count for the given breakpoint number. If 1340 count is omitted, the ignore count is set to 0. A breakpoint 1341 becomes active when the ignore count is zero. When non-zero, 1342 the count is decremented each time the breakpoint is reached 1343 and the breakpoint is not disabled and any associated 1344 condition evaluates to true. 1345 """ 1346 args = arg.split() 1347 if not args: 1348 self.error('Breakpoint number expected') 1349 return 1350 if len(args) == 1: 1351 count = 0 1352 elif len(args) == 2: 1353 try: 1354 count = int(args[1]) 1355 except ValueError: 1356 self._print_invalid_arg(arg) 1357 return 1358 else: 1359 self._print_invalid_arg(arg) 1360 return 1361 try: 1362 bp = self.get_bpbynumber(args[0].strip()) 1363 except ValueError as err: 1364 self.error(err) 1365 else: 1366 bp.ignore = count 1367 if count > 0: 1368 if count > 1: 1369 countstr = '%d crossings' % count 1370 else: 1371 countstr = '1 crossing' 1372 self.message('Will ignore next %s of breakpoint %d.' % 1373 (countstr, bp.number)) 1374 else: 1375 self.message('Will stop next time breakpoint %d is reached.' 1376 % bp.number) 1377 1378 complete_ignore = _complete_bpnumber 1379 1380 def do_clear(self, arg): 1381 """cl(ear) [filename:lineno | bpnumber ...] 1382 1383 With a space separated list of breakpoint numbers, clear 1384 those breakpoints. Without argument, clear all breaks (but 1385 first ask confirmation). With a filename:lineno argument, 1386 clear all breaks at that line in that file. 1387 """ 1388 if not arg: 1389 try: 1390 reply = input('Clear all breaks? ') 1391 except EOFError: 1392 reply = 'no' 1393 reply = reply.strip().lower() 1394 if reply in ('y', 'yes'): 1395 bplist = [bp for bp in bdb.Breakpoint.bpbynumber if bp] 1396 self.clear_all_breaks() 1397 for bp in bplist: 1398 self.message('Deleted %s' % bp) 1399 return 1400 if ':' in arg: 1401 # Make sure it works for "clear C:\foo\bar.py:12" 1402 i = arg.rfind(':') 1403 filename = arg[:i] 1404 arg = arg[i+1:] 1405 try: 1406 lineno = int(arg) 1407 except ValueError: 1408 err = "Invalid line number (%s)" % arg 1409 else: 1410 bplist = self.get_breaks(filename, lineno)[:] 1411 err = self.clear_break(filename, lineno) 1412 if err: 1413 self.error(err) 1414 else: 1415 for bp in bplist: 1416 self.message('Deleted %s' % bp) 1417 return 1418 numberlist = arg.split() 1419 for i in numberlist: 1420 try: 1421 bp = self.get_bpbynumber(i) 1422 except ValueError as err: 1423 self.error(err) 1424 else: 1425 self.clear_bpbynumber(i) 1426 self.message('Deleted %s' % bp) 1427 do_cl = do_clear # 'c' is already an abbreviation for 'continue' 1428 1429 complete_clear = _complete_location 1430 complete_cl = _complete_location 1431 1432 def do_where(self, arg): 1433 """w(here) 1434 1435 Print a stack trace, with the most recent frame at the bottom. 1436 An arrow indicates the "current frame", which determines the 1437 context of most commands. 'bt' is an alias for this command. 1438 """ 1439 if arg: 1440 self._print_invalid_arg(arg) 1441 return 1442 self.print_stack_trace() 1443 do_w = do_where 1444 do_bt = do_where 1445 1446 def _select_frame(self, number): 1447 assert 0 <= number < len(self.stack) 1448 self.curindex = number 1449 self.curframe = self.stack[self.curindex][0] 1450 self.curframe_locals = self.curframe.f_locals 1451 self.set_convenience_variable(self.curframe, '_frame', self.curframe) 1452 self.print_stack_entry(self.stack[self.curindex]) 1453 self.lineno = None 1454 1455 def do_exceptions(self, arg): 1456 """exceptions [number] 1457 1458 List or change current exception in an exception chain. 1459 1460 Without arguments, list all the current exception in the exception 1461 chain. Exceptions will be numbered, with the current exception indicated 1462 with an arrow. 1463 1464 If given an integer as argument, switch to the exception at that index. 1465 """ 1466 if not self._chained_exceptions: 1467 self.message( 1468 "Did not find chained exceptions. To move between" 1469 " exceptions, pdb/post_mortem must be given an exception" 1470 " object rather than a traceback." 1471 ) 1472 return 1473 if not arg: 1474 for ix, exc in enumerate(self._chained_exceptions): 1475 prompt = ">" if ix == self._chained_exception_index else " " 1476 rep = repr(exc) 1477 if len(rep) > 80: 1478 rep = rep[:77] + "..." 1479 indicator = ( 1480 " -" 1481 if self._chained_exceptions[ix].__traceback__ is None 1482 else f"{ix:>3}" 1483 ) 1484 self.message(f"{prompt} {indicator} {rep}") 1485 else: 1486 try: 1487 number = int(arg) 1488 except ValueError: 1489 self.error("Argument must be an integer") 1490 return 1491 if 0 <= number < len(self._chained_exceptions): 1492 if self._chained_exceptions[number].__traceback__ is None: 1493 self.error("This exception does not have a traceback, cannot jump to it") 1494 return 1495 1496 self._chained_exception_index = number 1497 self.setup(None, self._chained_exceptions[number].__traceback__) 1498 self.print_stack_entry(self.stack[self.curindex]) 1499 else: 1500 self.error("No exception with that number") 1501 1502 def do_up(self, arg): 1503 """u(p) [count] 1504 1505 Move the current frame count (default one) levels up in the 1506 stack trace (to an older frame). 1507 """ 1508 if self.curindex == 0: 1509 self.error('Oldest frame') 1510 return 1511 try: 1512 count = int(arg or 1) 1513 except ValueError: 1514 self.error('Invalid frame count (%s)' % arg) 1515 return 1516 if count < 0: 1517 newframe = 0 1518 else: 1519 newframe = max(0, self.curindex - count) 1520 self._select_frame(newframe) 1521 do_u = do_up 1522 1523 def do_down(self, arg): 1524 """d(own) [count] 1525 1526 Move the current frame count (default one) levels down in the 1527 stack trace (to a newer frame). 1528 """ 1529 if self.curindex + 1 == len(self.stack): 1530 self.error('Newest frame') 1531 return 1532 try: 1533 count = int(arg or 1) 1534 except ValueError: 1535 self.error('Invalid frame count (%s)' % arg) 1536 return 1537 if count < 0: 1538 newframe = len(self.stack) - 1 1539 else: 1540 newframe = min(len(self.stack) - 1, self.curindex + count) 1541 self._select_frame(newframe) 1542 do_d = do_down 1543 1544 def do_until(self, arg): 1545 """unt(il) [lineno] 1546 1547 Without argument, continue execution until the line with a 1548 number greater than the current one is reached. With a line 1549 number, continue execution until a line with a number greater 1550 or equal to that is reached. In both cases, also stop when 1551 the current frame returns. 1552 """ 1553 if arg: 1554 try: 1555 lineno = int(arg) 1556 except ValueError: 1557 self.error('Error in argument: %r' % arg) 1558 return 1559 if lineno <= self.curframe.f_lineno: 1560 self.error('"until" line number is smaller than current ' 1561 'line number') 1562 return 1563 else: 1564 lineno = None 1565 self.set_until(self.curframe, lineno) 1566 return 1 1567 do_unt = do_until 1568 1569 def do_step(self, arg): 1570 """s(tep) 1571 1572 Execute the current line, stop at the first possible occasion 1573 (either in a function that is called or in the current 1574 function). 1575 """ 1576 if arg: 1577 self._print_invalid_arg(arg) 1578 return 1579 self.set_step() 1580 return 1 1581 do_s = do_step 1582 1583 def do_next(self, arg): 1584 """n(ext) 1585 1586 Continue execution until the next line in the current function 1587 is reached or it returns. 1588 """ 1589 if arg: 1590 self._print_invalid_arg(arg) 1591 return 1592 self.set_next(self.curframe) 1593 return 1 1594 do_n = do_next 1595 1596 def do_run(self, arg): 1597 """run [args...] 1598 1599 Restart the debugged python program. If a string is supplied 1600 it is split with "shlex", and the result is used as the new 1601 sys.argv. History, breakpoints, actions and debugger options 1602 are preserved. "restart" is an alias for "run". 1603 """ 1604 if arg: 1605 import shlex 1606 argv0 = sys.argv[0:1] 1607 try: 1608 sys.argv = shlex.split(arg) 1609 except ValueError as e: 1610 self.error('Cannot run %s: %s' % (arg, e)) 1611 return 1612 sys.argv[:0] = argv0 1613 # this is caught in the main debugger loop 1614 raise Restart 1615 1616 do_restart = do_run 1617 1618 def do_return(self, arg): 1619 """r(eturn) 1620 1621 Continue execution until the current function returns. 1622 """ 1623 if arg: 1624 self._print_invalid_arg(arg) 1625 return 1626 self.set_return(self.curframe) 1627 return 1 1628 do_r = do_return 1629 1630 def do_continue(self, arg): 1631 """c(ont(inue)) 1632 1633 Continue execution, only stop when a breakpoint is encountered. 1634 """ 1635 if arg: 1636 self._print_invalid_arg(arg) 1637 return 1638 if not self.nosigint: 1639 try: 1640 Pdb._previous_sigint_handler = \ 1641 signal.signal(signal.SIGINT, self.sigint_handler) 1642 except ValueError: 1643 # ValueError happens when do_continue() is invoked from 1644 # a non-main thread in which case we just continue without 1645 # SIGINT set. Would printing a message here (once) make 1646 # sense? 1647 pass 1648 self.set_continue() 1649 return 1 1650 do_c = do_cont = do_continue 1651 1652 def do_jump(self, arg): 1653 """j(ump) lineno 1654 1655 Set the next line that will be executed. Only available in 1656 the bottom-most frame. This lets you jump back and execute 1657 code again, or jump forward to skip code that you don't want 1658 to run. 1659 1660 It should be noted that not all jumps are allowed -- for 1661 instance it is not possible to jump into the middle of a 1662 for loop or out of a finally clause. 1663 """ 1664 if self.curindex + 1 != len(self.stack): 1665 self.error('You can only jump within the bottom frame') 1666 return 1667 try: 1668 arg = int(arg) 1669 except ValueError: 1670 self.error("The 'jump' command requires a line number") 1671 else: 1672 try: 1673 # Do the jump, fix up our copy of the stack, and display the 1674 # new position 1675 self.curframe.f_lineno = arg 1676 self.stack[self.curindex] = self.stack[self.curindex][0], arg 1677 self.print_stack_entry(self.stack[self.curindex]) 1678 except ValueError as e: 1679 self.error('Jump failed: %s' % e) 1680 do_j = do_jump 1681 1682 def do_debug(self, arg): 1683 """debug code 1684 1685 Enter a recursive debugger that steps through the code 1686 argument (which is an arbitrary expression or statement to be 1687 executed in the current environment). 1688 """ 1689 sys.settrace(None) 1690 globals = self.curframe.f_globals 1691 locals = self.curframe_locals 1692 p = Pdb(self.completekey, self.stdin, self.stdout) 1693 p.prompt = "(%s) " % self.prompt.strip() 1694 self.message("ENTERING RECURSIVE DEBUGGER") 1695 try: 1696 sys.call_tracing(p.run, (arg, globals, locals)) 1697 except Exception: 1698 self._error_exc() 1699 self.message("LEAVING RECURSIVE DEBUGGER") 1700 sys.settrace(self.trace_dispatch) 1701 self.lastcmd = p.lastcmd 1702 1703 complete_debug = _complete_expression 1704 1705 def do_quit(self, arg): 1706 """q(uit) | exit 1707 1708 Quit from the debugger. The program being executed is aborted. 1709 """ 1710 self._user_requested_quit = True 1711 self.set_quit() 1712 return 1 1713 1714 do_q = do_quit 1715 do_exit = do_quit 1716 1717 def do_EOF(self, arg): 1718 """EOF 1719 1720 Handles the receipt of EOF as a command. 1721 """ 1722 self.message('') 1723 self._user_requested_quit = True 1724 self.set_quit() 1725 return 1 1726 1727 def do_args(self, arg): 1728 """a(rgs) 1729 1730 Print the argument list of the current function. 1731 """ 1732 if arg: 1733 self._print_invalid_arg(arg) 1734 return 1735 co = self.curframe.f_code 1736 dict = self.curframe_locals 1737 n = co.co_argcount + co.co_kwonlyargcount 1738 if co.co_flags & inspect.CO_VARARGS: n = n+1 1739 if co.co_flags & inspect.CO_VARKEYWORDS: n = n+1 1740 for i in range(n): 1741 name = co.co_varnames[i] 1742 if name in dict: 1743 self.message('%s = %s' % (name, self._safe_repr(dict[name], name))) 1744 else: 1745 self.message('%s = *** undefined ***' % (name,)) 1746 do_a = do_args 1747 1748 def do_retval(self, arg): 1749 """retval 1750 1751 Print the return value for the last return of a function. 1752 """ 1753 if arg: 1754 self._print_invalid_arg(arg) 1755 return 1756 if '__return__' in self.curframe_locals: 1757 self.message(self._safe_repr(self.curframe_locals['__return__'], "retval")) 1758 else: 1759 self.error('Not yet returned!') 1760 do_rv = do_retval 1761 1762 def _getval(self, arg): 1763 try: 1764 return eval(arg, self.curframe.f_globals, self.curframe_locals) 1765 except: 1766 self._error_exc() 1767 raise 1768 1769 def _getval_except(self, arg, frame=None): 1770 try: 1771 if frame is None: 1772 return eval(arg, self.curframe.f_globals, self.curframe_locals) 1773 else: 1774 return eval(arg, frame.f_globals, frame.f_locals) 1775 except BaseException as exc: 1776 return _rstr('** raised %s **' % self._format_exc(exc)) 1777 1778 def _error_exc(self): 1779 exc = sys.exception() 1780 self.error(self._format_exc(exc)) 1781 1782 def _msg_val_func(self, arg, func): 1783 try: 1784 val = self._getval(arg) 1785 except: 1786 return # _getval() has displayed the error 1787 try: 1788 self.message(func(val)) 1789 except: 1790 self._error_exc() 1791 1792 def _safe_repr(self, obj, expr): 1793 try: 1794 return repr(obj) 1795 except Exception as e: 1796 return _rstr(f"*** repr({expr}) failed: {self._format_exc(e)} ***") 1797 1798 def do_p(self, arg): 1799 """p expression 1800 1801 Print the value of the expression. 1802 """ 1803 self._msg_val_func(arg, repr) 1804 1805 def do_pp(self, arg): 1806 """pp expression 1807 1808 Pretty-print the value of the expression. 1809 """ 1810 self._msg_val_func(arg, pprint.pformat) 1811 1812 complete_print = _complete_expression 1813 complete_p = _complete_expression 1814 complete_pp = _complete_expression 1815 1816 def do_list(self, arg): 1817 """l(ist) [first[, last] | .] 1818 1819 List source code for the current file. Without arguments, 1820 list 11 lines around the current line or continue the previous 1821 listing. With . as argument, list 11 lines around the current 1822 line. With one argument, list 11 lines starting at that line. 1823 With two arguments, list the given range; if the second 1824 argument is less than the first, it is a count. 1825 1826 The current line in the current frame is indicated by "->". 1827 If an exception is being debugged, the line where the 1828 exception was originally raised or propagated is indicated by 1829 ">>", if it differs from the current line. 1830 """ 1831 self.lastcmd = 'list' 1832 last = None 1833 if arg and arg != '.': 1834 try: 1835 if ',' in arg: 1836 first, last = arg.split(',') 1837 first = int(first.strip()) 1838 last = int(last.strip()) 1839 if last < first: 1840 # assume it's a count 1841 last = first + last 1842 else: 1843 first = int(arg.strip()) 1844 first = max(1, first - 5) 1845 except ValueError: 1846 self.error('Error in argument: %r' % arg) 1847 return 1848 elif self.lineno is None or arg == '.': 1849 first = max(1, self.curframe.f_lineno - 5) 1850 else: 1851 first = self.lineno + 1 1852 if last is None: 1853 last = first + 10 1854 filename = self.curframe.f_code.co_filename 1855 # gh-93696: stdlib frozen modules provide a useful __file__ 1856 # this workaround can be removed with the closure of gh-89815 1857 if filename.startswith("<frozen"): 1858 tmp = self.curframe.f_globals.get("__file__") 1859 if isinstance(tmp, str): 1860 filename = tmp 1861 breaklist = self.get_file_breaks(filename) 1862 try: 1863 lines = linecache.getlines(filename, self.curframe.f_globals) 1864 self._print_lines(lines[first-1:last], first, breaklist, 1865 self.curframe) 1866 self.lineno = min(last, len(lines)) 1867 if len(lines) < last: 1868 self.message('[EOF]') 1869 except KeyboardInterrupt: 1870 pass 1871 do_l = do_list 1872 1873 def do_longlist(self, arg): 1874 """ll | longlist 1875 1876 List the whole source code for the current function or frame. 1877 """ 1878 if arg: 1879 self._print_invalid_arg(arg) 1880 return 1881 filename = self.curframe.f_code.co_filename 1882 breaklist = self.get_file_breaks(filename) 1883 try: 1884 lines, lineno = self._getsourcelines(self.curframe) 1885 except OSError as err: 1886 self.error(err) 1887 return 1888 self._print_lines(lines, lineno, breaklist, self.curframe) 1889 do_ll = do_longlist 1890 1891 def do_source(self, arg): 1892 """source expression 1893 1894 Try to get source code for the given object and display it. 1895 """ 1896 try: 1897 obj = self._getval(arg) 1898 except: 1899 return 1900 try: 1901 lines, lineno = self._getsourcelines(obj) 1902 except (OSError, TypeError) as err: 1903 self.error(err) 1904 return 1905 self._print_lines(lines, lineno) 1906 1907 complete_source = _complete_expression 1908 1909 def _print_lines(self, lines, start, breaks=(), frame=None): 1910 """Print a range of lines.""" 1911 if frame: 1912 current_lineno = frame.f_lineno 1913 exc_lineno = self.tb_lineno.get(frame, -1) 1914 else: 1915 current_lineno = exc_lineno = -1 1916 for lineno, line in enumerate(lines, start): 1917 s = str(lineno).rjust(3) 1918 if len(s) < 4: 1919 s += ' ' 1920 if lineno in breaks: 1921 s += 'B' 1922 else: 1923 s += ' ' 1924 if lineno == current_lineno: 1925 s += '->' 1926 elif lineno == exc_lineno: 1927 s += '>>' 1928 self.message(s + '\t' + line.rstrip()) 1929 1930 def do_whatis(self, arg): 1931 """whatis expression 1932 1933 Print the type of the argument. 1934 """ 1935 try: 1936 value = self._getval(arg) 1937 except: 1938 # _getval() already printed the error 1939 return 1940 code = None 1941 # Is it an instance method? 1942 try: 1943 code = value.__func__.__code__ 1944 except Exception: 1945 pass 1946 if code: 1947 self.message('Method %s' % code.co_name) 1948 return 1949 # Is it a function? 1950 try: 1951 code = value.__code__ 1952 except Exception: 1953 pass 1954 if code: 1955 self.message('Function %s' % code.co_name) 1956 return 1957 # Is it a class? 1958 if value.__class__ is type: 1959 self.message('Class %s.%s' % (value.__module__, value.__qualname__)) 1960 return 1961 # None of the above... 1962 self.message(type(value)) 1963 1964 complete_whatis = _complete_expression 1965 1966 def do_display(self, arg): 1967 """display [expression] 1968 1969 Display the value of the expression if it changed, each time execution 1970 stops in the current frame. 1971 1972 Without expression, list all display expressions for the current frame. 1973 """ 1974 if not arg: 1975 if self.displaying: 1976 self.message('Currently displaying:') 1977 for key, val in self.displaying.get(self.curframe, {}).items(): 1978 self.message('%s: %s' % (key, self._safe_repr(val, key))) 1979 else: 1980 self.message('No expression is being displayed') 1981 else: 1982 if err := self._compile_error_message(arg): 1983 self.error('Unable to display %s: %r' % (arg, err)) 1984 else: 1985 val = self._getval_except(arg) 1986 self.displaying.setdefault(self.curframe, {})[arg] = val 1987 self.message('display %s: %s' % (arg, self._safe_repr(val, arg))) 1988 1989 complete_display = _complete_expression 1990 1991 def do_undisplay(self, arg): 1992 """undisplay [expression] 1993 1994 Do not display the expression any more in the current frame. 1995 1996 Without expression, clear all display expressions for the current frame. 1997 """ 1998 if arg: 1999 try: 2000 del self.displaying.get(self.curframe, {})[arg] 2001 except KeyError: 2002 self.error('not displaying %s' % arg) 2003 else: 2004 self.displaying.pop(self.curframe, None) 2005 2006 def complete_undisplay(self, text, line, begidx, endidx): 2007 return [e for e in self.displaying.get(self.curframe, {}) 2008 if e.startswith(text)] 2009 2010 def do_interact(self, arg): 2011 """interact 2012 2013 Start an interactive interpreter whose global namespace 2014 contains all the (global and local) names found in the current scope. 2015 """ 2016 ns = {**self.curframe.f_globals, **self.curframe_locals} 2017 console = _PdbInteractiveConsole(ns, message=self.message) 2018 console.interact(banner="*pdb interact start*", 2019 exitmsg="*exit from pdb interact command*") 2020 2021 def do_alias(self, arg): 2022 """alias [name [command]] 2023 2024 Create an alias called 'name' that executes 'command'. The 2025 command must *not* be enclosed in quotes. Replaceable 2026 parameters can be indicated by %1, %2, and so on, while %* is 2027 replaced by all the parameters. If no command is given, the 2028 current alias for name is shown. If no name is given, all 2029 aliases are listed. 2030 2031 Aliases may be nested and can contain anything that can be 2032 legally typed at the pdb prompt. Note! You *can* override 2033 internal pdb commands with aliases! Those internal commands 2034 are then hidden until the alias is removed. Aliasing is 2035 recursively applied to the first word of the command line; all 2036 other words in the line are left alone. 2037 2038 As an example, here are two useful aliases (especially when 2039 placed in the .pdbrc file): 2040 2041 # Print instance variables (usage "pi classInst") 2042 alias pi for k in %1.__dict__.keys(): print("%1.",k,"=",%1.__dict__[k]) 2043 # Print instance variables in self 2044 alias ps pi self 2045 """ 2046 args = arg.split() 2047 if len(args) == 0: 2048 keys = sorted(self.aliases.keys()) 2049 for alias in keys: 2050 self.message("%s = %s" % (alias, self.aliases[alias])) 2051 return 2052 if len(args) == 1: 2053 if args[0] in self.aliases: 2054 self.message("%s = %s" % (args[0], self.aliases[args[0]])) 2055 else: 2056 self.error(f"Unknown alias '{args[0]}'") 2057 else: 2058 # Do a validation check to make sure no replaceable parameters 2059 # are skipped if %* is not used. 2060 alias = ' '.join(args[1:]) 2061 if '%*' not in alias: 2062 consecutive = True 2063 for idx in range(1, 10): 2064 if f'%{idx}' not in alias: 2065 consecutive = False 2066 if f'%{idx}' in alias and not consecutive: 2067 self.error("Replaceable parameters must be consecutive") 2068 return 2069 self.aliases[args[0]] = alias 2070 2071 def do_unalias(self, arg): 2072 """unalias name 2073 2074 Delete the specified alias. 2075 """ 2076 args = arg.split() 2077 if len(args) == 0: 2078 self._print_invalid_arg(arg) 2079 return 2080 if args[0] in self.aliases: 2081 del self.aliases[args[0]] 2082 2083 def complete_unalias(self, text, line, begidx, endidx): 2084 return [a for a in self.aliases if a.startswith(text)] 2085 2086 # List of all the commands making the program resume execution. 2087 commands_resuming = ['do_continue', 'do_step', 'do_next', 'do_return', 2088 'do_quit', 'do_jump'] 2089 2090 # Print a traceback starting at the top stack frame. 2091 # The most recently entered frame is printed last; 2092 # this is different from dbx and gdb, but consistent with 2093 # the Python interpreter's stack trace. 2094 # It is also consistent with the up/down commands (which are 2095 # compatible with dbx and gdb: up moves towards 'main()' 2096 # and down moves towards the most recent stack frame). 2097 2098 def print_stack_trace(self): 2099 try: 2100 for frame_lineno in self.stack: 2101 self.print_stack_entry(frame_lineno) 2102 except KeyboardInterrupt: 2103 pass 2104 2105 def print_stack_entry(self, frame_lineno, prompt_prefix=line_prefix): 2106 frame, lineno = frame_lineno 2107 if frame is self.curframe: 2108 prefix = '> ' 2109 else: 2110 prefix = ' ' 2111 self.message(prefix + 2112 self.format_stack_entry(frame_lineno, prompt_prefix)) 2113 2114 # Provide help 2115 2116 def do_help(self, arg): 2117 """h(elp) 2118 2119 Without argument, print the list of available commands. 2120 With a command name as argument, print help about that command. 2121 "help pdb" shows the full pdb documentation. 2122 "help exec" gives help on the ! command. 2123 """ 2124 if not arg: 2125 return cmd.Cmd.do_help(self, arg) 2126 try: 2127 try: 2128 topic = getattr(self, 'help_' + arg) 2129 return topic() 2130 except AttributeError: 2131 command = getattr(self, 'do_' + arg) 2132 except AttributeError: 2133 self.error('No help for %r' % arg) 2134 else: 2135 if sys.flags.optimize >= 2: 2136 self.error('No help for %r; please do not run Python with -OO ' 2137 'if you need command help' % arg) 2138 return 2139 if command.__doc__ is None: 2140 self.error('No help for %r; __doc__ string missing' % arg) 2141 return 2142 self.message(self._help_message_from_doc(command.__doc__)) 2143 2144 do_h = do_help 2145 2146 def help_exec(self): 2147 """(!) statement 2148 2149 Execute the (one-line) statement in the context of the current 2150 stack frame. The exclamation point can be omitted unless the 2151 first word of the statement resembles a debugger command, e.g.: 2152 (Pdb) ! n=42 2153 (Pdb) 2154 2155 To assign to a global variable you must always prefix the command with 2156 a 'global' command, e.g.: 2157 (Pdb) global list_options; list_options = ['-l'] 2158 (Pdb) 2159 """ 2160 self.message((self.help_exec.__doc__ or '').strip()) 2161 2162 def help_pdb(self): 2163 help() 2164 2165 # other helper functions 2166 2167 def lookupmodule(self, filename): 2168 """Helper function for break/clear parsing -- may be overridden. 2169 2170 lookupmodule() translates (possibly incomplete) file or module name 2171 into an absolute file name. 2172 2173 filename could be in format of: 2174 * an absolute path like '/path/to/file.py' 2175 * a relative path like 'file.py' or 'dir/file.py' 2176 * a module name like 'module' or 'package.module' 2177 2178 files and modules will be searched in sys.path. 2179 """ 2180 if not filename.endswith('.py'): 2181 # A module is passed in so convert it to equivalent file 2182 filename = filename.replace('.', os.sep) + '.py' 2183 2184 if os.path.isabs(filename): 2185 if os.path.exists(filename): 2186 return filename 2187 return None 2188 2189 for dirname in sys.path: 2190 while os.path.islink(dirname): 2191 dirname = os.readlink(dirname) 2192 fullname = os.path.join(dirname, filename) 2193 if os.path.exists(fullname): 2194 return fullname 2195 return None 2196 2197 def _run(self, target: _ExecutableTarget): 2198 # When bdb sets tracing, a number of call and line events happen 2199 # BEFORE debugger even reaches user's code (and the exact sequence of 2200 # events depends on python version). Take special measures to 2201 # avoid stopping before reaching the main script (see user_line and 2202 # user_call for details). 2203 self._wait_for_mainpyfile = True 2204 self._user_requested_quit = False 2205 2206 self.mainpyfile = self.canonic(target.filename) 2207 2208 # The target has to run in __main__ namespace (or imports from 2209 # __main__ will break). Clear __main__ and replace with 2210 # the target namespace. 2211 import __main__ 2212 __main__.__dict__.clear() 2213 __main__.__dict__.update(target.namespace) 2214 2215 # Clear the mtime table for program reruns, assume all the files 2216 # are up to date. 2217 self._file_mtime_table.clear() 2218 2219 self.run(target.code) 2220 2221 def _format_exc(self, exc: BaseException): 2222 return traceback.format_exception_only(exc)[-1].strip() 2223 2224 def _compile_error_message(self, expr): 2225 """Return the error message as string if compiling `expr` fails.""" 2226 try: 2227 compile(expr, "<stdin>", "eval") 2228 except SyntaxError as exc: 2229 return _rstr(self._format_exc(exc)) 2230 return "" 2231 2232 def _getsourcelines(self, obj): 2233 # GH-103319 2234 # inspect.getsourcelines() returns lineno = 0 for 2235 # module-level frame which breaks our code print line number 2236 # This method should be replaced by inspect.getsourcelines(obj) 2237 # once this bug is fixed in inspect 2238 lines, lineno = inspect.getsourcelines(obj) 2239 lineno = max(1, lineno) 2240 return lines, lineno 2241 2242 def _help_message_from_doc(self, doc, usage_only=False): 2243 lines = [line.strip() for line in doc.rstrip().splitlines()] 2244 if not lines: 2245 return "No help message found." 2246 if "" in lines: 2247 usage_end = lines.index("") 2248 else: 2249 usage_end = 1 2250 formatted = [] 2251 indent = " " * len(self.prompt) 2252 for i, line in enumerate(lines): 2253 if i == 0: 2254 prefix = "Usage: " 2255 elif i < usage_end: 2256 prefix = " " 2257 else: 2258 if usage_only: 2259 break 2260 prefix = "" 2261 formatted.append(indent + prefix + line) 2262 return "\n".join(formatted) 2263 2264 def _print_invalid_arg(self, arg): 2265 """Return the usage string for a function.""" 2266 2267 self.error(f"Invalid argument: {arg}") 2268 2269 # Yes it's a bit hacky. Get the caller name, get the method based on 2270 # that name, and get the docstring from that method. 2271 # This should NOT fail if the caller is a method of this class. 2272 doc = inspect.getdoc(getattr(self, sys._getframe(1).f_code.co_name)) 2273 if doc is not None: 2274 self.message(self._help_message_from_doc(doc, usage_only=True)) 2275 2276# Collect all command help into docstring, if not run with -OO 2277 2278if __doc__ is not None: 2279 # unfortunately we can't guess this order from the class definition 2280 _help_order = [ 2281 'help', 'where', 'down', 'up', 'break', 'tbreak', 'clear', 'disable', 2282 'enable', 'ignore', 'condition', 'commands', 'step', 'next', 'until', 2283 'jump', 'return', 'retval', 'run', 'continue', 'list', 'longlist', 2284 'args', 'p', 'pp', 'whatis', 'source', 'display', 'undisplay', 2285 'interact', 'alias', 'unalias', 'debug', 'quit', 2286 ] 2287 2288 for _command in _help_order: 2289 __doc__ += getattr(Pdb, 'do_' + _command).__doc__.strip() + '\n\n' 2290 __doc__ += Pdb.help_exec.__doc__ 2291 2292 del _help_order, _command 2293 2294 2295# Simplified interface 2296 2297def run(statement, globals=None, locals=None): 2298 """Execute the *statement* (given as a string or a code object) 2299 under debugger control. 2300 2301 The debugger prompt appears before any code is executed; you can set 2302 breakpoints and type continue, or you can step through the statement 2303 using step or next. 2304 2305 The optional *globals* and *locals* arguments specify the 2306 environment in which the code is executed; by default the 2307 dictionary of the module __main__ is used (see the explanation of 2308 the built-in exec() or eval() functions.). 2309 """ 2310 Pdb().run(statement, globals, locals) 2311 2312def runeval(expression, globals=None, locals=None): 2313 """Evaluate the *expression* (given as a string or a code object) 2314 under debugger control. 2315 2316 When runeval() returns, it returns the value of the expression. 2317 Otherwise this function is similar to run(). 2318 """ 2319 return Pdb().runeval(expression, globals, locals) 2320 2321def runctx(statement, globals, locals): 2322 # B/W compatibility 2323 run(statement, globals, locals) 2324 2325def runcall(*args, **kwds): 2326 """Call the function (a function or method object, not a string) 2327 with the given arguments. 2328 2329 When runcall() returns, it returns whatever the function call 2330 returned. The debugger prompt appears as soon as the function is 2331 entered. 2332 """ 2333 return Pdb().runcall(*args, **kwds) 2334 2335def set_trace(*, header=None): 2336 """Enter the debugger at the calling stack frame. 2337 2338 This is useful to hard-code a breakpoint at a given point in a 2339 program, even if the code is not otherwise being debugged (e.g. when 2340 an assertion fails). If given, *header* is printed to the console 2341 just before debugging begins. 2342 """ 2343 pdb = Pdb() 2344 if header is not None: 2345 pdb.message(header) 2346 pdb.set_trace(sys._getframe().f_back) 2347 2348# Post-Mortem interface 2349 2350def post_mortem(t=None): 2351 """Enter post-mortem debugging of the given *traceback*, or *exception* 2352 object. 2353 2354 If no traceback is given, it uses the one of the exception that is 2355 currently being handled (an exception must be being handled if the 2356 default is to be used). 2357 2358 If `t` is an exception object, the `exceptions` command makes it possible to 2359 list and inspect its chained exceptions (if any). 2360 """ 2361 return _post_mortem(t, Pdb()) 2362 2363 2364def _post_mortem(t, pdb_instance): 2365 """ 2366 Private version of post_mortem, which allow to pass a pdb instance 2367 for testing purposes. 2368 """ 2369 # handling the default 2370 if t is None: 2371 exc = sys.exception() 2372 if exc is not None: 2373 t = exc.__traceback__ 2374 2375 if t is None or (isinstance(t, BaseException) and t.__traceback__ is None): 2376 raise ValueError("A valid traceback must be passed if no " 2377 "exception is being handled") 2378 2379 pdb_instance.reset() 2380 pdb_instance.interaction(None, t) 2381 2382 2383def pm(): 2384 """Enter post-mortem debugging of the traceback found in sys.last_exc.""" 2385 post_mortem(sys.last_exc) 2386 2387 2388# Main program for testing 2389 2390TESTCMD = 'import x; x.main()' 2391 2392def test(): 2393 run(TESTCMD) 2394 2395# print help 2396def help(): 2397 import pydoc 2398 pydoc.pager(__doc__) 2399 2400_usage = """\ 2401Debug the Python program given by pyfile. Alternatively, 2402an executable module or package to debug can be specified using 2403the -m switch. 2404 2405Initial commands are read from .pdbrc files in your home directory 2406and in the current directory, if they exist. Commands supplied with 2407-c are executed after commands from .pdbrc files. 2408 2409To let the script run until an exception occurs, use "-c continue". 2410To let the script run up to a given line X in the debugged file, use 2411"-c 'until X'".""" 2412 2413 2414def main(): 2415 import argparse 2416 2417 parser = argparse.ArgumentParser(prog="pdb", 2418 usage="%(prog)s [-h] [-c command] (-m module | pyfile) [args ...]", 2419 description=_usage, 2420 formatter_class=argparse.RawDescriptionHelpFormatter, 2421 allow_abbrev=False) 2422 2423 # We need to maunally get the script from args, because the first positional 2424 # arguments could be either the script we need to debug, or the argument 2425 # to the -m module 2426 parser.add_argument('-c', '--command', action='append', default=[], metavar='command', dest='commands', 2427 help='pdb commands to execute as if given in a .pdbrc file') 2428 parser.add_argument('-m', metavar='module', dest='module') 2429 2430 if len(sys.argv) == 1: 2431 # If no arguments were given (python -m pdb), print the whole help message. 2432 # Without this check, argparse would only complain about missing required arguments. 2433 parser.print_help() 2434 sys.exit(2) 2435 2436 opts, args = parser.parse_known_args() 2437 2438 if opts.module: 2439 # If a module is being debugged, we consider the arguments after "-m module" to 2440 # be potential arguments to the module itself. We need to parse the arguments 2441 # before "-m" to check if there is any invalid argument. 2442 # e.g. "python -m pdb -m foo --spam" means passing "--spam" to "foo" 2443 # "python -m pdb --spam -m foo" means passing "--spam" to "pdb" and is invalid 2444 idx = sys.argv.index('-m') 2445 args_to_pdb = sys.argv[1:idx] 2446 # This will raise an error if there are invalid arguments 2447 parser.parse_args(args_to_pdb) 2448 else: 2449 # If a script is being debugged, then pdb expects the script name as the first argument. 2450 # Anything before the script is considered an argument to pdb itself, which would 2451 # be invalid because it's not parsed by argparse. 2452 invalid_args = list(itertools.takewhile(lambda a: a.startswith('-'), args)) 2453 if invalid_args: 2454 parser.error(f"unrecognized arguments: {' '.join(invalid_args)}") 2455 sys.exit(2) 2456 2457 if opts.module: 2458 file = opts.module 2459 target = _ModuleTarget(file) 2460 else: 2461 if not args: 2462 parser.error("no module or script to run") 2463 file = args.pop(0) 2464 if file.endswith('.pyz'): 2465 target = _ZipTarget(file) 2466 else: 2467 target = _ScriptTarget(file) 2468 2469 sys.argv[:] = [file] + args # Hide "pdb.py" and pdb options from argument list 2470 2471 # Note on saving/restoring sys.argv: it's a good idea when sys.argv was 2472 # modified by the script being debugged. It's a bad idea when it was 2473 # changed by the user from the command line. There is a "restart" command 2474 # which allows explicit specification of command line arguments. 2475 pdb = Pdb() 2476 pdb.rcLines.extend(opts.commands) 2477 while True: 2478 try: 2479 pdb._run(target) 2480 except Restart: 2481 print("Restarting", target, "with arguments:") 2482 print("\t" + " ".join(sys.argv[1:])) 2483 except SystemExit as e: 2484 # In most cases SystemExit does not warrant a post-mortem session. 2485 print("The program exited via sys.exit(). Exit status:", end=' ') 2486 print(e) 2487 except BaseException as e: 2488 traceback.print_exception(e, colorize=_colorize.can_colorize()) 2489 print("Uncaught exception. Entering post mortem debugging") 2490 print("Running 'cont' or 'step' will restart the program") 2491 try: 2492 pdb.interaction(None, e) 2493 except Restart: 2494 print("Restarting", target, "with arguments:") 2495 print("\t" + " ".join(sys.argv[1:])) 2496 continue 2497 if pdb._user_requested_quit: 2498 break 2499 print("The program finished and will be restarted") 2500 2501 2502# When invoked as main program, invoke the debugger on a script 2503if __name__ == '__main__': 2504 import pdb 2505 pdb.main() 2506