From 3aec761b21b13bf29a98575a0e32a665ba934986 Mon Sep 17 00:00:00 2001 From: Mark Florisson Date: Sat, 6 Nov 2010 23:56:59 +0100 Subject: [PATCH] Support dereferencing variables in Cython frames Set pretty printing of C structs on by default Export the 'cname' of 'self' local variables in the XML debug info properly --- Cython/Compiler/ParseTreeTransforms.py | 4 +- Cython/Debugger/Cygdb.py | 1 + .../Debugger/Tests/test_libcython_in_gdb.py | 8 ++-- Cython/Debugger/libcython.py | 42 ++++++++++++------- 4 files changed, 35 insertions(+), 20 deletions(-) diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index bc3514b3..1e00d50d 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -1577,8 +1577,8 @@ class DebugTransform(CythonTransform): vartype = 'CObject' cname = entry.cname - if entry.type.is_extension_type: - cname = entry.type.typeptr_cname + # if entry.type.is_extension_type: + # cname = entry.type.typeptr_cname attrs = dict( name=entry.name, diff --git a/Cython/Debugger/Cygdb.py b/Cython/Debugger/Cygdb.py index 6045659b..4c83c2c0 100644 --- a/Cython/Debugger/Cygdb.py +++ b/Cython/Debugger/Cygdb.py @@ -35,6 +35,7 @@ def make_command_file(path_to_debug_info, prefix_code='', no_import=False): f = os.fdopen(fd, 'w') f.write(prefix_code) f.write('set breakpoint pending on\n') + f.write("set print pretty on\n") f.write('python from Cython.Debugger import libcython\n') if not no_import: f.write('\n'.join('cy import %s\n' % fn for fn in debug_files)) diff --git a/Cython/Debugger/Tests/test_libcython_in_gdb.py b/Cython/Debugger/Tests/test_libcython_in_gdb.py index d9c3a068..c3373914 100644 --- a/Cython/Debugger/Tests/test_libcython_in_gdb.py +++ b/Cython/Debugger/Tests/test_libcython_in_gdb.py @@ -215,9 +215,9 @@ class TestLocalsGlobals(DebugTestCase): self.break_and_run('int(10)') result = gdb.execute('cy locals', to_string=True) - assert 'a = 0' in result, repr(result) - assert 'b = 1' in result, repr(result) - assert 'c = 2' in result, repr(result) + assert 'a = 0', repr(result) + assert 'b = (int) 1', result + assert 'c = (int) 2' in result, repr(result) def test_globals(self): self.break_and_run('int(10)') @@ -268,7 +268,7 @@ class TestPrint(DebugTestCase): def test_print(self): self.break_and_run('c = 2') result = gdb.execute('cy print b', to_string=True) - assert '= 1' in result + self.assertEqual('b = (int) 1\n', result) class TestUpDown(DebugTestCase): diff --git a/Cython/Debugger/libcython.py b/Cython/Debugger/libcython.py index b1beca5c..02c220ab 100644 --- a/Cython/Debugger/libcython.py +++ b/Cython/Debugger/libcython.py @@ -367,6 +367,19 @@ class CythonBase(object): return result + def print_gdb_value(self, name, value, max_name_length=None, prefix=''): + if libpython.pretty_printer_lookup(value): + typename = '' + else: + typename = '(%s) ' % (value.type,) + + if max_name_length is None: + print '%s%s = %s%s' % (prefix, name, typename, value) + else: + print '%s%-*s = %s%s' % (prefix, max_name_length, name, typename, + value) + + class SourceFileDescriptor(object): def __init__(self, filename, lexer, formatter=None): self.filename = filename @@ -977,11 +990,14 @@ class CyPrint(CythonCommand): if self.is_python_function(): return gdb.execute('py-print ' + name) elif self.is_cython_function(): - value = self.cy.cy_cvalue.invoke(name) - if max_name_length is None: - print '%s = %s' % (name, value) - else: - print '%-*s = %s' % (max_name_length, name, value) + value = self.cy.cy_cvalue.invoke(name.lstrip('*')) + for c in name: + if c == '*': + value = value.dereference() + else: + break + + self.print_gdb_value(name, value, max_name_length) else: gdb.execute('print ' + name) @@ -1011,7 +1027,7 @@ class CyLocals(CythonCommand): # variable not initialized yet pass else: - print '%s%-*s = %s' % (prefix, max_name_length, cyvar.name, value) + self.print_gdb_value(cyvar.name, value, max_name_length, prefix) @dispatch_on_frame(c_command='info locals', python_command='py-locals') def invoke(self, args, from_tty): @@ -1104,18 +1120,16 @@ class CyCValue(CyCName): @require_cython_frame @gdb_function_value_to_unicode def invoke(self, cyname, frame=None): - cname = super(CyCValue, self).invoke(cyname, frame=frame) try: + cname = super(CyCValue, self).invoke(cyname, frame=frame) return gdb.parse_and_eval(cname) - except RuntimeError: + except (gdb.GdbError, RuntimeError): # variable exists but may not have been initialized yet, or may be # in the globals dict of the Cython module - if cyname in self.get_cython_function().module.globals: - # look in the global dict - d = self.get_cython_globals_dict() - if cyname in d: - return d[cyname]._gdbval - # print cyname, self.get_cython_function().module.globals, '\n', self.get_cython_globals_dict() + d = self.get_cython_globals_dict() + if cyname in d: + return d[cyname]._gdbval + raise gdb.GdbError("Variable %s not initialized yet." % cyname) -- 2.26.2