Issue #11996: libpython (gdb), replace "py-bt" command by "py-bt-full" and add

a smarter "py-bt" command printing a classic Python traceback.
This commit is contained in:
Victor Stinner 2011-05-13 17:40:15 +02:00
parent 23157e5ddc
commit e670c889cc
3 changed files with 61 additions and 2 deletions

View File

@ -611,12 +611,29 @@ $''')
$''')
class PyBtTests(DebuggerTests):
def test_basic_command(self):
def test_bt(self):
'Verify that the "py-bt" command works'
bt = self.get_stack_trace(script=self.get_sample_script(),
cmds_after_breakpoint=['py-bt'])
self.assertMultilineMatches(bt,
r'''^.*
Traceback \(most recent call first\):
File ".*gdb_sample.py", line 10, in baz
id\(42\)
File ".*gdb_sample.py", line 7, in bar
baz\(a, b, c\)
File ".*gdb_sample.py", line 4, in foo
bar\(a, b, c\)
File ".*gdb_sample.py", line 12, in <module>
foo\(1, 2, 3\)
''')
def test_bt_full(self):
'Verify that the "py-bt-full" command works'
bt = self.get_stack_trace(script=self.get_sample_script(),
cmds_after_breakpoint=['py-bt-full'])
self.assertMultilineMatches(bt,
r'''^.*
#[0-9]+ Frame 0x[0-9a-f]+, for file .*gdb_sample.py, line 7, in bar \(a=1, b=2, c=3\)
baz\(a, b, c\)
#[0-9]+ Frame 0x[0-9a-f]+, for file .*gdb_sample.py, line 4, in foo \(a=1, b=2, c=3\)

View File

@ -359,6 +359,9 @@ IDLE
Tools/Demos
-----------
- Issue #11996: libpython (gdb), replace "py-bt" command by "py-bt-full" and
add a smarter "py-bt" command printing a classic Python traceback.
- Issue #11179: Make ccbench work under Python 3.1 and 2.7 again.
Extension Modules

View File

@ -931,6 +931,15 @@ class PyFrameObjectPtr(PyObjectPtr):
out.write(')')
def print_traceback(self):
if self.is_optimized_out():
sys.stdout.write(' (frame information optimized out)\n')
visited = set()
sys.stdout.write(' File "%s", line %i, in %s\n'
% (self.co_filename.proxyval(visited),
self.current_line_num(),
self.co_name.proxyval(visited)))
class PySetObjectPtr(PyObjectPtr):
_typename = 'PySetObject'
@ -1427,6 +1436,17 @@ class Frame(object):
else:
sys.stdout.write('#%i\n' % self.get_index())
def print_traceback(self):
if self.is_evalframeex():
pyop = self.get_pyop()
if pyop:
pyop.print_traceback()
sys.stdout.write(' %s\n' % pyop.current_line().strip())
else:
sys.stdout.write(' (unable to read python frame information)\n')
else:
sys.stdout.write(' (not a python frame)\n')
class PyList(gdb.Command):
'''List the current Python source code, if any
@ -1551,6 +1571,24 @@ if hasattr(gdb.Frame, 'select'):
PyUp()
PyDown()
class PyBacktraceFull(gdb.Command):
'Display the current python frame and all the frames within its call stack (if any)'
def __init__(self):
gdb.Command.__init__ (self,
"py-bt-full",
gdb.COMMAND_STACK,
gdb.COMPLETE_NONE)
def invoke(self, args, from_tty):
frame = Frame.get_selected_python_frame()
while frame:
if frame.is_evalframeex():
frame.print_summary()
frame = frame.older()
PyBacktraceFull()
class PyBacktrace(gdb.Command):
'Display the current python frame and all the frames within its call stack (if any)'
def __init__(self):
@ -1561,10 +1599,11 @@ class PyBacktrace(gdb.Command):
def invoke(self, args, from_tty):
sys.stdout.write('Traceback (most recent call first):\n')
frame = Frame.get_selected_python_frame()
while frame:
if frame.is_evalframeex():
frame.print_summary()
frame.print_traceback()
frame = frame.older()
PyBacktrace()