diff -r efc1d0fccb17 Modules/_lzmamodule.c --- a/Modules/_lzmamodule.c Wed Aug 15 15:02:13 2012 +0200 +++ b/Modules/_lzmamodule.c Wed Aug 15 15:22:25 2012 +0200 @@ -69,12 +69,49 @@ #endif } Decompressor; -/* LZMAError class object. */ -static PyObject *Error; +typedef struct { + /* LZMAError class object. */ + PyObject *Error; + /* An empty tuple, used by the filter specifier parsing code. */ + PyObject *empty_tuple; + PyObject *Compressor_type; + PyObject *Decompressor_type; +} _lzmastate; -/* An empty tuple, used by the filter specifier parsing code. */ -static PyObject *empty_tuple; +#define _lzma_state(o) ((_lzmastate *)PyModule_GetState(o)) + +static int +_lzma_clear(PyObject *m) +{ + _lzmastate *s = _lzma_state(m); + Py_CLEAR(s->Compressor_type); + Py_CLEAR(s->Decompressor_type); + Py_CLEAR(s->Error); + Py_CLEAR(s->empty_tuple); + return 0; +} + +static int +_lzma_traverse(PyObject *m, visitproc visit, void *arg) +{ + _lzmastate *s = _lzma_state(m); + Py_VISIT(s->Compressor_type); + Py_VISIT(s->Decompressor_type); + Py_VISIT(s->Error); + Py_VISIT(s->empty_tuple); + return 0; +} + +static void +_lzma_free(void *m) +{ + _lzma_clear((PyObject *)m); +} + +static PyModuleDef _lzmamodule; + +#define _lzmastate_global ((_lzmastate *)PyModule_GetState(PyState_FindModule(&_lzmamodule))) /* Helper functions. */ @@ -88,31 +125,31 @@ case LZMA_STREAM_END: return 0; case LZMA_UNSUPPORTED_CHECK: - PyErr_SetString(Error, "Unsupported integrity check"); + PyErr_SetString(_lzmastate_global->Error, "Unsupported integrity check"); return 1; case LZMA_MEM_ERROR: PyErr_NoMemory(); return 1; case LZMA_MEMLIMIT_ERROR: - PyErr_SetString(Error, "Memory usage limit exceeded"); + PyErr_SetString(_lzmastate_global->Error, "Memory usage limit exceeded"); return 1; case LZMA_FORMAT_ERROR: - PyErr_SetString(Error, "Input format not supported by decoder"); + PyErr_SetString(_lzmastate_global->Error, "Input format not supported by decoder"); return 1; case LZMA_OPTIONS_ERROR: - PyErr_SetString(Error, "Invalid or unsupported options"); + PyErr_SetString(_lzmastate_global->Error, "Invalid or unsupported options"); return 1; case LZMA_DATA_ERROR: - PyErr_SetString(Error, "Corrupt input data"); + PyErr_SetString(_lzmastate_global->Error, "Corrupt input data"); return 1; case LZMA_BUF_ERROR: - PyErr_SetString(Error, "Insufficient buffer space"); + PyErr_SetString(_lzmastate_global->Error, "Insufficient buffer space"); return 1; case LZMA_PROG_ERROR: - PyErr_SetString(Error, "Internal error"); + PyErr_SetString(_lzmastate_global->Error, "Internal error"); return 1; default: - PyErr_Format(Error, "Unrecognized error from liblzma: %d", lzret); + PyErr_Format(_lzmastate_global->Error, "Unrecognized error from liblzma: %d", lzret); return 1; } } @@ -210,11 +247,11 @@ if (lzma_lzma_preset(options, preset)) { PyMem_Free(options); - PyErr_Format(Error, "Invalid compression preset: %d", preset); + PyErr_Format(_lzmastate_global->Error, "Invalid compression preset: %d", preset); return NULL; } - if (!PyArg_ParseTupleAndKeywords(empty_tuple, spec, + if (!PyArg_ParseTupleAndKeywords(_lzmastate_global->empty_tuple, spec, "|OOO&O&O&O&O&O&O&O&", optnames, &id, &preset_obj, uint32_converter, &options->dict_size, @@ -241,7 +278,7 @@ uint32_t dist = 1; lzma_options_delta *options; - if (!PyArg_ParseTupleAndKeywords(empty_tuple, spec, "|OO&", optnames, + if (!PyArg_ParseTupleAndKeywords(_lzmastate_global->empty_tuple, spec, "|OO&", optnames, &id, uint32_converter, &dist)) { PyErr_SetString(PyExc_ValueError, "Invalid filter specifier for delta filter"); @@ -265,7 +302,7 @@ uint32_t start_offset = 0; lzma_options_bcj *options; - if (!PyArg_ParseTupleAndKeywords(empty_tuple, spec, "|OO&", optnames, + if (!PyArg_ParseTupleAndKeywords(_lzmastate_global->empty_tuple, spec, "|OO&", optnames, &id, uint32_converter, &start_offset)) { PyErr_SetString(PyExc_ValueError, "Invalid filter specifier for BCJ filter"); @@ -577,7 +614,7 @@ lzma_options_lzma options; if (lzma_lzma_preset(&options, preset)) { - PyErr_Format(Error, "Invalid compression preset: %d", preset); + PyErr_Format(_lzmastate_global->Error, "Invalid compression preset: %d", preset); return -1; } lzret = lzma_alone_encoder(lzs, &options); @@ -699,12 +736,16 @@ static void Compressor_dealloc(Compressor *self) { + PyTypeObject *type = Py_TYPE(self); lzma_end(&self->lzs); #ifdef WITH_THREAD if (self->lock != NULL) PyThread_free_lock(self->lock); #endif - Py_TYPE(self)->tp_free((PyObject *)self); + type->tp_free((PyObject *)self); + if((void *)type->tp_dealloc == (void *)Compressor_dealloc) { + Py_DECREF(type); + } } static PyMethodDef Compressor_methods[] = { @@ -743,47 +784,25 @@ "\n" "For one-shot compression, use the compress() function instead.\n"); -static PyTypeObject Compressor_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_lzma.LZMACompressor", /* tp_name */ - sizeof(Compressor), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)Compressor_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 */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - Compressor_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Compressor_methods, /* 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 */ - (initproc)Compressor_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ +static PyType_Slot Compressor_type_slots[] = { + {Py_tp_dealloc, (destructor)Compressor_dealloc}, + {Py_tp_doc, Compressor_doc}, + {Py_tp_methods, Compressor_methods}, + {Py_tp_init, (initproc)Compressor_init}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_free, }, + {0, 0} }; +static PyType_Spec Compressor_type_spec = { + "_lzma.LZMACompressor", + sizeof(Compressor), + 0, + Py_TPFLAGS_DEFAULT, + Compressor_type_slots, +}; + + /* LZMADecompressor class. */ @@ -979,13 +998,17 @@ static void Decompressor_dealloc(Decompressor *self) { + PyTypeObject *type = Py_TYPE(self); lzma_end(&self->lzs); Py_CLEAR(self->unused_data); #ifdef WITH_THREAD if (self->lock != NULL) PyThread_free_lock(self->lock); #endif - Py_TYPE(self)->tp_free((PyObject *)self); + type->tp_free((PyObject *)self); + if((void *)type->tp_dealloc == (void *)Decompressor_dealloc) { + Py_DECREF(type); + } } static PyMethodDef Decompressor_methods[] = { @@ -1034,47 +1057,26 @@ "\n" "For one-shot decompression, use the decompress() function instead.\n"); -static PyTypeObject Decompressor_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_lzma.LZMADecompressor", /* tp_name */ - sizeof(Decompressor), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)Decompressor_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 */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - Decompressor_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Decompressor_methods, /* tp_methods */ - Decompressor_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)Decompressor_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ +static PyType_Slot Decompressor_type_slots[] = { + {Py_tp_dealloc, (destructor)Decompressor_dealloc}, + {Py_tp_doc, Decompressor_doc}, + {Py_tp_methods, Decompressor_methods}, + {Py_tp_members, Decompressor_members}, + {Py_tp_init, (initproc)Decompressor_init}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_free, }, + {0, 0} }; +static PyType_Spec Decompressor_type_spec = { + "_lzma.LZMADecompressor", + sizeof(Decompressor), + 0, + Py_TPFLAGS_DEFAULT, + Decompressor_type_slots, +}; + + /* Module-level functions. */ @@ -1192,12 +1194,12 @@ PyModuleDef_HEAD_INIT, "_lzma", NULL, - -1, + sizeof(_lzmastate), module_methods, NULL, - NULL, - NULL, - NULL, + _lzma_traverse, + _lzma_clear, + _lzma_free, }; /* Some of our constants are more than 32 bits wide, so PyModule_AddIntConstant @@ -1222,12 +1224,14 @@ { PyObject *m; - empty_tuple = PyTuple_New(0); - if (empty_tuple == NULL) + m = PyModule_Create(&_lzmamodule); + if (m == NULL) return NULL; - m = PyModule_Create(&_lzmamodule); - if (m == NULL) + PyState_AddModule(m, &_lzmamodule); + + _lzma_state(m)->empty_tuple = PyTuple_New(0); + if (_lzma_state(m)->empty_tuple == NULL) return NULL; if (PyModule_AddIntMacro(m, FORMAT_AUTO) == -1 || @@ -1260,26 +1264,28 @@ ADD_INT_PREFIX_MACRO(m, PRESET_EXTREME) == -1) return NULL; - Error = PyErr_NewExceptionWithDoc( + _lzma_state(m)->Error = PyErr_NewExceptionWithDoc( "_lzma.LZMAError", "Call to liblzma failed.", NULL, NULL); - if (Error == NULL) + if (_lzma_state(m)->Error == NULL) return NULL; - Py_INCREF(Error); - if (PyModule_AddObject(m, "LZMAError", Error) == -1) + Py_INCREF(_lzma_state(m)->Error); + if (PyModule_AddObject(m, "LZMAError", _lzma_state(m)->Error) == -1) return NULL; - if (PyType_Ready(&Compressor_type) == -1) + _lzma_state(m)->Compressor_type = PyType_FromSpec(&Compressor_type_spec); + if (_lzma_state(m)->Compressor_type == NULL) return NULL; - Py_INCREF(&Compressor_type); + Py_INCREF(_lzma_state(m)->Compressor_type); if (PyModule_AddObject(m, "LZMACompressor", - (PyObject *)&Compressor_type) == -1) + _lzma_state(m)->Compressor_type) == -1) return NULL; - if (PyType_Ready(&Decompressor_type) == -1) + _lzma_state(m)->Decompressor_type = PyType_FromSpec(&Decompressor_type_spec); + if (_lzma_state(m)->Decompressor_type == NULL) return NULL; - Py_INCREF(&Decompressor_type); + Py_INCREF(_lzma_state(m)->Decompressor_type); if (PyModule_AddObject(m, "LZMADecompressor", - (PyObject *)&Decompressor_type) == -1) + _lzma_state(m)->Decompressor_type) == -1) return NULL; return m;