From 286810d25b67f0d7df4bcf5ff772e558a73670c2 Mon Sep 17 00:00:00 2001 From: jyj Date: Sat, 25 Mar 2023 15:04:15 +0900 Subject: [PATCH 1/2] Fix byteorder parameter of int.from_bytes to optional --- vm/src/builtins/int.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/vm/src/builtins/int.rs b/vm/src/builtins/int.rs index f46047f67..0ad9949c6 100644 --- a/vm/src/builtins/int.rs +++ b/vm/src/builtins/int.rs @@ -794,6 +794,7 @@ pub struct IntOptions { #[derive(FromArgs)] struct IntFromByteArgs { bytes: PyBytesInner, + #[pyarg(any, default = "ArgByteOrder::Big")] byteorder: ArgByteOrder, #[pyarg(named, optional)] signed: OptionalArg, From 8c9a33b737f135114449706772a6c2455781aec4 Mon Sep 17 00:00:00 2001 From: jyj Date: Sat, 25 Mar 2023 13:17:06 +0900 Subject: [PATCH 2/2] Update random/test_random from CPython v3.11.2 --- Lib/random.py | 82 ++++++++++++++--------------------------- Lib/test/test_random.py | 77 ++++++++++++++++++++------------------ 2 files changed, 70 insertions(+), 89 deletions(-) diff --git a/Lib/random.py b/Lib/random.py index f8735d42a..85bad08d5 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -167,15 +167,11 @@ class Random(_random.Random): elif version == 2 and isinstance(a, (str, bytes, bytearray)): if isinstance(a, str): a = a.encode() - a = int.from_bytes(a + _sha512(a).digest(), 'big') + a = int.from_bytes(a + _sha512(a).digest()) elif not isinstance(a, (type(None), int, float, str, bytes, bytearray)): - _warn('Seeding based on hashing is deprecated\n' - 'since Python 3.9 and will be removed in a subsequent ' - 'version. The only \n' - 'supported seed types are: None, ' - 'int, float, str, bytes, and bytearray.', - DeprecationWarning, 2) + raise TypeError('The only supported seed types are: None,\n' + 'int, float, str, bytes, and bytearray.') super().seed(a) self.gauss_next = None @@ -250,10 +246,8 @@ class Random(_random.Random): break def _randbelow_with_getrandbits(self, n): - "Return a random int in the range [0,n). Returns 0 if n==0." + "Return a random int in the range [0,n). Defined for n > 0." - if not n: - return 0 getrandbits = self.getrandbits k = n.bit_length() # don't use (n-1) here because n can be 1 r = getrandbits(k) # 0 <= r < 2**k @@ -262,7 +256,7 @@ class Random(_random.Random): return r def _randbelow_without_getrandbits(self, n, maxsize=1< 0. The implementation does not use getrandbits, but only random. """ @@ -273,8 +267,6 @@ class Random(_random.Random): "enough bits to choose from a population range this large.\n" "To remove the range limitation, add a getrandbits() method.") return _floor(random() * n) - if n == 0: - return 0 rem = maxsize % n limit = (maxsize - rem) / maxsize # int(limit * maxsize) % n == 0 r = random() @@ -303,10 +295,10 @@ class Random(_random.Random): ## -------------------- integer methods ------------------- def randrange(self, start, stop=None, step=_ONE): - """Choose a random item from range(start, stop[, step]). + """Choose a random item from range(stop) or range(start, stop[, step]). - This fixes the problem with randint() which includes the - endpoint; in Python this is usually not what you want. + Roughly equivalent to ``choice(range(start, stop, step))`` but + supports arbitrarily large ranges and is optimized for common cases. """ @@ -387,37 +379,24 @@ class Random(_random.Random): def choice(self, seq): """Choose a random element from a non-empty sequence.""" - # raises IndexError if seq is empty + + # As an accommodation for NumPy, we don't use "if not seq" + # because bool(numpy.array()) raises a ValueError. + if not len(seq): + raise IndexError('Cannot choose from an empty sequence') return seq[self._randbelow(len(seq))] - def shuffle(self, x, random=None): - """Shuffle list x in place, and return None. + def shuffle(self, x): + """Shuffle list x in place, and return None.""" - Optional argument random is a 0-argument function returning a - random float in [0.0, 1.0); if it is the default None, the - standard random.random will be used. - - """ - - if random is None: - randbelow = self._randbelow - for i in reversed(range(1, len(x))): - # pick an element in x[:i+1] with which to exchange x[i] - j = randbelow(i + 1) - x[i], x[j] = x[j], x[i] - else: - _warn('The *random* parameter to shuffle() has been deprecated\n' - 'since Python 3.9 and will be removed in a subsequent ' - 'version.', - DeprecationWarning, 2) - floor = _floor - for i in reversed(range(1, len(x))): - # pick an element in x[:i+1] with which to exchange x[i] - j = floor(random() * (i + 1)) - x[i], x[j] = x[j], x[i] + randbelow = self._randbelow + for i in reversed(range(1, len(x))): + # pick an element in x[:i+1] with which to exchange x[i] + j = randbelow(i + 1) + x[i], x[j] = x[j], x[i] def sample(self, population, k, *, counts=None): - """Chooses k unique random elements from a population sequence or set. + """Chooses k unique random elements from a population sequence. Returns a new list containing elements from the population while leaving the original population unchanged. The resulting list is @@ -470,13 +449,8 @@ class Random(_random.Random): # causing them to eat more entropy than necessary. if not isinstance(population, _Sequence): - if isinstance(population, _Set): - _warn('Sampling from a set deprecated\n' - 'since Python 3.9 and will be removed in a subsequent version.', - DeprecationWarning, 2) - population = tuple(population) - else: - raise TypeError("Population must be a sequence. For dicts or sets, use sorted(d).") + raise TypeError("Population must be a sequence. " + "For dicts or sets, use sorted(d).") n = len(population) if counts is not None: cum_counts = list(_accumulate(counts)) @@ -580,7 +554,7 @@ class Random(_random.Random): low, high = high, low return low + (high - low) * _sqrt(u * c) - def normalvariate(self, mu, sigma): + def normalvariate(self, mu=0.0, sigma=1.0): """Normal distribution. mu is the mean, and sigma is the standard deviation. @@ -601,7 +575,7 @@ class Random(_random.Random): break return mu + z * sigma - def gauss(self, mu, sigma): + def gauss(self, mu=0.0, sigma=1.0): """Gaussian distribution. mu is the mean, and sigma is the standard deviation. This is @@ -833,15 +807,15 @@ class SystemRandom(Random): """ def random(self): - """Get the next random number in the range [0.0, 1.0).""" - return (int.from_bytes(_urandom(7), 'big') >> 3) * RECIP_BPF + """Get the next random number in the range 0.0 <= X < 1.0.""" + return (int.from_bytes(_urandom(7)) >> 3) * RECIP_BPF def getrandbits(self, k): """getrandbits(k) -> x. Generates an int with k random bits.""" if k < 0: raise ValueError('number of bits must be non-negative') numbytes = (k + 7) // 8 # bits / 8 and rounded up - x = int.from_bytes(_urandom(numbytes), 'big') + x = int.from_bytes(_urandom(numbytes)) return x >> (numbytes * 8 - k) # trim excess bits def randbytes(self, n): diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index e7028504e..4bf00d5db 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -52,12 +52,11 @@ class TestBasicOps: self.gen.seed(arg) for arg in [1+2j, tuple('abc'), MySeed()]: - with self.assertWarns(DeprecationWarning): + with self.assertRaises(TypeError): self.gen.seed(arg) for arg in [list(range(3)), dict(one=1)]: - with self.assertWarns(DeprecationWarning): - self.assertRaises(TypeError, self.gen.seed, arg) + self.assertRaises(TypeError, self.gen.seed, arg) self.assertRaises(TypeError, self.gen.seed, 1, 2, 3, 4) self.assertRaises(TypeError, type(self.gen), []) @@ -110,15 +109,6 @@ class TestBasicOps: self.assertTrue(lst != shuffled_lst) self.assertRaises(TypeError, shuffle, (1, 2, 3)) - def test_shuffle_random_argument(self): - # Test random argument to shuffle. - shuffle = self.gen.shuffle - mock_random = unittest.mock.Mock(return_value=0.5) - seq = bytearray(b'abcdefghijk') - with self.assertWarns(DeprecationWarning): - shuffle(seq, mock_random) - mock_random.assert_called_with() - def test_choice(self): choice = self.gen.choice with self.assertRaises(IndexError): @@ -126,6 +116,21 @@ class TestBasicOps: self.assertEqual(choice([50]), 50) self.assertIn(choice([25, 75]), [25, 75]) + def test_choice_with_numpy(self): + # Accommodation for NumPy arrays which have disabled __bool__(). + # See: https://github.com/python/cpython/issues/100805 + choice = self.gen.choice + + class NA(list): + "Simulate numpy.array() behavior" + def __bool__(self): + raise RuntimeError + + with self.assertRaises(IndexError): + choice(NA([])) + self.assertEqual(choice(NA([50])), 50) + self.assertIn(choice(NA([25, 75])), [25, 75]) + def test_sample(self): # For the entire allowable range of 0 <= k <= N, validate that # the sample is of the correct length and contains only unique items @@ -169,7 +174,7 @@ class TestBasicOps: self.assertRaises(TypeError, self.gen.sample, dict.fromkeys('abcdef'), 2) def test_sample_on_sets(self): - with self.assertWarns(DeprecationWarning): + with self.assertRaises(TypeError): population = {10, 20, 30, 40, 50, 60, 70} self.gen.sample(population, k=5) @@ -391,23 +396,6 @@ class TestBasicOps: restoredseq = [newgen.random() for i in range(10)] self.assertEqual(origseq, restoredseq) - @test.support.cpython_only - def test_bug_41052(self): - # _random.Random should not be allowed to serialization - import _random - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - r = _random.Random() - self.assertRaises(TypeError, pickle.dumps, r, proto) - - @test.support.cpython_only - def test_bug_42008(self): - # _random.Random should call seed with first element of arg tuple - import _random - r1 = _random.Random() - r1.seed(8675309) - r2 = _random.Random(8675309) - self.assertEqual(r1.random(), r2.random()) - # TODO: RUSTPYTHON AttributeError: 'super' object has no attribute 'getstate' @unittest.expectedFailure def test_bug_1727780(self): @@ -445,6 +433,10 @@ class TestBasicOps: self.assertRaises(ValueError, self.gen.randbytes, -1) self.assertRaises(TypeError, self.gen.randbytes, 1.0) + def test_mu_sigma_default_args(self): + self.assertIsInstance(self.gen.normalvariate(), float) + self.assertIsInstance(self.gen.gauss(), float) + try: random.SystemRandom().random() @@ -592,6 +584,25 @@ class SystemRandom_TestBasicOps(TestBasicOps, unittest.TestCase): self.assertTrue(2**k > n > 2**(k-1)) # note the stronger assertion +class TestRawMersenneTwister(unittest.TestCase): + @test.support.cpython_only + def test_bug_41052(self): + # _random.Random should not be allowed to serialization + import _random + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + r = _random.Random() + self.assertRaises(TypeError, pickle.dumps, r, proto) + + @test.support.cpython_only + def test_bug_42008(self): + # _random.Random should call seed with first element of arg tuple + import _random + r1 = _random.Random() + r1.seed(8675309) + r2 = _random.Random(8675309) + self.assertEqual(r1.random(), r2.random()) + + class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase): gen = random.Random() @@ -846,10 +857,6 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase): maxsize+1, maxsize=maxsize ) self.gen._randbelow_without_getrandbits(5640, maxsize=maxsize) - # issue 33203: test that _randbelow returns zero on - # n == 0 also in its getrandbits-independent branch. - x = self.gen._randbelow_without_getrandbits(0, maxsize=maxsize) - self.assertEqual(x, 0) # This might be going too far to test a single line, but because of our # noble aim of achieving 100% test coverage we need to write a case in @@ -1331,7 +1338,7 @@ class TestModule(unittest.TestCase): # tests validity but not completeness of the __all__ list self.assertTrue(set(random.__all__) <= set(dir(random))) - @unittest.skipUnless(hasattr(os, "fork"), "fork() required") + @test.support.requires_fork() def test_after_fork(self): # Test the global Random instance gets reseeded in child r, w = os.pipe()