Commit f510accf authored by Stefan Behnel's avatar Stefan Behnel

Allow @final class decorator in pure mode. Was previously rejected for Python...

Allow @final class decorator in pure mode. Was previously rejected for Python classes with an @cclass decorator.
Closes #2040.
parent bae7fdc4
...@@ -79,6 +79,9 @@ Bugs fixed ...@@ -79,6 +79,9 @@ Bugs fixed
* Some declaration types in ``libc.limits`` were corrected. * Some declaration types in ``libc.limits`` were corrected.
Patch by Jeroen Demeyer. (Github issue #2016) Patch by Jeroen Demeyer. (Github issue #2016)
* ``@cython.final`` was not accepted on Python classes with an ``@cython.cclass``
decorator. (Github issue #2040)
Other changes Other changes
------------- -------------
......
...@@ -1033,7 +1033,8 @@ class InterpretCompilerDirectives(CythonTransform): ...@@ -1033,7 +1033,8 @@ class InterpretCompilerDirectives(CythonTransform):
directives = [] directives = []
realdecs = [] realdecs = []
both = [] both = []
for dec in node.decorators: # Decorators coming first take precedence.
for dec in node.decorators[::-1]:
new_directives = self.try_to_parse_directives(dec.decorator) new_directives = self.try_to_parse_directives(dec.decorator)
if new_directives is not None: if new_directives is not None:
for directive in new_directives: for directive in new_directives:
...@@ -1043,15 +1044,17 @@ class InterpretCompilerDirectives(CythonTransform): ...@@ -1043,15 +1044,17 @@ class InterpretCompilerDirectives(CythonTransform):
directives.append(directive) directives.append(directive)
if directive[0] == 'staticmethod': if directive[0] == 'staticmethod':
both.append(dec) both.append(dec)
# Adapt scope type based on decorators that change it.
if directive[0] == 'cclass' and scope_name == 'class':
scope_name = 'cclass'
else: else:
realdecs.append(dec) realdecs.append(dec)
if realdecs and isinstance(node, (Nodes.CFuncDefNode, Nodes.CClassDefNode, Nodes.CVarDefNode)): if realdecs and (scope_name == 'cclass' or
isinstance(node, (Nodes.CFuncDefNode, Nodes.CClassDefNode, Nodes.CVarDefNode))):
raise PostParseError(realdecs[0].pos, "Cdef functions/classes cannot take arbitrary decorators.") raise PostParseError(realdecs[0].pos, "Cdef functions/classes cannot take arbitrary decorators.")
else: node.decorators = realdecs[::-1] + both[::-1]
node.decorators = realdecs + both
# merge or override repeated directives # merge or override repeated directives
optdict = {} optdict = {}
directives.reverse() # Decorators coming first take precedence
for directive in directives: for directive in directives:
name, value = directive name, value = directive
if name in optdict: if name in optdict:
......
...@@ -341,3 +341,22 @@ def ccall_except_check_always(x): ...@@ -341,3 +341,22 @@ def ccall_except_check_always(x):
if x == 0: if x == 0:
raise ValueError raise ValueError
return x+1 return x+1
@cython.final
@cython.cclass
class CClass(object):
"""
>>> c = CClass(2)
>>> c.get_attr()
int
2
"""
cython.declare(attr=cython.int)
def __init__(self, attr):
self.attr = attr
def get_attr(self):
print(cython.typeof(self.attr))
return self.attr
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment