diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-01-25-12-31-43.bpo-40077.j-KC3N.rst b/Misc/NEWS.d/next/Core and Builtins/2022-01-25-12-31-43.bpo-40077.j-KC3N.rst new file mode 100644 index 00000000000000..6a61569b6e675a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-01-25-12-31-43.bpo-40077.j-KC3N.rst @@ -0,0 +1 @@ +Convert :mod:`pickle` to use heap types. \ No newline at end of file diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 0d9e57aa90d22f..77dfb2353a9db4 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -177,6 +177,13 @@ typedef struct { /* functools.partial, used for implementing __newobj_ex__ with protocols 2 and 3 */ PyObject *partial; + + /* pickle heap type */ + PyTypeObject *Pickler_Type; + PyTypeObject *Unpickler_Type; + PyTypeObject *PicklerMemoProxyType; + PyTypeObject *UnpicklerMemoProxyType; + PyTypeObject *Pdata_Type; } PickleState; /* Forward declaration of the _pickle module definition. */ @@ -197,6 +204,11 @@ _Pickle_GetGlobalState(void) return _Pickle_GetState(PyState_FindModule(&_picklemodule)); } +#define find_pickle_state_by_type(tp) \ + (_Pickle_GetState(_PyType_GetModuleByDef(tp, &_picklemodule))) +#define get_pickle_state_by_class(cls) \ + (_Pickle_GetState(PyType_GetModule(cls))) + /* Clear the given pickle module state. */ static void _Pickle_ClearState(PickleState *st) @@ -215,6 +227,11 @@ _Pickle_ClearState(PickleState *st) Py_CLEAR(st->codecs_encode); Py_CLEAR(st->getattr); Py_CLEAR(st->partial); + Py_CLEAR(st->Pickler_Type); + Py_CLEAR(st->Unpickler_Type); + Py_CLEAR(st->Pdata_Type); + Py_CLEAR(st->PicklerMemoProxyType); + Py_CLEAR(st->UnpicklerMemoProxyType); } /* Initialize the given pickle module state. */ @@ -442,28 +459,34 @@ typedef struct { static void Pdata_dealloc(Pdata *self) { + PyTypeObject *tp = Py_TYPE(self); Py_ssize_t i = Py_SIZE(self); while (--i >= 0) { Py_DECREF(self->data[i]); } PyMem_Free(self->data); PyObject_Free(self); + Py_DECREF(tp); } -static PyTypeObject Pdata_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_pickle.Pdata", /*tp_name*/ - sizeof(Pdata), /*tp_basicsize*/ - sizeof(PyObject *), /*tp_itemsize*/ - (destructor)Pdata_dealloc, /*tp_dealloc*/ +static PyType_Slot Pdata_Type_spec_slots[] = { + {Py_tp_dealloc, (destructor)Pdata_dealloc}, + {0, 0} +}; + +static PyType_Spec Pdata_Type_spec = { + .name = "_pickle.Pdata", + .basicsize = sizeof(Pdata), + .itemsize = sizeof(PyObject *), + .slots = Pdata_Type_spec_slots, }; static PyObject * -Pdata_New(void) +Pdata_New(PickleState *state) { Pdata *self; - if (!(self = PyObject_New(Pdata, &Pdata_Type))) + if (!(self = PyObject_New(Pdata, state->Pdata_Type))) return NULL; Py_SET_SIZE(self, 0); self->mark_set = 0; @@ -712,8 +735,6 @@ typedef struct { /* Forward declarations */ static int save(PicklerObject *, PyObject *, int); static int save_reduce(PicklerObject *, PyObject *, PyObject *); -static PyTypeObject Pickler_Type; -static PyTypeObject Unpickler_Type; #include "clinic/_pickle.c.h" @@ -1106,11 +1127,11 @@ _Pickler_Write(PicklerObject *self, const char *s, Py_ssize_t data_len) } static PicklerObject * -_Pickler_New(void) +_Pickler_New(PickleState *state) { PicklerObject *self; - self = PyObject_GC_New(PicklerObject, &Pickler_Type); + self = PyObject_GC_New(PicklerObject, state->Pickler_Type); if (self == NULL) return NULL; @@ -1590,11 +1611,11 @@ _Unpickler_MemoCleanup(UnpicklerObject *self) } static UnpicklerObject * -_Unpickler_New(void) +_Unpickler_New(PickleState *state) { UnpicklerObject *self; - self = PyObject_GC_New(UnpicklerObject, &Unpickler_Type); + self = PyObject_GC_New(UnpicklerObject, state->Unpickler_Type); if (self == NULL) return NULL; @@ -1620,7 +1641,7 @@ _Unpickler_New(void) self->memo_size = 32; self->memo_len = 0; self->memo = _Unpickler_NewMemo(self->memo_size); - self->stack = (Pdata *)Pdata_New(); + self->stack = (Pdata *)Pdata_New(state); if (self->memo == NULL || self->stack == NULL) { Py_DECREF(self); @@ -4632,6 +4653,8 @@ static struct PyMethodDef Pickler_methods[] = { static void Pickler_dealloc(PicklerObject *self) { + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); Py_XDECREF(self->output_buffer); @@ -4644,7 +4667,8 @@ Pickler_dealloc(PicklerObject *self) PyMemoTable_Del(self->memo); - Py_TYPE(self)->tp_free((PyObject *)self); + tp->tp_free((PyObject *)self); + Py_DECREF(tp); } static int @@ -4889,9 +4913,12 @@ static PyMethodDef picklerproxy_methods[] = { static void PicklerMemoProxy_dealloc(PicklerMemoProxyObject *self) { + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); Py_XDECREF(self->pickler); PyObject_GC_Del((PyObject *)self); + Py_DECREF(tp); } static int @@ -4909,43 +4936,31 @@ PicklerMemoProxy_clear(PicklerMemoProxyObject *self) return 0; } -static PyTypeObject PicklerMemoProxyType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_pickle.PicklerMemoProxy", /*tp_name*/ - sizeof(PicklerMemoProxyObject), /*tp_basicsize*/ - 0, - (destructor)PicklerMemoProxy_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - PyObject_HashNotImplemented, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - PyObject_GenericSetAttr, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, - 0, /* tp_doc */ - (traverseproc)PicklerMemoProxy_traverse, /* tp_traverse */ - (inquiry)PicklerMemoProxy_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - picklerproxy_methods, /* tp_methods */ +static PyType_Slot PicklerMemoProxyType_spec_slots[] = { + {Py_tp_dealloc, (destructor)PicklerMemoProxy_dealloc}, + {Py_tp_hash, PyObject_HashNotImplemented}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_setattro, PyObject_GenericSetAttr}, + {Py_tp_traverse, (traverseproc)PicklerMemoProxy_traverse}, + {Py_tp_clear, (inquiry)PicklerMemoProxy_clear}, + {Py_tp_methods, picklerproxy_methods}, + {0, 0} +}; + +static PyType_Spec PicklerMemoProxyType_spec = { + .name = "_pickle.PicklerMemoProxy", + .basicsize = sizeof(PicklerMemoProxyObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .slots = PicklerMemoProxyType_spec_slots, }; static PyObject * PicklerMemoProxy_New(PicklerObject *pickler) { PicklerMemoProxyObject *self; + PickleState *state = get_pickle_state_by_class(Py_TYPE(pickler)); - self = PyObject_GC_New(PicklerMemoProxyObject, &PicklerMemoProxyType); + self = PyObject_GC_New(PicklerMemoProxyObject, state->PicklerMemoProxyType); if (self == NULL) return NULL; Py_INCREF(pickler); @@ -4973,7 +4988,9 @@ Pickler_set_memo(PicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored)) return -1; } - if (Py_IS_TYPE(obj, &PicklerMemoProxyType)) { + PickleState *state = get_pickle_state_by_class(Py_TYPE(self)); + + if (Py_IS_TYPE(obj, state->PicklerMemoProxyType)) { PicklerObject *pickler = ((PicklerMemoProxyObject *)obj)->pickler; @@ -5070,47 +5087,26 @@ static PyGetSetDef Pickler_getsets[] = { {NULL} }; -static PyTypeObject Pickler_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_pickle.Pickler" , /*tp_name*/ - sizeof(PicklerObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)Pickler_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, - _pickle_Pickler___init____doc__, /*tp_doc*/ - (traverseproc)Pickler_traverse, /*tp_traverse*/ - (inquiry)Pickler_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - Pickler_methods, /*tp_methods*/ - Pickler_members, /*tp_members*/ - Pickler_getsets, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - _pickle_Pickler___init__, /*tp_init*/ - PyType_GenericAlloc, /*tp_alloc*/ - PyType_GenericNew, /*tp_new*/ - PyObject_GC_Del, /*tp_free*/ - 0, /*tp_is_gc*/ +static PyType_Slot Pickler_Type_spec_slots[] = { + {Py_tp_dealloc, (destructor)Pickler_dealloc}, + {Py_tp_doc, (void *)_pickle_Pickler___init____doc__}, + {Py_tp_traverse, (traverseproc)Pickler_traverse}, + {Py_tp_clear, (inquiry)Pickler_clear}, + {Py_tp_methods, Pickler_methods}, + {Py_tp_members, Pickler_members}, + {Py_tp_getset, Pickler_getsets}, + {Py_tp_init, _pickle_Pickler___init__}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_free, PyObject_GC_Del}, + {0, 0} +}; + +static PyType_Spec Pickler_Type_spec = { + .name = "_pickle.Pickler", + .basicsize = sizeof(PicklerObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .slots = Pickler_Type_spec_slots, }; /* Temporary helper for calling self.find_class(). @@ -7149,6 +7145,8 @@ static struct PyMethodDef Unpickler_methods[] = { static void Unpickler_dealloc(UnpicklerObject *self) { + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack((PyObject *)self); Py_XDECREF(self->readline); Py_XDECREF(self->readinto); @@ -7168,7 +7166,8 @@ Unpickler_dealloc(UnpicklerObject *self) PyMem_Free(self->encoding); PyMem_Free(self->errors); - Py_TYPE(self)->tp_free((PyObject *)self); + tp->tp_free((PyObject *)self); + Py_DECREF(tp); } static int @@ -7274,7 +7273,9 @@ _pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, return -1; } - self->stack = (Pdata *)Pdata_New(); + PickleState *state = find_pickle_state_by_type(Py_TYPE(self)); + + self->stack = (Pdata *)Pdata_New(state); if (self->stack == NULL) return -1; @@ -7401,9 +7402,12 @@ static PyMethodDef unpicklerproxy_methods[] = { static void UnpicklerMemoProxy_dealloc(UnpicklerMemoProxyObject *self) { + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); Py_XDECREF(self->unpickler); PyObject_GC_Del((PyObject *)self); + Py_DECREF(tp); } static int @@ -7421,35 +7425,22 @@ UnpicklerMemoProxy_clear(UnpicklerMemoProxyObject *self) return 0; } -static PyTypeObject UnpicklerMemoProxyType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_pickle.UnpicklerMemoProxy", /*tp_name*/ - sizeof(UnpicklerMemoProxyObject), /*tp_basicsize*/ - 0, - (destructor)UnpicklerMemoProxy_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - PyObject_HashNotImplemented, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - PyObject_GenericSetAttr, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, - 0, /* tp_doc */ - (traverseproc)UnpicklerMemoProxy_traverse, /* tp_traverse */ - (inquiry)UnpicklerMemoProxy_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - unpicklerproxy_methods, /* tp_methods */ +static PyType_Slot UnpicklerMemoProxyType_spec_slots[] = { + {Py_tp_dealloc, (destructor)UnpicklerMemoProxy_dealloc}, + {Py_tp_hash, PyObject_HashNotImplemented}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_setattro, PyObject_GenericSetAttr}, + {Py_tp_traverse, (traverseproc)UnpicklerMemoProxy_traverse}, + {Py_tp_clear, (inquiry)UnpicklerMemoProxy_clear}, + {Py_tp_methods, unpicklerproxy_methods}, + {0, 0} +}; + +static PyType_Spec UnpicklerMemoProxyType_spec = { + .name = "_pickle.UnpicklerMemoProxy", + .basicsize = sizeof(UnpicklerMemoProxyObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .slots = UnpicklerMemoProxyType_spec_slots, }; static PyObject * @@ -7457,8 +7448,10 @@ UnpicklerMemoProxy_New(UnpicklerObject *unpickler) { UnpicklerMemoProxyObject *self; + PickleState *state = find_pickle_state_by_type(Py_TYPE(unpickler)); + self = PyObject_GC_New(UnpicklerMemoProxyObject, - &UnpicklerMemoProxyType); + state->UnpicklerMemoProxyType); if (self == NULL) return NULL; Py_INCREF(unpickler); @@ -7488,7 +7481,9 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored return -1; } - if (Py_IS_TYPE(obj, &UnpicklerMemoProxyType)) { + PickleState *state = find_pickle_state_by_type(Py_TYPE(self)); + + if (Py_IS_TYPE(obj, state->UnpicklerMemoProxyType)) { UnpicklerObject *unpickler = ((UnpicklerMemoProxyObject *)obj)->unpickler; @@ -7592,47 +7587,25 @@ static PyGetSetDef Unpickler_getsets[] = { {NULL} }; -static PyTypeObject Unpickler_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_pickle.Unpickler", /*tp_name*/ - sizeof(UnpicklerObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)Unpickler_dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, - _pickle_Unpickler___init____doc__, /*tp_doc*/ - (traverseproc)Unpickler_traverse, /*tp_traverse*/ - (inquiry)Unpickler_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - Unpickler_methods, /*tp_methods*/ - 0, /*tp_members*/ - Unpickler_getsets, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - _pickle_Unpickler___init__, /*tp_init*/ - PyType_GenericAlloc, /*tp_alloc*/ - PyType_GenericNew, /*tp_new*/ - PyObject_GC_Del, /*tp_free*/ - 0, /*tp_is_gc*/ +static PyType_Slot Unpickler_Type_spec_slots[] = { + {Py_tp_dealloc, (destructor)Unpickler_dealloc}, + {Py_tp_doc, (void *)_pickle_Unpickler___init____doc__}, + {Py_tp_traverse, (traverseproc)Unpickler_traverse}, + {Py_tp_clear, (inquiry)Unpickler_clear}, + {Py_tp_methods, Unpickler_methods}, + {Py_tp_getset, Unpickler_getsets}, + {Py_tp_init, _pickle_Unpickler___init__}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_free, PyObject_GC_Del}, + {0, 0} +}; + +static PyType_Spec Unpickler_Type_spec = { + .name = "_pickle.Unpickler", + .basicsize = sizeof(UnpicklerObject), + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + .slots = Unpickler_Type_spec_slots, }; /*[clinic input] @@ -7681,7 +7654,8 @@ _pickle_dump_impl(PyObject *module, PyObject *obj, PyObject *file, PyObject *buffer_callback) /*[clinic end generated code: output=706186dba996490c input=5ed6653da99cd97c]*/ { - PicklerObject *pickler = _Pickler_New(); + PickleState *state = _Pickle_GetState(module); + PicklerObject *pickler = _Pickler_New(state); if (pickler == NULL) return NULL; @@ -7746,7 +7720,8 @@ _pickle_dumps_impl(PyObject *module, PyObject *obj, PyObject *protocol, /*[clinic end generated code: output=fbab0093a5580fdf input=e543272436c6f987]*/ { PyObject *result; - PicklerObject *pickler = _Pickler_New(); + PickleState *state = _Pickle_GetState(module); + PicklerObject *pickler = _Pickler_New(state); if (pickler == NULL) return NULL; @@ -7812,7 +7787,8 @@ _pickle_load_impl(PyObject *module, PyObject *file, int fix_imports, /*[clinic end generated code: output=250452d141c23e76 input=46c7c31c92f4f371]*/ { PyObject *result; - UnpicklerObject *unpickler = _Unpickler_New(); + PickleState *state = _Pickle_GetState(module); + UnpicklerObject *unpickler = _Unpickler_New(state); if (unpickler == NULL) return NULL; @@ -7872,7 +7848,8 @@ _pickle_loads_impl(PyObject *module, PyObject *data, int fix_imports, /*[clinic end generated code: output=82ac1e6b588e6d02 input=b3615540d0535087]*/ { PyObject *result; - UnpicklerObject *unpickler = _Unpickler_New(); + PickleState *state = _Pickle_GetState(module); + UnpicklerObject *unpickler = _Unpickler_New(state); if (unpickler == NULL) return NULL; @@ -7936,6 +7913,11 @@ pickle_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(st->codecs_encode); Py_VISIT(st->getattr); Py_VISIT(st->partial); + Py_VISIT(st->Pickler_Type); + Py_VISIT(st->Unpickler_Type); + Py_VISIT(st->Pdata_Type); + Py_VISIT(st->PicklerMemoProxyType); + Py_VISIT(st->UnpicklerMemoProxyType); return 0; } @@ -7955,7 +7937,7 @@ PyMODINIT_FUNC PyInit__pickle(void) { PyObject *m; - PickleState *st; + PickleState *state; m = PyState_FindModule(&_picklemodule); if (m) { @@ -7963,55 +7945,63 @@ PyInit__pickle(void) return m; } - if (PyType_Ready(&Pdata_Type) < 0) - return NULL; - if (PyType_Ready(&PicklerMemoProxyType) < 0) - return NULL; - if (PyType_Ready(&UnpicklerMemoProxyType) < 0) - return NULL; - /* Create the module and add the functions. */ m = PyModule_Create(&_picklemodule); if (m == NULL) return NULL; + state = _Pickle_GetState(m); + + state->Pdata_Type = (PyTypeObject *)PyType_FromModuleAndSpec(m, &Pdata_Type_spec, NULL); + if (PyType_Ready(state->Pdata_Type) < 0) { + return NULL; + } + state->PicklerMemoProxyType = (PyTypeObject *)PyType_FromModuleAndSpec(m, &PicklerMemoProxyType_spec, NULL); + if (PyType_Ready(state->PicklerMemoProxyType) < 0) { + return NULL; + } + state->UnpicklerMemoProxyType = (PyTypeObject *)PyType_FromModuleAndSpec(m, &UnpicklerMemoProxyType_spec, NULL); + if (PyType_Ready(state->UnpicklerMemoProxyType) < 0) { + return NULL; + } + /* Add types */ - if (PyModule_AddType(m, &Pickler_Type) < 0) { + state->Pickler_Type = (PyTypeObject *)PyType_FromModuleAndSpec(m, &Pickler_Type_spec, NULL); + if (PyModule_AddType(m, state->Pickler_Type) < 0) { return NULL; } - if (PyModule_AddType(m, &Unpickler_Type) < 0) { + state->Unpickler_Type = (PyTypeObject *)PyType_FromModuleAndSpec(m, &Unpickler_Type_spec, NULL); + if (PyModule_AddType(m, state->Unpickler_Type) < 0) { return NULL; } if (PyModule_AddType(m, &PyPickleBuffer_Type) < 0) { return NULL; } - st = _Pickle_GetState(m); - /* Initialize the exceptions. */ - st->PickleError = PyErr_NewException("_pickle.PickleError", NULL, NULL); - if (st->PickleError == NULL) + state->PickleError = PyErr_NewException("_pickle.PickleError", NULL, NULL); + if (state->PickleError == NULL) return NULL; - st->PicklingError = \ - PyErr_NewException("_pickle.PicklingError", st->PickleError, NULL); - if (st->PicklingError == NULL) + state->PicklingError = \ + PyErr_NewException("_pickle.PicklingError", state->PickleError, NULL); + if (state->PicklingError == NULL) return NULL; - st->UnpicklingError = \ - PyErr_NewException("_pickle.UnpicklingError", st->PickleError, NULL); - if (st->UnpicklingError == NULL) + state->UnpicklingError = \ + PyErr_NewException("_pickle.UnpicklingError", state->PickleError, NULL); + if (state->UnpicklingError == NULL) return NULL; - Py_INCREF(st->PickleError); - if (PyModule_AddObject(m, "PickleError", st->PickleError) < 0) + Py_INCREF(state->PickleError); + if (PyModule_AddObject(m, "PickleError", state->PickleError) < 0) return NULL; - Py_INCREF(st->PicklingError); - if (PyModule_AddObject(m, "PicklingError", st->PicklingError) < 0) + Py_INCREF(state->PicklingError); + if (PyModule_AddObject(m, "PicklingError", state->PicklingError) < 0) return NULL; - Py_INCREF(st->UnpicklingError); - if (PyModule_AddObject(m, "UnpicklingError", st->UnpicklingError) < 0) + Py_INCREF(state->UnpicklingError); + if (PyModule_AddObject(m, "UnpicklingError", state->UnpicklingError) < 0) return NULL; - if (_Pickle_InitState(st) < 0) + if (_Pickle_InitState(state) < 0) return NULL; return m;