Commit 3aec761b authored by Mark Florisson's avatar Mark Florisson

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
parent 42fea3e8
...@@ -1577,8 +1577,8 @@ class DebugTransform(CythonTransform): ...@@ -1577,8 +1577,8 @@ class DebugTransform(CythonTransform):
vartype = 'CObject' vartype = 'CObject'
cname = entry.cname cname = entry.cname
if entry.type.is_extension_type: # if entry.type.is_extension_type:
cname = entry.type.typeptr_cname # cname = entry.type.typeptr_cname
attrs = dict( attrs = dict(
name=entry.name, name=entry.name,
......
...@@ -35,6 +35,7 @@ def make_command_file(path_to_debug_info, prefix_code='', no_import=False): ...@@ -35,6 +35,7 @@ def make_command_file(path_to_debug_info, prefix_code='', no_import=False):
f = os.fdopen(fd, 'w') f = os.fdopen(fd, 'w')
f.write(prefix_code) f.write(prefix_code)
f.write('set breakpoint pending on\n') f.write('set breakpoint pending on\n')
f.write("set print pretty on\n")
f.write('python from Cython.Debugger import libcython\n') f.write('python from Cython.Debugger import libcython\n')
if not no_import: if not no_import:
f.write('\n'.join('cy import %s\n' % fn for fn in debug_files)) f.write('\n'.join('cy import %s\n' % fn for fn in debug_files))
......
...@@ -215,9 +215,9 @@ class TestLocalsGlobals(DebugTestCase): ...@@ -215,9 +215,9 @@ class TestLocalsGlobals(DebugTestCase):
self.break_and_run('int(10)') self.break_and_run('int(10)')
result = gdb.execute('cy locals', to_string=True) result = gdb.execute('cy locals', to_string=True)
assert 'a = 0' in result, repr(result) assert 'a = 0', repr(result)
assert 'b = 1' in result, repr(result) assert 'b = (int) 1', result
assert 'c = 2' in result, repr(result) assert 'c = (int) 2' in result, repr(result)
def test_globals(self): def test_globals(self):
self.break_and_run('int(10)') self.break_and_run('int(10)')
...@@ -268,7 +268,7 @@ class TestPrint(DebugTestCase): ...@@ -268,7 +268,7 @@ class TestPrint(DebugTestCase):
def test_print(self): def test_print(self):
self.break_and_run('c = 2') self.break_and_run('c = 2')
result = gdb.execute('cy print b', to_string=True) result = gdb.execute('cy print b', to_string=True)
assert '= 1' in result self.assertEqual('b = (int) 1\n', result)
class TestUpDown(DebugTestCase): class TestUpDown(DebugTestCase):
......
...@@ -367,6 +367,19 @@ class CythonBase(object): ...@@ -367,6 +367,19 @@ class CythonBase(object):
return result 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): class SourceFileDescriptor(object):
def __init__(self, filename, lexer, formatter=None): def __init__(self, filename, lexer, formatter=None):
self.filename = filename self.filename = filename
...@@ -977,11 +990,14 @@ class CyPrint(CythonCommand): ...@@ -977,11 +990,14 @@ class CyPrint(CythonCommand):
if self.is_python_function(): if self.is_python_function():
return gdb.execute('py-print ' + name) return gdb.execute('py-print ' + name)
elif self.is_cython_function(): elif self.is_cython_function():
value = self.cy.cy_cvalue.invoke(name) value = self.cy.cy_cvalue.invoke(name.lstrip('*'))
if max_name_length is None: for c in name:
print '%s = %s' % (name, value) if c == '*':
else: value = value.dereference()
print '%-*s = %s' % (max_name_length, name, value) else:
break
self.print_gdb_value(name, value, max_name_length)
else: else:
gdb.execute('print ' + name) gdb.execute('print ' + name)
...@@ -1011,7 +1027,7 @@ class CyLocals(CythonCommand): ...@@ -1011,7 +1027,7 @@ class CyLocals(CythonCommand):
# variable not initialized yet # variable not initialized yet
pass pass
else: 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') @dispatch_on_frame(c_command='info locals', python_command='py-locals')
def invoke(self, args, from_tty): def invoke(self, args, from_tty):
...@@ -1104,18 +1120,16 @@ class CyCValue(CyCName): ...@@ -1104,18 +1120,16 @@ class CyCValue(CyCName):
@require_cython_frame @require_cython_frame
@gdb_function_value_to_unicode @gdb_function_value_to_unicode
def invoke(self, cyname, frame=None): def invoke(self, cyname, frame=None):
cname = super(CyCValue, self).invoke(cyname, frame=frame)
try: try:
cname = super(CyCValue, self).invoke(cyname, frame=frame)
return gdb.parse_and_eval(cname) return gdb.parse_and_eval(cname)
except RuntimeError: except (gdb.GdbError, RuntimeError):
# variable exists but may not have been initialized yet, or may be # variable exists but may not have been initialized yet, or may be
# in the globals dict of the Cython module # in the globals dict of the Cython module
if cyname in self.get_cython_function().module.globals: d = self.get_cython_globals_dict()
# look in the global dict if cyname in d:
d = self.get_cython_globals_dict() return d[cyname]._gdbval
if cyname in d:
return d[cyname]._gdbval
# print cyname, self.get_cython_function().module.globals, '\n', self.get_cython_globals_dict()
raise gdb.GdbError("Variable %s not initialized yet." % cyname) raise gdb.GdbError("Variable %s not initialized yet." % cyname)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment