11/* ------------------------------------------------------------------------- */
22
3- #ifndef Py_LIMITED_API
4- /* stable ABI Python >= 3.6, keep in sync with setup.cfg py_limited_api */
5- #define Py_LIMITED_API 0x03060000
6- #endif
7-
83#include "Python.h"
94
105#include "structmember.h"
138#define PyVarObject_HEAD_INIT (type , size ) PyObject_HEAD_INIT(type) size,
149#endif
1510
11+ /* Heap types in Python < 3.9 don't support __weaklistoffset__ and
12+ * __dictoffset__ in PyMemberDef.
13+ */
14+ #if PY_VERSION_HEX >= 0x03090000
15+ #define WRAPT_HEAPTYPE_SUPPORT_OFFSET 1
16+ #endif
17+
18+ /* Instanes of heap types in Python < 3.8 don't hold strong ref to their
19+ * type object.
20+ */
21+ #if PY_VERSION_HEX >= 0x03080000
22+ #define WRAPT_HEAPTYPE_STRONG_TYPEREF 1
23+ #endif
24+
1625/* ------------------------------------------------------------------------- */
1726
1827typedef struct {
@@ -147,6 +156,7 @@ static int WraptObjectProxy_init(WraptObjectProxyObject *self,
147156static int WraptObjectProxy_traverse (WraptObjectProxyObject * self ,
148157 visitproc visit , void * arg )
149158{
159+ Py_VISIT (Py_TYPE (self ));
150160 Py_VISIT (self -> dict );
151161 Py_VISIT (self -> wrapped );
152162
@@ -167,7 +177,10 @@ static int WraptObjectProxy_clear(WraptObjectProxyObject *self)
167177
168178static void WraptObjectProxy_dealloc (WraptObjectProxyObject * self )
169179{
180+ #ifdef WRAPT_HEAPTYPE_STRONG_TYPEREF
181+ /* Type decref causes segfaults in <= 3.7 */
170182 PyTypeObject * tp = Py_TYPE (self );
183+ #endif
171184
172185 PyObject_GC_UnTrack (self );
173186
@@ -179,7 +192,9 @@ static void WraptObjectProxy_dealloc(WraptObjectProxyObject *self)
179192 freefunc free_func = PyType_GetSlot (Py_TYPE (self ), Py_tp_free );
180193 free_func (self );
181194
195+ #ifdef WRAPT_HEAPTYPE_STRONG_TYPEREF
182196 Py_DECREF (tp );
197+ #endif
183198}
184199
185200/* ------------------------------------------------------------------------- */
@@ -1589,8 +1604,10 @@ static PyGetSetDef WraptObjectProxy_getset[] = {
15891604};
15901605
15911606static struct PyMemberDef WraptObjectProxy_Type_members [] = {
1607+ #ifdef WRAPT_HEAPTYPE_SUPPORT_OFFSET
15921608 {"__weaklistoffset__" , T_PYSSIZET , offsetof(WraptObjectProxyObject , weakreflist ), READONLY },
15931609 {"__dictoffset__" , T_PYSSIZET , offsetof(WraptObjectProxyObject , dict ), READONLY },
1610+ #endif
15941611 {NULL },
15951612};
15961613
@@ -1697,6 +1714,7 @@ static PyType_Spec WraptCallableObjectProxy_Type_spec = {
16971714 "CallableObjectProxy" ,
16981715 sizeof (WraptObjectProxyObject ),
16991716 0 ,
1717+ /* Only define HAVE_GC if the object defines custom traverse and clear */
17001718 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE ,
17011719 WraptCallableObjectProxy_Type_slots
17021720};
@@ -2772,12 +2790,21 @@ init_type(PyObject *module, PyObject **newtype, PyType_Spec *spec,
27722790 return -1 ;
27732791 }
27742792 }
2793+ #if PY_VERSION_HEX >= 0x03090000
2794+ * newtype = PyType_FromModuleAndSpec (module , spec , bases );
2795+ #else
27752796 * newtype = PyType_FromSpecWithBases (spec , bases );
2797+ #endif
27762798 Py_XDECREF (bases );
27772799 if (* newtype == NULL ) {
27782800 return -1 ;
27792801 }
27802802 assert (((PyTypeObject * )* newtype )-> tp_traverse != NULL );
2803+ #ifndef WRAPT_HEAPTYPE_SUPPORT_OFFSET
2804+ /* hack for Python <= 3.8 */
2805+ ((PyTypeObject * )* newtype )-> tp_weaklistoffset = offsetof(WraptObjectProxyObject , weakreflist );
2806+ ((PyTypeObject * )* newtype )-> tp_dictoffset = offsetof(WraptObjectProxyObject , dict );
2807+ #endif
27812808 }
27822809
27832810 if (PyModule_AddObject (module , attrname , * newtype ) < 0 ) {
0 commit comments