diff -r a4dfcbb860e4 Modules/operator.c --- a/Modules/operator.c Thu Aug 16 11:05:39 2012 +0200 +++ b/Modules/operator.c Thu Aug 16 11:09:17 2012 +0200 @@ -1,6 +1,43 @@ #include "Python.h" +typedef struct { + PyObject *itemgetter_type; + PyObject *attrgetter_type; + PyObject *methodcaller_type; +} operatorstate; + +#define operator_state(o) ((operatorstate *)PyModule_GetState(o)) + +static int +operator_clear(PyObject *m) +{ + Py_CLEAR(operator_state(m)->itemgetter_type); + Py_CLEAR(operator_state(m)->attrgetter_type); + Py_CLEAR(operator_state(m)->methodcaller_type); + return 0; +} + +static int +operator_traverse(PyObject *m, visitproc visit, void *arg) +{ + Py_VISIT(operator_state(m)->itemgetter_type); + Py_VISIT(operator_state(m)->attrgetter_type); + Py_VISIT(operator_state(m)->methodcaller_type); + return 0; +} + +static void +operator_free(void *m) +{ + operator_clear((PyObject *)m); +} + +static PyModuleDef operatormodule; + +#define operatorstate_global ((operatorstate *)PyModule_GetState(PyState_FindModule(&operatormodule))) + + PyDoc_STRVAR(operator_doc, "Operator interface.\n\ \n\ @@ -378,7 +415,6 @@ PyObject *item; } itemgetterobject; -static PyTypeObject itemgetter_type; static PyObject * itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -398,9 +434,11 @@ item = args; /* create itemgetterobject structure */ - ig = PyObject_GC_New(itemgetterobject, &itemgetter_type); + ig = PyObject_GC_New(itemgetterobject, + (PyTypeObject *)operatorstate_global->itemgetter_type); if (ig == NULL) return NULL; + Py_INCREF(operatorstate_global->itemgetter_type); Py_INCREF(item); ig->item = item; @@ -413,8 +451,12 @@ static void itemgetter_dealloc(itemgetterobject *ig) { + PyTypeObject *type = Py_TYPE(ig); PyObject_GC_UnTrack(ig); Py_XDECREF(ig->item); + if((void *)type->tp_dealloc == (void *)itemgetter_dealloc) { + Py_DECREF(type); + } PyObject_GC_Del(ig); } @@ -463,49 +505,27 @@ After, f=itemgetter(2), the call f(r) returns r[2].\n\ After, g=itemgetter(2,5,3), the call g(r) returns (r[2], r[5], r[3])"); -static PyTypeObject itemgetter_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "operator.itemgetter", /* tp_name */ - sizeof(itemgetterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)itemgetter_dealloc, /* 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 */ - (ternaryfunc)itemgetter_call, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - itemgetter_doc, /* tp_doc */ - (traverseproc)itemgetter_traverse, /* 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 */ - itemgetter_new, /* tp_new */ - 0, /* tp_free */ + +static PyType_Slot itemgetter_type_slots[] = { + {Py_tp_dealloc, (destructor)itemgetter_dealloc}, + {Py_tp_call, (ternaryfunc)itemgetter_call}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, itemgetter_doc}, + {Py_tp_traverse, (traverseproc)itemgetter_traverse}, + {Py_tp_new, itemgetter_new}, + {Py_tp_is_gc, }, + {0, 0} }; +static PyType_Spec itemgetter_type_spec = { + "operator.itemgetter", + sizeof(itemgetterobject), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + itemgetter_type_slots, +}; + + /* attrgetter object **********************************************************/ @@ -515,8 +535,6 @@ PyObject *attr; } attrgetterobject; -static PyTypeObject attrgetter_type; - static PyObject * attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -616,11 +634,13 @@ } /* create attrgetterobject structure */ - ag = PyObject_GC_New(attrgetterobject, &attrgetter_type); + ag = PyObject_GC_New(attrgetterobject, + (PyTypeObject *)operatorstate_global->attrgetter_type); if (ag == NULL) { Py_DECREF(attr); return NULL; } + Py_INCREF(operatorstate_global->attrgetter_type); ag->attr = attr; ag->nattrs = nattrs; @@ -632,8 +652,12 @@ static void attrgetter_dealloc(attrgetterobject *ag) { + PyTypeObject *type = Py_TYPE(ag); PyObject_GC_UnTrack(ag); Py_XDECREF(ag->attr); + if ((void *)type->tp_dealloc == (void *)attrgetter_dealloc) { + Py_DECREF(type); + } PyObject_GC_Del(ag); } @@ -717,49 +741,28 @@ After, h=attrgetter('name.first', 'name.last'), the call h(r) returns\n\ (r.name.first, r.name.last)."); -static PyTypeObject attrgetter_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "operator.attrgetter", /* tp_name */ - sizeof(attrgetterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)attrgetter_dealloc, /* 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 */ - (ternaryfunc)attrgetter_call, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - attrgetter_doc, /* tp_doc */ - (traverseproc)attrgetter_traverse, /* 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 */ - attrgetter_new, /* tp_new */ - 0, /* tp_free */ + + + +static PyType_Slot attrgetter_type_slots[] = { + {Py_tp_dealloc, (destructor)attrgetter_dealloc}, + {Py_tp_call, (ternaryfunc)attrgetter_call}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, attrgetter_doc}, + {Py_tp_traverse, (traverseproc)attrgetter_traverse}, + {Py_tp_new, attrgetter_new}, + {0, 0} }; +static PyType_Spec attrgetter_type_spec = { + "operator.attrgetter", + sizeof(attrgetterobject), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + attrgetter_type_slots, +}; + + /* methodcaller object **********************************************************/ @@ -770,8 +773,6 @@ PyObject *kwds; } methodcallerobject; -static PyTypeObject methodcaller_type; - static PyObject * methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -785,7 +786,8 @@ } /* create methodcallerobject structure */ - mc = PyObject_GC_New(methodcallerobject, &methodcaller_type); + mc = PyObject_GC_New(methodcallerobject, + (PyTypeObject *)operatorstate_global->methodcaller_type); if (mc == NULL) return NULL; @@ -794,6 +796,7 @@ Py_DECREF(mc); return NULL; } + Py_INCREF(operatorstate_global->methodcaller_type); mc->args = newargs; name = PyTuple_GET_ITEM(args, 0); @@ -848,49 +851,28 @@ After, g = methodcaller('name', 'date', foo=1), the call g(r) returns\n\ r.name('date', foo=1)."); -static PyTypeObject methodcaller_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "operator.methodcaller", /* tp_name */ - sizeof(methodcallerobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)methodcaller_dealloc, /* 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 */ - (ternaryfunc)methodcaller_call, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - methodcaller_doc, /* tp_doc */ - (traverseproc)methodcaller_traverse, /* 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 */ - methodcaller_new, /* tp_new */ - 0, /* tp_free */ + + + +static PyType_Slot methodcaller_type_slots[] = { + {Py_tp_dealloc, (destructor)methodcaller_dealloc}, + {Py_tp_call, (ternaryfunc)methodcaller_call}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, methodcaller_doc}, + {Py_tp_traverse, (traverseproc)methodcaller_traverse}, + {Py_tp_new, methodcaller_new}, + {0, 0} }; +static PyType_Spec methodcaller_type_spec = { + "operator.methodcaller", + sizeof(methodcallerobject), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + methodcaller_type_slots, +}; + + /* Initialization function for the module (*must* be called PyInit_operator) */ @@ -899,12 +881,12 @@ PyModuleDef_HEAD_INIT, "operator", operator_doc, - -1, + sizeof(operatorstate), operator_methods, NULL, - NULL, - NULL, - NULL + operator_traverse, + operator_clear, + operator_free, }; PyMODINIT_FUNC @@ -917,19 +899,23 @@ if (m == NULL) return NULL; - if (PyType_Ready(&itemgetter_type) < 0) + operator_state(m)->itemgetter_type = PyType_FromSpec(&itemgetter_type_spec); + if (operator_state(m)->itemgetter_type == NULL) return NULL; - Py_INCREF(&itemgetter_type); - PyModule_AddObject(m, "itemgetter", (PyObject *)&itemgetter_type); + Py_INCREF(operator_state(m)->itemgetter_type); + PyModule_AddObject(m, "itemgetter", operator_state(m)->itemgetter_type); - if (PyType_Ready(&attrgetter_type) < 0) + operator_state(m)->attrgetter_type = PyType_FromSpec(&attrgetter_type_spec); + if (operator_state(m)->attrgetter_type == NULL) return NULL; - Py_INCREF(&attrgetter_type); - PyModule_AddObject(m, "attrgetter", (PyObject *)&attrgetter_type); + Py_INCREF(operator_state(m)->attrgetter_type); + PyModule_AddObject(m, "attrgetter", operator_state(m)->attrgetter_type); - if (PyType_Ready(&methodcaller_type) < 0) + operator_state(m)->methodcaller_type = + PyType_FromSpec(&methodcaller_type_spec); + if (operator_state(m)->methodcaller_type == NULL) return NULL; - Py_INCREF(&methodcaller_type); - PyModule_AddObject(m, "methodcaller", (PyObject *)&methodcaller_type); + Py_INCREF(operator_state(m)->methodcaller_type); + PyModule_AddObject(m, "methodcaller", operator_state(m)->methodcaller_type); return m; }