Commit ac48e447 authored by Stefan Behnel's avatar Stefan Behnel

reject properties with additional decorators in cdef classes

parent a27d2259
...@@ -1299,30 +1299,40 @@ class PropertyTransform(ScopeTrackingTransform): ...@@ -1299,30 +1299,40 @@ class PropertyTransform(ScopeTrackingTransform):
if self.scope_type != 'cclass' or not node.decorators: if self.scope_type != 'cclass' or not node.decorators:
return node return node
properties = self._properties[-1] properties = self._properties[-1]
# restrict transformation to outermost decorator as wrapped properties will probably not work for decorator_node in node.decorators[::-1]:
decorator_node = node.decorators[-1] decorator = decorator_node.decorator
decorator = decorator_node.decorator if decorator.is_name and decorator.name == 'property':
if decorator.is_name and decorator.name == 'property': if len(node.decorators) > 1:
name = node.name return self._reject_decorated_property(node, decorator_node)
node.name = '__get__' name = node.name
node.decorators.remove(decorator_node) node.name = '__get__'
stat_list = [node] node.decorators.remove(decorator_node)
if name in properties: stat_list = [node]
prop = properties[name] if name in properties:
prop.pos = node.pos prop = properties[name]
prop.pos = node.pos
prop.doc = node.doc
prop.body.stats = stat_list
return []
prop = Nodes.PropertyNode(node.pos, name=name)
prop.doc = node.doc prop.doc = node.doc
prop.body.stats = stat_list prop.body = Nodes.StatListNode(node.pos, stats=stat_list)
return [] properties[name] = prop
prop = Nodes.PropertyNode(node.pos, name=name) return [prop]
prop.doc = node.doc elif decorator.is_attribute and decorator.obj.name in properties:
prop.body = Nodes.StatListNode(node.pos, stats=stat_list) handler_name = self._map_property_attribute(decorator.attribute)
properties[name] = prop if handler_name:
return [prop] assert decorator.obj.name == node.name
elif decorator.is_attribute and decorator.obj.name in properties: if len(node.decorators) > 1:
handler_name = self._map_property_attribute(decorator.attribute) return self._reject_decorated_property(node, decorator_node)
if handler_name: return self._add_to_property(properties, node, handler_name, decorator_node)
assert decorator.obj.name == node.name return node
return self._add_to_property(properties, node, handler_name, decorator_node)
def _reject_decorated_property(self, node, decorator_node):
# restrict transformation to outermost decorator as wrapped properties will probably not work
for deco in node.decorators:
if deco != decorator_node:
error(deco.pos, "Property methods with additional decorators are not supported")
return node return node
def _add_to_property(self, properties, node, name, decorator): def _add_to_property(self, properties, node, name, decorator):
......
# mode: error
# ticket: 264
# tag: property, decorator
from functools import wraps
def wrap_func(f):
@wraps(f)
def wrap(*args, **kwargs):
print("WRAPPED")
return f(*args, **kwargs)
return wrap
cdef class Prop:
@property
@wrap_func
def prop1(self):
return 1
@property
def prop2(self):
return 2
@wrap_func
@prop2.setter
def prop2(self, value):
pass
@prop2.setter
@wrap_func
def prop2(self, value):
pass
_ERRORS = """
19:4: Property methods with additional decorators are not supported
27:4: Property methods with additional decorators are not supported
33:4: Property methods with additional decorators are not supported
"""
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