diff -r cdd8c29dceb8 Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c Wed Aug 15 16:49:37 2012 +0200 +++ b/Modules/_testcapimodule.c Wed Aug 15 16:57:13 2012 +0200 @@ -15,14 +15,53 @@ #ifdef WITH_THREAD #include "pythread.h" #endif /* WITH_THREAD */ -static PyObject *TestError; /* set to exception object in init */ + +typedef struct { + PyObject *TestError; + PyObject *_HashInheritanceTester_Type; + PyObject *test_structmembersType; +} _testcapistate; + + +#define _testcapi_state(o) ((_testcapistate *)PyModule_GetState(o)) + +static int +_testcapi_clear(PyObject *m) +{ + _testcapistate *state = _testcapi_state(m); + Py_CLEAR(state->TestError); + Py_CLEAR(state->_HashInheritanceTester_Type); + Py_CLEAR(state->test_structmembersType); + return 0; +} + +static int +_testcapi_traverse(PyObject *m, visitproc visit, void *arg) +{ + _testcapistate *state = _testcapi_state(m); + Py_VISIT(state->TestError); + Py_VISIT(state->_HashInheritanceTester_Type); + Py_VISIT(state->test_structmembersType); + return 0; +} + +static void +_testcapi_free(void *m) +{ + _testcapi_clear((PyObject *)m); +} + +static PyModuleDef _testcapimodule; + +#define _testcapistate_global ((_testcapistate *)PyModule_GetState(PyState_FindModule(&_testcapimodule))) + /* set to exception object in init */ /* Raise TestError with test_name + ": " + msg, and return NULL. */ static PyObject * raiseTestError(const char* test_name, const char* msg) { - PyErr_Format(TestError, "%s: %s", test_name, msg); + PyErr_Format(_testcapistate_global->TestError, "%s: %s", test_name, msg); return NULL; } @@ -36,7 +75,7 @@ sizeof_error(const char* fatname, const char* typname, int expected, int got) { - PyErr_Format(TestError, + PyErr_Format(_testcapistate_global->TestError, "%s #define == %d but sizeof(%s) == %d", fatname, expected, typname, got); return (PyObject*)NULL; @@ -94,7 +133,7 @@ for (i = 0; i < NLIST; ++i) { PyObject* anint = PyList_GET_ITEM(list, i); if (PyLong_AS_LONG(anint) != NLIST-1-i) { - PyErr_SetString(TestError, + PyErr_SetString(_testcapistate_global->TestError, "test_list_api: reverse screwed up"); Py_DECREF(list); return (PyObject*)NULL; @@ -143,7 +182,7 @@ if (iterations != count) { PyErr_SetString( - TestError, + _testcapistate_global->TestError, "test_dict_iteration: dict iteration went wrong "); return -1; } else { @@ -170,47 +209,24 @@ /* Issue #4701: Check that PyObject_Hash implicitly calls * PyType_Ready if it hasn't already been called */ -static PyTypeObject _HashInheritanceTester_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "hashinheritancetester", /* Name of this type */ - sizeof(PyObject), /* Basic object size */ - 0, /* Item size for varobject */ - (destructor)PyObject_Del, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ + +static PyType_Slot _HashInheritanceTester_Type_slots[] = { + {Py_tp_dealloc, (destructor)PyObject_Del}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_free, }, + {0, 0} }; +static PyType_Spec _HashInheritanceTester_Type_spec = { + "hashinheritancetester", + sizeof(PyObject), + 0, + Py_TPFLAGS_DEFAULT, + _HashInheritanceTester_Type_slots, +}; + + static PyObject* test_lazy_hash_inheritance(PyObject* self) { @@ -218,7 +234,7 @@ PyObject *obj; Py_hash_t hash; - type = &_HashInheritanceTester_Type; + type = (PyTypeObject *)_testcapistate_global->_HashInheritanceTester_Type; if (type->tp_dict != NULL) /* The type has already been initialized. This probably means @@ -227,19 +243,22 @@ obj = PyObject_New(PyObject, type); + Py_INCREF(type); if (obj == NULL) { PyErr_Clear(); PyErr_SetString( - TestError, + _testcapistate_global->TestError, "test_lazy_hash_inheritance: failed to create object"); + Py_DECREF(type); return NULL; } if (type->tp_dict != NULL) { PyErr_SetString( - TestError, + _testcapistate_global->TestError, "test_lazy_hash_inheritance: type initialised too soon"); Py_DECREF(obj); + Py_DECREF(type); return NULL; } @@ -247,29 +266,33 @@ if ((hash == -1) && PyErr_Occurred()) { PyErr_Clear(); PyErr_SetString( - TestError, + _testcapistate_global->TestError, "test_lazy_hash_inheritance: could not hash object"); Py_DECREF(obj); + Py_DECREF(type); return NULL; } if (type->tp_dict == NULL) { PyErr_SetString( - TestError, + _testcapistate_global->TestError, "test_lazy_hash_inheritance: type not initialised by hash()"); Py_DECREF(obj); + Py_DECREF(type); return NULL; } if (type->tp_hash != PyType_Type.tp_hash) { PyErr_SetString( - TestError, + _testcapistate_global->TestError, "test_lazy_hash_inheritance: unexpected hash function"); Py_DECREF(obj); + Py_DECREF(type); return NULL; } Py_DECREF(obj); + Py_DECREF(type); Py_RETURN_NONE; } @@ -1893,7 +1916,7 @@ result = PyUnicode_CompareWithASCIIString(py_s, "str"); Py_DECREF(py_s); if (!result) { - PyErr_SetString(TestError, "Python string ending in NULL " + PyErr_SetString(_testcapistate_global->TestError, "Python string ending in NULL " "should not compare equal to c string."); return NULL; } @@ -2601,6 +2624,7 @@ ob = PyObject_New(test_structmembers, type); if (ob == NULL) return NULL; + Py_INCREF(type); memset(&ob->structmembers, 0, sizeof(all_structmembers)); if (!PyArg_ParseTupleAndKeywords(args, kwargs, fmt, keywords, &ob->structmembers.bool_member, @@ -2622,11 +2646,13 @@ #endif )) { Py_DECREF(ob); + Py_DECREF(type); return NULL; } if (s != NULL) { if (string_len > 5) { Py_DECREF(ob); + Py_DECREF(type); PyErr_SetString(PyExc_ValueError, "string too long"); return NULL; } @@ -2641,80 +2667,68 @@ static void test_structmembers_free(PyObject *ob) { + PyTypeObject *type = Py_TYPE(ob); PyObject_FREE(ob); + if((void *)type->tp_dealloc == (void *)test_structmembers_free) { + Py_DECREF(type); + } } -static PyTypeObject test_structmembersType = { - PyVarObject_HEAD_INIT(NULL, 0) - "test_structmembersType", - sizeof(test_structmembers), /* tp_basicsize */ - 0, /* tp_itemsize */ - test_structmembers_free, /* destructor tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - PyObject_GenericSetAttr, /* tp_setattro */ - 0, /* tp_as_buffer */ - 0, /* tp_flags */ - "Type containing all structmember types", - 0, /* traverseproc tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - test_members, /* tp_members */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - test_structmembers_new, /* tp_new */ +static PyType_Slot test_structmembersType_slots[] = { + {Py_tp_dealloc, test_structmembers_free}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_setattro, PyObject_GenericSetAttr}, + {Py_tp_doc, "Type containing all structmember types"}, + {Py_tp_members, test_members}, + {Py_tp_new, test_structmembers_new}, + {0, 0} }; - +static PyType_Spec test_structmembersType_spec = { + "test_structmembersType", + sizeof(test_structmembers), + 0, + Py_TPFLAGS_DEFAULT, + test_structmembersType_slots, +}; static struct PyModuleDef _testcapimodule = { PyModuleDef_HEAD_INIT, "_testcapi", NULL, - -1, + sizeof(_testcapistate), TestMethods, NULL, - NULL, - NULL, - NULL + _testcapi_traverse, + _testcapi_clear, + _testcapi_free }; PyMODINIT_FUNC PyInit__testcapi(void) { PyObject *m; + _testcapistate *state; m = PyModule_Create(&_testcapimodule); if (m == NULL) return NULL; - Py_TYPE(&_HashInheritanceTester_Type)=&PyType_Type; + state = _testcapi_state(m); - Py_TYPE(&test_structmembersType)=&PyType_Type; - Py_INCREF(&test_structmembersType); + state->_HashInheritanceTester_Type = + PyType_FromSpec(&_HashInheritanceTester_Type_spec); + if(state->_HashInheritanceTester_Type == NULL) + return NULL; + + state->test_structmembersType = + PyType_FromSpec(&test_structmembersType_spec); + if(state->test_structmembersType == NULL) + return NULL; + Py_INCREF(state->test_structmembersType); /* don't use a name starting with "test", since we don't want test_capi to automatically call this */ - PyModule_AddObject(m, "_test_structmembersType", (PyObject *)&test_structmembersType); + PyModule_AddObject(m, "_test_structmembersType", state->test_structmembersType); PyModule_AddObject(m, "CHAR_MAX", PyLong_FromLong(CHAR_MAX)); PyModule_AddObject(m, "CHAR_MIN", PyLong_FromLong(CHAR_MIN)); @@ -2741,8 +2755,8 @@ Py_INCREF(&PyInstanceMethod_Type); PyModule_AddObject(m, "instancemethod", (PyObject *)&PyInstanceMethod_Type); - TestError = PyErr_NewException("_testcapi.error", NULL, NULL); - Py_INCREF(TestError); - PyModule_AddObject(m, "error", TestError); + state->TestError = PyErr_NewException("_testcapi.error", NULL, NULL); + Py_INCREF(state->TestError); + PyModule_AddObject(m, "error", state->TestError); return m; }