Python-checkins
Threads by month
- ----- 2024 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
July 2010
- 21 participants
- 1138 discussions
30 Jul '10
Author: victor.stinner
Date: Fri Jul 30 21:43:11 2010
New Revision: 83295
Log:
test_subprocess: don't skip test_bytes_program()
The test now pass in any case.
Merge also with py3k.
Modified:
python/branches/import_unicode/Lib/test/test_subprocess.py
Modified: python/branches/import_unicode/Lib/test/test_subprocess.py
==============================================================================
--- python/branches/import_unicode/Lib/test/test_subprocess.py (original)
+++ python/branches/import_unicode/Lib/test/test_subprocess.py Fri Jul 30 21:43:11 2010
@@ -854,7 +854,7 @@
[sys.executable, "-c", script],
env=env)
stdout = stdout.rstrip(b'\n\r')
- self.assertEquals(stdout.decode('ascii'), repr(value))
+ self.assertEqual(stdout.decode('ascii'), repr(value))
# test bytes
key = key.encode("ascii", "surrogateescape")
@@ -866,28 +866,28 @@
[sys.executable, "-c", script],
env=env)
stdout = stdout.rstrip(b'\n\r')
- self.assertEquals(stdout.decode('ascii'), repr(value))
+ self.assertEqual(stdout.decode('ascii'), repr(value))
- def test_absolute_bytes_program(self):
- exitcode = subprocess.call([os.fsencode(sys.executable), "-c", "pass"])
- self.assertEquals(exitcode, 0)
-
- @unittest.skipIf(sysconfig.is_python_build(), "need an installed Python")
def test_bytes_program(self):
+ abs_program = os.fsencode(sys.executable)
path, program = os.path.split(sys.executable)
program = os.fsencode(program)
+ # absolute bytes path
+ exitcode = subprocess.call([abs_program, "-c", "pass"])
+ self.assertEqual(exitcode, 0)
+
# bytes program, unicode PATH
env = os.environ.copy()
env["PATH"] = path
exitcode = subprocess.call([program, "-c", "pass"], env=env)
- self.assertEquals(exitcode, 0)
+ self.assertEqual(exitcode, 0)
# bytes program, bytes PATH
envb = os.environb.copy()
envb[b"PATH"] = os.fsencode(path)
exitcode = subprocess.call([program, "-c", "pass"], env=envb)
- self.assertEquals(exitcode, 0)
+ self.assertEqual(exitcode, 0)
@unittest.skipUnless(mswindows, "Windows specific tests")
1
0
r83294 - in python/branches/py3k/Lib: test/test_urllib.py urllib/parse.py
by senthil.kumaran 30 Jul '10
by senthil.kumaran 30 Jul '10
30 Jul '10
Author: senthil.kumaran
Date: Fri Jul 30 21:34:36 2010
New Revision: 83294
Log:
Fix issue9301 - handle unquote({}) kind of case.
Modified:
python/branches/py3k/Lib/test/test_urllib.py
python/branches/py3k/Lib/urllib/parse.py
Modified: python/branches/py3k/Lib/test/test_urllib.py
==============================================================================
--- python/branches/py3k/Lib/test/test_urllib.py (original)
+++ python/branches/py3k/Lib/test/test_urllib.py Fri Jul 30 21:34:36 2010
@@ -527,6 +527,7 @@
self.assertEqual(expect, result,
"using quote_plus(): %r != %r" % (expect, result))
+
class UnquotingTests(unittest.TestCase):
"""Tests for unquote() and unquote_plus()
@@ -555,6 +556,7 @@
"using unquote(): not all characters escaped: "
"%s" % result)
self.assertRaises(TypeError, urllib.parse.unquote, None)
+ self.assertRaises(TypeError, urllib.parse.unquote, ())
def test_unquoting_badpercent(self):
# Test unquoting on bad percent-escapes
@@ -589,8 +591,8 @@
result = urllib.parse.unquote_to_bytes(given)
self.assertEqual(expect, result, "using unquote_to_bytes(): %r != %r"
% (expect, result))
-
self.assertRaises(TypeError, urllib.parse.unquote_to_bytes, None)
+ self.assertRaises(TypeError, urllib.parse.unquote_to_bytes, ())
def test_unquoting_mixed_case(self):
# Test unquoting on mixed-case hex digits in the percent-escapes
Modified: python/branches/py3k/Lib/urllib/parse.py
==============================================================================
--- python/branches/py3k/Lib/urllib/parse.py (original)
+++ python/branches/py3k/Lib/urllib/parse.py Fri Jul 30 21:34:36 2010
@@ -313,9 +313,7 @@
"""unquote_to_bytes('abc%20def') -> b'abc def'."""
# Note: strings are encoded as UTF-8. This is only an issue if it contains
# unescaped non-ASCII characters, which URIs should not.
- if not string:
- if string is None:
- raise TypeError('None object is invalid for unquote_to_bytes()')
+ if string in (b'', ''):
return b''
if isinstance(string, str):
string = string.encode('utf-8')
@@ -340,9 +338,7 @@
unquote('abc%20def') -> 'abc def'.
"""
- if not string:
- if string is None:
- raise TypeError('None object is invalid for unquote() function.')
+ if string in (b'', ''):
return string
res = string.split('%')
if len(res) == 1:
1
0
r83293 - in python/branches/py3k: Doc/library/pdb.rst Lib/pdb.py Lib/test/test_pdb.py Misc/NEWS
by georg.brandl 30 Jul '10
by georg.brandl 30 Jul '10
30 Jul '10
Author: georg.brandl
Date: Fri Jul 30 20:46:38 2010
New Revision: 83293
Log:
Show the traceback line numbers as well as the current line numbers if an exception is being debugged. Courtesy of pdb++ by Antonio Cuni. Also document -> and >> markers for "list".
Modified:
python/branches/py3k/Doc/library/pdb.rst
python/branches/py3k/Lib/pdb.py
python/branches/py3k/Lib/test/test_pdb.py
python/branches/py3k/Misc/NEWS
Modified: python/branches/py3k/Doc/library/pdb.rst
==============================================================================
--- python/branches/py3k/Doc/library/pdb.rst (original)
+++ python/branches/py3k/Doc/library/pdb.rst Fri Jul 30 20:46:38 2010
@@ -368,9 +368,18 @@
list 11 lines around at that line. With two arguments, list the given range;
if the second argument is less than the first, it is interpreted as a count.
+ The current line in the current frame is indicated by ``->``. If an
+ exception is being debugged, the line where the exception was originally
+ raised or propagated is indicated by ``>>``, if it differs from the current
+ line.
+
+ .. versionadded:: 3.2
+ The ``>>`` marker.
+
.. pdbcommand:: ll | longlist
- List all source code for the current function or frame.
+ List all source code for the current function or frame. Interesting lines
+ are marked as for :pdbcmd:`list`.
.. versionadded:: 3.2
Modified: python/branches/py3k/Lib/pdb.py
==============================================================================
--- python/branches/py3k/Lib/pdb.py (original)
+++ python/branches/py3k/Lib/pdb.py Fri Jul 30 20:46:38 2010
@@ -70,8 +70,10 @@
import linecache
import cmd
import bdb
+import dis
import os
import re
+import code
import pprint
import traceback
import inspect
@@ -107,14 +109,22 @@
def getsourcelines(obj):
lines, lineno = inspect.findsource(obj)
- if inspect.isframe(obj) and lineno == 0 and \
- obj.f_globals is obj.f_locals:
+ if inspect.isframe(obj) and obj.f_globals is obj.f_locals:
# must be a module frame: do not try to cut a block out of it
- return lines, 0
+ return lines, 1
elif inspect.ismodule(obj):
- return lines, 0
+ return lines, 1
return inspect.getblock(lines[lineno:]), lineno+1
+def lasti2lineno(code, lasti):
+ linestarts = list(dis.findlinestarts(code))
+ linestarts.reverse()
+ for i, lineno in linestarts:
+ if lasti >= i:
+ return lineno
+ return 0
+
+
# 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
@@ -133,6 +143,7 @@
self.aliases = {}
self.mainpyfile = ''
self._wait_for_mainpyfile = 0
+ self.tb_lineno = {}
# Try to load readline if it exists
try:
import readline
@@ -179,10 +190,18 @@
self.stack = []
self.curindex = 0
self.curframe = None
+ self.tb_lineno.clear()
- def setup(self, f, t):
+ def setup(self, f, tb):
self.forget()
- self.stack, self.curindex = self.get_stack(f, t)
+ self.stack, self.curindex = self.get_stack(f, tb)
+ while tb:
+ # when setting up post-mortem debugging with a traceback, save all
+ # the original line numbers to be displayed along the current line
+ # numbers (which can be different, e.g. due to finally clauses)
+ lineno = lasti2lineno(tb.tb_frame.f_code, tb.tb_lasti)
+ self.tb_lineno[tb.tb_frame] = lineno
+ tb = tb.tb_next
self.curframe = self.stack[self.curindex][0]
# The f_locals dictionary is updated from the actual frame
# locals whenever the .f_locals accessor is called, so we
@@ -1005,13 +1024,18 @@
def do_list(self, arg):
"""l(ist) [first [,last] | .]
- List source code for the current file.
- Without arguments, list 11 lines around the current line
- or continue the previous listing.
- With . as argument, list 11 lines around the current line.
- With one argument, list 11 lines starting at that line.
- With two arguments, list the given range;
- if the second argument is less than the first, it is a count.
+
+ List source code for the current file. Without arguments,
+ list 11 lines around the current line or continue the previous
+ listing. With . as argument, list 11 lines around the current
+ line. With one argument, list 11 lines starting at that line.
+ With two arguments, list the given range; if the second
+ argument is less than the first, it is a count.
+
+ The current line in the current frame is indicated by "->".
+ If an exception is being debugged, the line where the
+ exception was originally raised or propagated is indicated by
+ ">>", if it differs from the current line.
"""
self.lastcmd = 'list'
last = None
@@ -1039,10 +1063,9 @@
filename = self.curframe.f_code.co_filename
breaklist = self.get_file_breaks(filename)
try:
- # XXX add tb_lineno feature
lines = linecache.getlines(filename, self.curframe.f_globals)
self._print_lines(lines[first-1:last], first, breaklist,
- self.curframe.f_lineno, -1)
+ self.curframe)
self.lineno = min(last, len(lines))
if len(lines) < last:
self.message('[EOF]')
@@ -1061,7 +1084,7 @@
except IOError as err:
self.error(err)
return
- self._print_lines(lines, lineno, breaklist, self.curframe.f_lineno, -1)
+ self._print_lines(lines, lineno, breaklist, self.curframe)
do_ll = do_longlist
def do_source(self, arg):
@@ -1077,10 +1100,15 @@
except (IOError, TypeError) as err:
self.error(err)
return
- self._print_lines(lines, lineno, [], -1, -1)
+ self._print_lines(lines, lineno)
- def _print_lines(self, lines, start, breaks, current, special):
+ def _print_lines(self, lines, start, breaks=(), frame=None):
"""Print a range of lines."""
+ if frame:
+ current_lineno = frame.f_lineno
+ exc_lineno = self.tb_lineno.get(frame, -1)
+ else:
+ current_lineno = exc_lineno = -1
for lineno, line in enumerate(lines, start):
s = str(lineno).rjust(3)
if len(s) < 4:
@@ -1089,9 +1117,9 @@
s += 'B'
else:
s += ' '
- if lineno == current:
+ if lineno == current_lineno:
s += '->'
- elif lineno == special:
+ elif lineno == exc_lineno:
s += '>>'
self.message(s + '\t' + line.rstrip())
Modified: python/branches/py3k/Lib/test/test_pdb.py
==============================================================================
--- python/branches/py3k/Lib/test/test_pdb.py (original)
+++ python/branches/py3k/Lib/test/test_pdb.py Fri Jul 30 20:46:38 2010
@@ -359,6 +359,68 @@
"""
+def test_post_mortem():
+ """Test post mortem traceback debugging.
+
+ >>> def test_function_2():
+ ... try:
+ ... 1/0
+ ... finally:
+ ... print('Exception!')
+
+ >>> def test_function():
+ ... import pdb; pdb.Pdb().set_trace()
+ ... test_function_2()
+ ... print('Not reached.')
+
+ >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
+ ... 'next', # step over exception-raising call
+ ... 'bt', # get a backtrace
+ ... 'list', # list code of test_function()
+ ... 'down', # step into test_function_2()
+ ... 'list', # list code of test_function_2()
+ ... 'continue',
+ ... ]):
+ ... try:
+ ... test_function()
+ ... except ZeroDivisionError:
+ ... print('Correctly reraised.')
+ > <doctest test.test_pdb.test_post_mortem[1]>(3)test_function()
+ -> test_function_2()
+ (Pdb) next
+ Exception!
+ ZeroDivisionError: division by zero
+ > <doctest test.test_pdb.test_post_mortem[1]>(3)test_function()
+ -> test_function_2()
+ (Pdb) bt
+ ...
+ <doctest test.test_pdb.test_post_mortem[2]>(10)<module>()
+ -> test_function()
+ > <doctest test.test_pdb.test_post_mortem[1]>(3)test_function()
+ -> test_function_2()
+ <doctest test.test_pdb.test_post_mortem[0]>(3)test_function_2()
+ -> 1/0
+ (Pdb) list
+ 1 def test_function():
+ 2 import pdb; pdb.Pdb().set_trace()
+ 3 -> test_function_2()
+ 4 print('Not reached.')
+ [EOF]
+ (Pdb) down
+ > <doctest test.test_pdb.test_post_mortem[0]>(3)test_function_2()
+ -> 1/0
+ (Pdb) list
+ 1 def test_function_2():
+ 2 try:
+ 3 >> 1/0
+ 4 finally:
+ 5 -> print('Exception!')
+ [EOF]
+ (Pdb) continue
+ Correctly reraised.
+ """
+
+
def test_pdb_skip_modules():
"""This illustrates the simple case of module skipping.
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS (original)
+++ python/branches/py3k/Misc/NEWS Fri Jul 30 20:46:38 2010
@@ -475,6 +475,10 @@
Library
-------
+- For traceback debugging, the pdb listing now also shows the locations
+ where the exception was originally (re)raised, if it differs from the
+ last line executed (e.g. in case of finally clauses).
+
- The pdb command "source" has been added. It displays the source
code for a given object, if possible.
1
0
Author: georg.brandl
Date: Fri Jul 30 20:15:16 2010
New Revision: 83292
Log:
Test that "source" with nonexisting things works as expected.
Modified:
python/branches/py3k/Lib/test/test_pdb.py
Modified: python/branches/py3k/Lib/test/test_pdb.py
==============================================================================
--- python/branches/py3k/Lib/test/test_pdb.py (original)
+++ python/branches/py3k/Lib/test/test_pdb.py Fri Jul 30 20:15:16 2010
@@ -298,6 +298,7 @@
... 'step', # step into do_nothing
... 'longlist', # list all lines
... 'source do_something', # list all lines of function
+ ... 'source fooxxx', # something that doesn't exit
... 'continue',
... ]):
... test_function()
@@ -352,6 +353,8 @@
(Pdb) source do_something
... def do_something():
... print(42)
+ (Pdb) source fooxxx
+ *** ...
(Pdb) continue
"""
1
0
Author: georg.brandl
Date: Fri Jul 30 20:08:12 2010
New Revision: 83291
Log:
Fix source finding if the given frame is a module-level frame.
Modified:
python/branches/py3k/Lib/pdb.py
Modified: python/branches/py3k/Lib/pdb.py
==============================================================================
--- python/branches/py3k/Lib/pdb.py (original)
+++ python/branches/py3k/Lib/pdb.py Fri Jul 30 20:08:12 2010
@@ -105,6 +105,15 @@
fp.close()
return answer
+def getsourcelines(obj):
+ lines, lineno = inspect.findsource(obj)
+ if inspect.isframe(obj) and lineno == 0 and \
+ obj.f_globals is obj.f_locals:
+ # must be a module frame: do not try to cut a block out of it
+ return lines, 0
+ elif inspect.ismodule(obj):
+ return lines, 0
+ return inspect.getblock(lines[lineno:]), lineno+1
# Interaction prompt line will separate file and call info from code
# text using value of line_prefix string. A newline and arrow may
@@ -1048,7 +1057,7 @@
filename = self.curframe.f_code.co_filename
breaklist = self.get_file_breaks(filename)
try:
- lines, lineno = inspect.getsourcelines(self.curframe)
+ lines, lineno = getsourcelines(self.curframe)
except IOError as err:
self.error(err)
return
@@ -1064,7 +1073,7 @@
except:
return
try:
- lines, lineno = inspect.getsourcelines(obj)
+ lines, lineno = getsourcelines(obj)
except (IOError, TypeError) as err:
self.error(err)
return
1
0
Author: victor.stinner
Date: Fri Jul 30 19:48:28 2010
New Revision: 83290
Log:
typo: lives => live
Modified:
python/branches/import_unicode/Include/Python.h
Modified: python/branches/import_unicode/Include/Python.h
==============================================================================
--- python/branches/import_unicode/Include/Python.h (original)
+++ python/branches/import_unicode/Include/Python.h Fri Jul 30 19:48:28 2010
@@ -128,7 +128,7 @@
/* _Py_Mangle is defined in compile.c */
PyAPI_FUNC(PyObject*) _Py_Mangle(PyObject *p, PyObject *name);
-/* _Py_char2wchar and _Py_wchar2char lives in main.c */
+/* _Py_char2wchar and _Py_wchar2char live in main.c */
PyAPI_FUNC(wchar_t *) _Py_char2wchar(char *);
PyAPI_FUNC(char*) _Py_wchar2char(const wchar_t *text);
1
0
r83289 - in python/branches/py3k: Misc/NEWS PCbuild/pyproject.vsprops PCbuild/readme.txt
by martin.v.loewis 30 Jul '10
by martin.v.loewis 30 Jul '10
30 Jul '10
Author: martin.v.loewis
Date: Fri Jul 30 19:30:51 2010
New Revision: 83289
Log:
Use OpenSSL 1.0.0a on Windows.
Modified:
python/branches/py3k/Misc/NEWS
python/branches/py3k/PCbuild/pyproject.vsprops
python/branches/py3k/PCbuild/readme.txt
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS (original)
+++ python/branches/py3k/Misc/NEWS Fri Jul 30 19:30:51 2010
@@ -1672,6 +1672,8 @@
Build
-----
+- Use OpenSSL 1.0.0a on Windows.
+
- Issue #9280: Make sharedinstall depend on sharedmods.
- Issue #9189: Make a user-specified CFLAGS, CPPFLAGS, or LDFLAGS
Modified: python/branches/py3k/PCbuild/pyproject.vsprops
==============================================================================
--- python/branches/py3k/PCbuild/pyproject.vsprops (original)
+++ python/branches/py3k/PCbuild/pyproject.vsprops Fri Jul 30 19:30:51 2010
@@ -58,7 +58,7 @@
/>
<UserMacro
Name="opensslDir"
- Value="$(externalsDir)\openssl-0.9.8l"
+ Value="$(externalsDir)\openssl-1.0.0a"
/>
<UserMacro
Name="tcltkDir"
Modified: python/branches/py3k/PCbuild/readme.txt
==============================================================================
--- python/branches/py3k/PCbuild/readme.txt (original)
+++ python/branches/py3k/PCbuild/readme.txt Fri Jul 30 19:30:51 2010
@@ -139,7 +139,7 @@
Get the source code through
- svn export http://svn.python.org/projects/external/openssl-0.9.8l
+ svn export http://svn.python.org/projects/external/openssl-1.0.0a
** NOTE: if you use the Tools\buildbot\external(-amd64).bat approach for
obtaining external sources then you don't need to manually get the source
1
0
Author: martin.v.loewis
Date: Fri Jul 30 19:29:39 2010
New Revision: 83288
Log:
Drop 2.4 support. Add disabled algorithms to Configure options.
Modified:
python/branches/py3k/PCbuild/build_ssl.py
Modified: python/branches/py3k/PCbuild/build_ssl.py
==============================================================================
--- python/branches/py3k/PCbuild/build_ssl.py (original)
+++ python/branches/py3k/PCbuild/build_ssl.py Fri Jul 30 19:29:39 2010
@@ -23,6 +23,7 @@
# python.exe build_ssl.py Release x64
# python.exe build_ssl.py Release Win32
+from __future__ import with_statement
import os, sys, re, shutil
# Find all "foo.exe" files on the PATH.
@@ -121,13 +122,10 @@
"""
if not os.path.isfile(makefile):
return
- # 2.4 compatibility
fin = open(makefile)
- if 1: # with open(makefile) as fin:
+ with open(makefile) as fin:
lines = fin.readlines()
- fin.close()
- fout = open(makefile, 'w')
- if 1: # with open(makefile, 'w') as fout:
+ with open(makefile, 'w') as fout:
for line in lines:
if line.startswith("PERL="):
continue
@@ -143,11 +141,10 @@
line = line + noalgo
line = line + '\n'
fout.write(line)
- fout.close()
def run_configure(configure, do_script):
- print("perl Configure "+configure)
- os.system("perl Configure "+configure)
+ print("perl Configure "+configure+" no-idea no-mdc2")
+ os.system("perl Configure "+configure+" no-idea no-mdc2")
print(do_script)
os.system(do_script)
1
0
r83287 - in python/branches/py3k: Doc/library/pdb.rst Lib/pdb.py Lib/test/test_pdb.py Misc/ACKS Misc/NEWS
by georg.brandl 30 Jul '10
by georg.brandl 30 Jul '10
30 Jul '10
Author: georg.brandl
Date: Fri Jul 30 19:04:28 2010
New Revision: 83287
Log:
Add "longlist" and "source" commands, ideas borrowed from pdb++ by Antonio Cuni.
Modified:
python/branches/py3k/Doc/library/pdb.rst
python/branches/py3k/Lib/pdb.py
python/branches/py3k/Lib/test/test_pdb.py
python/branches/py3k/Misc/ACKS
python/branches/py3k/Misc/NEWS
Modified: python/branches/py3k/Doc/library/pdb.rst
==============================================================================
--- python/branches/py3k/Doc/library/pdb.rst (original)
+++ python/branches/py3k/Doc/library/pdb.rst Fri Jul 30 19:04:28 2010
@@ -368,6 +368,12 @@
list 11 lines around at that line. With two arguments, list the given range;
if the second argument is less than the first, it is interpreted as a count.
+.. pdbcommand:: ll | longlist
+
+ List all source code for the current function or frame.
+
+ .. versionadded:: 3.2
+
.. pdbcommand:: a(rgs)
Print the argument list of the current function.
@@ -385,6 +391,12 @@
Print the type of the *expression*.
+.. pdbcommand:: source expression
+
+ Try to get source code for the given object and display it.
+
+ .. versionadded:: 3.2
+
.. _debugger-aliases:
.. pdbcommand:: alias [name [command]]
Modified: python/branches/py3k/Lib/pdb.py
==============================================================================
--- python/branches/py3k/Lib/pdb.py (original)
+++ python/branches/py3k/Lib/pdb.py Fri Jul 30 19:04:28 2010
@@ -74,6 +74,8 @@
import re
import pprint
import traceback
+import inspect
+import types
class Restart(Exception):
@@ -1028,25 +1030,62 @@
filename = self.curframe.f_code.co_filename
breaklist = self.get_file_breaks(filename)
try:
- for lineno in range(first, last+1):
- line = linecache.getline(filename, lineno,
- self.curframe.f_globals)
- if not line:
- self.message('[EOF]')
- break
- else:
- s = repr(lineno).rjust(3)
- if len(s) < 4: s = s + ' '
- if lineno in breaklist: s = s + 'B'
- else: s = s + ' '
- if lineno == self.curframe.f_lineno:
- s = s + '->'
- self.message(s + '\t' + line.rstrip())
- self.lineno = lineno
+ # XXX add tb_lineno feature
+ lines = linecache.getlines(filename, self.curframe.f_globals)
+ self._print_lines(lines[first-1:last], first, breaklist,
+ self.curframe.f_lineno, -1)
+ self.lineno = min(last, len(lines))
+ if len(lines) < last:
+ self.message('[EOF]')
except KeyboardInterrupt:
pass
do_l = do_list
+ def do_longlist(self, arg):
+ """longlist | ll
+ List the whole source code for the current function or frame.
+ """
+ filename = self.curframe.f_code.co_filename
+ breaklist = self.get_file_breaks(filename)
+ try:
+ lines, lineno = inspect.getsourcelines(self.curframe)
+ except IOError as err:
+ self.error(err)
+ return
+ self._print_lines(lines, lineno, breaklist, self.curframe.f_lineno, -1)
+ do_ll = do_longlist
+
+ def do_source(self, arg):
+ """source expression
+ Try to get source code for the given object and display it.
+ """
+ try:
+ obj = self._getval(arg)
+ except:
+ return
+ try:
+ lines, lineno = inspect.getsourcelines(obj)
+ except (IOError, TypeError) as err:
+ self.error(err)
+ return
+ self._print_lines(lines, lineno, [], -1, -1)
+
+ def _print_lines(self, lines, start, breaks, current, special):
+ """Print a range of lines."""
+ for lineno, line in enumerate(lines, start):
+ s = str(lineno).rjust(3)
+ if len(s) < 4:
+ s += ' '
+ if lineno in breaks:
+ s += 'B'
+ else:
+ s += ' '
+ if lineno == current:
+ s += '->'
+ elif lineno == special:
+ s += '>>'
+ self.message(s + '\t' + line.rstrip())
+
def do_whatis(self, arg):
"""whatis arg
Print the type of the argument.
@@ -1249,10 +1288,12 @@
_help_order = [
'help', 'where', 'down', 'up', 'break', 'tbreak', 'clear', 'disable',
'enable', 'ignore', 'condition', 'commands', 'step', 'next', 'until',
- 'jump', 'return', 'retval', 'run', 'continue', 'list', 'args', 'print',
- 'whatis', 'alias', 'unalias', 'quit',
+ 'jump', 'return', 'retval', 'run', 'continue', 'list', 'longlist',
+ 'args', 'print', 'pp', 'whatis', 'source', 'alias', 'unalias',
+ 'debug', 'quit',
]
+docs = set()
for _command in _help_order:
__doc__ += getattr(Pdb, 'do_' + _command).__doc__.strip() + '\n\n'
__doc__ += Pdb.help_exec.__doc__
Modified: python/branches/py3k/Lib/test/test_pdb.py
==============================================================================
--- python/branches/py3k/Lib/test/test_pdb.py (original)
+++ python/branches/py3k/Lib/test/test_pdb.py Fri Jul 30 19:04:28 2010
@@ -257,6 +257,105 @@
"""
+def do_nothing():
+ pass
+
+def do_something():
+ print(42)
+
+def test_list_commands():
+ """Test the list and source commands of pdb.
+
+ >>> def test_function_2(foo):
+ ... import test_pdb
+ ... test_pdb.do_nothing()
+ ... 'some...'
+ ... 'more...'
+ ... 'code...'
+ ... 'to...'
+ ... 'make...'
+ ... 'a...'
+ ... 'long...'
+ ... 'listing...'
+ ... 'useful...'
+ ... '...'
+ ... '...'
+ ... return foo
+
+ >>> def test_function():
+ ... import pdb; pdb.Pdb().set_trace()
+ ... ret = test_function_2('baz')
+
+ >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
+ ... 'list', # list first function
+ ... 'step', # step into second function
+ ... 'list', # list second function
+ ... 'list', # continue listing to EOF
+ ... 'list 1,3', # list specific lines
+ ... 'list x', # invalid argument
+ ... 'next', # step to import
+ ... 'next', # step over import
+ ... 'step', # step into do_nothing
+ ... 'longlist', # list all lines
+ ... 'source do_something', # list all lines of function
+ ... 'continue',
+ ... ]):
+ ... test_function()
+ > <doctest test.test_pdb.test_list_commands[1]>(3)test_function()
+ -> ret = test_function_2('baz')
+ (Pdb) list
+ 1 def test_function():
+ 2 import pdb; pdb.Pdb().set_trace()
+ 3 -> ret = test_function_2('baz')
+ [EOF]
+ (Pdb) step
+ --Call--
+ > <doctest test.test_pdb.test_list_commands[0]>(1)test_function_2()
+ -> def test_function_2(foo):
+ (Pdb) list
+ 1 -> def test_function_2(foo):
+ 2 import test_pdb
+ 3 test_pdb.do_nothing()
+ 4 'some...'
+ 5 'more...'
+ 6 'code...'
+ 7 'to...'
+ 8 'make...'
+ 9 'a...'
+ 10 'long...'
+ 11 'listing...'
+ (Pdb) list
+ 12 'useful...'
+ 13 '...'
+ 14 '...'
+ 15 return foo
+ [EOF]
+ (Pdb) list 1,3
+ 1 -> def test_function_2(foo):
+ 2 import test_pdb
+ 3 test_pdb.do_nothing()
+ (Pdb) list x
+ *** ...
+ (Pdb) next
+ > <doctest test.test_pdb.test_list_commands[0]>(2)test_function_2()
+ -> import test_pdb
+ (Pdb) next
+ > <doctest test.test_pdb.test_list_commands[0]>(3)test_function_2()
+ -> test_pdb.do_nothing()
+ (Pdb) step
+ --Call--
+ > /home/gbr/devel/python/Lib/test/test_pdb.py(260)do_nothing()
+ -> def do_nothing():
+ (Pdb) longlist
+ ... -> def do_nothing():
+ ... pass
+ (Pdb) source do_something
+ ... def do_something():
+ ... print(42)
+ (Pdb) continue
+ """
+
+
def test_pdb_skip_modules():
"""This illustrates the simple case of module skipping.
Modified: python/branches/py3k/Misc/ACKS
==============================================================================
--- python/branches/py3k/Misc/ACKS (original)
+++ python/branches/py3k/Misc/ACKS Fri Jul 30 19:04:28 2010
@@ -180,6 +180,7 @@
Joaquin Cuenca Abela
John Cugini
Tom Culliton
+Antonio Cuni
Brian Curtin
Lisandro Dalcin
Andrew Dalke
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS (original)
+++ python/branches/py3k/Misc/NEWS Fri Jul 30 19:04:28 2010
@@ -475,6 +475,15 @@
Library
-------
+- The pdb command "source" has been added. It displays the source
+ code for a given object, if possible.
+
+- The pdb command "longlist" has been added. It displays the whole
+ source code for the current function.
+
+- Issue #1503502: Make pdb.Pdb easier to subclass by putting message
+ and error output into methods.
+
- Issue #809887: Make the output of pdb's breakpoint deletions more
consistent; emit a message when a breakpoint is enabled or disabled.
1
0
r83286 - in python/branches/py3k/Lib: pdb.py test/test_doctest.py test/test_pdb.py
by georg.brandl 30 Jul '10
by georg.brandl 30 Jul '10
30 Jul '10
Author: georg.brandl
Date: Fri Jul 30 18:00:46 2010
New Revision: 83286
Log:
Several enhancements to pdb and its test suite.
* added basic test for basic commands
* removed duplication of command docs, and moved them to their implementation
* unified and useful display of exceptions
* output messages and errors using overridable methods (also fixes #1503502)
Modified:
python/branches/py3k/Lib/pdb.py
python/branches/py3k/Lib/test/test_doctest.py
python/branches/py3k/Lib/test/test_pdb.py
Modified: python/branches/py3k/Lib/pdb.py
==============================================================================
--- python/branches/py3k/Lib/pdb.py (original)
+++ python/branches/py3k/Lib/pdb.py Fri Jul 30 18:00:46 2010
@@ -62,176 +62,14 @@
Debugger commands
=================
-h(elp)
- Without argument, print the list of available commands. With
- a command name as argument, print help about that command.
-
-w(here)
- Print a stack trace, with the most recent frame at the bottom.
- An arrow indicates the "current frame", which determines the
- context of most commands.
-
-d(own) [count]
- Move the current frame count (default one) levels down in the
- stack trace (to a newer frame).
-
-u(p) [count]
- Move the current frame count (default one) levels up in the
- stack trace (to an older frame).
-
-b(reak) [ ([filename:]lineno | function) [, condition] ]
- With a filename:lineno argument, set a break there. If
- filename is omitted, use the current file. With a function
- name, set a break at the first executable line of that
- function. Without argument, list all breaks. Each breakpoint
- is assigned a number to which all the other breakpoint
- commands refer.
-
- The condition argument, if present, is a string which must
- evaluate to true in order for the breakpoint to be honored.
-
-tbreak [ ([filename:]lineno | function) [, condition] ]
- Temporary breakpoint, which is removed automatically when it
- is first hit. The arguments are the same as for break.
-
-cl(ear) [bpnumber [bpnumber ...] ]
- With a space separated list of breakpoint numbers, clear those
- breakpoints. Without argument, clear all breaks (but first
- ask confirmation).
-
-disable bpnumber [bpnumber ...]
- Disable the breakpoints given as a space separated list of
- breakpoint numbers. Disabling a breakpoint means it cannot
- cause the program to stop execution, but unlike clearing a
- breakpoint, it remains in the list of breakpoints and can be
- (re-)enabled.
-
-enable bpnumber [bpnumber ...]
- Enable the breakpoints specified.
-
-ignore bpnumber [count]
- Set the ignore count for the given breakpoint number. If
- count is omitted, the ignore count is set to 0. A breakpoint
- becomes active when the ignore count is zero. When non-zero,
- the count is decremented each time the breakpoint is reached
- and the breakpoint is not disabled and any associated
- condition evaluates to true.
-
-condition bpnumber [condition]
- Set a new condition for the breakpoint, an expression which
- must evaluate to true before the breakpoint is honored. If
- condition is absent, any existing condition is removed; i.e.,
- the breakpoint is made unconditional.
-
-commands [bpnumber]
- Specify a list of commands for the breakpoint. Type a line
- containing just 'end' to terminate the commands. The commands
- are executed when the breakpoint is hit.
-
- With no breakpoint number argument, refers to the last
- breakpoint set.
-
-s(tep)
- Execute the current line, stop at the first possible occasion
- (either in a function that is called or in the current
- function).
-
-n(ext)
- Continue execution until the next line in the current function
- is reached or it returns.
-
-unt(il) [lineno]
- Without argument, continue execution until the line with a
- number greater than the current one is reached. With a line
- number, continue execution until a line with a number greater
- or equal to that is reached. In both cases, also stop when
- the current frame returns.
-
-j(ump) lineno
- Set the next line that will be executed. Only available in
- the bottom-most frame. This lets you jump back and execute
- code again, or jump forward to skip code that you don't want
- to run.
-
- It should be noted that not all jumps are allowed -- for
- instance it is not possible to jump into the middle of a
- for loop or out of a finally clause.
-
-r(eturn)
- Continue execution until the current function returns.
-
-run [args...]
- Restart the debugged python program. If a string is supplied
- it is splitted with "shlex", and the result is used as the new
- sys.argv. History, breakpoints, actions and debugger options
- are preserved. "restart" is an alias for "run".
-
-c(ont(inue))
- Continue execution, only stop when a breakpoint is encountered.
-
-l(ist) [first [,last]]
- List source code for the current file.
- Without arguments, list 11 lines around the current line
- or continue the previous listing.
- With . as argument, list 11 lines around the current line.
- With one argument, list 11 lines starting at that line.
- With two arguments, list the given range;
- if the second argument is less than the first, it is a count.
-
-a(rgs)
- Print the argument list of the current function.
-
-p expression
- Print the value of the expression.
-
-(!) statement
- Execute the (one-line) statement in the context of the current
- stack frame. The exclamation point can be omitted unless the
- first word of the statement resembles a debugger command. To
- assign to a global variable you must always prefix the command
- with a 'global' command, e.g.:
- (Pdb) global list_options; list_options = ['-l']
- (Pdb)
-
-
-whatis arg
- Print the type of the argument.
-
-alias [name [command]]
- Creates an alias called 'name' that executes 'command'. The
- command must *not* be enclosed in quotes. Replaceable
- parameters can be indicated by %1, %2, and so on, while %* is
- replaced by all the parameters. If no command is given, the
- current alias for name is shown. If no name is given, all
- aliases are listed.
-
- Aliases may be nested and can contain anything that can be
- legally typed at the pdb prompt. Note! You *can* override
- internal pdb commands with aliases! Those internal commands
- are then hidden until the alias is removed. Aliasing is
- recursively applied to the first word of the command line; all
- other words in the line are left alone.
-
- As an example, here are two useful aliases (especially when
- placed in the .pdbrc file):
-
- # Print instance variables (usage "pi classInst")
- alias pi for k in %1.__dict__.keys(): print "%1.",k,"=",%1.__dict__[k]
- # Print instance variables in self
- alias ps pi self
-
-unalias name
- Delete the specified alias.
-
-q(uit)
- Quit from the debugger. The program being executed is aborted.
"""
+# NOTE: the actual command documentation is collected from docstrings of the
+# commands and is appended to __doc__ after the class has been defined.
import sys
import linecache
import cmd
import bdb
-from reprlib import Repr
import os
import re
import pprint
@@ -242,12 +80,6 @@
"""Causes a debugger to be restarted for the debugged python program."""
pass
-# Create a custom safe Repr instance and increase its maxstring.
-# The default of 30 truncates error messages too easily.
-_repr = Repr()
-_repr.maxstring = 200
-_saferepr = _repr.repr
-
__all__ = ["run", "pm", "Pdb", "runeval", "runctx", "runcall", "set_trace",
"post_mortem", "help"]
@@ -374,7 +206,7 @@
if self._wait_for_mainpyfile:
return
if self.stop_here(frame):
- print('--Call--', file=self.stdout)
+ self.message('--Call--')
self.interaction(frame, None)
def user_line(self, frame):
@@ -416,7 +248,7 @@
if self._wait_for_mainpyfile:
return
frame.f_locals['__return__'] = return_value
- print('--Return--', file=self.stdout)
+ self.message('--Return--')
self.interaction(frame, None)
def user_exception(self, frame, exc_info):
@@ -426,8 +258,8 @@
return
exc_type, exc_value, exc_traceback = exc_info
frame.f_locals['__exception__'] = exc_type, exc_value
- exc_type_name = exc_type.__name__
- print(exc_type_name + ':', _saferepr(exc_value), file=self.stdout)
+ self.message(traceback.format_exception_only(exc_type,
+ exc_value)[-1].strip())
self.interaction(frame, exc_traceback)
# General interaction function
@@ -448,7 +280,7 @@
"""
# reproduce the behavior of the standard displayhook, not printing None
if obj is not None:
- print(repr(obj))
+ self.message(repr(obj))
def default(self, line):
if line[:1] == '!': line = line[1:]
@@ -469,11 +301,8 @@
sys.stdin = save_stdin
sys.displayhook = save_displayhook
except:
- t, v = sys.exc_info()[:2]
- if type(t) == type(''):
- exc_type_name = t
- else: exc_type_name = t.__name__
- print('***', exc_type_name + ':', v, file=self.stdout)
+ exc_info = sys.exc_info()[:2]
+ self.error(traceback.format_exception_only(*exc_info)[-1].strip())
def precmd(self, line):
"""Handle alias expansion and ';;' separator."""
@@ -540,25 +369,62 @@
return 1
return
+ # interface abstraction functions
+
+ def message(self, msg):
+ print(msg, file=self.stdout)
+
+ def error(self, msg):
+ print('***', msg, file=self.stdout)
+
# Command definitions, called by cmdloop()
# The argument is the remaining string on the command line
# Return true to exit from the command loop
- do_h = cmd.Cmd.do_help
-
def do_commands(self, arg):
- """Defines a list of commands associated to a breakpoint.
+ """commands [bpnumber]
+ (com) ...
+ (com) end
+ (Pdb)
+
+ Specify a list of commands for breakpoint number bpnumber.
+ The commands themselves are entered on the following lines.
+ Type a line containing just 'end' to terminate the commands.
+ The commands are executed when the breakpoint is hit.
+
+ To remove all commands from a breakpoint, type commands and
+ follow it immediately with end; that is, give no commands.
+
+ With no bpnumber argument, commands refers to the last
+ breakpoint set.
- Those commands will be executed whenever the breakpoint causes
- the program to stop execution."""
+ You can use breakpoint commands to start your program up
+ again. Simply use the continue command, or step, or any other
+ command that resumes execution.
+
+ Specifying any command resuming execution (currently continue,
+ step, next, return, jump, quit and their abbreviations)
+ terminates the command list (as if that command was
+ immediately followed by end). This is because any time you
+ resume execution (even with a simple next or step), you may
+ encounter another breakpoint -- which could have its own
+ command list, leading to ambiguities about which list to
+ execute.
+
+ If you use the 'silent' command in the command list, the usual
+ message about stopping at a breakpoint is not printed. This
+ may be desirable for breakpoints that are to print a specific
+ message and then continue. If none of the other commands
+ print anything, you will see no sign that the breakpoint was
+ reached.
+ """
if not arg:
bnum = len(bdb.Breakpoint.bpbynumber) - 1
else:
try:
bnum = int(arg)
except:
- print("Usage: commands [bnum]\n ...\n end",
- file=self.stdout)
+ self.error("Usage: commands [bnum]\n ...\n end")
return
self.commands_bnum = bnum
self.commands[bnum] = []
@@ -574,13 +440,26 @@
self.prompt = prompt_back
def do_break(self, arg, temporary = 0):
- # break [ ([filename:]lineno | function) [, "condition"] ]
+ """b(reak) [ ([filename:]lineno | function) [, condition] ]
+ Without argument, list all breaks.
+
+ With a line number argument, set a break at this line in the
+ current file. With a function name, set a break at the first
+ executable line of that function. If a second argument is
+ present, it is a string specifying an expression which must
+ evaluate to true before the breakpoint is honored.
+
+ The line number may be prefixed with a filename and a colon,
+ to specify a breakpoint in another file (probably one that
+ hasn't been loaded yet). The file is searched for on
+ sys.path; the .py suffix may be omitted.
+ """
if not arg:
if self.breaks: # There's at least one
- print("Num Type Disp Enb Where", file=self.stdout)
+ self.message("Num Type Disp Enb Where")
for bp in bdb.Breakpoint.bpbynumber:
if bp:
- bp.bpprint(self.stdout)
+ self.message(bp.bpformat())
return
# parse arguments; comma has lowest precedence
# and cannot occur in filename
@@ -599,8 +478,7 @@
filename = arg[:colon].rstrip()
f = self.lookupmodule(filename)
if not f:
- print('*** ', repr(filename), end=' ', file=self.stdout)
- print('not found from sys.path', file=self.stdout)
+ self.error('%r not found from sys.path' % filename)
return
else:
filename = f
@@ -608,7 +486,7 @@
try:
lineno = int(arg)
except ValueError as msg:
- print('*** Bad lineno:', arg, file=self.stdout)
+ self.error('Bad lineno: %s' % arg)
return
else:
# no colon; can be lineno or function
@@ -634,9 +512,8 @@
# last thing to try
(ok, filename, ln) = self.lineinfo(arg)
if not ok:
- print('*** The specified object %r is not a function '
- 'or was not found along sys.path.' % arg,
- file=self.stdout)
+ self.error('The specified object %r is not a function '
+ 'or was not found along sys.path.' % arg)
return
funcname = ok # ok contains a function name
lineno = int(ln)
@@ -647,12 +524,12 @@
if line:
# now set the break point
err = self.set_break(filename, line, temporary, cond, funcname)
- if err: print('***', err, file=self.stdout)
+ if err:
+ self.error(err, file=self.stdout)
else:
bp = self.get_breaks(filename, line)[-1]
- print("Breakpoint %d at %s:%d" % (bp.number,
- bp.file,
- bp.line), file=self.stdout)
+ self.message("Breakpoint %d at %s:%d" %
+ (bp.number, bp.file, bp.line))
# To be overridden in derived debuggers
def defaultFile(self):
@@ -665,6 +542,10 @@
do_b = do_break
def do_tbreak(self, arg):
+ """tbreak [ ([filename:]lineno | function) [, condition] ]
+ Same arguments as break, but sets a temporary breakpoint: it
+ is automatically deleted when first hit.
+ """
self.do_break(arg, 1)
def lineinfo(self, identifier):
@@ -711,40 +592,56 @@
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)
+ self.message('End of file')
return 0
line = line.strip()
# Don't allow setting breakpoint at a blank line
if (not line or (line[0] == '#') or
(line[:3] == '"""') or line[:3] == "'''"):
- print('*** Blank or comment', file=self.stdout)
+ self.error('Blank or comment')
return 0
return lineno
def do_enable(self, arg):
+ """enable bpnumber [bpnumber ...]
+ Enables the breakpoints given as a space separated list of
+ breakpoint numbers.
+ """
args = arg.split()
for i in args:
try:
bp = self.get_bpbynumber(i)
except ValueError as err:
- print('***', err, file=self.stdout)
+ self.error(err)
else:
bp.enable()
- print('Enabled %s' % bp, file=self.stdout)
+ self.message('Enabled %s' % bp)
def do_disable(self, arg):
+ """disable bpnumber [bpnumber ...]
+ Disables the breakpoints given as a space separated list of
+ breakpoint numbers. Disabling a breakpoint means it cannot
+ cause the program to stop execution, but unlike clearing a
+ breakpoint, it remains in the list of breakpoints and can be
+ (re-)enabled.
+ """
args = arg.split()
for i in args:
try:
bp = self.get_bpbynumber(i)
except ValueError as err:
- print('***', err, file=self.stdout)
+ self.error(err)
else:
bp.disable()
- print('Disabled %s' % bp, file=self.stdout)
+ self.message('Disabled %s' % bp)
def do_condition(self, arg):
- # arg is breakpoint number and condition
+ """condition bpnumber [condition]
+ Set a new condition for the breakpoint, an expression which
+ must evaluate to true before the breakpoint is honored. If
+ condition is absent, any existing condition is removed; i.e.,
+ the breakpoint is made unconditional.
+ """
args = arg.split(' ', 1)
try:
cond = args[1]
@@ -753,18 +650,23 @@
try:
bp = self.get_bpbynumber(args[0].strip())
except ValueError as err:
- print('***', err, file=self.stdout)
+ self.error(err)
else:
bp.cond = cond
if not cond:
- print('Breakpoint %d is now unconditional.' % bp.number,
- file=self.stdout)
+ self.message('Breakpoint %d is now unconditional.' % bp.number)
else:
- print('New condition set for breakpoint %d.' % bp.number,
- file=self.stdout)
+ self.message('New condition set for breakpoint %d.' % bp.number)
def do_ignore(self, arg):
- """arg is bp number followed by ignore count."""
+ """ignore bpnumber [count]
+ Set the ignore count for the given breakpoint number. If
+ count is omitted, the ignore count is set to 0. A breakpoint
+ becomes active when the ignore count is zero. When non-zero,
+ the count is decremented each time the breakpoint is reached
+ and the breakpoint is not disabled and any associated
+ condition evaluates to true.
+ """
args = arg.split()
try:
count = int(args[1].strip())
@@ -773,25 +675,27 @@
try:
bp = self.get_bpbynumber(args[0].strip())
except ValueError as err:
- print('***', err, file=self.stdout)
+ self.error(err)
else:
bp.ignore = count
if count > 0:
- reply = 'Will ignore next '
if count > 1:
- reply = reply + '%d crossings' % count
+ countstr = '%d crossings' % count
else:
- reply = reply + '1 crossing'
- print(reply + ' of breakpoint %d.' % bp.number, file=self.stdout)
+ countstr = '1 crossing'
+ self.message('Will ignore next %s of breakpoint %d.' %
+ (countstr, bp.number))
else:
- print('Will stop next time breakpoint %d is reached.'
- % bp.number, file=self.stdout)
+ self.message('Will stop next time breakpoint %d is reached.'
+ % bp.number)
def do_clear(self, arg):
- """Three possibilities, tried in this order:
- clear -> clear all breaks, ask for confirmation
- clear file:lineno -> clear all breaks at file:lineno
- clear bpno bpno ... -> clear breakpoints by number"""
+ """cl(ear) filename:lineno\ncl(ear) [bpnumber [bpnumber...]]
+ With a space separated list of breakpoint numbers, clear
+ those breakpoints. Without argument, clear all breaks (but
+ first ask confirmation). With a filename:lineno argument,
+ clear all breaks at that line in that file.
+ """
if not arg:
try:
reply = input('Clear all breaks? ')
@@ -802,7 +706,7 @@
bplist = [bp for bp in bdb.Breakpoint.bpbynumber if bp]
self.clear_all_breaks()
for bp in bplist:
- print('Deleted %s' % bp, file=self.stdout)
+ self.message('Deleted %s' % bp)
return
if ':' in arg:
# Make sure it works for "clear C:\foo\bar.py:12"
@@ -817,23 +721,28 @@
bplist = self.get_breaks(filename, lineno)
err = self.clear_break(filename, lineno)
if err:
- print('***', err, file=self.stdout)
+ self.error(err)
else:
for bp in bplist:
- print('Deleted %s' % bp, file=self.stdout)
+ self.message('Deleted %s' % bp)
return
numberlist = arg.split()
for i in numberlist:
try:
bp = self.get_bpbynumber(i)
except ValueError as err:
- print('***', err, file=self.stdout)
+ self.error(err)
else:
self.clear_break(bp.file, bp.line)
- print('Deleted %s' % bp, file=self.stdout)
+ self.message('Deleted %s' % bp)
do_cl = do_clear # 'c' is already an abbreviation for 'continue'
def do_where(self, arg):
+ """w(here)
+ Print a stack trace, with the most recent frame at the bottom.
+ An arrow indicates the "current frame", which determines the
+ context of most commands. 'bt' is an alias for this command.
+ """
self.print_stack_trace()
do_w = do_where
do_bt = do_where
@@ -847,13 +756,17 @@
self.lineno = None
def do_up(self, arg):
+ """u(p) [count]
+ Move the current frame count (default one) levels up in the
+ stack trace (to an older frame).
+ """
if self.curindex == 0:
- print('*** Oldest frame', file=self.stdout)
+ self.error('Oldest frame')
return
try:
count = int(arg or 1)
except ValueError:
- print('*** Invalid frame count (%s)' % arg, file=self.stdout)
+ self.error('Invalid frame count (%s)' % arg)
return
if count < 0:
newframe = 0
@@ -863,13 +776,17 @@
do_u = do_up
def do_down(self, arg):
+ """d(own) [count]
+ Move the current frame count (default one) levels down in the
+ stack trace (to a newer frame).
+ """
if self.curindex + 1 == len(self.stack):
- print('*** Newest frame', file=self.stdout)
+ self.error('Newest frame')
return
try:
count = int(arg or 1)
except ValueError:
- print('*** Invalid frame count (%s)' % arg, file=self.stdout)
+ self.error('Invalid frame count (%s)' % arg)
return
if count < 0:
newframe = len(self.stack) - 1
@@ -879,15 +796,22 @@
do_d = do_down
def do_until(self, arg):
+ """unt(il) [lineno]
+ Without argument, continue execution until the line with a
+ number greater than the current one is reached. With a line
+ number, continue execution until a line with a number greater
+ or equal to that is reached. In both cases, also stop when
+ the current frame returns.
+ """
if arg:
try:
lineno = int(arg)
except ValueError:
- print('*** Error in argument:', repr(arg), file=self.stdout)
+ self.error('Error in argument: %r' % arg)
return
if lineno <= self.curframe.f_lineno:
- print('*** "until" line number is smaller than current '
- 'line number', file=self.stdout)
+ self.error('"until" line number is smaller than current '
+ 'line number')
return
else:
lineno = None
@@ -896,45 +820,75 @@
do_unt = do_until
def do_step(self, arg):
+ """s(tep)
+ Execute the current line, stop at the first possible occasion
+ (either in a function that is called or in the current
+ function).
+ """
self.set_step()
return 1
do_s = do_step
def do_next(self, arg):
+ """n(ext)
+ Continue execution until the next line in the current function
+ is reached or it returns.
+ """
self.set_next(self.curframe)
return 1
do_n = do_next
def do_run(self, arg):
- """Restart program by raising an exception to be caught in the main
- debugger loop. If arguments were given, set them in sys.argv."""
+ """run [args...]
+ Restart the debugged python program. If a string is supplied
+ it is splitted with "shlex", and the result is used as the new
+ sys.argv. History, breakpoints, actions and debugger options
+ are preserved. "restart" is an alias for "run".
+ """
if arg:
import shlex
argv0 = sys.argv[0:1]
sys.argv = shlex.split(arg)
sys.argv[:0] = argv0
+ # this is caught in the main debugger loop
raise Restart
do_restart = do_run
def do_return(self, arg):
+ """r(eturn)
+ Continue execution until the current function returns.
+ """
self.set_return(self.curframe)
return 1
do_r = do_return
def do_continue(self, arg):
+ """c(ont(inue))
+ Continue execution, only stop when a breakpoint is encountered.
+ """
self.set_continue()
return 1
do_c = do_cont = do_continue
def do_jump(self, arg):
+ """j(ump) lineno
+ Set the next line that will be executed. Only available in
+ the bottom-most frame. This lets you jump back and execute
+ code again, or jump forward to skip code that you don't want
+ to run.
+
+ It should be noted that not all jumps are allowed -- for
+ instance it is not possible to jump into the middle of a
+ for loop or out of a finally clause.
+ """
if self.curindex + 1 != len(self.stack):
- print("*** You can only jump within the bottom frame", file=self.stdout)
+ self.error('You can only jump within the bottom frame')
return
try:
arg = int(arg)
except ValueError:
- print("*** The 'jump' command requires a line number.", file=self.stdout)
+ self.error("The 'jump' command requires a line number")
else:
try:
# Do the jump, fix up our copy of the stack, and display the
@@ -943,22 +897,30 @@
self.stack[self.curindex] = self.stack[self.curindex][0], arg
self.print_stack_entry(self.stack[self.curindex])
except ValueError as e:
- print('*** Jump failed:', e, file=self.stdout)
+ self.error('Jump failed: %s' % e)
do_j = do_jump
def do_debug(self, arg):
+ """debug code
+ Enter a recursive debugger that steps through the code
+ argument (which is an arbitrary expression or statement to be
+ executed in the current environment).
+ """
sys.settrace(None)
globals = self.curframe.f_globals
locals = self.curframe_locals
p = Pdb(self.completekey, self.stdin, self.stdout)
p.prompt = "(%s) " % self.prompt.strip()
- print("ENTERING RECURSIVE DEBUGGER", file=self.stdout)
+ self.message("ENTERING RECURSIVE DEBUGGER")
sys.call_tracing(p.run, (arg, globals, locals))
- print("LEAVING RECURSIVE DEBUGGER", file=self.stdout)
+ self.message("LEAVING RECURSIVE DEBUGGER")
sys.settrace(self.trace_dispatch)
self.lastcmd = p.lastcmd
def do_quit(self, arg):
+ """q(uit)\nexit
+ Quit from the debugger. The program being executed is aborted.
+ """
self._user_requested_quit = 1
self.set_quit()
return 1
@@ -967,12 +929,18 @@
do_exit = do_quit
def do_EOF(self, arg):
- print(file=self.stdout)
+ """EOF
+ Handles the receipt of EOF as a command.
+ """
+ self.message('')
self._user_requested_quit = 1
self.set_quit()
return 1
def do_args(self, arg):
+ """a(rgs)
+ Print the argument list of the current function.
+ """
co = self.curframe.f_code
dict = self.curframe_locals
n = co.co_argcount
@@ -980,60 +948,76 @@
if co.co_flags & 8: n = n+1
for i in range(n):
name = co.co_varnames[i]
- print(name, '=', end=' ', file=self.stdout)
- if name in dict: print(dict[name], file=self.stdout)
- else: print("*** undefined ***", file=self.stdout)
+ if name in dict:
+ self.message('%s = %r' % (name, dict[name]))
+ else:
+ self.message('%s = *** undefined ***' % (name,))
do_a = do_args
def do_retval(self, arg):
+ """retval
+ Print the return value for the last return of a function.
+ """
if '__return__' in self.curframe_locals:
- print(self.curframe_locals['__return__'], file=self.stdout)
+ self.message(repr(self.curframe_locals['__return__']))
else:
- print('*** Not yet returned!', file=self.stdout)
+ self.error('Not yet returned!')
do_rv = do_retval
def _getval(self, arg):
try:
return eval(arg, self.curframe.f_globals, self.curframe_locals)
except:
- t, v = sys.exc_info()[:2]
- if isinstance(t, str):
- exc_type_name = t
- else: exc_type_name = t.__name__
- print('***', exc_type_name + ':', repr(v), file=self.stdout)
+ exc_info = sys.exc_info()[:2]
+ self.error(traceback.format_exception_only(*exc_info)[-1].strip())
raise
def do_p(self, arg):
+ """p(rint) expression
+ Print the value of the expression.
+ """
try:
- print(repr(self._getval(arg)), file=self.stdout)
+ self.message(repr(self._getval(arg)))
except:
pass
# make "print" an alias of "p" since print isn't a Python statement anymore
do_print = do_p
def do_pp(self, arg):
+ """pp expression
+ Pretty-print the value of the expression.
+ """
try:
- pprint.pprint(self._getval(arg), self.stdout)
+ self.message(pprint.pformat(self._getval(arg)))
except:
pass
def do_list(self, arg):
+ """l(ist) [first [,last] | .]
+ List source code for the current file.
+ Without arguments, list 11 lines around the current line
+ or continue the previous listing.
+ With . as argument, list 11 lines around the current line.
+ With one argument, list 11 lines starting at that line.
+ With two arguments, list the given range;
+ if the second argument is less than the first, it is a count.
+ """
self.lastcmd = 'list'
last = None
if arg and arg != '.':
try:
- x = eval(arg, {}, {})
- if type(x) == type(()):
- first, last = x
- first = int(first)
- last = int(last)
+ if ',' in arg:
+ first, last = arg.split(',')
+ first = int(first.strip())
+ last = int(last.strip())
if last < first:
- # Assume it's a count
+ # assume it's a count
last = first + last
else:
- first = max(1, int(x) - 5)
- except:
- print('*** Error in argument:', repr(arg), file=self.stdout)
+ first = int(arg.strip())
+ first = max(1, first - 5)
+ except ValueError:
+ self.error('Error in argument: %r' % arg)
return
elif self.lineno is None or arg == '.':
first = max(1, self.curframe.f_lineno - 5)
@@ -1048,7 +1032,7 @@
line = linecache.getline(filename, lineno,
self.curframe.f_globals)
if not line:
- print('[EOF]', file=self.stdout)
+ self.message('[EOF]')
break
else:
s = repr(lineno).rjust(3)
@@ -1057,58 +1041,90 @@
else: s = s + ' '
if lineno == self.curframe.f_lineno:
s = s + '->'
- print(s + '\t' + line, end='', file=self.stdout)
+ self.message(s + '\t' + line.rstrip())
self.lineno = lineno
except KeyboardInterrupt:
pass
do_l = do_list
def do_whatis(self, arg):
+ """whatis arg
+ Print the type of the argument.
+ """
try:
- value = eval(arg, self.curframe.f_globals,
- self.curframe_locals)
+ value = self._getval(arg)
except:
- t, v = sys.exc_info()[:2]
- if type(t) == type(''):
- exc_type_name = t
- else: exc_type_name = t.__name__
- print('***', exc_type_name + ':', repr(v), file=self.stdout)
+ # _getval() already printed the error
return
code = None
# Is it a function?
- try: code = value.__code__
- except: pass
+ try:
+ code = value.__code__
+ except Exception:
+ pass
if code:
- print('Function', code.co_name, file=self.stdout)
+ self.message('Function %s' % code.co_name)
return
# Is it an instance method?
- try: code = value.__func__.__code__
- except: pass
+ try:
+ code = value.__func__.__code__
+ except Exception:
+ pass
if code:
- print('Method', code.co_name, file=self.stdout)
+ self.message('Method %s' % code.co_name)
+ return
+ # Is it a class?
+ if value.__class__ is type:
+ self.message('Class %s.%s' % (value.__module__, value.__name__))
return
# None of the above...
- print(type(value), file=self.stdout)
+ self.message(type(value))
def do_alias(self, arg):
+ """alias [name [command [parameter parameter ...] ]]
+ Create an alias called 'name' that executes 'command'. The
+ command must *not* be enclosed in quotes. Replaceable
+ parameters can be indicated by %1, %2, and so on, while %* is
+ replaced by all the parameters. If no command is given, the
+ current alias for name is shown. If no name is given, all
+ aliases are listed.
+
+ Aliases may be nested and can contain anything that can be
+ legally typed at the pdb prompt. Note! You *can* override
+ internal pdb commands with aliases! Those internal commands
+ are then hidden until the alias is removed. Aliasing is
+ recursively applied to the first word of the command line; all
+ other words in the line are left alone.
+
+ As an example, here are two useful aliases (especially when
+ placed in the .pdbrc file):
+
+ # Print instance variables (usage "pi classInst")
+ alias pi for k in %1.__dict__.keys(): print "%1.",k,"=",%1.__dict__[k]
+ # Print instance variables in self
+ alias ps pi self
+ """
args = arg.split()
if len(args) == 0:
keys = sorted(self.aliases.keys())
for alias in keys:
- print("%s = %s" % (alias, self.aliases[alias]), file=self.stdout)
+ self.message("%s = %s" % (alias, self.aliases[alias]))
return
if args[0] in self.aliases and len(args) == 1:
- print("%s = %s" % (args[0], self.aliases[args[0]]), file=self.stdout)
+ self.message("%s = %s" % (args[0], self.aliases[args[0]]))
else:
self.aliases[args[0]] = ' '.join(args[1:])
def do_unalias(self, arg):
+ """unalias name
+ Delete the specified alias.
+ """
args = arg.split()
if len(args) == 0: return
if args[0] in self.aliases:
del self.aliases[args[0]]
- #list of all the commands making the program resume execution.
+ # List of all the commands making the program resume execution.
commands_resuming = ['do_continue', 'do_step', 'do_next', 'do_return',
'do_quit', 'do_jump']
@@ -1130,292 +1146,53 @@
def print_stack_entry(self, frame_lineno, prompt_prefix=line_prefix):
frame, lineno = frame_lineno
if frame is self.curframe:
- print('>', end=' ', file=self.stdout)
+ prefix = '> '
else:
- print(' ', end=' ', file=self.stdout)
- print(self.format_stack_entry(frame_lineno,
- prompt_prefix), file=self.stdout)
-
-
- # Help methods (derived from docstring)
-
- def help_help(self):
- self.help_h()
-
- def help_h(self):
- print("""h(elp)
-Without argument, print the list of available commands.
-With a command name as argument, print help about that command
-"help pdb" shows the full pdb documentation
-"help exec" gives help on the ! command""", file=self.stdout)
-
- def help_where(self):
- self.help_w()
-
- def help_w(self):
- print("""w(here)
-Print a stack trace, with the most recent frame at the bottom.
-An arrow indicates the "current frame", which determines the
-context of most commands. 'bt' is an alias for this command.""", file=self.stdout)
-
- help_bt = help_w
-
- def help_down(self):
- self.help_d()
-
- def help_d(self):
- print("""d(own)
-Move the current frame one level down in the stack trace
-(to a newer frame).""", file=self.stdout)
-
- def help_up(self):
- self.help_u()
-
- def help_u(self):
- print("""u(p)
-Move the current frame one level up in the stack trace
-(to an older frame).""", file=self.stdout)
-
- def help_break(self):
- self.help_b()
-
- def help_b(self):
- print("""b(reak) ([file:]lineno | function) [, condition]
-With a line number argument, set a break there in the current
-file. With a function name, set a break at first executable line
-of that function. Without argument, list all breaks. If a second
-argument is present, it is a string specifying an expression
-which must evaluate to true before the breakpoint is honored.
-
-The line number may be prefixed with a filename and a colon,
-to specify a breakpoint in another file (probably one that
-hasn't been loaded yet). The file is searched for on sys.path;
-the .py suffix may be omitted.""", file=self.stdout)
-
- def help_clear(self):
- self.help_cl()
-
- def help_cl(self):
- print("cl(ear) filename:lineno", file=self.stdout)
- print("""cl(ear) [bpnumber [bpnumber...]]
-With a space separated list of breakpoint numbers, clear
-those breakpoints. Without argument, clear all breaks (but
-first ask confirmation). With a filename:lineno argument,
-clear all breaks at that line in that file.""", file=self.stdout)
-
- def help_tbreak(self):
- print("""tbreak same arguments as break, but breakpoint is
-removed when first hit.""", file=self.stdout)
-
- def help_enable(self):
- print("""enable bpnumber [bpnumber ...]
-Enables the breakpoints given as a space separated list of
-bp numbers.""", file=self.stdout)
-
- def help_disable(self):
- print("""disable bpnumber [bpnumber ...]
-Disables the breakpoints given as a space separated list of
-bp numbers.""", file=self.stdout)
-
- def help_ignore(self):
- print("""ignore bpnumber count
-Sets the ignore count for the given breakpoint number. A breakpoint
-becomes active when the ignore count is zero. When non-zero, the
-count is decremented each time the breakpoint is reached and the
-breakpoint is not disabled and any associated condition evaluates
-to true.""", file=self.stdout)
-
- def help_condition(self):
- print("""condition bpnumber str_condition
-str_condition is a string specifying an expression which
-must evaluate to true before the breakpoint is honored.
-If str_condition is absent, any existing condition is removed;
-i.e., the breakpoint is made unconditional.""", file=self.stdout)
-
- def help_step(self):
- self.help_s()
-
- def help_s(self):
- print("""s(tep)
-Execute the current line, stop at the first possible occasion
-(either in a function that is called or in the current function).""", file=self.stdout)
-
- def help_until(self):
- self.help_unt()
-
- def help_unt(self):
- print("""unt(il)
-Continue execution until the line with a number greater than the current
-one is reached or until the current frame returns""")
-
- def help_next(self):
- self.help_n()
-
- def help_n(self):
- print("""n(ext)
-Continue execution until the next line in the current function
-is reached or it returns.""", file=self.stdout)
-
- def help_return(self):
- self.help_r()
-
- def help_r(self):
- print("""r(eturn)
-Continue execution until the current function returns.""", file=self.stdout)
-
- def help_continue(self):
- self.help_c()
-
- def help_cont(self):
- self.help_c()
-
- def help_c(self):
- print("""c(ont(inue))
-Continue execution, only stop when a breakpoint is encountered.""", file=self.stdout)
-
- def help_jump(self):
- self.help_j()
-
- def help_j(self):
- print("""j(ump) lineno
-Set the next line that will be executed.""", file=self.stdout)
-
- def help_debug(self):
- print("""debug code
-Enter a recursive debugger that steps through the code argument
-(which is an arbitrary expression or statement to be executed
-in the current environment).""", file=self.stdout)
-
- def help_list(self):
- self.help_l()
-
- def help_l(self):
- print("""l(ist) [first [,last]]
-List source code for the current file.
-Without arguments, list 11 lines around the current line
-or continue the previous listing.
-With one argument, list 11 lines starting at that line.
-With two arguments, list the given range;
-if the second argument is less than the first, it is a count.""", file=self.stdout)
-
- def help_args(self):
- self.help_a()
-
- def help_a(self):
- print("""a(rgs)
-Print the arguments of the current function.""", file=self.stdout)
-
- def help_p(self):
- print("""p(rint) expression
-Print the value of the expression.""", file=self.stdout)
-
- def help_pp(self):
- print("""pp expression
-Pretty-print the value of the expression.""", file=self.stdout)
+ prefix = ' '
+ self.message(prefix +
+ self.format_stack_entry(frame_lineno, prompt_prefix))
+
+ # Provide help
+
+ def do_help(self, arg):
+ """h(elp)
+ Without argument, print the list of available commands.
+ With a command name as argument, print help about that command.
+ "help pdb" shows the full pdb documentation.
+ "help exec" gives help on the ! command.
+ """
+ if not arg:
+ return cmd.Cmd.do_help(self, arg)
+ try:
+ try:
+ topic = getattr(self, 'help_' + arg)
+ return topic()
+ except AttributeError:
+ command = getattr(self, 'do_' + arg)
+ except AttributeError:
+ self.error('No help for %r' % arg)
+ else:
+ self.message(command.__doc__.rstrip())
+
+ do_h = do_help
def help_exec(self):
- print("""(!) statement
-Execute the (one-line) statement in the context of
-the current stack frame.
-The exclamation point can be omitted unless the first word
-of the statement resembles a debugger command.
-To assign to a global variable you must always prefix the
-command with a 'global' command, e.g.:
-(Pdb) global list_options; list_options = ['-l']
-(Pdb)""", file=self.stdout)
-
- def help_run(self):
- print("""run [args...]
-Restart the debugged python program. If a string is supplied, it is
-splitted with "shlex" and the result is used as the new sys.argv.
-History, breakpoints, actions and debugger options are preserved.
-"restart" is an alias for "run".""")
-
- help_restart = help_run
-
- def help_quit(self):
- self.help_q()
-
- def help_q(self):
- print("""q(uit) or exit - Quit from the debugger.
-The program being executed is aborted.""", file=self.stdout)
-
- help_exit = help_q
-
- def help_whatis(self):
- print("""whatis arg
-Prints the type of the argument.""", file=self.stdout)
-
- def help_EOF(self):
- print("""EOF
-Handles the receipt of EOF as a command.""", file=self.stdout)
-
- def help_alias(self):
- print("""alias [name [command [parameter parameter ...] ]]
-Creates an alias called 'name' the executes 'command'. The command
-must *not* be enclosed in quotes. Replaceable parameters are
-indicated by %1, %2, and so on, while %* is replaced by all the
-parameters. If no command is given, the current alias for name
-is shown. If no name is given, all aliases are listed.
-
-Aliases may be nested and can contain anything that can be
-legally typed at the pdb prompt. Note! You *can* override
-internal pdb commands with aliases! Those internal commands
-are then hidden until the alias is removed. Aliasing is recursively
-applied to the first word of the command line; all other words
-in the line are left alone.
-
-Some useful aliases (especially when placed in the .pdbrc file) are:
-
-#Print instance variables (usage "pi classInst")
-alias pi for k in %1.__dict__.keys(): print "%1.",k,"=",%1.__dict__[k]
-
-#Print instance variables in self
-alias ps pi self
-""", file=self.stdout)
-
- def help_unalias(self):
- print("""unalias name
-Deletes the specified alias.""", file=self.stdout)
-
- def help_commands(self):
- print("""commands [bpnumber]
-(com) ...
-(com) end
-(Pdb)
-
-Specify a list of commands for breakpoint number bpnumber. The
-commands themselves appear on the following lines. Type a line
-containing just 'end' to terminate the commands.
-
-To remove all commands from a breakpoint, type commands and
-follow it immediately with end; that is, give no commands.
-
-With no bpnumber argument, commands refers to the last
-breakpoint set.
-
-You can use breakpoint commands to start your program up again.
-Simply use the continue command, or step, or any other
-command that resumes execution.
-
-Specifying any command resuming execution (currently continue,
-step, next, return, jump, quit and their abbreviations) terminates
-the command list (as if that command was immediately followed by end).
-This is because any time you resume execution
-(even with a simple next or step), you may encounter
-another breakpoint--which could have its own command list, leading to
-ambiguities about which list to execute.
-
- If you use the 'silent' command in the command list, the
-usual message about stopping at a breakpoint is not printed. This may
-be desirable for breakpoints that are to print a specific message and
-then continue. If none of the other commands print anything, you
-see no sign that the breakpoint was reached.
-""", file=self.stdout)
+ """(!) statement
+ Execute the (one-line) statement in the context of the current
+ stack frame. The exclamation point can be omitted unless the
+ first word of the statement resembles a debugger command. To
+ assign to a global variable you must always prefix the command
+ with a 'global' command, e.g.:
+ (Pdb) global list_options; list_options = ['-l']
+ (Pdb)
+ """
+ self.message(self.help_exec.__doc__.strip())
def help_pdb(self):
help()
+ # other helper functions
+
def lookupmodule(self, filename):
"""Helper function for break/clear parsing -- may be overridden.
@@ -1466,6 +1243,22 @@
(fp.read(), self.mainpyfile)
self.run(statement)
+# Collect all command help into docstring
+
+# unfortunately we can't guess this order from the class definition
+_help_order = [
+ 'help', 'where', 'down', 'up', 'break', 'tbreak', 'clear', 'disable',
+ 'enable', 'ignore', 'condition', 'commands', 'step', 'next', 'until',
+ 'jump', 'return', 'retval', 'run', 'continue', 'list', 'args', 'print',
+ 'whatis', 'alias', 'unalias', 'quit',
+]
+
+for _command in _help_order:
+ __doc__ += getattr(Pdb, 'do_' + _command).__doc__.strip() + '\n\n'
+__doc__ += Pdb.help_exec.__doc__
+
+del _help_order, _command
+
# Simplified interface
def run(statement, globals=None, locals=None):
@@ -1492,9 +1285,9 @@
# sys.exc_info() returns (type, value, traceback) if an exception is
# being handled, otherwise it returns None
t = sys.exc_info()[2]
- if t is None:
- raise ValueError("A valid traceback must be passed if no "
- "exception is being handled")
+ if t is None:
+ raise ValueError("A valid traceback must be passed if no "
+ "exception is being handled")
p = Pdb()
p.reset()
Modified: python/branches/py3k/Lib/test/test_doctest.py
==============================================================================
--- python/branches/py3k/Lib/test/test_doctest.py (original)
+++ python/branches/py3k/Lib/test/test_doctest.py Fri Jul 30 18:00:46 2010
@@ -1898,7 +1898,7 @@
> <doctest foo[1]>(1)<module>()
-> calls_set_trace()
(Pdb) print(foo)
- *** NameError: NameError("name 'foo' is not defined",)
+ *** NameError: name 'foo' is not defined
(Pdb) continue
TestResults(failed=0, attempted=2)
"""
Modified: python/branches/py3k/Lib/test/test_pdb.py
==============================================================================
--- python/branches/py3k/Lib/test/test_pdb.py (original)
+++ python/branches/py3k/Lib/test/test_pdb.py Fri Jul 30 18:00:46 2010
@@ -54,6 +54,209 @@
"""
+def test_pdb_basic_commands():
+ """Test the basic commands of pdb.
+
+ >>> def test_function_2(foo, bar='default'):
+ ... print(foo)
+ ... for i in range(5):
+ ... print(i)
+ ... print(bar)
+ ... for i in range(10):
+ ... never_executed
+ ... print('after for')
+ ... print('...')
+ ... return foo.upper()
+
+ >>> def test_function():
+ ... import pdb; pdb.Pdb().set_trace()
+ ... ret = test_function_2('baz')
+ ... print(ret)
+
+ >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
+ ... 'step', # entering the function call
+ ... 'args', # display function args
+ ... 'list', # list function source
+ ... 'bt', # display backtrace
+ ... 'up', # step up to test_function()
+ ... 'down', # step down to test_function_2() again
+ ... 'next', # stepping to print(foo)
+ ... 'next', # stepping to the for loop
+ ... 'step', # stepping into the for loop
+ ... 'until', # continuing until out of the for loop
+ ... 'next', # executing the print(bar)
+ ... 'jump 8', # jump over second for loop
+ ... 'return', # return out of function
+ ... 'retval', # display return value
+ ... 'continue',
+ ... ]):
+ ... test_function()
+ > <doctest test.test_pdb.test_pdb_basic_commands[1]>(3)test_function()
+ -> ret = test_function_2('baz')
+ (Pdb) step
+ --Call--
+ > <doctest test.test_pdb.test_pdb_basic_commands[0]>(1)test_function_2()
+ -> def test_function_2(foo, bar='default'):
+ (Pdb) args
+ foo = 'baz'
+ bar = 'default'
+ (Pdb) list
+ 1 -> def test_function_2(foo, bar='default'):
+ 2 print(foo)
+ 3 for i in range(5):
+ 4 print(i)
+ 5 print(bar)
+ 6 for i in range(10):
+ 7 never_executed
+ 8 print('after for')
+ 9 print('...')
+ 10 return foo.upper()
+ [EOF]
+ (Pdb) bt
+ ...
+ <doctest test.test_pdb.test_pdb_basic_commands[2]>(18)<module>()
+ -> test_function()
+ <doctest test.test_pdb.test_pdb_basic_commands[1]>(3)test_function()
+ -> ret = test_function_2('baz')
+ > <doctest test.test_pdb.test_pdb_basic_commands[0]>(1)test_function_2()
+ -> def test_function_2(foo, bar='default'):
+ (Pdb) up
+ > <doctest test.test_pdb.test_pdb_basic_commands[1]>(3)test_function()
+ -> ret = test_function_2('baz')
+ (Pdb) down
+ > <doctest test.test_pdb.test_pdb_basic_commands[0]>(1)test_function_2()
+ -> def test_function_2(foo, bar='default'):
+ (Pdb) next
+ > <doctest test.test_pdb.test_pdb_basic_commands[0]>(2)test_function_2()
+ -> print(foo)
+ (Pdb) next
+ baz
+ > <doctest test.test_pdb.test_pdb_basic_commands[0]>(3)test_function_2()
+ -> for i in range(5):
+ (Pdb) step
+ > <doctest test.test_pdb.test_pdb_basic_commands[0]>(4)test_function_2()
+ -> print(i)
+ (Pdb) until
+ 0
+ 1
+ 2
+ 3
+ 4
+ > <doctest test.test_pdb.test_pdb_basic_commands[0]>(5)test_function_2()
+ -> print(bar)
+ (Pdb) next
+ default
+ > <doctest test.test_pdb.test_pdb_basic_commands[0]>(6)test_function_2()
+ -> for i in range(10):
+ (Pdb) jump 8
+ > <doctest test.test_pdb.test_pdb_basic_commands[0]>(8)test_function_2()
+ -> print('after for')
+ (Pdb) return
+ after for
+ ...
+ --Return--
+ > <doctest test.test_pdb.test_pdb_basic_commands[0]>(10)test_function_2()->'BAZ'
+ -> return foo.upper()
+ (Pdb) retval
+ 'BAZ'
+ (Pdb) continue
+ BAZ
+ """
+
+
+def test_pdb_breakpoint_commands():
+ """Test basic commands related to breakpoints.
+
+ >>> def test_function():
+ ... import pdb; pdb.Pdb().set_trace()
+ ... print(1)
+ ... print(2)
+ ... print(3)
+ ... print(4)
+
+ First, need to clear bdb state that might be left over from previous tests.
+ Otherwise, the new breakpoints might get assigned different numbers.
+
+ >>> from bdb import Breakpoint
+ >>> Breakpoint.next = 1
+ >>> Breakpoint.bplist = {}
+ >>> Breakpoint.bpbynumber = [None]
+
+ Now test the breakpoint commands. NORMALIZE_WHITESPACE is needed because
+ the breakpoint list outputs a tab for the "stop only" and "ignore next"
+ lines, which we don't want to put in here.
+
+ >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE
+ ... 'break 3',
+ ... 'disable 1',
+ ... 'ignore 1 10',
+ ... 'condition 1 1 < 2',
+ ... 'break 4',
+ ... 'break',
+ ... 'condition 1',
+ ... 'enable 1',
+ ... 'clear 1',
+ ... 'commands 2',
+ ... 'print 42',
+ ... 'end',
+ ... 'continue', # will stop at breakpoint 2 (line 4)
+ ... 'clear', # clear all!
+ ... 'y',
+ ... 'tbreak 5',
+ ... 'continue', # will stop at temporary breakpoint
+ ... 'break', # make sure breakpoint is gone
+ ... 'continue',
+ ... ]):
+ ... test_function()
+ > <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>(3)test_function()
+ -> print(1)
+ (Pdb) break 3
+ Breakpoint 1 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:3
+ (Pdb) disable 1
+ Disabled breakpoint 1 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:3
+ (Pdb) ignore 1 10
+ Will ignore next 10 crossings of breakpoint 1.
+ (Pdb) condition 1 1 < 2
+ New condition set for breakpoint 1.
+ (Pdb) break 4
+ Breakpoint 2 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:4
+ (Pdb) break
+ Num Type Disp Enb Where
+ 1 breakpoint keep no at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:3
+ stop only if 1 < 2
+ ignore next 10 hits
+ 2 breakpoint keep yes at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:4
+ (Pdb) condition 1
+ Breakpoint 1 is now unconditional.
+ (Pdb) enable 1
+ Enabled breakpoint 1 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:3
+ (Pdb) clear 1
+ Deleted breakpoint 1 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:3
+ (Pdb) commands 2
+ (com) print 42
+ (com) end
+ (Pdb) continue
+ 1
+ 42
+ > <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>(4)test_function()
+ -> print(2)
+ (Pdb) clear
+ Clear all breaks? y
+ Deleted breakpoint 2 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:4
+ (Pdb) tbreak 5
+ Breakpoint 3 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:5
+ (Pdb) continue
+ 2
+ Deleted breakpoint 3 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:5
+ > <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>(5)test_function()
+ -> print(3)
+ (Pdb) break
+ (Pdb) continue
+ 3
+ 4
+ """
+
+
def test_pdb_skip_modules():
"""This illustrates the simple case of module skipping.
@@ -167,84 +370,6 @@
"""
-def test_pdb_breakpoints():
- """Test handling of breakpoints.
-
- >>> def test_function():
- ... import pdb; pdb.Pdb().set_trace()
- ... print(1)
- ... print(2)
- ... print(3)
- ... print(4)
-
- First, need to clear bdb state that might be left over from previous tests.
- Otherwise, the new breakpoints might get assigned different numbers.
-
- >>> from bdb import Breakpoint
- >>> Breakpoint.next = 1
- >>> Breakpoint.bplist = {}
- >>> Breakpoint.bpbynumber = [None]
-
- Now test the breakpoint commands. NORMALIZE_WHITESPACE is needed because
- the breakpoint list outputs a tab for the "stop only" and "ignore next"
- lines, which we don't want to put in here.
-
- >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE
- ... 'break 3',
- ... 'disable 1',
- ... 'ignore 1 10',
- ... 'condition 1 1 < 2',
- ... 'break 4',
- ... 'break',
- ... 'condition 1',
- ... 'enable 1',
- ... 'clear 1',
- ... 'commands 2',
- ... 'print 42',
- ... 'end',
- ... 'continue', # will stop at breakpoint 2
- ... 'continue',
- ... ]):
- ... test_function()
- > <doctest test.test_pdb.test_pdb_breakpoints[0]>(3)test_function()
- -> print(1)
- (Pdb) break 3
- Breakpoint 1 at <doctest test.test_pdb.test_pdb_breakpoints[0]>:3
- (Pdb) disable 1
- Disabled breakpoint 1 at <doctest test.test_pdb.test_pdb_breakpoints[0]>:3
- (Pdb) ignore 1 10
- Will ignore next 10 crossings of breakpoint 1.
- (Pdb) condition 1 1 < 2
- New condition set for breakpoint 1.
- (Pdb) break 4
- Breakpoint 2 at <doctest test.test_pdb.test_pdb_breakpoints[0]>:4
- (Pdb) break
- Num Type Disp Enb Where
- 1 breakpoint keep no at <doctest test.test_pdb.test_pdb_breakpoints[0]>:3
- stop only if 1 < 2
- ignore next 10 hits
- 2 breakpoint keep yes at <doctest test.test_pdb.test_pdb_breakpoints[0]>:4
- (Pdb) condition 1
- Breakpoint 1 is now unconditional.
- (Pdb) enable 1
- Enabled breakpoint 1 at <doctest test.test_pdb.test_pdb_breakpoints[0]>:3
- (Pdb) clear 1
- Deleted breakpoint 1 at <doctest test.test_pdb.test_pdb_breakpoints[0]>:3
- (Pdb) commands 2
- (com) print 42
- (com) end
- (Pdb) continue
- 1
- 42
- > <doctest test.test_pdb.test_pdb_breakpoints[0]>(4)test_function()
- -> print(2)
- (Pdb) continue
- 2
- 3
- 4
- """
-
-
def pdb_invoke(method, arg):
"""Run pdb.method(arg)."""
import pdb; getattr(pdb, method)(arg)
1
0