qname = '%s.%s.%s' % (entry.scope.outer_scope.qualified_name,
entry.scope.name,
entry.name)
+ elif entry.in_closure:
+ cname = '%s->%s' % (Naming.cur_scope_cname,
+ entry.cname)
+ qname = entry.qualified_name
else:
cname = entry.cname
qname = entry.qualified_name
-
+
if not entry.pos:
# this happens for variables that are not in the user's code,
# e.g. for the global __builtins__, __doc__, etc. We can just
output = gdb.execute('cy run', to_string=True)
assert 'abort' in output.lower()
+
class DebugStepperTestCase(DebugTestCase):
def step(self, varnames_and_values, source_line=None, lineno=None):
class TestClosure(DebugTestCase):
- def test_cython_closure(self):
- self.break_and_run('def inner():')
+ def break_and_run_func(self, funcname):
+ gdb.execute('cy break ' + funcname)
+ gdb.execute('cy run')
+
+ def test_inner(self):
+ self.break_and_run_func('inner')
# Allow the Cython-generated code to initialize the scope variable
gdb.execute('cy step')
- self.assertEqual(str(self.read_var('a')), '1')
+ self.assertEqual(str(self.read_var('a')), "'an object'")
print_result = gdb.execute('cy print a', to_string=True).strip()
- self.assertEqual(print_result, 'a = 1')
+ self.assertEqual(print_result, "a = 'an object'")
- def test_cython_closure_no_closing_variables(self):
- self.break_and_run('def inner2():')
- self.assertEqual(gdb.execute('cy locals', to_string=True), '')
+ def test_outer(self):
+ self.break_and_run_func('outer')
+
+ # Initialize scope with 'a' uninitialized
+ gdb.execute('cy step')
+
+ # Initialize 'a' to 1
+ gdb.execute('cy step')
+ print_result = gdb.execute('cy print a', to_string=True).strip()
+ self.assertEqual(print_result, "a = 'an object'")
_do_debug = os.environ.get('GDB_DEBUG')
value)
def is_initialized(self, cython_func, local_name):
+ islocal = local_name in cython_func.locals
+ if islocal:
+ cyvar = cython_func.locals[local_name]
+ if '->' in cyvar.cname:
+ # Closed over free variable
+ try:
+ gdb.parse_and_eval(cyvar.cname)
+ return True
+ except RuntimeError:
+ return False
+
cur_lineno = self.get_cython_lineno()
return (local_name in cython_func.arguments or
- (local_name in cython_func.locals and
- cur_lineno > cython_func.locals[local_name].lineno))
+ (islocal and cur_lineno > cyvar.lineno))
class SourceFileDescriptor(object):
def __init__(self, filename, lexer, formatter=None):