Commit fdddf34e authored by mattip's avatar mattip

add a new ReplacePropertyNode pass

parent 726ebd82
......@@ -1398,67 +1398,6 @@ class DecoratorTransform(ScopeTrackingTransform, SkipDeclarations):
node.decorators = None
return self.chain_decorators(node, decs, node.name)
def visit_CFuncDefNode(self, node):
scope_type = self.scope_type
if scope_type != 'cclass' or not node.decorators:
return node
# XXX currently only handle getter property
# transform @property decorators
properties = self._properties[-1]
for decorator_node in node.decorators[::-1]:
decorator = decorator_node.decorator
if decorator.is_name and decorator.name == 'property':
if len(node.decorators) > 1:
return self._reject_decorated_property(node, decorator_node)
name = node.declarator.base.name
# XXX Disables handling property decorator
# return [node]
node.name = name #EncodedString('__get__')
node.decorators.remove(decorator_node)
stat_list = [node]
if name in properties:
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.body = Nodes.StatListNode(node.pos, stats=stat_list)
prop.is_wrapper = True
properties[name] = prop
return [prop]
elif decorator.is_attribute and decorator.obj.name in properties:
# TODO fix this
raise error(decorator_node.pos, "Not handled yet")
handler_name = self._map_property_attribute(decorator.attribute)
if handler_name:
if decorator.obj.name != node.name:
# CPython generates neither an error nor warning, but nothing useful either.
error(decorator_node.pos,
"Mismatching property names, expected '%s', got '%s'" % (
decorator.obj.name, node.name))
elif len(node.decorators) > 1:
return self._reject_decorated_property(node, decorator_node)
else:
return self._add_to_property(properties, node, handler_name, decorator_node)
# we clear node.decorators, so we need to set the
# is_staticmethod/is_classmethod attributes now
for decorator in node.decorators:
# TODO fix this
raise error(decorator.pos, "Not handled yet")
func = decorator.decorator
if func.is_name:
node.is_classmethod |= func.name == 'classmethod'
node.is_staticmethod |= func.name == 'staticmethod'
# transform normal decorators
decs = node.decorators
node.decorators = None
return self.chain_decorators(node, decs, None)
@staticmethod
def _reject_decorated_property(node, decorator_node):
# restrict transformation to outermost decorator as wrapped properties will probably not work
......@@ -2300,6 +2239,25 @@ class AnalyseExpressionsTransform(CythonTransform):
node = node.base
return node
class ReplacePropertyNode(CythonTransform):
def visit_CFuncDefNode(self, node):
if not node.decorators:
return node
# transform @property decorators
for decorator_node in node.decorators[::-1]:
decorator = decorator_node.decorator
if decorator.is_name and decorator.name == 'property':
if len(node.decorators) > 1:
return self._reject_decorated_property(node, decorator_node)
name = node.declarator.base.name
node.name = name #EncodedString('__get__')
newstats = node.body.analyse_expressions(node.local_scope)
newnode = newstats.stats[0].value
newnode.name = name
node.decorators.remove(decorator_node)
return [newnode]
# XXX still need to update everywhere that used the old node
class FindInvalidUseOfFusedTypes(CythonTransform):
......
......@@ -146,7 +146,7 @@ def create_pipeline(context, mode, exclude_classes=()):
from .ParseTreeTransforms import CreateClosureClasses, MarkClosureVisitor, DecoratorTransform
from .ParseTreeTransforms import TrackNumpyAttributes, InterpretCompilerDirectives, TransformBuiltinMethods
from .ParseTreeTransforms import ExpandInplaceOperators, ParallelRangeTransform
from .ParseTreeTransforms import CalculateQualifiedNamesTransform
from .ParseTreeTransforms import CalculateQualifiedNamesTransform, ReplacePropertyNode
from .TypeInference import MarkParallelAssignments, MarkOverflowingArithmetic
from .ParseTreeTransforms import AdjustDefByDirectives, AlignFunctionDefinitions
from .ParseTreeTransforms import RemoveUnreachableCode, GilCheck
......@@ -198,6 +198,7 @@ def create_pipeline(context, mode, exclude_classes=()):
AnalyseDeclarationsTransform(context),
AutoTestDictTransform(context),
EmbedSignature(context),
ReplacePropertyNode(context),
EarlyReplaceBuiltinCalls(context), ## Necessary?
TransformBuiltinMethods(context),
MarkParallelAssignments(context),
......
......@@ -121,9 +121,7 @@ def sum(Foo f):
cdef extern from "foo.h":
ctypedef class foo_extension.Foo [object FooStructOpaque]:
# Importing will warn until we can use this syntax
# ctypedef class foo_extension.Foo [object FooStructOpaque, check_size]:
ctypedef class foo_extension.Foo [object FooStructOpaque, check_size ignore]:
@property
cdef int field0(self):
return PyFoo_GET0(self)
......@@ -196,9 +194,6 @@ except AttributeError as e:
opaque_foo = foo_extension.OpaqueFoo(23, 123, 1023)
# Remove warnings filter once we can use check_size=False
with warnings.catch_warnings():
warnings.simplefilter("ignore")
opaque_ret = getter1.sum(opaque_foo)
opaque_ret = getter1.sum(opaque_foo)
assert opaque_ret == ret
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