diff options
author | da-woods <dw-git@d-woods.co.uk> | 2021-08-07 09:28:31 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-07 10:28:31 +0200 |
commit | ec8c0804f1a847e7f9b92210d756507afb6ae9b3 (patch) | |
tree | 7a248cb5d0e3d3b476799893800fc49bd43a5ffd | |
parent | 563c261155f6ce787be80c68d6a3524393142589 (diff) | |
download | cython-ec8c0804f1a847e7f9b92210d756507afb6ae9b3.tar.gz |
Restore error when using arbitrary decorators on cdef functions (GH-4323)
These were lost when cdef properties (for extern types) were introduced.
Closes #4322 (based on my interpretation of the problem as an error-reporting issue)
-rw-r--r-- | Cython/Compiler/ParseTreeTransforms.py | 10 | ||||
-rw-r--r-- | tests/errors/cdef_func_decorators.pyx | 39 |
2 files changed, 48 insertions, 1 deletions
diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index a959c880e..0eb91163a 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -1123,6 +1123,7 @@ class InterpretCompilerDirectives(CythonTransform): realdecs.append(dec) if realdecs and (scope_name == 'cclass' or isinstance(node, (Nodes.CClassDefNode, Nodes.CVarDefNode))): + # Note - arbitrary C function decorators are caught later in DecoratorTransform raise PostParseError(realdecs[0].pos, "Cdef functions/classes cannot take arbitrary decorators.") node.decorators = realdecs[::-1] + both[::-1] # merge or override repeated directives @@ -1438,7 +1439,14 @@ class DecoratorTransform(ScopeTrackingTransform, SkipDeclarations): def visit_CFuncDefNode(self, node): node = self.visit_FuncDefNode(node) - if self.scope_type != 'cclass' or self.scope_node.visibility != "extern" or not node.decorators: + if not node.decorators: + return node + elif self.scope_type != 'cclass' or self.scope_node.visibility != "extern": + # at the moment cdef functions are very restricted in what decorators they can take + # so it's simple to test for the small number of allowed decorators.... + if not (len(node.decorators) == 1 and node.decorators[0].decorator.is_name and + node.decorators[0].decorator.name == "staticmethod"): + error(node.decorators[0].pos, "Cdef functions cannot take arbitrary decorators.") return node ret_node = node diff --git a/tests/errors/cdef_func_decorators.pyx b/tests/errors/cdef_func_decorators.pyx new file mode 100644 index 000000000..e249b2e97 --- /dev/null +++ b/tests/errors/cdef_func_decorators.pyx @@ -0,0 +1,39 @@ +# mode: error +# tag: decorator + +from functools import wraps + +@wraps +cdef cant_be_decoratored(): + pass + +@wraps +cpdef also_cant_be_decorated(): + pass + +cdef class C: + @wraps + cdef still_cant_be_decorated(self): + pass + + @property + cdef property_only_works_for_extern_classes(self): + pass + + @wraps + cpdef also_still_cant_be_decorated(self): + pass + + @wraps + @wraps + cdef two_is_just_as_bad_as_one(self): + pass + +_ERRORS = """ +6:0: Cdef functions cannot take arbitrary decorators. +10:0: Cdef functions cannot take arbitrary decorators. +15:4: Cdef functions cannot take arbitrary decorators. +19:4: Cdef functions cannot take arbitrary decorators. +23:4: Cdef functions cannot take arbitrary decorators. +27:4: Cdef functions cannot take arbitrary decorators. +""" |