Describe the bug
I am making a convenient extension class wrapping a bitfield, but Cython is not revealing my descriptor class when wrapping a cdef function.
To Reproduce
This has been converted to Pyrex syntax to be explicit (could be reproduced)
cdef class flag:
"""A flag value, works similar to a property by using descriptors."""
cdef long int mask
def __init__(self, func) -> None:
self.mask = func(None)
def __get__(self, instance, owner):
"""Called when this is accessed through an attribute."""
if instance is None:
return self # Acessed through a class directly
return (instance.value & self.mask) == self.mask
def __set__(self, instance, value):
if value == True:
instance.value |= self.mask
else:
instance.value &= ~self.mask
cdef class Simple:
"""A simple bitfield"""
cdef int value
def __init__(self, value):
self.value = value
@flag
cdef one(self):
return 1 << 1
@flag
cdef two(self):
return 1 << 2
On the latest stable release, this did not compile with the following error:
Error compiling Cython file:
------------------------------------------------------------
...
cdef int value
def __init__(self, value):
self.value = value
^
------------------------------------------------------------
flags.pyx:31:4: Cdef functions/classes cannot take arbitrary decorators.
On master branch (installed through pip install -U git+https://github.com/cython/cython) this compiles, but. The issue now becomes that the one and two attributes is not available to Python as demonstrated below:
>>> import flags
>>> s = flags.Simple(1)
>>> dir(s)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__pyx_vtable__', '__reduce__', '__reduce_cython__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__setstate_cython__', '__sizeof__', '__str__', '__subclasshook__']
Expected behavior
I would expect my Simple class to expose 2 instances of my flag extension type called one and two. When I do s.one I would expect it to call __get__. When the flag extension type is initialized, it calls the C function and gets the bit mask.
This is from Python:
class flag:
"""A flag value, works similar to a property by using descriptors."""
def __init__(self, func) -> None:
self.mask = func(None)
def __get__(self, instance, owner):
"""Called when this is accessed through an attribute."""
if instance is None:
return self # Acessed through a class directly
return (instance.value & self.mask) == self.mask
def __set__(self, instance, value):
if value == True:
instance.value |= self.mask
else:
instance.value &= ~self.mask
class Simple:
"""A simple bitfield"""
def __init__(self, value):
self.value = value
@flag
def one(self):
return 1 << 1
@flag
def two(self):
return 1 << 2
s = Simple(6)
print(type(Simple.one)) # <class '__main__.flag'>
print(s.one) # True
print(s.two) # True
Environment (please complete the following information):
- OS: Windows
- Python version 3.9.5
- Cython version 3.0.0.a9
Describe the bug
I am making a convenient extension class wrapping a bitfield, but Cython is not revealing my descriptor class when wrapping a
cdeffunction.To Reproduce
This has been converted to Pyrex syntax to be explicit (could be reproduced)
On the latest stable release, this did not compile with the following error:
On master branch (installed through
pip install -U git+https://github.com/cython/cython) this compiles, but. The issue now becomes that theoneandtwoattributes is not available to Python as demonstrated below:Expected behavior
I would expect my
Simpleclass to expose 2 instances of myflagextension type calledoneandtwo. When I dos.oneI would expect it to call__get__. When theflagextension type is initialized, it calls the C function and gets the bit mask.This is from Python:
Environment (please complete the following information):