From: Mark Florisson Date: Sat, 18 Dec 2010 18:51:51 +0000 (+0100) Subject: Debugger closure support X-Git-Tag: 0.14.1rc0~12^2~5^2 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=9140d0f93533feff17da179351581dd868f74d13;p=cython.git Debugger closure support --- diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index ad3b390b..b982fc08 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -1591,6 +1591,11 @@ class DebugTransform(CythonTransform): #self.c_output_file = options.output_file self.c_output_file = result.c_file + # Closure support, basically treat nested functions as if the AST were + # never nested + self.in_funcdef = False + self.nested_funcdefs = [] + # tells visit_NameNode whether it should register step-into functions self.register_stepinto = False @@ -1606,6 +1611,8 @@ class DebugTransform(CythonTransform): # serialize functions self.tb.start('Functions') self.visitchildren(node) + for nested_funcdef in self.nested_funcdefs: + self.visit_FuncDefNode(nested_funcdef) self.tb.end('Functions') # 2.3 compatibility. Serialize global variables @@ -1625,8 +1632,14 @@ class DebugTransform(CythonTransform): # Cython.Compiler.ModuleNode.ModuleNode._serialize_lineno_map return node - def visit_FuncDefNode(self, node): + def visit_FuncDefNode(self, node): self.visited.add(node.local_scope.qualified_name) + + if self.in_funcdef: + if not self.register_stepinto: + self.nested_funcdefs.append(node) + return node + # node.entry.visibility = 'extern' if node.py_func is None: pf_cname = '' @@ -1654,7 +1667,9 @@ class DebugTransform(CythonTransform): self.tb.start('StepIntoFunctions') self.register_stepinto = True + self.in_funcdef = True self.visitchildren(node) + self.in_funcdef = False self.register_stepinto = False self.tb.end('StepIntoFunctions') self.tb.end('Function') diff --git a/Cython/Compiler/Tests/TestParseTreeTransforms.py b/Cython/Compiler/Tests/TestParseTreeTransforms.py index adf8105f..9361de58 100644 --- a/Cython/Compiler/Tests/TestParseTreeTransforms.py +++ b/Cython/Compiler/Tests/TestParseTreeTransforms.py @@ -182,7 +182,8 @@ class TestDebugTransform(DebuggerTestCase): self.assertEqual('PythonObject', xml_globals.get('python_var')) # test functions - funcnames = 'codefile.spam', 'codefile.ham', 'codefile.eggs' + funcnames = ('codefile.spam', 'codefile.ham', 'codefile.eggs', + 'codefile.closure', 'codefile.inner') required_xml_attrs = 'name', 'cname', 'qualified_name' assert all([f in xml_funcs for f in funcnames]) spam, ham, eggs = [xml_funcs[funcname] for funcname in funcnames] diff --git a/Cython/Debugger/Tests/codefile b/Cython/Debugger/Tests/codefile index 53d6518d..95279818 100644 --- a/Cython/Debugger/Tests/codefile +++ b/Cython/Debugger/Tests/codefile @@ -21,16 +21,22 @@ def spam(a=0): puts("spam") os.path.join("foo", "bar") some_c_function() + +cpdef eggs(): + pass cdef ham(): pass -cpdef eggs(): - pass - cdef class SomeClass(object): def spam(self): pass +def closure(): + a = 1 + def inner(): + b = 2 + return inner + spam() print "bye!" diff --git a/Cython/Debugger/Tests/test_libcython_in_gdb.py b/Cython/Debugger/Tests/test_libcython_in_gdb.py index 2c9e7ef5..b68d36c7 100644 --- a/Cython/Debugger/Tests/test_libcython_in_gdb.py +++ b/Cython/Debugger/Tests/test_libcython_in_gdb.py @@ -98,7 +98,7 @@ class TestDebugInformationClasses(DebugTestCase): 'codefile.SomeClass.spam') self.assertEqual(self.spam_func.module, self.module) - assert self.eggs_func.pf_cname + assert self.eggs_func.pf_cname, (self.eggs_func, self.eggs_func.pf_cname) assert not self.ham_func.pf_cname assert not self.spam_func.pf_cname assert not self.spam_meth.pf_cname