diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-09-09-15-40-57.bpo-38074.MsVbeI.rst b/Misc/NEWS.d/next/Core and Builtins/2019-09-09-15-40-57.bpo-38074.MsVbeI.rst new file mode 100644 index 00000000000..a20b40e750b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-09-09-15-40-57.bpo-38074.MsVbeI.rst @@ -0,0 +1 @@ +zlib module made PEP-384 compatible \ No newline at end of file diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index a3d9ed6646d..3e77080a31c 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -32,10 +32,16 @@ /* Initial buffer size. */ #define DEF_BUF_SIZE (16*1024) -static PyTypeObject Comptype; -static PyTypeObject Decomptype; +static PyModuleDef zlibmodule; -static PyObject *ZlibError; +typedef struct { + PyTypeObject *Comptype; + PyTypeObject *Decomptype; + PyObject *ZlibError; +} _zlibstate; + +#define _zlibstate(o) ((_zlibstate *)PyModule_GetState(o)) +#define _zlibstate_global ((_zlibstate *)PyModule_GetState(PyState_FindModule(&zlibmodule))) typedef struct { @@ -73,9 +79,9 @@ zlib_error(z_stream zst, int err, const char *msg) } } if (zmsg == Z_NULL) - PyErr_Format(ZlibError, "Error %d %s", err, msg); + PyErr_Format(_zlibstate_global->ZlibError, "Error %d %s", err, msg); else - PyErr_Format(ZlibError, "Error %d %s: %.200s", err, msg, zmsg); + PyErr_Format(_zlibstate_global->ZlibError, "Error %d %s: %.200s", err, msg, zmsg); } /*[clinic input] @@ -226,7 +232,7 @@ zlib_compress_impl(PyObject *module, Py_buffer *data, int level) "Out of memory while compressing data"); goto error; case Z_STREAM_ERROR: - PyErr_SetString(ZlibError, "Bad compression level"); + PyErr_SetString(_zlibstate_global->ZlibError, "Bad compression level"); goto error; default: deflateEnd(&zst); @@ -462,7 +468,7 @@ zlib_compressobj_impl(PyObject *module, int level, int method, int wbits, goto error; } - self = newcompobject(&Comptype); + self = newcompobject(_zlibstate_global->Comptype); if (self == NULL) goto error; self->zst.opaque = NULL; @@ -558,7 +564,7 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict) return NULL; } - self = newcompobject(&Decomptype); + self = newcompobject(_zlibstate_global->Decomptype); if (self == NULL) return NULL; self->zst.opaque = NULL; @@ -581,7 +587,7 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict) return NULL; } #else - PyErr_Format(ZlibError, + PyErr_Format(_zlibstate_global->ZlibError, "zlib version %s does not allow raw inflate with dictionary", ZLIB_VERSION); Py_DECREF(self); @@ -608,11 +614,13 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict) static void Dealloc(compobject *self) { + PyObject *type = (PyObject *)Py_TYPE(self); PyThread_free_lock(self->lock); Py_XDECREF(self->unused_data); Py_XDECREF(self->unconsumed_tail); Py_XDECREF(self->zdict); PyObject_Del(self); + Py_DECREF(type); } static void @@ -944,7 +952,7 @@ zlib_Compress_copy_impl(compobject *self) compobject *retval = NULL; int err; - retval = newcompobject(&Comptype); + retval = newcompobject(_zlibstate_global->Comptype); if (!retval) return NULL; /* Copy the zstream state @@ -1025,7 +1033,7 @@ zlib_Decompress_copy_impl(compobject *self) compobject *retval = NULL; int err; - retval = newcompobject(&Decomptype); + retval = newcompobject(_zlibstate_global->Decomptype); if (!retval) return NULL; /* Copy the zstream state @@ -1309,67 +1317,33 @@ static PyMethodDef zlib_methods[] = {NULL, NULL} }; -static PyTypeObject Comptype = { - PyVarObject_HEAD_INIT(0, 0) +static PyType_Slot Comptype_slots[] = { + {Py_tp_dealloc, Comp_dealloc}, + {Py_tp_methods, comp_methods}, + {0, 0}, +}; + +static PyType_Spec Comptype_spec = { "zlib.Compress", sizeof(compobject), 0, - (destructor)Comp_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, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - comp_methods, /*tp_methods*/ + Py_TPFLAGS_DEFAULT, + Comptype_slots }; -static PyTypeObject Decomptype = { - PyVarObject_HEAD_INIT(0, 0) +static PyType_Slot Decomptype_slots[] = { + {Py_tp_dealloc, Decomp_dealloc}, + {Py_tp_methods, Decomp_methods}, + {Py_tp_members, Decomp_members}, + {0, 0}, +}; + +static PyType_Spec Decomptype_spec = { "zlib.Decompress", sizeof(compobject), 0, - (destructor)Decomp_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, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - Decomp_methods, /*tp_methods*/ - Decomp_members, /*tp_members*/ + Py_TPFLAGS_DEFAULT, + Decomptype_slots }; PyDoc_STRVAR(zlib_module_documentation, @@ -1387,34 +1361,72 @@ PyDoc_STRVAR(zlib_module_documentation, "Compressor objects support compress() and flush() methods; decompressor\n" "objects support decompress() and flush()."); +static int +zlib_clear(PyObject *m) +{ + _zlibstate *state = _zlibstate(m); + Py_CLEAR(state->Comptype); + Py_CLEAR(state->Decomptype); + Py_CLEAR(state->ZlibError); + return 0; +} + +static int +zlib_traverse(PyObject *m, visitproc visit, void *arg) +{ + _zlibstate *state = _zlibstate(m); + Py_VISIT(state->Comptype); + Py_VISIT(state->Decomptype); + Py_VISIT(state->ZlibError); + return 0; +} + +static void +zlib_free(void *m) +{ + zlib_clear((PyObject *)m); +} + static struct PyModuleDef zlibmodule = { PyModuleDef_HEAD_INIT, "zlib", zlib_module_documentation, - -1, + sizeof(_zlibstate), zlib_methods, NULL, - NULL, - NULL, - NULL + zlib_traverse, + zlib_clear, + zlib_free, }; PyMODINIT_FUNC PyInit_zlib(void) { PyObject *m, *ver; - if (PyType_Ready(&Comptype) < 0) - return NULL; - if (PyType_Ready(&Decomptype) < 0) - return NULL; + m = PyState_FindModule(&zlibmodule); + if (m != NULL) { + Py_INCREF(m); + return m; + } m = PyModule_Create(&zlibmodule); if (m == NULL) return NULL; - ZlibError = PyErr_NewException("zlib.error", NULL, NULL); + PyTypeObject *Comptype = (PyTypeObject *)PyType_FromSpec(&Comptype_spec); + if (Comptype == NULL) + return NULL; + _zlibstate(m)->Comptype = Comptype; + + PyTypeObject *Decomptype = (PyTypeObject *)PyType_FromSpec(&Decomptype_spec); + if (Decomptype == NULL) + return NULL; + _zlibstate(m)->Decomptype = Decomptype; + + PyObject *ZlibError = PyErr_NewException("zlib.error", NULL, NULL); if (ZlibError != NULL) { Py_INCREF(ZlibError); PyModule_AddObject(m, "error", ZlibError); + _zlibstate(m)->ZlibError = ZlibError; } PyModule_AddIntMacro(m, MAX_WBITS); PyModule_AddIntMacro(m, DEFLATED); @@ -1457,5 +1469,6 @@ PyInit_zlib(void) PyModule_AddStringConstant(m, "__version__", "1.0"); + PyState_AddModule(m, &zlibmodule); return m; }