summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorda-woods <dw-git@d-woods.co.uk>2021-10-01 10:29:34 +0100
committerGitHub <noreply@github.com>2021-10-01 11:29:34 +0200
commit8c7b0f3fb745aa7bd0afedfbeb862eecc5fdff0c (patch)
treeb1fdb15649af652449d36f923c97e1167c1ca953
parent494f517e622f8a9e43f490408ec244a785d556e2 (diff)
downloadcython-8c7b0f3fb745aa7bd0afedfbeb862eecc5fdff0c.tar.gz
Handle function "outer_attrs" more consistently (GH-4375)
A few children of function nodes need to be consistently evaluated outside the function scope. This PR attempts to do so and thus fixes https://github.com/cython/cython/issues/4367.
-rw-r--r--Cython/Compiler/Nodes.py2
-rw-r--r--Cython/Compiler/ParseTreeTransforms.py2
-rw-r--r--Cython/Compiler/Visitor.py4
-rw-r--r--tests/run/decorators.pyx20
4 files changed, 25 insertions, 3 deletions
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py
index 4b0da59cf..9765b4cb2 100644
--- a/Cython/Compiler/Nodes.py
+++ b/Cython/Compiler/Nodes.py
@@ -1750,6 +1750,8 @@ class FuncDefNode(StatNode, BlockNode):
code_object = None
return_type_annotation = None
+ outer_attrs = None # overridden by some derived classes - to be visited outside the node's scope
+
def analyse_default_values(self, env):
default_seen = 0
for arg in self.args:
diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py
index 0eb91163a..d6ef3fdfc 100644
--- a/Cython/Compiler/ParseTreeTransforms.py
+++ b/Cython/Compiler/ParseTreeTransforms.py
@@ -2054,8 +2054,6 @@ if VALUE is not None:
def visit_DefNode(self, node):
node = self.visit_FuncDefNode(node)
env = self.current_env()
- if isinstance(node, Nodes.DefNode) and node.is_wrapper:
- env = env.parent_scope
if (not isinstance(node, Nodes.DefNode) or
node.fused_py_func or node.is_generator_body or
not node.needs_assignment_synthesis(env)):
diff --git a/Cython/Compiler/Visitor.py b/Cython/Compiler/Visitor.py
index 5d35c8aac..3181ed448 100644
--- a/Cython/Compiler/Visitor.py
+++ b/Cython/Compiler/Visitor.py
@@ -370,8 +370,10 @@ class EnvTransform(CythonTransform):
self.env_stack.pop()
def visit_FuncDefNode(self, node):
+ outer_attrs = node.outer_attrs
+ self.visitchildren(node, attrs=outer_attrs)
self.enter_scope(node, node.local_scope)
- self._process_children(node)
+ self.visitchildren(node, attrs=None, exclude=outer_attrs)
self.exit_scope()
return node
diff --git a/tests/run/decorators.pyx b/tests/run/decorators.pyx
index 85834eb8b..54623e0cb 100644
--- a/tests/run/decorators.pyx
+++ b/tests/run/decorators.pyx
@@ -61,3 +61,23 @@ a = A()
@a.decorate
def i(x):
return x - 1
+
+def append_to_list_decorator(lst):
+ def do_append_to_list_dec(func):
+ def new_func():
+ return lst + func()
+ return new_func
+ return do_append_to_list_dec
+
+def outer(arg1, arg2):
+ """
+ ensure decorators are analysed in the correct scope
+ https://github.com/cython/cython/issues/4367
+ mainly intended as a compile-time test (but it does run...)
+ >>> outer(append_to_list_decorator, [1,2,3])
+ [1, 2, 3, 4]
+ """
+ @arg1([x for x in arg2])
+ def method():
+ return [4]
+ return method()