From 469d3e78959d41a1a689bf8b6ef0982d0db14272 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 1 Aug 2010 19:35:16 +0000 Subject: Merged revisions 83259,83261,83264-83265,83268-83269,83271-83272,83281 via svnmerge from svn+ssh://svn.python.org/python/branches/py3k ........ r83259 | georg.brandl | 2010-07-30 09:03:39 +0200 (Fr, 30 Jul 2010) | 1 line Clarification. ........ r83261 | georg.brandl | 2010-07-30 09:21:26 +0200 (Fr, 30 Jul 2010) | 1 line #9230: allow Pdb.checkline() to be called without a current frame, for setting breakpoints before starting debugging. ........ r83264 | georg.brandl | 2010-07-30 10:45:26 +0200 (Fr, 30 Jul 2010) | 1 line Document the "jump" command in pdb.__doc__, and add a version tag for "until X". ........ r83265 | georg.brandl | 2010-07-30 10:54:49 +0200 (Fr, 30 Jul 2010) | 1 line #8015: fix crash when entering an empty line for breakpoint commands. Also restore environment properly when an exception occurs during the definition of commands. ........ r83268 | georg.brandl | 2010-07-30 11:23:23 +0200 (Fr, 30 Jul 2010) | 2 lines Issue #8048: Prevent doctests from failing when sys.displayhook has been reassigned. ........ r83269 | georg.brandl | 2010-07-30 11:43:00 +0200 (Fr, 30 Jul 2010) | 1 line #6719: In pdb, do not stop somewhere in the encodings machinery if the source file to be debugged is in a non-builtin encoding. ........ r83271 | georg.brandl | 2010-07-30 11:59:28 +0200 (Fr, 30 Jul 2010) | 1 line #5727: Restore the ability to use readline when calling into pdb in doctests. ........ r83272 | georg.brandl | 2010-07-30 12:29:19 +0200 (Fr, 30 Jul 2010) | 1 line #5294: Fix the behavior of pdb "continue" command when called in the top-level debugged frame. ........ r83281 | georg.brandl | 2010-07-30 15:36:43 +0200 (Fr, 30 Jul 2010) | 1 line Add myself for pdb. ........ --- Doc/library/ftplib.rst | 6 +++--- Lib/bdb.py | 10 +++++++--- Lib/doctest.py | 7 +++++++ Lib/pdb.py | 25 ++++++++++++++++++------- Lib/test/test_doctest.py | 29 +++++++++++++++++++++++++++++ Lib/test/test_pdb.py | 42 ++++++++++++++++++++++++++++++++++++++++++ Misc/NEWS | 15 +++++++++++++++ Misc/maintainers.rst | 2 +- 8 files changed, 122 insertions(+), 14 deletions(-) diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst index 9a3b305..c85e0b3 100644 --- a/Doc/library/ftplib.rst +++ b/Doc/library/ftplib.rst @@ -180,9 +180,9 @@ followed by ``lines`` for the text version or ``binary`` for the binary version. Retrieve a file or directory listing in ASCII transfer mode. *cmd* should be an appropriate ``RETR`` command (see :meth:`retrbinary`) or a command such as ``LIST``, ``NLST`` or ``MLSD`` (usually just the string - ``'LIST'``). The *callback* function is called for each line, with the - trailing CRLF stripped. The default *callback* prints the line to - ``sys.stdout``. + ``'LIST'``). The *callback* function is called for each line with a + string argument containing the line with the trailing CRLF stripped. + The default *callback* prints the line to ``sys.stdout``. .. method:: FTP.set_pasv(boolean) diff --git a/Lib/bdb.py b/Lib/bdb.py index 3b4f991..f16414d 100644 --- a/Lib/bdb.py +++ b/Lib/bdb.py @@ -109,6 +109,8 @@ class Bdb: self.is_skipped_module(frame.f_globals.get('__name__')): return False if frame is self.stopframe: + if self.stoplineno == -1: + return False return frame.f_lineno >= self.stoplineno while frame is not None and frame is not self.stopframe: if frame is self.botframe: @@ -165,10 +167,12 @@ class Bdb: but only if we are to stop at or just below this level.""" pass - def _set_stopinfo(self, stopframe, returnframe, stoplineno=-1): + def _set_stopinfo(self, stopframe, returnframe, stoplineno=0): self.stopframe = stopframe self.returnframe = returnframe self.quitting = 0 + # stoplineno >= 0 means: stop at line >= the stoplineno + # stoplineno -1 means: don't stop at all self.stoplineno = stoplineno # Derived classes and clients can call the following methods @@ -181,7 +185,7 @@ class Bdb: def set_step(self): """Stop after one line of code.""" - self._set_stopinfo(None,None) + self._set_stopinfo(None, None) def set_next(self, frame): """Stop on the next line in or below the given frame.""" @@ -208,7 +212,7 @@ class Bdb: def set_continue(self): # Don't stop except at breakpoints or when finished - self._set_stopinfo(self.botframe, None) + self._set_stopinfo(self.botframe, None, -1) if not self.breaks: # no breakpoints; run without debugger overhead sys.settrace(None) diff --git a/Lib/doctest.py b/Lib/doctest.py index 18bdc0a..c8d5cf4 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -318,6 +318,8 @@ class _OutputRedirectingPdb(pdb.Pdb): self.__out = out self.__debugger_used = False pdb.Pdb.__init__(self, stdout=out) + # still use input() to get user input + self.use_rawinput = 1 def set_trace(self, frame=None): self.__debugger_used = True @@ -1379,12 +1381,17 @@ class DocTestRunner: self.save_linecache_getlines = linecache.getlines linecache.getlines = self.__patched_linecache_getlines + # Make sure sys.displayhook just prints the value to stdout + save_displayhook = sys.displayhook + sys.displayhook = sys.__displayhook__ + try: return self.__run(test, compileflags, out) finally: sys.stdout = save_stdout pdb.set_trace = save_set_trace linecache.getlines = self.save_linecache_getlines + sys.displayhook = save_displayhook if clear_globs: test.globs.clear() import builtins diff --git a/Lib/pdb.py b/Lib/pdb.py index 22dcff7..1fb5174 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -183,6 +183,8 @@ class Pdb(bdb.Bdb, cmd.Cmd): def user_return(self, frame, return_value): """This function is called when a return trap is set here.""" + if self._wait_for_mainpyfile: + return frame.f_locals['__return__'] = return_value print('--Return--', file=self.stdout) self.interaction(frame, None) @@ -190,6 +192,8 @@ class Pdb(bdb.Bdb, cmd.Cmd): def user_exception(self, frame, exc_info): """This function is called if an exception occurs, but only if we are to stop at or just below this level.""" + if self._wait_for_mainpyfile: + return exc_type, exc_value, exc_traceback = exc_info frame.f_locals['__exception__'] = exc_type, exc_value exc_type_name = exc_type.__name__ @@ -275,8 +279,10 @@ class Pdb(bdb.Bdb, cmd.Cmd): return self.handle_command_def(line) def handle_command_def(self,line): - """ Handles one command line during command list definition. """ + """Handles one command line during command list definition.""" cmd, arg, line = self.parseline(line) + if not cmd: + return if cmd == 'silent': self.commands_silent[self.commands_bnum] = True return # continue to handle other cmd def in the cmd list @@ -284,7 +290,7 @@ class Pdb(bdb.Bdb, cmd.Cmd): self.cmdqueue = [] return 1 # end of cmd list cmdlist = self.commands[self.commands_bnum] - if (arg): + if arg: cmdlist.append(cmd+' '+arg) else: cmdlist.append(cmd) @@ -327,9 +333,11 @@ class Pdb(bdb.Bdb, cmd.Cmd): prompt_back = self.prompt self.prompt = '(com) ' self.commands_defining = True - self.cmdloop() - self.commands_defining = False - self.prompt = prompt_back + try: + self.cmdloop() + finally: + self.commands_defining = False + self.prompt = prompt_back def do_break(self, arg, temporary = 0): # break [ ([filename:]lineno | function) [, "condition"] ] @@ -465,7 +473,10 @@ class Pdb(bdb.Bdb, cmd.Cmd): Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank line or EOF). Warning: testing is not comprehensive. """ - line = linecache.getline(filename, lineno, self.curframe.f_globals) + # this method should be callable before starting debugging, so default + # to "no globals" if there is no current frame + globs = self.curframe.f_globals if hasattr(self, 'curframe') else None + line = linecache.getline(filename, lineno, globs) if not line: print('End of file', file=self.stdout) return 0 @@ -1293,7 +1304,7 @@ def main(): # changed by the user from the command line. There is a "restart" command # which allows explicit specification of command line arguments. pdb = Pdb() - while 1: + while True: try: pdb._runscript(mainpyfile) if pdb._user_requested_quit: diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index c9b1b85..0cb4f18 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -907,6 +907,35 @@ unexpected exception: ZeroDivisionError: integer division or modulo by zero TestResults(failed=1, attempted=1) """ + def displayhook(): r""" +Test that changing sys.displayhook doesn't matter for doctest. + + >>> import sys + >>> orig_displayhook = sys.displayhook + >>> def my_displayhook(x): + ... print('hi!') + >>> sys.displayhook = my_displayhook + >>> def f(): + ... ''' + ... >>> 3 + ... 3 + ... ''' + >>> test = doctest.DocTestFinder().find(f)[0] + >>> r = doctest.DocTestRunner(verbose=False).run(test) + >>> post_displayhook = sys.displayhook + + We need to restore sys.displayhook now, so that we'll be able to test + results. + + >>> sys.displayhook = orig_displayhook + + Ok, now we can check that everything is ok. + + >>> r + TestResults(failed=0, attempted=1) + >>> post_displayhook is my_displayhook + True +""" def optionflags(): r""" Tests of `DocTestRunner`'s option flag handling. diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 5d52707..9ab0b33 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -126,6 +126,48 @@ def test_pdb_skip_modules_with_callback(): """ +def test_pdb_continue_in_bottomframe(): + """Test that "continue" and "next" work properly in bottom frame (issue #5294). + + >>> def test_function(): + ... import pdb, sys; inst = pdb.Pdb() + ... inst.set_trace() + ... inst.botframe = sys._getframe() # hackery to get the right botframe + ... print(1) + ... print(2) + ... print(3) + ... print(4) + + >>> with PdbTestInput([ + ... 'next', + ... 'break 7', + ... 'continue', + ... 'next', + ... 'continue', + ... 'continue', + ... ]): + ... test_function() + > (4)test_function() + -> inst.botframe = sys._getframe() # hackery to get the right botframe + (Pdb) next + > (5)test_function() + -> print(1) + (Pdb) break 7 + Breakpoint 1 at :7 + (Pdb) continue + 1 + 2 + > (7)test_function() + -> print(3) + (Pdb) next + 3 + > (8)test_function() + -> print(4) + (Pdb) continue + 4 + """ + + def test_main(): from test import test_pdb support.run_doctest(test_pdb, verbosity=True) diff --git a/Misc/NEWS b/Misc/NEWS index 6752203..4b232f8 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -87,6 +87,21 @@ Library - Issue #7909: Do not touch paths with the special prefixes ``\\.\`` or ``\\?\`` in ntpath.normpath(). +- Issue #5294: Fix the behavior of pdb's "continue" command when called + in the top-level debugged frame. + +- Issue #5727: Restore the ability to use readline when calling into pdb + in doctests. + +- Issue #6719: In pdb, do not stop somewhere in the encodings machinery + if the source file to be debugged is in a non-builtin encoding. + +- Issue #8048: Prevent doctests from failing when sys.displayhook has + been reassigned. + +- Issue #8015: In pdb, do not crash when an empty line is entered as + a breakpoint command. + - Issue #5146: Handle UID THREAD command correctly in imaplib. - Issue #5147: Fix the header generated for cookie files written by diff --git a/Misc/maintainers.rst b/Misc/maintainers.rst index b9984b1..8fda2d0 100644 --- a/Misc/maintainers.rst +++ b/Misc/maintainers.rst @@ -147,7 +147,7 @@ optparse aronacher os loewis ossaudiodev parser -pdb +pdb georg.brandl pickle alexandre.vassalotti, pitrou pickletools alexandre.vassalotti pipes -- cgit v0.12