]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-135326: Restore support of __index__ in random.getrandbits() (#135332)
authorSerhiy Storchaka <storchaka@gmail.com>
Tue, 10 Jun 2025 10:41:10 +0000 (13:41 +0300)
committerGitHub <noreply@github.com>
Tue, 10 Jun 2025 10:41:10 +0000 (12:41 +0200)
Lib/test/test_random.py
Misc/NEWS.d/next/Library/2025-06-10-10-00-17.gh-issue-135326.sOHe_p.rst [new file with mode: 0644]
Modules/_randommodule.c
Modules/clinic/_randommodule.c.h

index 22b097b974c640063c5df75932baa155c3dcca48..29caa0aade024f161e42825fc7a2afe25ceb5522 100644 (file)
@@ -14,6 +14,15 @@ from test import support
 from fractions import Fraction
 from collections import abc, Counter
 
+
+class MyIndex:
+    def __init__(self, value):
+        self.value = value
+
+    def __index__(self):
+        return self.value
+
+
 class TestBasicOps:
     # Superclass with tests common to all generators.
     # Subclasses must arrange for self.gen to retrieve the Random instance
@@ -393,7 +402,7 @@ class TestBasicOps:
         self.assertRaises(TypeError, self.gen.getrandbits, 1, 2)
         self.assertRaises(ValueError, self.gen.getrandbits, -1)
         self.assertRaises(OverflowError, self.gen.getrandbits, 1<<1000)
-        self.assertRaises(ValueError, self.gen.getrandbits, -1<<1000)
+        self.assertRaises((ValueError, OverflowError), self.gen.getrandbits, -1<<1000)
         self.assertRaises(TypeError, self.gen.getrandbits, 10.1)
 
     def test_pickling(self):
@@ -809,6 +818,9 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase):
         self.gen.seed(1234567)
         self.assertEqual(self.gen.getrandbits(100),
                          97904845777343510404718956115)
+        self.gen.seed(1234567)
+        self.assertEqual(self.gen.getrandbits(MyIndex(100)),
+                         97904845777343510404718956115)
 
     def test_getrandbits_2G_bits(self):
         size = 2**31
diff --git a/Misc/NEWS.d/next/Library/2025-06-10-10-00-17.gh-issue-135326.sOHe_p.rst b/Misc/NEWS.d/next/Library/2025-06-10-10-00-17.gh-issue-135326.sOHe_p.rst
new file mode 100644 (file)
index 0000000..c83f67b
--- /dev/null
@@ -0,0 +1,2 @@
+Restore support of integer-like objects with :meth:`!__index__` in
+:func:`random.getrandbits`.
index 8fb040fb6c5b35d34d39cc3eb8861cef3485d9f8..6a311bb0d71f9fa06f784add69930c1608f178b2 100644 (file)
@@ -495,21 +495,27 @@ _random_Random_setstate_impl(RandomObject *self, PyObject *state)
 _random.Random.getrandbits
 
   self: self(type="RandomObject *")
-  k: unsigned_long_long(bitwise=False)
+  k: long_long
   /
 
 getrandbits(k) -> x.  Generates an int with k random bits.
 [clinic start generated code]*/
 
 static PyObject *
-_random_Random_getrandbits_impl(RandomObject *self, unsigned long long k)
-/*[clinic end generated code: output=25a604fab95885d4 input=88e51091eea2f042]*/
+_random_Random_getrandbits_impl(RandomObject *self, long long k)
+/*[clinic end generated code: output=c2c02a7b0bfdf7f7 input=834d0fe668b981e4]*/
 {
     Py_ssize_t i, words;
     uint32_t r;
     uint32_t *wordarray;
     PyObject *result;
 
+    if (k < 0) {
+        PyErr_SetString(PyExc_ValueError,
+                        "number of bits must be non-negative");
+        return NULL;
+    }
+
     if (k == 0)
         return PyLong_FromLong(0);
 
index 12c845d4c44d00607e686de0a85f033f82cb650d..b9f2e53bb5c9250732a50570e9e1e8e1b8ff597d 100644 (file)
@@ -3,7 +3,6 @@ preserve
 [clinic start generated code]*/
 
 #include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
-#include "pycore_long.h"          // _PyLong_UnsignedLongLong_Converter()
 #include "pycore_modsupport.h"    // _PyArg_CheckPositional()
 
 PyDoc_STRVAR(_random_Random_random__doc__,
@@ -125,15 +124,16 @@ PyDoc_STRVAR(_random_Random_getrandbits__doc__,
     {"getrandbits", (PyCFunction)_random_Random_getrandbits, METH_O, _random_Random_getrandbits__doc__},
 
 static PyObject *
-_random_Random_getrandbits_impl(RandomObject *self, unsigned long long k);
+_random_Random_getrandbits_impl(RandomObject *self, long long k);
 
 static PyObject *
 _random_Random_getrandbits(RandomObject *self, PyObject *arg)
 {
     PyObject *return_value = NULL;
-    unsigned long long k;
+    long long k;
 
-    if (!_PyLong_UnsignedLongLong_Converter(arg, &k)) {
+    k = PyLong_AsLongLong(arg);
+    if (k == -1 && PyErr_Occurred()) {
         goto exit;
     }
     Py_BEGIN_CRITICAL_SECTION(self);
@@ -143,4 +143,4 @@ _random_Random_getrandbits(RandomObject *self, PyObject *arg)
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=e9a5c68295678cff input=a9049054013a1b77]*/
+/*[clinic end generated code: output=d3a199bc869e5c63 input=a9049054013a1b77]*/