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