bpo-1635741: Port audioop extension module to multiphase initialization (PEP 489) (GH-18608)

Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
Hai Shi 2020-03-12 00:49:11 +08:00 committed by GitHub
parent a158168a78
commit 41fbf865a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 38 deletions

View File

@ -0,0 +1 @@
Port audioop extension module to multiphase initialization (:pep:`489`).

View File

@ -375,15 +375,22 @@ static PyModuleDef audioopmodule;
typedef struct { typedef struct {
PyObject *AudioopError; PyObject *AudioopError;
} _audioopstate; } audioop_state;
#define _audioopstate(o) ((_audioopstate *)PyModule_GetState(o)) static inline audioop_state *
get_audioop_state(PyObject *module)
{
void *state = PyModule_GetState(module);
assert(state != NULL);
return (audioop_state *)state;
}
static int static int
audioop_check_size(PyObject *module, int size) audioop_check_size(PyObject *module, int size)
{ {
if (size < 1 || size > 4) { if (size < 1 || size > 4) {
PyErr_SetString(_audioopstate(module)->AudioopError, "Size should be 1, 2, 3 or 4"); PyErr_SetString(get_audioop_state(module)->AudioopError,
"Size should be 1, 2, 3 or 4");
return 0; return 0;
} }
else else
@ -396,7 +403,8 @@ audioop_check_parameters(PyObject *module, Py_ssize_t len, int size)
if (!audioop_check_size(module, size)) if (!audioop_check_size(module, size))
return 0; return 0;
if (len % size != 0) { if (len % size != 0) {
PyErr_SetString(_audioopstate(module)->AudioopError, "not a whole number of frames"); PyErr_SetString(get_audioop_state(module)->AudioopError,
"not a whole number of frames");
return 0; return 0;
} }
return 1; return 1;
@ -428,7 +436,8 @@ audioop_getsample_impl(PyObject *module, Py_buffer *fragment, int width,
if (!audioop_check_parameters(module, fragment->len, width)) if (!audioop_check_parameters(module, fragment->len, width))
return NULL; return NULL;
if (index < 0 || index >= fragment->len/width) { if (index < 0 || index >= fragment->len/width) {
PyErr_SetString(_audioopstate(module)->AudioopError, "Index out of range"); PyErr_SetString(get_audioop_state(module)->AudioopError,
"Index out of range");
return NULL; return NULL;
} }
val = GETRAWSAMPLE(width, fragment->buf, index*width); val = GETRAWSAMPLE(width, fragment->buf, index*width);
@ -619,7 +628,8 @@ audioop_findfit_impl(PyObject *module, Py_buffer *fragment,
double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor; double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
if (fragment->len & 1 || reference->len & 1) { if (fragment->len & 1 || reference->len & 1) {
PyErr_SetString(_audioopstate(module)->AudioopError, "Strings should be even-sized"); PyErr_SetString(get_audioop_state(module)->AudioopError,
"Strings should be even-sized");
return NULL; return NULL;
} }
cp1 = (const int16_t *)fragment->buf; cp1 = (const int16_t *)fragment->buf;
@ -628,7 +638,8 @@ audioop_findfit_impl(PyObject *module, Py_buffer *fragment,
len2 = reference->len >> 1; len2 = reference->len >> 1;
if (len1 < len2) { if (len1 < len2) {
PyErr_SetString(_audioopstate(module)->AudioopError, "First sample should be longer"); PyErr_SetString(get_audioop_state(module)->AudioopError,
"First sample should be longer");
return NULL; return NULL;
} }
sum_ri_2 = _sum2(cp2, cp2, len2); sum_ri_2 = _sum2(cp2, cp2, len2);
@ -686,11 +697,13 @@ audioop_findfactor_impl(PyObject *module, Py_buffer *fragment,
double sum_ri_2, sum_aij_ri, result; double sum_ri_2, sum_aij_ri, result;
if (fragment->len & 1 || reference->len & 1) { if (fragment->len & 1 || reference->len & 1) {
PyErr_SetString(_audioopstate(module)->AudioopError, "Strings should be even-sized"); PyErr_SetString(get_audioop_state(module)->AudioopError,
"Strings should be even-sized");
return NULL; return NULL;
} }
if (fragment->len != reference->len) { if (fragment->len != reference->len) {
PyErr_SetString(_audioopstate(module)->AudioopError, "Samples should be same size"); PyErr_SetString(get_audioop_state(module)->AudioopError,
"Samples should be same size");
return NULL; return NULL;
} }
cp1 = (const int16_t *)fragment->buf; cp1 = (const int16_t *)fragment->buf;
@ -730,14 +743,16 @@ audioop_findmax_impl(PyObject *module, Py_buffer *fragment,
double result, best_result; double result, best_result;
if (fragment->len & 1) { if (fragment->len & 1) {
PyErr_SetString(_audioopstate(module)->AudioopError, "Strings should be even-sized"); PyErr_SetString(get_audioop_state(module)->AudioopError,
"Strings should be even-sized");
return NULL; return NULL;
} }
cp1 = (const int16_t *)fragment->buf; cp1 = (const int16_t *)fragment->buf;
len1 = fragment->len >> 1; len1 = fragment->len >> 1;
if (length < 0 || len1 < length) { if (length < 0 || len1 < length) {
PyErr_SetString(_audioopstate(module)->AudioopError, "Input sample should be longer"); PyErr_SetString(get_audioop_state(module)->AudioopError,
"Input sample should be longer");
return NULL; return NULL;
} }
@ -969,7 +984,8 @@ audioop_tomono_impl(PyObject *module, Py_buffer *fragment, int width,
if (!audioop_check_parameters(module, len, width)) if (!audioop_check_parameters(module, len, width))
return NULL; return NULL;
if (((len / width) & 1) != 0) { if (((len / width) & 1) != 0) {
PyErr_SetString(_audioopstate(module)->AudioopError, "not a whole number of frames"); PyErr_SetString(get_audioop_state(module)->AudioopError,
"not a whole number of frames");
return NULL; return NULL;
} }
@ -1064,7 +1080,8 @@ audioop_add_impl(PyObject *module, Py_buffer *fragment1,
if (!audioop_check_parameters(module, fragment1->len, width)) if (!audioop_check_parameters(module, fragment1->len, width))
return NULL; return NULL;
if (fragment1->len != fragment2->len) { if (fragment1->len != fragment2->len) {
PyErr_SetString(_audioopstate(module)->AudioopError, "Lengths should be the same"); PyErr_SetString(get_audioop_state(module)->AudioopError,
"Lengths should be the same");
return NULL; return NULL;
} }
@ -1310,7 +1327,8 @@ audioop_ratecv_impl(PyObject *module, Py_buffer *fragment, int width,
if (!audioop_check_size(module, width)) if (!audioop_check_size(module, width))
return NULL; return NULL;
if (nchannels < 1) { if (nchannels < 1) {
PyErr_SetString(_audioopstate(module)->AudioopError, "# of channels should be >= 1"); PyErr_SetString(get_audioop_state(module)->AudioopError,
"# of channels should be >= 1");
return NULL; return NULL;
} }
if (width > INT_MAX / nchannels) { if (width > INT_MAX / nchannels) {
@ -1323,17 +1341,19 @@ audioop_ratecv_impl(PyObject *module, Py_buffer *fragment, int width,
} }
bytes_per_frame = width * nchannels; bytes_per_frame = width * nchannels;
if (weightA < 1 || weightB < 0) { if (weightA < 1 || weightB < 0) {
PyErr_SetString(_audioopstate(module)->AudioopError, PyErr_SetString(get_audioop_state(module)->AudioopError,
"weightA should be >= 1, weightB should be >= 0"); "weightA should be >= 1, weightB should be >= 0");
return NULL; return NULL;
} }
assert(fragment->len >= 0); assert(fragment->len >= 0);
if (fragment->len % bytes_per_frame != 0) { if (fragment->len % bytes_per_frame != 0) {
PyErr_SetString(_audioopstate(module)->AudioopError, "not a whole number of frames"); PyErr_SetString(get_audioop_state(module)->AudioopError,
"not a whole number of frames");
return NULL; return NULL;
} }
if (inrate <= 0 || outrate <= 0) { if (inrate <= 0 || outrate <= 0) {
PyErr_SetString(_audioopstate(module)->AudioopError, "sampling rate not > 0"); PyErr_SetString(get_audioop_state(module)->AudioopError,
"sampling rate not > 0");
return NULL; return NULL;
} }
/* divide inrate and outrate by their greatest common divisor */ /* divide inrate and outrate by their greatest common divisor */
@ -1374,7 +1394,7 @@ audioop_ratecv_impl(PyObject *module, Py_buffer *fragment, int width,
&d, &PyTuple_Type, &samps)) &d, &PyTuple_Type, &samps))
goto exit; goto exit;
if (PyTuple_Size(samps) != nchannels) { if (PyTuple_Size(samps) != nchannels) {
PyErr_SetString(_audioopstate(module)->AudioopError, PyErr_SetString(get_audioop_state(module)->AudioopError,
"illegal state argument"); "illegal state argument");
goto exit; goto exit;
} }
@ -1903,31 +1923,61 @@ static PyMethodDef audioop_methods[] = {
}; };
static int static int
audioop_traverse(PyObject *m, visitproc visit, void *arg) { audioop_traverse(PyObject *module, visitproc visit, void *arg)
_audioopstate *state = _audioopstate(m); {
if (state != NULL) audioop_state *state = (audioop_state *)PyModule_GetState(module);
if (state) {
Py_VISIT(state->AudioopError); Py_VISIT(state->AudioopError);
}
return 0; return 0;
} }
static int static int
audioop_clear(PyObject *m) { audioop_clear(PyObject *module)
_audioopstate *state = _audioopstate(m); {
if (state != NULL) audioop_state *state = (audioop_state *)PyModule_GetState(module);
if (state) {
Py_CLEAR(state->AudioopError); Py_CLEAR(state->AudioopError);
}
return 0; return 0;
} }
static void static void
audioop_free(void *m) { audioop_free(void *module) {
audioop_clear((PyObject *)m); audioop_clear((PyObject *)module);
} }
static int
audioop_exec(PyObject* module)
{
audioop_state *state = get_audioop_state(module);
state->AudioopError = PyErr_NewException("audioop.error", NULL, NULL);
if (state->AudioopError == NULL) {
return -1;
}
Py_INCREF(state->AudioopError);
if (PyModule_AddObject(module, "error", state->AudioopError) < 0) {
Py_DECREF(state->AudioopError);
return -1;
}
return 0;
}
static PyModuleDef_Slot audioop_slots[] = {
{Py_mod_exec, audioop_exec},
{0, NULL}
};
static struct PyModuleDef audioopmodule = { static struct PyModuleDef audioopmodule = {
PyModuleDef_HEAD_INIT, PyModuleDef_HEAD_INIT,
"audioop", "audioop",
NULL, NULL,
sizeof(_audioopstate), sizeof(audioop_state),
audioop_methods, audioop_methods,
NULL, audioop_slots,
audioop_traverse, audioop_traverse,
audioop_clear, audioop_clear,
audioop_free audioop_free
@ -1936,14 +1986,5 @@ static struct PyModuleDef audioopmodule = {
PyMODINIT_FUNC PyMODINIT_FUNC
PyInit_audioop(void) PyInit_audioop(void)
{ {
PyObject *m = PyModule_Create(&audioopmodule); return PyModuleDef_Init(&audioopmodule);
if (m == NULL)
return NULL;
PyObject *AudioopError = PyErr_NewException("audioop.error", NULL, NULL);
if (AudioopError == NULL)
return NULL;
Py_INCREF(AudioopError);
PyModule_AddObject(m, "error", AudioopError);
_audioopstate(m)->AudioopError = AudioopError;
return m;
} }