This started as a spelling and whitespace cleanup. The comment for

the set_trace fiddling didn't make sense to me, and I ended up reworking
that part of the code.  We really do want to save and restore
pdb.set_trace, so that each dynamically nested level of doctest gets
sys.stdout fiddled to what's appropriate for *it*.  The only "trick"
really needed is that these layers of set_trace wrappers each call the
original pdb.set_trace (instead of the current pdb.set_trace).
This commit is contained in:
Tim Peters 2004-08-09 15:43:47 +00:00
parent 0d2a75c7b8
commit 413ced6c22
2 changed files with 21 additions and 19 deletions

View File

@ -1254,27 +1254,30 @@ class DocTestRunner:
if compileflags is None: if compileflags is None:
compileflags = _extract_future_flags(test.globs) compileflags = _extract_future_flags(test.globs)
save_stdout = sys.stdout
if out is None: if out is None:
out = sys.stdout.write out = save_stdout.write
saveout = sys.stdout sys.stdout = self._fakeout
# Note that don't save away the previous pdb.set_trace. Rather, # Patch pdb.set_trace to restore sys.stdout, so that interactive
# we safe pdb.set_trace on import (see import section above). # debugging output is visible (not still redirected to self._fakeout).
# We then call and restore that original cersion. We do it this # Note that we run "the real" pdb.set_trace (captured at doctest
# way to make this feature testable. If we kept and called the # import time) in our replacement. Because the current run() may
# previous version, we'd end up restoring the original stdout, # run another doctest (and so on), the current pdb.set_trace may be
# which is not what we want. # our set_trace function, which changes sys.stdout. If we called
# a chain of those, we wouldn't be left with the save_stdout
# *this* run() invocation wants.
def set_trace(): def set_trace():
sys.stdout = saveout sys.stdout = save_stdout
real_pdb_set_trace() real_pdb_set_trace()
save_set_trace = pdb.set_trace
pdb.set_trace = set_trace
try: try:
sys.stdout = self._fakeout
pdb.set_trace = set_trace
return self.__run(test, compileflags, out) return self.__run(test, compileflags, out)
finally: finally:
sys.stdout = saveout sys.stdout = save_stdout
pdb.set_trace = real_pdb_set_trace pdb.set_trace = save_set_trace
if clear_globs: if clear_globs:
test.globs.clear() test.globs.clear()

View File

@ -987,11 +987,11 @@ Run the debugger on the docstring, and then restore sys.stdin.
def test_pdb_set_trace(): def test_pdb_set_trace():
r"""Using pdb.set_trace from a doctest r"""Using pdb.set_trace from a doctest
You can use pdb.set_trace from a doctest. To do so, you must You can use pdb.set_trace from a doctest. To do so, you must
retrieve the set_trace function from the pdb module at the time retrieve the set_trace function from the pdb module at the time
you use it. The doctest module changes sys,stdout so that it can you use it. The doctest module changes sys.stdout so that it can
capture program output. It also temporarily replaces pdb.set_trace capture program output. It also temporarily replaces pdb.set_trace
with a version that restores stdout. This is necessary for you to with a version that restores stdout. This is necessary for you to
see debugger output. see debugger output.
>>> doc = ''' >>> doc = '''
@ -1042,7 +1042,6 @@ def test_pdb_set_trace():
... ''' ... '''
>>> test = doctest.DocTest(doc, globals(), "foo", "foo.py", 0) >>> test = doctest.DocTest(doc, globals(), "foo", "foo.py", 0)
>>> import tempfile
>>> fake_stdin = tempfile.TemporaryFile(mode='w+') >>> fake_stdin = tempfile.TemporaryFile(mode='w+')
>>> fake_stdin.write('\n'.join([ >>> fake_stdin.write('\n'.join([
... 'up', # up out of pdb.set_trace ... 'up', # up out of pdb.set_trace