Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type of result of contextmanager is not recognized #3158

Open
mrh1997 opened this issue Sep 28, 2019 · 2 comments

Comments

@mrh1997
Copy link

commented Sep 28, 2019

The following piece of Cython code does not work. I get the error message "Cannot convert Python object to 'int'":

cdef class CustomCType:
    cdef int x;
    def __enter__(self) -> 'CustomCType':
         return self
...
with CustomCType() as cobj:
    c_func_that_requires_intparam(cobj.x)

everything works fine when replacing the "with" statement with

cobj = CustomCType()
with  cobj:
    c_func_that_requires_intparam(cobj.x)

The problem seems to be, that the result type of __enter__() is not evaluated

@scoder

This comment has been minimized.

Copy link
Contributor

commented Sep 29, 2019

Both are not equivalent. You are not assigning the return value of __enter__ to anything in the second case.

In order to make Cython care about the return value, you could use a cdef (or cpdef) method for __enter__ instead of a plain Python method.

@mrh1997

This comment has been minimized.

Copy link
Author

commented Sep 29, 2019

Oh. I intuitively thought Cython would use the standard type annotation information (not only the cython specific ones). My fault.

After switching to the proposed "cdef" variant (same with "cpdef") cython works ;-)
But the C compiler emits a warning :-(

warning C4133: "=": Inkompatible Typen - von "PyObject *" zu "__pyx_obj_5pytcc_Binary *"

I looked into the generated code and it is definitly bad typed:

PyObject *__pyx_t_3 = NULL;
struct __pyx_obj_5pytcc_Binary *__pyx_t_4 = NULL;
...
__pyx_t_3 = ((PyObject *)((struct __pyx_vtabstruct_5pytcc_Binary *)((struct __pyx_obj_5pytcc_Binary *)__pyx_t_1)->__pyx_vtab)->__pyx___enter__(((struct __pyx_obj_5pytcc_Binary *)__pyx_t_1), 0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 152, __pyx_L3_error)
__Pyx_GOTREF(__pyx_t_3);
__pyx_t_4 = __pyx_t_3;      // <- WARNING as __pyx_t_3 and __pyx_t_4 have different pointer types!!! 

One more thing: __enter__() has to be cdef (at least in my case), while __exit__() must not be cdef. When I tried to implement it as cdef I get an AttributeError during runtime. This is somewhat counterintuitive

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.