]> granicus.if.org Git - python/commitdiff
bpo-38074: Make zlib extension module PEP-384 compatible (GH-15792)
authorDino Viehland <dinoviehland@gmail.com>
Tue, 10 Sep 2019 10:27:03 +0000 (11:27 +0100)
committerT. Wouters <thomas@python.org>
Tue, 10 Sep 2019 10:27:03 +0000 (03:27 -0700)
Updated zlibmodule.c to be PEP 384 compliant.

Misc/NEWS.d/next/Core and Builtins/2019-09-09-15-40-57.bpo-38074.MsVbeI.rst [new file with mode: 0644]
Modules/zlibmodule.c

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 (file)
index 0000000..a20b40e
--- /dev/null
@@ -0,0 +1 @@
+zlib module made PEP-384 compatible
\ No newline at end of file
index a3d9ed6646dec8e265e0996689885567249248c7..3e77080a31cb5755e5cde0102abbcab2efe81f9f 100644 (file)
 /* 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;
 }