[Python-checkins] bpo-38303: Make audioop extension module PEP-384 compatible (GH-16497)

Miss Skeleton (bot) webhook-mailer at python.org
Tue Oct 22 09:07:15 EDT 2019


https://github.com/python/cpython/commit/f548a3e4a28c5496755f9f8d057fc8d031b27655
commit: f548a3e4a28c5496755f9f8d057fc8d031b27655
branch: master
author: Tyler Kieft <tyler.kieft at gmail.com>
committer: Miss Skeleton (bot) <31488909+miss-islington at users.noreply.github.com>
date: 2019-10-22T06:07:03-07:00
summary:

bpo-38303: Make audioop extension module PEP-384 compatible (GH-16497)



https://bugs.python.org/issue38303



Automerge-Triggered-By: @encukou

files:
A Misc/NEWS.d/next/C API/2019-09-30-16-53-30.bpo-38303.YoIs0M.rst
M Misc/ACKS
M Modules/audioop.c

diff --git a/Misc/ACKS b/Misc/ACKS
index d8e2630814a86..78beee5f34eec 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -847,6 +847,7 @@ Dhiru Kholia
 Artem Khramov
 Akshit Khurana
 Sanyam Khurana
+Tyler Kieft
 Mads Kiilerich
 Jason Killen
 Jan Kim
diff --git a/Misc/NEWS.d/next/C API/2019-09-30-16-53-30.bpo-38303.YoIs0M.rst b/Misc/NEWS.d/next/C API/2019-09-30-16-53-30.bpo-38303.YoIs0M.rst
new file mode 100644
index 0000000000000..03048bbfce533
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2019-09-30-16-53-30.bpo-38303.YoIs0M.rst	
@@ -0,0 +1 @@
+Update audioop extension module to use the stable ABI (PEP-384). Patch by Tyler Kieft.
diff --git a/Modules/audioop.c b/Modules/audioop.c
index f4fdeb23ffa95..7726c88b1a9d4 100644
--- a/Modules/audioop.c
+++ b/Modules/audioop.c
@@ -371,14 +371,19 @@ static const int stepsizeTable[89] = {
             SETINT32((cp), (i), (val));         \
     } while(0)
 
+static PyModuleDef audioopmodule;
 
-static PyObject *AudioopError;
+typedef struct {
+    PyObject *AudioopError;
+} _audioopstate;
+
+#define _audioopstate(o) ((_audioopstate *)PyModule_GetState(o))
 
 static int
-audioop_check_size(int size)
+audioop_check_size(PyObject *module, int size)
 {
     if (size < 1 || size > 4) {
-        PyErr_SetString(AudioopError, "Size should be 1, 2, 3 or 4");
+        PyErr_SetString(_audioopstate(module)->AudioopError, "Size should be 1, 2, 3 or 4");
         return 0;
     }
     else
@@ -386,12 +391,12 @@ audioop_check_size(int size)
 }
 
 static int
-audioop_check_parameters(Py_ssize_t len, int size)
+audioop_check_parameters(PyObject *module, Py_ssize_t len, int size)
 {
-    if (!audioop_check_size(size))
+    if (!audioop_check_size(module, size))
         return 0;
     if (len % size != 0) {
-        PyErr_SetString(AudioopError, "not a whole number of frames");
+        PyErr_SetString(_audioopstate(module)->AudioopError, "not a whole number of frames");
         return 0;
     }
     return 1;
@@ -420,10 +425,10 @@ audioop_getsample_impl(PyObject *module, Py_buffer *fragment, int width,
 {
     int val;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
     if (index < 0 || index >= fragment->len/width) {
-        PyErr_SetString(AudioopError, "Index out of range");
+        PyErr_SetString(_audioopstate(module)->AudioopError, "Index out of range");
         return NULL;
     }
     val = GETRAWSAMPLE(width, fragment->buf, index*width);
@@ -447,7 +452,7 @@ audioop_max_impl(PyObject *module, Py_buffer *fragment, int width)
     Py_ssize_t i;
     unsigned int absval, max = 0;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
     for (i = 0; i < fragment->len; i += width) {
         int val = GETRAWSAMPLE(width, fragment->buf, i);
@@ -479,7 +484,7 @@ audioop_minmax_impl(PyObject *module, Py_buffer *fragment, int width)
     a warning */
     int min = 0x7fffffff, max = -0x7FFFFFFF-1;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
     for (i = 0; i < fragment->len; i += width) {
         int val = GETRAWSAMPLE(width, fragment->buf, i);
@@ -507,7 +512,7 @@ audioop_avg_impl(PyObject *module, Py_buffer *fragment, int width)
     int avg;
     double sum = 0.0;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
     for (i = 0; i < fragment->len; i += width)
         sum += GETRAWSAMPLE(width, fragment->buf, i);
@@ -536,7 +541,7 @@ audioop_rms_impl(PyObject *module, Py_buffer *fragment, int width)
     unsigned int res;
     double sum_squares = 0.0;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
     for (i = 0; i < fragment->len; i += width) {
         double val = GETRAWSAMPLE(width, fragment->buf, i);
@@ -614,7 +619,7 @@ audioop_findfit_impl(PyObject *module, Py_buffer *fragment,
     double sum_ri_2, sum_aij_2, sum_aij_ri, result, best_result, factor;
 
     if (fragment->len & 1 || reference->len & 1) {
-        PyErr_SetString(AudioopError, "Strings should be even-sized");
+        PyErr_SetString(_audioopstate(module)->AudioopError, "Strings should be even-sized");
         return NULL;
     }
     cp1 = (const int16_t *)fragment->buf;
@@ -623,7 +628,7 @@ audioop_findfit_impl(PyObject *module, Py_buffer *fragment,
     len2 = reference->len >> 1;
 
     if (len1 < len2) {
-        PyErr_SetString(AudioopError, "First sample should be longer");
+        PyErr_SetString(_audioopstate(module)->AudioopError, "First sample should be longer");
         return NULL;
     }
     sum_ri_2 = _sum2(cp2, cp2, len2);
@@ -681,11 +686,11 @@ audioop_findfactor_impl(PyObject *module, Py_buffer *fragment,
     double sum_ri_2, sum_aij_ri, result;
 
     if (fragment->len & 1 || reference->len & 1) {
-        PyErr_SetString(AudioopError, "Strings should be even-sized");
+        PyErr_SetString(_audioopstate(module)->AudioopError, "Strings should be even-sized");
         return NULL;
     }
     if (fragment->len != reference->len) {
-        PyErr_SetString(AudioopError, "Samples should be same size");
+        PyErr_SetString(_audioopstate(module)->AudioopError, "Samples should be same size");
         return NULL;
     }
     cp1 = (const int16_t *)fragment->buf;
@@ -725,14 +730,14 @@ audioop_findmax_impl(PyObject *module, Py_buffer *fragment,
     double result, best_result;
 
     if (fragment->len & 1) {
-        PyErr_SetString(AudioopError, "Strings should be even-sized");
+        PyErr_SetString(_audioopstate(module)->AudioopError, "Strings should be even-sized");
         return NULL;
     }
     cp1 = (const int16_t *)fragment->buf;
     len1 = fragment->len >> 1;
 
     if (length < 0 || len1 < length) {
-        PyErr_SetString(AudioopError, "Input sample should be longer");
+        PyErr_SetString(_audioopstate(module)->AudioopError, "Input sample should be longer");
         return NULL;
     }
 
@@ -777,7 +782,7 @@ audioop_avgpp_impl(PyObject *module, Py_buffer *fragment, int width)
     unsigned int avg;
     int diff, prevdiff, nextreme = 0;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
     if (fragment->len <= width)
         return PyLong_FromLong(0);
@@ -833,7 +838,7 @@ audioop_maxpp_impl(PyObject *module, Py_buffer *fragment, int width)
     unsigned int max = 0, extremediff;
     int diff, prevdiff;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
     if (fragment->len <= width)
         return PyLong_FromLong(0);
@@ -885,7 +890,7 @@ audioop_cross_impl(PyObject *module, Py_buffer *fragment, int width)
     int prevval;
     Py_ssize_t ncross;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
     ncross = -1;
     prevval = 17; /* Anything <> 0,1 */
@@ -918,7 +923,7 @@ audioop_mul_impl(PyObject *module, Py_buffer *fragment, int width,
     double maxval, minval;
     PyObject *rv;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
 
     maxval = (double) maxvals[width];
@@ -961,10 +966,10 @@ audioop_tomono_impl(PyObject *module, Py_buffer *fragment, int width,
 
     cp = fragment->buf;
     len = fragment->len;
-    if (!audioop_check_parameters(len, width))
+    if (!audioop_check_parameters(module, len, width))
         return NULL;
     if (((len / width) & 1) != 0) {
-        PyErr_SetString(AudioopError, "not a whole number of frames");
+        PyErr_SetString(_audioopstate(module)->AudioopError, "not a whole number of frames");
         return NULL;
     }
 
@@ -1008,7 +1013,7 @@ audioop_tostereo_impl(PyObject *module, Py_buffer *fragment, int width,
     double maxval, minval;
     PyObject *rv;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
 
     maxval = (double) maxvals[width];
@@ -1056,10 +1061,10 @@ audioop_add_impl(PyObject *module, Py_buffer *fragment1,
     int minval, maxval, newval;
     PyObject *rv;
 
-    if (!audioop_check_parameters(fragment1->len, width))
+    if (!audioop_check_parameters(module, fragment1->len, width))
         return NULL;
     if (fragment1->len != fragment2->len) {
-        PyErr_SetString(AudioopError, "Lengths should be the same");
+        PyErr_SetString(_audioopstate(module)->AudioopError, "Lengths should be the same");
         return NULL;
     }
 
@@ -1114,7 +1119,7 @@ audioop_bias_impl(PyObject *module, Py_buffer *fragment, int width, int bias)
     unsigned int val = 0, mask;
     PyObject *rv;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
 
     rv = PyBytes_FromStringAndSize(NULL, fragment->len);
@@ -1172,7 +1177,7 @@ audioop_reverse_impl(PyObject *module, Py_buffer *fragment, int width)
     Py_ssize_t i;
     PyObject *rv;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
 
     rv = PyBytes_FromStringAndSize(NULL, fragment->len);
@@ -1205,7 +1210,7 @@ audioop_byteswap_impl(PyObject *module, Py_buffer *fragment, int width)
     Py_ssize_t i;
     PyObject *rv;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
 
     rv = PyBytes_FromStringAndSize(NULL, fragment->len);
@@ -1241,9 +1246,9 @@ audioop_lin2lin_impl(PyObject *module, Py_buffer *fragment, int width,
     Py_ssize_t i, j;
     PyObject *rv;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
-    if (!audioop_check_size(newwidth))
+    if (!audioop_check_size(module, newwidth))
         return NULL;
 
     if (fragment->len/width > PY_SSIZE_T_MAX/newwidth) {
@@ -1302,10 +1307,10 @@ audioop_ratecv_impl(PyObject *module, Py_buffer *fragment, int width,
     PyObject *samps, *str, *rv = NULL, *channel;
     int bytes_per_frame;
 
-    if (!audioop_check_size(width))
+    if (!audioop_check_size(module, width))
         return NULL;
     if (nchannels < 1) {
-        PyErr_SetString(AudioopError, "# of channels should be >= 1");
+        PyErr_SetString(_audioopstate(module)->AudioopError, "# of channels should be >= 1");
         return NULL;
     }
     if (width > INT_MAX / nchannels) {
@@ -1318,17 +1323,17 @@ audioop_ratecv_impl(PyObject *module, Py_buffer *fragment, int width,
     }
     bytes_per_frame = width * nchannels;
     if (weightA < 1 || weightB < 0) {
-        PyErr_SetString(AudioopError,
+        PyErr_SetString(_audioopstate(module)->AudioopError,
             "weightA should be >= 1, weightB should be >= 0");
         return NULL;
     }
     assert(fragment->len >= 0);
     if (fragment->len % bytes_per_frame != 0) {
-        PyErr_SetString(AudioopError, "not a whole number of frames");
+        PyErr_SetString(_audioopstate(module)->AudioopError, "not a whole number of frames");
         return NULL;
     }
     if (inrate <= 0 || outrate <= 0) {
-        PyErr_SetString(AudioopError, "sampling rate not > 0");
+        PyErr_SetString(_audioopstate(module)->AudioopError, "sampling rate not > 0");
         return NULL;
     }
     /* divide inrate and outrate by their greatest common divisor */
@@ -1369,7 +1374,7 @@ audioop_ratecv_impl(PyObject *module, Py_buffer *fragment, int width,
                         &d, &PyTuple_Type, &samps))
             goto exit;
         if (PyTuple_Size(samps) != nchannels) {
-            PyErr_SetString(AudioopError,
+            PyErr_SetString(_audioopstate(module)->AudioopError,
                             "illegal state argument");
             goto exit;
         }
@@ -1491,7 +1496,7 @@ audioop_lin2ulaw_impl(PyObject *module, Py_buffer *fragment, int width)
     Py_ssize_t i;
     PyObject *rv;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
 
     rv = PyBytes_FromStringAndSize(NULL, fragment->len/width);
@@ -1525,7 +1530,7 @@ audioop_ulaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
     Py_ssize_t i;
     PyObject *rv;
 
-    if (!audioop_check_size(width))
+    if (!audioop_check_size(module, width))
         return NULL;
 
     if (fragment->len > PY_SSIZE_T_MAX/width) {
@@ -1564,7 +1569,7 @@ audioop_lin2alaw_impl(PyObject *module, Py_buffer *fragment, int width)
     Py_ssize_t i;
     PyObject *rv;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
 
     rv = PyBytes_FromStringAndSize(NULL, fragment->len/width);
@@ -1599,7 +1604,7 @@ audioop_alaw2lin_impl(PyObject *module, Py_buffer *fragment, int width)
     int val;
     PyObject *rv;
 
-    if (!audioop_check_size(width))
+    if (!audioop_check_size(module, width))
         return NULL;
 
     if (fragment->len > PY_SSIZE_T_MAX/width) {
@@ -1643,7 +1648,7 @@ audioop_lin2adpcm_impl(PyObject *module, Py_buffer *fragment, int width,
     PyObject *rv = NULL, *str;
     int outputbuffer = 0, bufferstep;
 
-    if (!audioop_check_parameters(fragment->len, width))
+    if (!audioop_check_parameters(module, fragment->len, width))
         return NULL;
 
     /* Decode state, should have (value, step) */
@@ -1773,7 +1778,7 @@ audioop_adpcm2lin_impl(PyObject *module, Py_buffer *fragment, int width,
     PyObject *rv, *str;
     int inputbuffer = 0, bufferstep;
 
-    if (!audioop_check_size(width))
+    if (!audioop_check_size(module, width))
         return NULL;
 
     /* Decode state, should have (value, step) */
@@ -1897,31 +1902,48 @@ static PyMethodDef audioop_methods[] = {
     { 0,          0 }
 };
 
+static int
+audioop_traverse(PyObject *m, visitproc visit, void *arg) {
+    _audioopstate *state = _audioopstate(m);
+    if (state != NULL)
+        Py_VISIT(state->AudioopError);
+    return 0;
+}
+static int
+audioop_clear(PyObject *m) {
+    _audioopstate *state = _audioopstate(m);
+    if (state != NULL)
+        Py_CLEAR(state->AudioopError);
+    return 0;
+}
+static void
+audioop_free(void *m) {
+    audioop_clear((PyObject *)m);
+}
 
 static struct PyModuleDef audioopmodule = {
     PyModuleDef_HEAD_INIT,
     "audioop",
     NULL,
-    -1,
+    sizeof(_audioopstate),
     audioop_methods,
     NULL,
-    NULL,
-    NULL,
-    NULL
+    audioop_traverse,
+    audioop_clear,
+    audioop_free
 };
 
 PyMODINIT_FUNC
 PyInit_audioop(void)
 {
-    PyObject *m, *d;
-    m = PyModule_Create(&audioopmodule);
+    PyObject *m = PyModule_Create(&audioopmodule);
     if (m == NULL)
         return NULL;
-    d = PyModule_GetDict(m);
-    if (d == NULL)
+    PyObject *AudioopError = PyErr_NewException("audioop.error", NULL, NULL);
+    if (AudioopError == NULL)
         return NULL;
-    AudioopError = PyErr_NewException("audioop.error", NULL, NULL);
-    if (AudioopError != NULL)
-         PyDict_SetItemString(d,"error",AudioopError);
+    Py_INCREF(AudioopError);
+    PyModule_AddObject(m, "error", AudioopError);
+    _audioopstate(m)->AudioopError = AudioopError;
     return m;
 }



More information about the Python-checkins mailing list