Commit c03afec7 authored by Matti Picus's avatar Matti Picus Committed by Stefan Behnel

ENH: add more tests and fixes for @property cdef decorator (GH-3115)

parent 43cdef76
......@@ -875,8 +875,6 @@ class ExprNode(Node):
#
src = self
src_type = self.type
if src_type.is_cfunction and src_type.entry.is_cgetter:
src_type = src_type.return_type
if self.check_for_coercion_error(dst_type, env):
return self
......@@ -3637,10 +3635,7 @@ class IndexNode(_IndexingBaseNode):
self.nogil = env.nogil
base_type = self.base.type
if base_type.is_cfunction:
if self.base.entry.is_cgetter:
base_type = base_type.return_type
else:
if not base_type.is_cfunction:
self.index = self.index.analyse_types(env)
self.original_index_type = self.index.type
......@@ -3727,10 +3722,7 @@ class IndexNode(_IndexingBaseNode):
def analyse_as_c_array(self, env, is_slice):
base_type = self.base.type
if hasattr(self.base, 'entry') and self.base.entry.is_cgetter:
self.type = base_type.return_type.base_type
else:
self.type = base_type.base_type
self.type = base_type.base_type
if is_slice:
self.type = base_type
elif self.index.type.is_pyobject:
......@@ -6731,7 +6723,7 @@ class AttributeNode(ExprNode):
is_attribute = 1
subexprs = ['obj']
type = PyrexTypes.error_type
_type = PyrexTypes.error_type
entry = None
is_called = 0
needs_none_check = True
......@@ -6739,6 +6731,20 @@ class AttributeNode(ExprNode):
is_special_lookup = False
is_py_attr = 0
@property
def type(self):
if self._type.is_cfunction and hasattr(self._type, 'entry') and self._type.entry.is_cgetter:
return self._type.return_type
return self._type
@type.setter
def type(self, value):
# XXX review where the attribute is set
# make sure it is not already a cgetter
if self._type.is_cfunction and hasattr(self._type, 'entry') and self._type.entry.is_cgetter:
error(self.pos, "%s.type already set" % self.__name__)
self._type = value
def as_cython_attribute(self):
if (isinstance(self.obj, NameNode) and
self.obj.is_cython_module and not
......@@ -7014,7 +7020,7 @@ class AttributeNode(ExprNode):
# (foo = pycfunction(foo_func_obj)) and need to go through
# regular Python lookup as well
if (entry.is_variable and not entry.fused_cfunction) or entry.is_cmethod:
self.type = entry.type
self._type = entry.type
self.member = entry.cname
return
else:
......@@ -7034,7 +7040,7 @@ class AttributeNode(ExprNode):
# mangle private '__*' Python attributes used inside of a class
self.attribute = env.mangle_class_private_name(self.attribute)
self.member = self.attribute
self.type = py_object_type
self._type = py_object_type
self.is_py_attr = 1
if not obj_type.is_pyobject and not obj_type.is_error:
......@@ -11210,10 +11216,6 @@ class NumBinopNode(BinopNode):
self.operand2 = self.operand2.coerce_to(self.type, env)
def compute_c_result_type(self, type1, type2):
if type1.is_cfunction and type1.entry.is_cgetter:
type1 = type1.return_type
if type2.is_cfunction and type2.entry.is_cgetter:
type2 = type2.return_type
if self.c_types_okay(type1, type2):
widest_type = PyrexTypes.widest_numeric_type(type1, type2)
if widest_type is PyrexTypes.c_bint_type:
......@@ -12218,10 +12220,6 @@ class CmpNode(object):
operand2 = self.operand2
type1 = operand1.type
type2 = operand2.type
if type1.is_cfunction and type1.entry.is_cgetter:
type1 = type1.return_type
if type2.is_cfunction and type2.entry.is_cgetter:
type2 = type2.return_type
new_common_type = None
......
......@@ -134,6 +134,10 @@ def sum(Foo f):
# notices the alias and replaces the __getattr__ in c by f->f0 anyway
return f.field0 + f.field1 + f.field2
def check_pyobj(Foo f):
# compare the c code to the check_pyobj in getter2.pyx
return bool(f.field1)
######## getter.pxd ########
# Access base Foo fields from C via getter functions
......@@ -175,7 +179,20 @@ def check_10(getter.Foo f):
return f.fieldF1 != 10
def vec0(getter.Foo f):
return f.vector[0]
return f.vector[0]
def check_binop(getter.Foo f):
return f.fieldF1 / 10
######## getter2.pyx ########
cimport getter
def check_pyobj(getter.Foo f):
return bool(f.fieldF1)
def check_unary(getter.Foo f):
return -f.fieldF1
######## getter_fail0.pyx ########
......@@ -201,7 +218,7 @@ cdef extern from "foo.h":
######## runner.py ########
import warnings
import foo_extension, getter0, getter1
import foo_extension, getter0, getter1, getter2
def sum(f):
# pure python field access, but code is identical to cython cdef sum
......@@ -225,6 +242,12 @@ opaque_foo = foo_extension.OpaqueFoo(23, 123, 1023)
opaque_ret = getter0.sum(opaque_foo)
assert opaque_ret == ret
val = getter2.check_pyobj(opaque_foo)
assert val is True
val = getter2.check_unary(opaque_foo)
assert val == -123
try:
f0 = opaque_ret.field0
assert False
......
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