enabled support to 3.12 per GIL interpeter using multistage module inizialization

This commit is contained in:
Domingo Dirutigliano
2025-03-15 09:13:46 +01:00
parent 440e03642b
commit c710db0510

View File

@@ -13,7 +13,21 @@
#define Py_ARRAY_LENGTH(array) (sizeof(array) / sizeof((array)[0]))
#endif
static PyObject *BrotliError;
void set_brotli_exception(const char *message) {
PyObject *module = PyImport_ImportModule("brotli");
if (!module) {
PyErr_Print();
return;
}
PyObject *obj = PyObject_GetAttrString(module, "error");
if (!obj) {
PyErr_Print();
return;
}
PyErr_SetString(obj, message);
return;
}
/* -----------------------------------
BlocksOutputBuffer code
@@ -231,20 +245,20 @@ static int as_bounded_int(PyObject *o, int* result, int lower_bound, int upper_b
static int mode_convertor(PyObject *o, BrotliEncoderMode *mode) {
if (!PyInt_Check(o)) {
PyErr_SetString(BrotliError, "Invalid mode");
set_brotli_exception("Invalid mode");
return 0;
}
int mode_value = -1;
if (!as_bounded_int(o, &mode_value, 0, 255)) {
PyErr_SetString(BrotliError, "Invalid mode");
set_brotli_exception("Invalid mode");
return 0;
}
*mode = (BrotliEncoderMode) mode_value;
if (*mode != BROTLI_MODE_GENERIC &&
*mode != BROTLI_MODE_TEXT &&
*mode != BROTLI_MODE_FONT) {
PyErr_SetString(BrotliError, "Invalid mode");
set_brotli_exception("Invalid mode");
return 0;
}
@@ -253,12 +267,12 @@ static int mode_convertor(PyObject *o, BrotliEncoderMode *mode) {
static int quality_convertor(PyObject *o, int *quality) {
if (!PyInt_Check(o)) {
PyErr_SetString(BrotliError, "Invalid quality");
set_brotli_exception("Invalid quality");
return 0;
}
if (!as_bounded_int(o, quality, 0, 11)) {
PyErr_SetString(BrotliError, "Invalid quality. Range is 0 to 11.");
set_brotli_exception("Invalid quality. Range is 0 to 11.");
return 0;
}
@@ -267,12 +281,12 @@ static int quality_convertor(PyObject *o, int *quality) {
static int lgwin_convertor(PyObject *o, int *lgwin) {
if (!PyInt_Check(o)) {
PyErr_SetString(BrotliError, "Invalid lgwin");
set_brotli_exception("Invalid lgwin");
return 0;
}
if (!as_bounded_int(o, lgwin, 10, 24)) {
PyErr_SetString(BrotliError, "Invalid lgwin. Range is 10 to 24.");
set_brotli_exception("Invalid lgwin. Range is 10 to 24.");
return 0;
}
@@ -281,12 +295,12 @@ static int lgwin_convertor(PyObject *o, int *lgwin) {
static int lgblock_convertor(PyObject *o, int *lgblock) {
if (!PyInt_Check(o)) {
PyErr_SetString(BrotliError, "Invalid lgblock");
set_brotli_exception("Invalid lgblock");
return 0;
}
if (!as_bounded_int(o, lgblock, 0, 24) || (*lgblock != 0 && *lgblock < 16)) {
PyErr_SetString(BrotliError, "Invalid lgblock. Can be 0 or in range 16 to 24.");
set_brotli_exception("Invalid lgblock. Can be 0 or in range 16 to 24.");
return 0;
}
@@ -465,8 +479,7 @@ static PyObject* brotli_Compressor_process(brotli_Compressor *self, PyObject *ar
}
error:
PyErr_SetString(BrotliError,
"BrotliEncoderCompressStream failed while processing the stream");
set_brotli_exception("BrotliEncoderCompressStream failed while processing the stream");
ret = NULL;
finally:
@@ -502,8 +515,7 @@ static PyObject* brotli_Compressor_flush(brotli_Compressor *self) {
}
error:
PyErr_SetString(BrotliError,
"BrotliEncoderCompressStream failed while flushing the stream");
set_brotli_exception("BrotliEncoderCompressStream failed while flushing the stream");
ret = NULL;
finally:
return ret;
@@ -542,8 +554,7 @@ static PyObject* brotli_Compressor_finish(brotli_Compressor *self) {
goto finally;
error:
PyErr_SetString(BrotliError,
"BrotliEncoderCompressStream failed while finishing the stream");
set_brotli_exception("BrotliEncoderCompressStream failed while finishing the stream");
ret = NULL;
finally:
return ret;
@@ -786,7 +797,7 @@ static PyObject* brotli_Decompressor_process(brotli_Decompressor *self, PyObject
if (self->unconsumed_data_length > 0) {
if (input.len > 0) {
PyErr_SetString(BrotliError, "process called with data when accept_more_data is False");
set_brotli_exception("process called with data when accept_more_data is False");
ret = NULL;
goto finally;
}
@@ -803,8 +814,7 @@ static PyObject* brotli_Decompressor_process(brotli_Decompressor *self, PyObject
}
error:
PyErr_SetString(BrotliError,
"BrotliDecoderDecompressStream failed while processing the stream");
set_brotli_exception("BrotliDecoderDecompressStream failed while processing the stream");
ret = NULL;
finally:
@@ -828,7 +838,7 @@ PyDoc_STRVAR(brotli_Decompressor_is_finished_doc,
static PyObject* brotli_Decompressor_is_finished(brotli_Decompressor *self) {
if (!self->dec) {
PyErr_SetString(BrotliError, "BrotliDecoderState is NULL while checking is_finished");
set_brotli_exception("BrotliDecoderState is NULL while checking is_finished");
return NULL;
}
@@ -998,7 +1008,7 @@ static PyObject* brotli_decompress(PyObject *self, PyObject *args, PyObject *key
error:
BlocksOutputBuffer_OnError(&buffer);
PyErr_SetString(BrotliError, "BrotliDecompress failed");
set_brotli_exception("BrotliDecompress failed");
ret = NULL;
finally:
@@ -1014,47 +1024,21 @@ static PyMethodDef brotli_methods[] = {
PyDoc_STRVAR(brotli_doc, "Implementation module for the Brotli library.");
#if PY_MAJOR_VERSION >= 3
#define INIT_BROTLI PyInit__brotli
#define CREATE_BROTLI PyModule_Create(&brotli_module)
#define RETURN_BROTLI return m
#define RETURN_NULL return NULL
static struct PyModuleDef brotli_module = {
PyModuleDef_HEAD_INIT,
"_brotli", /* m_name */
brotli_doc, /* m_doc */
0, /* m_size */
brotli_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL /* m_free */
};
#else
#define INIT_BROTLI init_brotli
#define CREATE_BROTLI Py_InitModule3("_brotli", brotli_methods, brotli_doc)
#define RETURN_BROTLI return
#define RETURN_NULL return
#endif
PyMODINIT_FUNC INIT_BROTLI(void) {
PyObject *m = CREATE_BROTLI;
BrotliError = PyErr_NewException((char*) "brotli.error", NULL, NULL);
if (BrotliError != NULL) {
Py_INCREF(BrotliError);
PyModule_AddObject(m, "error", BrotliError);
static int init_brotli_mod(PyObject *m) {
PyObject* err = PyErr_NewException("brotli.error", NULL, NULL);
if (err != NULL) {
Py_INCREF(err);
PyModule_AddObject(m, "error", err);
}
if (PyType_Ready(&brotli_CompressorType) < 0) {
RETURN_NULL;
return -1;
}
Py_INCREF(&brotli_CompressorType);
PyModule_AddObject(m, "Compressor", (PyObject *)&brotli_CompressorType);
if (PyType_Ready(&brotli_DecompressorType) < 0) {
RETURN_NULL;
return -1;
}
Py_INCREF(&brotli_DecompressorType);
PyModule_AddObject(m, "Decompressor", (PyObject *)&brotli_DecompressorType);
@@ -1069,5 +1053,40 @@ PyMODINIT_FUNC INIT_BROTLI(void) {
decoderVersion >> 24, (decoderVersion >> 12) & 0xFFF, decoderVersion & 0xFFF);
PyModule_AddStringConstant(m, "__version__", version);
RETURN_BROTLI;
return 0;
}
#if PY_MAJOR_VERSION >= 3
static PyModuleDef_Slot brotli_mod_slots[] = {
{Py_mod_exec, init_brotli_mod},
#if PY_MINOR_VERSION >= 12
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
#endif
{0, NULL}
};
static struct PyModuleDef brotli_module = {
PyModuleDef_HEAD_INIT,
"_brotli", /* m_name */
brotli_doc, /* m_doc */
0, /* m_size */
brotli_methods, /* m_methods */
brotli_mod_slots, /* m_slots */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL /* m_free */
};
PyMODINIT_FUNC PyInit__brotli(void){
return PyModuleDef_Init(&brotli_module);
}
#else
PyMODINIT_FUNC init_brotli(void) {
PyObject *m = Py_InitModule3("_brotli", brotli_methods, brotli_doc);
init_brotli_mod(m);
}
#endif