summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/ftplib.rst6
-rw-r--r--Lib/bdb.py10
-rw-r--r--Lib/doctest.py7
-rwxr-xr-xLib/pdb.py27
-rw-r--r--Lib/test/test_doctest.py29
-rw-r--r--Lib/test/test_pdb.py42
-rw-r--r--Misc/NEWS15
-rw-r--r--Misc/maintainers.rst2
8 files changed, 123 insertions, 15 deletions
diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst
index 27cc444..4b25d85 100644
--- a/Doc/library/ftplib.rst
+++ b/Doc/library/ftplib.rst
@@ -220,9 +220,9 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
Retrieve a file or directory listing in ASCII transfer mode. *command*
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 aa6779d..d0fcff8 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:
@@ -166,10 +168,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
@@ -182,7 +186,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."""
@@ -209,7 +213,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 917684c..8bca63d 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -335,6 +335,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
@@ -1381,12 +1383,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()
diff --git a/Lib/pdb.py b/Lib/pdb.py
index 0751c17..a6109d4 100755
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -183,14 +183,18 @@ 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 >>self.stdout, '--Return--'
self.interaction(frame, None)
def user_exception(self, frame, exc_info):
- exc_type, exc_value, exc_traceback = 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
if type(exc_type) == type(''):
exc_type_name = exc_type
@@ -277,8 +281,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
@@ -286,7 +292,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)
@@ -329,9 +335,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"] ]
@@ -467,7 +475,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 >>self.stdout, 'End of file'
return 0
@@ -1298,7 +1309,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 e51bacc..b30bcab 100644
--- a/Lib/test/test_doctest.py
+++ b/Lib/test/test_doctest.py
@@ -981,6 +981,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 ce64d17..8aca812 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()
+ > <doctest test.test_pdb.test_pdb_continue_in_bottomframe[0]>(4)test_function()
+ -> inst.botframe = sys._getframe() # hackery to get the right botframe
+ (Pdb) next
+ > <doctest test.test_pdb.test_pdb_continue_in_bottomframe[0]>(5)test_function()
+ -> print(1)
+ (Pdb) break 7
+ Breakpoint 1 at <doctest test.test_pdb.test_pdb_continue_in_bottomframe[0]>:7
+ (Pdb) continue
+ 1
+ 2
+ > <doctest test.test_pdb.test_pdb_continue_in_bottomframe[0]>(7)test_function()
+ -> print(3)
+ (Pdb) next
+ 3
+ > <doctest test.test_pdb.test_pdb_continue_in_bottomframe[0]>(8)test_function()
+ -> print(4)
+ (Pdb) continue
+ 4
+ """
+
+
def test_main():
from test import test_pdb
test_support.run_doctest(test_pdb, verbosity=True)
diff --git a/Misc/NEWS b/Misc/NEWS
index 18ac2c8..fb3e59e 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -24,6 +24,21 @@ Core and Builtins
Library
-------
+- 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 #9448: Fix a leak of OS resources (mutexes or semaphores) when
re-initializing a buffered IO object by calling its ``__init__`` method.
diff --git a/Misc/maintainers.rst b/Misc/maintainers.rst
index a80d8f2..825242f 100644
--- a/Misc/maintainers.rst
+++ b/Misc/maintainers.rst
@@ -151,7 +151,7 @@ optparse aronacher
os loewis
ossaudiodev
parser
-pdb
+pdb georg.brandl
pickle alexandre.vassalotti, pitrou
pickletools alexandre.vassalotti
pipes