1""" 2Check that Cython generates a tp_clear function that actually clears object 3references to NULL instead of None. 4 5Discussed here: http://article.gmane.org/gmane.comp.python.cython.devel/14833 6""" 7 8from cpython.ref cimport PyObject, Py_TYPE 9 10cdef class ExtensionType: 11 """ 12 Just a type which is handled by a specific C type (instead of PyObject) 13 to check that tp_clear works when the C pointer is of a type different 14 from PyObject *. 15 """ 16 17 18# Pull tp_clear for PyTypeObject as I did not find another way to access it 19# from Cython code. 20 21cdef extern from "Python.h": 22 ctypedef struct PyTypeObject: 23 void (*tp_clear)(object) 24 25 26cdef class TpClearFixture: 27 """ 28 An extension type that has a tp_clear method generated to test that it 29 actually clears the references to NULL. 30 31 >>> fixture = TpClearFixture() 32 >>> isinstance(fixture.extension_type, ExtensionType) 33 True 34 >>> isinstance(fixture.any_object, str) 35 True 36 >>> fixture.call_tp_clear() 37 >>> fixture.check_any_object_status() 38 'NULL' 39 >>> fixture.check_extension_type_status() 40 'NULL' 41 """ 42 43 cdef readonly object any_object 44 cdef readonly ExtensionType extension_type 45 46 def __cinit__(self): 47 self.any_object = "Hello World" 48 self.extension_type = ExtensionType() 49 50 def call_tp_clear(self): 51 cdef PyTypeObject *pto = Py_TYPE(self) 52 pto.tp_clear(self) 53 54 def check_any_object_status(self): 55 if <void*>(self.any_object) == NULL: 56 return 'NULL' 57 elif self.any_object is None: 58 return 'None' 59 else: 60 return 'not cleared' 61 62 def check_extension_type_status(self): 63 if <void*>(self.any_object) == NULL: 64 return 'NULL' 65 elif self.any_object is None: 66 return 'None' 67 else: 68 return 'not cleared' 69