From 2d8757758d0d75882fef0fe0e3c74c4756b3e81e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 29 Apr 2020 18:49:00 +0200 Subject: [PATCH] bpo-40286: Remove C implementation of Random.randbytes() (GH-19797) Remove _random.Random.randbytes(): the C implementation of randbytes(). Implement the method in Python to ease subclassing: randbytes() now directly reuses getrandbits(). --- Lib/random.py | 6 +++ .../2020-04-29-18-02-16.bpo-40286.txbQNx.rst | 3 ++ Modules/_randommodule.c | 45 ------------------- Modules/clinic/_randommodule.c.h | 43 +----------------- 4 files changed, 10 insertions(+), 87 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-04-29-18-02-16.bpo-40286.txbQNx.rst diff --git a/Lib/random.py b/Lib/random.py index f1df18d5c18..80fe447db6c 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -192,6 +192,12 @@ class Random(_random.Random): ## ---- Methods below this point do not need to be overridden when ## ---- subclassing for the purpose of using a different core generator. +## -------------------- bytes methods --------------------- + + def randbytes(self, n): + """Generate n random bytes.""" + return self.getrandbits(n * 8).to_bytes(n, 'little') + ## -------------------- pickle support ------------------- # Issue 17489: Since __reduce__ was defined to fix #759889 this is no diff --git a/Misc/NEWS.d/next/Library/2020-04-29-18-02-16.bpo-40286.txbQNx.rst b/Misc/NEWS.d/next/Library/2020-04-29-18-02-16.bpo-40286.txbQNx.rst new file mode 100644 index 00000000000..ab9bfa65e07 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-04-29-18-02-16.bpo-40286.txbQNx.rst @@ -0,0 +1,3 @@ +Remove ``_random.Random.randbytes()``: the C implementation of +``randbytes()``. Implement the method in Python to ease subclassing: +``randbytes()`` now directly reuses ``getrandbits()``. diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c index 0fc2d07bb50..3589173edcb 100644 --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -513,50 +513,6 @@ _random_Random_getrandbits_impl(RandomObject *self, int k) return result; } -/*[clinic input] - -_random.Random.randbytes - - self: self(type="RandomObject *") - n: Py_ssize_t - / - -Generate n random bytes. -[clinic start generated code]*/ - -static PyObject * -_random_Random_randbytes_impl(RandomObject *self, Py_ssize_t n) -/*[clinic end generated code: output=67a28548079a17ea input=7ba658a24150d233]*/ -{ - if (n < 0) { - PyErr_SetString(PyExc_ValueError, - "number of bytes must be non-negative"); - return NULL; - } - - PyObject *bytes = PyBytes_FromStringAndSize(NULL, n); - if (bytes == NULL) { - return NULL; - } - uint8_t *ptr = (uint8_t *)PyBytes_AS_STRING(bytes); - - for (; n; ptr += 4, n -= 4) { - uint32_t word = genrand_uint32(self); -#if PY_BIG_ENDIAN - /* Convert to little endian */ - word = _Py_bswap32(word); -#endif - if (n < 4) { - /* Drop least significant bits */ - memcpy(ptr, (uint8_t *)&word + (4 - n), n); - break; - } - memcpy(ptr, &word, 4); - } - - return bytes; -} - static PyObject * random_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -586,7 +542,6 @@ static PyMethodDef random_methods[] = { _RANDOM_RANDOM_GETSTATE_METHODDEF _RANDOM_RANDOM_SETSTATE_METHODDEF _RANDOM_RANDOM_GETRANDBITS_METHODDEF - _RANDOM_RANDOM_RANDBYTES_METHODDEF {NULL, NULL} /* sentinel */ }; diff --git a/Modules/clinic/_randommodule.c.h b/Modules/clinic/_randommodule.c.h index dda78f6013c..a467811d93b 100644 --- a/Modules/clinic/_randommodule.c.h +++ b/Modules/clinic/_randommodule.c.h @@ -114,45 +114,4 @@ _random_Random_getrandbits(RandomObject *self, PyObject *arg) exit: return return_value; } - -PyDoc_STRVAR(_random_Random_randbytes__doc__, -"randbytes($self, n, /)\n" -"--\n" -"\n" -"Generate n random bytes."); - -#define _RANDOM_RANDOM_RANDBYTES_METHODDEF \ - {"randbytes", (PyCFunction)_random_Random_randbytes, METH_O, _random_Random_randbytes__doc__}, - -static PyObject * -_random_Random_randbytes_impl(RandomObject *self, Py_ssize_t n); - -static PyObject * -_random_Random_randbytes(RandomObject *self, PyObject *arg) -{ - PyObject *return_value = NULL; - Py_ssize_t n; - - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - goto exit; - } - { - Py_ssize_t ival = -1; - PyObject *iobj = PyNumber_Index(arg); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) { - goto exit; - } - n = ival; - } - return_value = _random_Random_randbytes_impl(self, n); - -exit: - return return_value; -} -/*[clinic end generated code: output=e515c651860c4001 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a7feb0c9c8d1b627 input=a9049054013a1b77]*/