bpo-38074: Make zlib extension module PEP-384 compatible (GH-15792)

Updated zlibmodule.c to be PEP 384 compliant.
This commit is contained in:
Dino Viehland 2019-09-10 11:27:03 +01:00 committed by T. Wouters
parent 4f384af067
commit a1ffad0719
2 changed files with 87 additions and 73 deletions

View File

@ -0,0 +1 @@
zlib module made PEP-384 compatible

View File

@ -32,10 +32,16 @@
/* Initial buffer size. */ /* Initial buffer size. */
#define DEF_BUF_SIZE (16*1024) #define DEF_BUF_SIZE (16*1024)
static PyTypeObject Comptype; static PyModuleDef zlibmodule;
static PyTypeObject Decomptype;
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 typedef struct
{ {
@ -73,9 +79,9 @@ zlib_error(z_stream zst, int err, const char *msg)
} }
} }
if (zmsg == Z_NULL) if (zmsg == Z_NULL)
PyErr_Format(ZlibError, "Error %d %s", err, msg); PyErr_Format(_zlibstate_global->ZlibError, "Error %d %s", err, msg);
else 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] /*[clinic input]
@ -226,7 +232,7 @@ zlib_compress_impl(PyObject *module, Py_buffer *data, int level)
"Out of memory while compressing data"); "Out of memory while compressing data");
goto error; goto error;
case Z_STREAM_ERROR: case Z_STREAM_ERROR:
PyErr_SetString(ZlibError, "Bad compression level"); PyErr_SetString(_zlibstate_global->ZlibError, "Bad compression level");
goto error; goto error;
default: default:
deflateEnd(&zst); deflateEnd(&zst);
@ -462,7 +468,7 @@ zlib_compressobj_impl(PyObject *module, int level, int method, int wbits,
goto error; goto error;
} }
self = newcompobject(&Comptype); self = newcompobject(_zlibstate_global->Comptype);
if (self == NULL) if (self == NULL)
goto error; goto error;
self->zst.opaque = NULL; self->zst.opaque = NULL;
@ -558,7 +564,7 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict)
return NULL; return NULL;
} }
self = newcompobject(&Decomptype); self = newcompobject(_zlibstate_global->Decomptype);
if (self == NULL) if (self == NULL)
return NULL; return NULL;
self->zst.opaque = NULL; self->zst.opaque = NULL;
@ -581,7 +587,7 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict)
return NULL; return NULL;
} }
#else #else
PyErr_Format(ZlibError, PyErr_Format(_zlibstate_global->ZlibError,
"zlib version %s does not allow raw inflate with dictionary", "zlib version %s does not allow raw inflate with dictionary",
ZLIB_VERSION); ZLIB_VERSION);
Py_DECREF(self); Py_DECREF(self);
@ -608,11 +614,13 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict)
static void static void
Dealloc(compobject *self) Dealloc(compobject *self)
{ {
PyObject *type = (PyObject *)Py_TYPE(self);
PyThread_free_lock(self->lock); PyThread_free_lock(self->lock);
Py_XDECREF(self->unused_data); Py_XDECREF(self->unused_data);
Py_XDECREF(self->unconsumed_tail); Py_XDECREF(self->unconsumed_tail);
Py_XDECREF(self->zdict); Py_XDECREF(self->zdict);
PyObject_Del(self); PyObject_Del(self);
Py_DECREF(type);
} }
static void static void
@ -944,7 +952,7 @@ zlib_Compress_copy_impl(compobject *self)
compobject *retval = NULL; compobject *retval = NULL;
int err; int err;
retval = newcompobject(&Comptype); retval = newcompobject(_zlibstate_global->Comptype);
if (!retval) return NULL; if (!retval) return NULL;
/* Copy the zstream state /* Copy the zstream state
@ -1025,7 +1033,7 @@ zlib_Decompress_copy_impl(compobject *self)
compobject *retval = NULL; compobject *retval = NULL;
int err; int err;
retval = newcompobject(&Decomptype); retval = newcompobject(_zlibstate_global->Decomptype);
if (!retval) return NULL; if (!retval) return NULL;
/* Copy the zstream state /* Copy the zstream state
@ -1309,67 +1317,33 @@ static PyMethodDef zlib_methods[] =
{NULL, NULL} {NULL, NULL}
}; };
static PyTypeObject Comptype = { static PyType_Slot Comptype_slots[] = {
PyVarObject_HEAD_INIT(0, 0) {Py_tp_dealloc, Comp_dealloc},
{Py_tp_methods, comp_methods},
{0, 0},
};
static PyType_Spec Comptype_spec = {
"zlib.Compress", "zlib.Compress",
sizeof(compobject), sizeof(compobject),
0, 0,
(destructor)Comp_dealloc, /*tp_dealloc*/ Py_TPFLAGS_DEFAULT,
0, /*tp_vectorcall_offset*/ Comptype_slots
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*/
}; };
static PyTypeObject Decomptype = { static PyType_Slot Decomptype_slots[] = {
PyVarObject_HEAD_INIT(0, 0) {Py_tp_dealloc, Decomp_dealloc},
{Py_tp_methods, Decomp_methods},
{Py_tp_members, Decomp_members},
{0, 0},
};
static PyType_Spec Decomptype_spec = {
"zlib.Decompress", "zlib.Decompress",
sizeof(compobject), sizeof(compobject),
0, 0,
(destructor)Decomp_dealloc, /*tp_dealloc*/ Py_TPFLAGS_DEFAULT,
0, /*tp_vectorcall_offset*/ Decomptype_slots
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*/
}; };
PyDoc_STRVAR(zlib_module_documentation, PyDoc_STRVAR(zlib_module_documentation,
@ -1387,34 +1361,72 @@ PyDoc_STRVAR(zlib_module_documentation,
"Compressor objects support compress() and flush() methods; decompressor\n" "Compressor objects support compress() and flush() methods; decompressor\n"
"objects support decompress() and flush()."); "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 = { static struct PyModuleDef zlibmodule = {
PyModuleDef_HEAD_INIT, PyModuleDef_HEAD_INIT,
"zlib", "zlib",
zlib_module_documentation, zlib_module_documentation,
-1, sizeof(_zlibstate),
zlib_methods, zlib_methods,
NULL, NULL,
NULL, zlib_traverse,
NULL, zlib_clear,
NULL zlib_free,
}; };
PyMODINIT_FUNC PyMODINIT_FUNC
PyInit_zlib(void) PyInit_zlib(void)
{ {
PyObject *m, *ver; PyObject *m, *ver;
if (PyType_Ready(&Comptype) < 0) m = PyState_FindModule(&zlibmodule);
return NULL; if (m != NULL) {
if (PyType_Ready(&Decomptype) < 0) Py_INCREF(m);
return NULL; return m;
}
m = PyModule_Create(&zlibmodule); m = PyModule_Create(&zlibmodule);
if (m == NULL) if (m == NULL)
return 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) { if (ZlibError != NULL) {
Py_INCREF(ZlibError); Py_INCREF(ZlibError);
PyModule_AddObject(m, "error", ZlibError); PyModule_AddObject(m, "error", ZlibError);
_zlibstate(m)->ZlibError = ZlibError;
} }
PyModule_AddIntMacro(m, MAX_WBITS); PyModule_AddIntMacro(m, MAX_WBITS);
PyModule_AddIntMacro(m, DEFLATED); PyModule_AddIntMacro(m, DEFLATED);
@ -1457,5 +1469,6 @@ PyInit_zlib(void)
PyModule_AddStringConstant(m, "__version__", "1.0"); PyModule_AddStringConstant(m, "__version__", "1.0");
PyState_AddModule(m, &zlibmodule);
return m; return m;
} }