""" Check that Cython generates a tp_clear function that actually clears object references to NULL instead of None. Discussed here: https://article.gmane.org/gmane.comp.python.cython.devel/14833 """ from cpython.ref cimport PyObject, Py_TYPE cdef class ExtensionType: """ Just a type which is handled by a specific C type (instead of PyObject) to check that tp_clear works when the C pointer is of a type different from PyObject *. """ # Pull tp_clear for PyTypeObject as I did not find another way to access it # from Cython code. cdef extern from "Python.h": ctypedef struct PyTypeObject: void (*tp_clear)(object) cdef class TpClearFixture: """ An extension type that has a tp_clear method generated to test that it actually clears the references to NULL. >>> fixture = TpClearFixture() >>> isinstance(fixture.extension_type, ExtensionType) True >>> isinstance(fixture.any_object, str) True >>> fixture.call_tp_clear() >>> fixture.check_any_object_status() 'NULL' >>> fixture.check_extension_type_status() 'NULL' """ cdef readonly object any_object cdef readonly ExtensionType extension_type def __cinit__(self): self.any_object = "Hello World" self.extension_type = ExtensionType() def call_tp_clear(self): cdef PyTypeObject *pto = Py_TYPE(self) pto.tp_clear(self) def check_any_object_status(self): if (self.any_object) == NULL: return 'NULL' elif self.any_object is None: return 'None' else: return 'not cleared' def check_extension_type_status(self): if (self.any_object) == NULL: return 'NULL' elif self.any_object is None: return 'None' else: return 'not cleared'