diff options
author | Georg Brandl <georg@python.org> | 2010-12-04 16:21:42 (GMT) |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2010-12-04 16:21:42 (GMT) |
commit | cbc79c76a8fd11660ac6aa7681ed1d9e75d5df2e (patch) | |
tree | 6517d21805ab84ccea279853d41c6a22b36ff034 | |
parent | 44f2b640ff0260f5e338e41ad3a2d13185396979 (diff) | |
download | cpython-cbc79c76a8fd11660ac6aa7681ed1d9e75d5df2e.zip cpython-cbc79c76a8fd11660ac6aa7681ed1d9e75d5df2e.tar.gz cpython-cbc79c76a8fd11660ac6aa7681ed1d9e75d5df2e.tar.bz2 |
Add display/undisplay pdb commands.
-rw-r--r-- | Doc/library/pdb.rst | 16 | ||||
-rwxr-xr-x | Lib/pdb.py | 68 | ||||
-rw-r--r-- | Misc/NEWS | 2 |
3 files changed, 84 insertions, 2 deletions
diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst index 959fde1..8335993 100644 --- a/Doc/library/pdb.rst +++ b/Doc/library/pdb.rst @@ -417,6 +417,22 @@ by the local file. .. versionadded:: 3.2 +.. pdbcommand:: display [expression] + + Display the value of the expression if it changed, each time execution stops + in the current frame. + + Without expression, list all display expressions for the current frame. + + .. versionadded:: 3.2 + +.. pdbcommand:: undisplay [expression] + + Do not display the expression any more in the current frame. Without + expression, clear all display expressions for the current frame. + + .. versionadded:: 3.2 + .. pdbcommand:: interact Start an interative interpreter (using the :mod:`code` module) whose global @@ -125,6 +125,12 @@ def lasti2lineno(code, lasti): return 0 +class _rstr(str): + """String that doesn't quote its repr.""" + def __repr__(self): + return self + + # Interaction prompt line will separate file and call info from code # text using value of line_prefix string. A newline and arrow may # be to your liking. You can set it once pdb is imported using the @@ -142,6 +148,7 @@ class Pdb(bdb.Bdb, cmd.Cmd): self.use_rawinput = 0 self.prompt = '(Pdb) ' self.aliases = {} + self.displaying = {} self.mainpyfile = '' self._wait_for_mainpyfile = False self.tb_lineno = {} @@ -311,6 +318,20 @@ class Pdb(bdb.Bdb, cmd.Cmd): except KeyboardInterrupt: self.message('--KeyboardInterrupt--') + # Called before loop, handles display expressions + def preloop(self): + displaying = self.displaying.get(self.curframe) + if displaying: + for expr, oldvalue in displaying.items(): + newvalue = self._getval_except(expr) + # check for identity first; this prevents custom __eq__ to + # be called at every loop, and also prevents instances whose + # fields are changed to be displayed + if newvalue is not oldvalue and newvalue != oldvalue: + displaying[expr] = newvalue + self.message('display %s: %r [old: %r]' % + (expr, newvalue, oldvalue)) + def interaction(self, frame, traceback): if self.setup(frame, traceback): # no interaction desired at this time (happens if .pdbrc contains @@ -1041,6 +1062,17 @@ class Pdb(bdb.Bdb, cmd.Cmd): self.error(traceback.format_exception_only(*exc_info)[-1].strip()) raise + def _getval_except(self, arg, frame=None): + try: + if frame is None: + return eval(arg, self.curframe.f_globals, self.curframe_locals) + else: + return eval(arg, frame.f_globals, frame.f_locals) + except: + exc_info = sys.exc_info()[:2] + err = traceback.format_exception_only(*exc_info)[-1].strip() + return _rstr('** raised %s **' % err) + def do_p(self, arg): """p(rint) expression Print the value of the expression. @@ -1195,6 +1227,38 @@ class Pdb(bdb.Bdb, cmd.Cmd): # None of the above... self.message(type(value)) + def do_display(self, arg): + """display [expression] + + Display the value of the expression if it changed, each time execution + stops in the current frame. + + Without expression, list all display expressions for the current frame. + """ + if not arg: + self.message('Currently displaying:') + for item in self.displaying.get(self.curframe, {}).items(): + self.message('%s: %r' % item) + else: + val = self._getval_except(arg) + self.displaying.setdefault(self.curframe, {})[arg] = val + self.message('display %s: %r' % (arg, val)) + + def do_undisplay(self, arg): + """undisplay [expression] + + Do not display the expression any more in the current frame. + + Without expression, clear all display expressions for the current frame. + """ + if arg: + try: + del self.displaying.get(self.curframe, {})[arg] + except KeyError: + self.error('not displaying %s' % arg) + else: + self.displaying.pop(self.curframe, None) + def do_interact(self, arg): """interact @@ -1380,8 +1444,8 @@ if __doc__ is not None: 'help', 'where', 'down', 'up', 'break', 'tbreak', 'clear', 'disable', 'enable', 'ignore', 'condition', 'commands', 'step', 'next', 'until', 'jump', 'return', 'retval', 'run', 'continue', 'list', 'longlist', - 'args', 'print', 'pp', 'whatis', 'source', 'interact', 'alias', - 'unalias', 'debug', 'quit', + 'args', 'print', 'pp', 'whatis', 'source', 'display', 'undisplay', + 'interact', 'alias', 'unalias', 'debug', 'quit', ] for _command in _help_order: @@ -49,6 +49,8 @@ Core and Builtins Library ------- +- Add the "display" and "undisplay" pdb commands. + - Issue #7245: Add a SIGINT handler in pdb that allows to break a program again after a "continue" command. |