summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorda-woods <dw-git@d-woods.co.uk>2021-08-07 09:28:31 +0100
committerGitHub <noreply@github.com>2021-08-07 10:28:31 +0200
commitec8c0804f1a847e7f9b92210d756507afb6ae9b3 (patch)
tree7a248cb5d0e3d3b476799893800fc49bd43a5ffd
parent563c261155f6ce787be80c68d6a3524393142589 (diff)
downloadcython-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.py10
-rw-r--r--tests/errors/cdef_func_decorators.pyx39
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.
+"""