Index: Tools/gdb/libpython.py =================================================================== --- Tools/gdb/libpython.py (revision 80091) +++ Tools/gdb/libpython.py (working copy) @@ -1097,6 +1097,11 @@ register (gdb.current_objfile ()) + +# Unfortunately, the exact API exposed by the gdb module varies somewhat +# from build to build +# See http://bugs.python.org/issue8279?#msg102276 + class Frame(object): ''' Wrapper for gdb.Frame, adding various methods @@ -1119,7 +1124,16 @@ return None def select(self): + '''If supported, select this frame and return True; return False if unsupported + + Not all builds have a gdb.Frame.select method; seems to be present on Fedora 12 + onwards, but absent on Ubuntu buildbot''' + if not hasattr(self._gdbframe, 'select'): + print ('Unable to select frame: ' + 'this build of gdb does not expose a gdb.Frame.select method') + return False self._gdbframe.select() + return True def get_index(self): '''Calculate index of frame, starting at 0 for the newest frame within @@ -1133,8 +1147,9 @@ return index def is_evalframeex(self): + '''Is this a PyEval_EvalFrameEx frame?''' if self._gdbframe.function(): - if self._gdbframe.function().name == 'PyEval_EvalFrameEx': + if self._gdbframe.name() == 'PyEval_EvalFrameEx': ''' I believe we also need to filter on the inline struct frame_id.inline_depth, only regarding frames with @@ -1271,8 +1286,8 @@ if iter_frame.is_evalframeex(): # Result: - iter_frame.select() - iter_frame.print_summary() + if iter_frame.select(): + iter_frame.print_summary() return frame = iter_frame Index: Lib/test/test_gdb.py =================================================================== --- Lib/test/test_gdb.py (revision 80091) +++ Lib/test/test_gdb.py (working copy) @@ -9,7 +9,7 @@ import sys import unittest -from test.test_support import run_unittest +from test.test_support import run_unittest, findfile try: gdb_version, _ = subprocess.Popen(["gdb", "--version"], @@ -144,6 +144,9 @@ self.assert_(m, msg='%r did not match %r' % (actual, pattern)) + def get_sample_script(self): + return findfile('gdb_sample.py') + class PrettyPrintTests(DebuggerTests): def test_getting_backtrace(self): gdb_output = self.get_stack_trace('print 42') @@ -531,133 +534,127 @@ def test_basic_command(self): 'Verify that the "py-list" command works' - bt = self.get_stack_trace(script='Lib/test/test_gdb_sample.py', + bt = self.get_stack_trace(script=self.get_sample_script(), cmds_after_breakpoint=['py-list']) - self.assertListing(''' - 5 - 6 def bar(a, b, c): - 7 baz(a, b, c) - 8 - 9 def baz(*args): - >10 print(42) - 11 - 12 foo(1, 2, 3) -''', - bt) + self.assertListing(' 5 \n' + ' 6 def bar(a, b, c):\n' + ' 7 baz(a, b, c)\n' + ' 8 \n' + ' 9 def baz(*args):\n' + ' >10 print(42)\n' + ' 11 \n' + ' 12 foo(1, 2, 3)\n', + bt) def test_one_abs_arg(self): 'Verify the "py-list" command with one absolute argument' - bt = self.get_stack_trace(script='Lib/test/test_gdb_sample.py', + bt = self.get_stack_trace(script=self.get_sample_script(), cmds_after_breakpoint=['py-list 9']) - self.assertListing(''' - 9 def baz(*args): - >10 print(42) - 11 - 12 foo(1, 2, 3) -''', - bt) + self.assertListing(' 9 def baz(*args):\n' + ' >10 print(42)\n' + ' 11 \n' + ' 12 foo(1, 2, 3)\n', + bt) def test_two_abs_args(self): 'Verify the "py-list" command with two absolute arguments' - bt = self.get_stack_trace(script='Lib/test/test_gdb_sample.py', + bt = self.get_stack_trace(script=self.get_sample_script(), cmds_after_breakpoint=['py-list 1,3']) - self.assertListing(''' - 1 # Sample script for use by test_gdb.py - 2 - 3 def foo(a, b, c): -''', - bt) + self.assertListing(' 1 # Sample script for use by test_gdb.py\n' + ' 2 \n' + ' 3 def foo(a, b, c):\n', + bt) class StackNavigationTests(DebuggerTests): def test_pyup_command(self): 'Verify that the "py-up" command works' - bt = self.get_stack_trace(script='Lib/test/test_gdb_sample.py', + bt = self.get_stack_trace(script=self.get_sample_script(), cmds_after_breakpoint=['py-up']) self.assertMultilineMatches(bt, r'''^.* -#[0-9]+ Frame 0x[0-9a-f]+, for file Lib/test/test_gdb_sample.py, line 7, in bar \(a=1, b=2, c=3\) +#[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\) $''') def test_down_at_bottom(self): 'Verify handling of "py-down" at the bottom of the stack' - bt = self.get_stack_trace(script='Lib/test/test_gdb_sample.py', + bt = self.get_stack_trace(script=self.get_sample_script(), cmds_after_breakpoint=['py-down']) self.assertEndsWith(bt, 'Unable to find a newer python frame\n') def test_up_at_top(self): 'Verify handling of "py-up" at the top of the stack' - bt = self.get_stack_trace(script='Lib/test/test_gdb_sample.py', + bt = self.get_stack_trace(script=self.get_sample_script(), cmds_after_breakpoint=['py-up'] * 4) self.assertEndsWith(bt, 'Unable to find an older python frame\n') def test_up_then_down(self): 'Verify "py-up" followed by "py-down"' - bt = self.get_stack_trace(script='Lib/test/test_gdb_sample.py', + bt = self.get_stack_trace(script=self.get_sample_script(), cmds_after_breakpoint=['py-up', 'py-down']) self.assertMultilineMatches(bt, r'''^.* -#[0-9]+ Frame 0x[0-9a-f]+, for file Lib/test/test_gdb_sample.py, line 7, in bar \(a=1, b=2, c=3\) +#[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 Lib/test/test_gdb_sample.py, line 10, in baz \(args=\(1, 2, 3\)\) +#[0-9]+ Frame 0x[0-9a-f]+, for file .*gdb_sample.py, line 10, in baz \(args=\(1, 2, 3\)\) print\(42\) $''') class PyBtTests(DebuggerTests): def test_basic_command(self): 'Verify that the "py-bt" command works' - bt = self.get_stack_trace(script='Lib/test/test_gdb_sample.py', + bt = self.get_stack_trace(script=self.get_sample_script(), cmds_after_breakpoint=['py-bt']) self.assertMultilineMatches(bt, r'''^.* -#[0-9]+ Frame 0x[0-9a-f]+, for file Lib/test/test_gdb_sample.py, line 7, in bar \(a=1, b=2, c=3\) +#[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 Lib/test/test_gdb_sample.py, line 4, in foo \(a=1, b=2, c=3\) +#[0-9]+ Frame 0x[0-9a-f]+, for file .*gdb_sample.py, line 4, in foo \(a=1, b=2, c=3\) bar\(a, b, c\) -#[0-9]+ Frame 0x[0-9a-f]+, for file Lib/test/test_gdb_sample.py, line 12, in \(\) +#[0-9]+ Frame 0x[0-9a-f]+, for file .*gdb_sample.py, line 12, in \(\) foo\(1, 2, 3\) ''') class PyPrintTests(DebuggerTests): def test_basic_command(self): 'Verify that the "py-print" command works' - bt = self.get_stack_trace(script='Lib/test/test_gdb_sample.py', + bt = self.get_stack_trace(script=self.get_sample_script(), cmds_after_breakpoint=['py-print args']) self.assertMultilineMatches(bt, r".*\nlocal 'args' = \(1, 2, 3\)\n.*") def test_print_after_up(self): - bt = self.get_stack_trace(script='Lib/test/test_gdb_sample.py', + bt = self.get_stack_trace(script=self.get_sample_script(), cmds_after_breakpoint=['py-up', 'py-print c', 'py-print b', 'py-print a']) self.assertMultilineMatches(bt, r".*\nlocal 'c' = 3\nlocal 'b' = 2\nlocal 'a' = 1\n.*") def test_printing_global(self): - bt = self.get_stack_trace(script='Lib/test/test_gdb_sample.py', + bt = self.get_stack_trace(script=self.get_sample_script(), cmds_after_breakpoint=['py-print __name__']) self.assertMultilineMatches(bt, r".*\nglobal '__name__' = '__main__'\n.*") def test_printing_builtin(self): - bt = self.get_stack_trace(script='Lib/test/test_gdb_sample.py', + bt = self.get_stack_trace(script=self.get_sample_script(), cmds_after_breakpoint=['py-print len']) self.assertMultilineMatches(bt, r".*\nbuiltin 'len' = \n.*") class PyLocalsTests(DebuggerTests): def test_basic_command(self): - bt = self.get_stack_trace(script='Lib/test/test_gdb_sample.py', + bt = self.get_stack_trace(script=self.get_sample_script(), cmds_after_breakpoint=['py-locals']) self.assertMultilineMatches(bt, r".*\nargs = \(1, 2, 3\)\n.*") def test_locals_after_up(self): - bt = self.get_stack_trace(script='Lib/test/test_gdb_sample.py', + bt = self.get_stack_trace(script=self.get_sample_script(), cmds_after_breakpoint=['py-up', 'py-locals']) self.assertMultilineMatches(bt, r".*\na = 1\nb = 2\nc = 3\n.*")