diff options
author | da-woods <dw-git@d-woods.co.uk> | 2021-10-01 10:29:34 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-01 11:29:34 +0200 |
commit | 8c7b0f3fb745aa7bd0afedfbeb862eecc5fdff0c (patch) | |
tree | b1fdb15649af652449d36f923c97e1167c1ca953 | |
parent | 494f517e622f8a9e43f490408ec244a785d556e2 (diff) | |
download | cython-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.py | 2 | ||||
-rw-r--r-- | Cython/Compiler/ParseTreeTransforms.py | 2 | ||||
-rw-r--r-- | Cython/Compiler/Visitor.py | 4 | ||||
-rw-r--r-- | tests/run/decorators.pyx | 20 |
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() |