From 70a071d9e1d65f8c168b4b96a18c86d5230789c5 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Tue, 4 May 2021 01:55:40 -0700 Subject: [PATCH] bpo-40465: Remove random module features deprecated in 3.9 (GH-25874) --- Doc/library/random.rst | 22 ++++---- Lib/random.py | 50 +++++-------------- Lib/test/test_random.py | 16 ++---- .../2021-05-03-19-59-14.bpo-40465.1tB4Y0.rst | 1 + 4 files changed, 25 insertions(+), 64 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2021-05-03-19-59-14.bpo-40465.1tB4Y0.rst diff --git a/Doc/library/random.rst b/Doc/library/random.rst index e924127d8b8..e444f957324 100644 --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -86,8 +86,8 @@ Bookkeeping functions .. versionchanged:: 3.2 Moved to the version 2 scheme which uses all of the bits in a string seed. - .. deprecated:: 3.9 - In the future, the *seed* must be one of the following types: + .. versionchanged:: 3.11 + The *seed* must be one of the following types: *NoneType*, :class:`int`, :class:`float`, :class:`str`, :class:`bytes`, or :class:`bytearray`. @@ -208,13 +208,10 @@ Functions for sequences Raises a :exc:`ValueError` if all weights are zero. -.. function:: shuffle(x[, random]) +.. function:: shuffle(x) Shuffle the sequence *x* in place. - The optional argument *random* is a 0-argument function returning a random - float in [0.0, 1.0); by default, this is the function :func:`.random`. - To shuffle an immutable sequence and return a new shuffled list, use ``sample(x, k=len(x))`` instead. @@ -230,8 +227,8 @@ Functions for sequences .. function:: sample(population, k, *, counts=None) - Return a *k* length list of unique elements chosen from the population sequence - or set. Used for random sampling without replacement. + Return a *k* length list of unique elements chosen from the population + sequence. Used for random sampling without replacement. Returns a new list containing elements from the population while leaving the original population unchanged. The resulting list is in selection order so that @@ -257,11 +254,10 @@ Functions for sequences .. versionchanged:: 3.9 Added the *counts* parameter. - .. deprecated:: 3.9 - In the future, the *population* must be a sequence. Instances of - :class:`set` are no longer supported. The set must first be converted - to a :class:`list` or :class:`tuple`, preferably in a deterministic - order so that the sample is reproducible. + .. versionchanged:: 3.11 + + The *population* must be a sequence. Automatic conversion of sets + to lists is longer supported. .. _real-valued-distributions: diff --git a/Lib/random.py b/Lib/random.py index 1310a2d9d0e..38c4a540522 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -157,12 +157,8 @@ def seed(self, a=None, version=2): a = int.from_bytes(a + _sha512(a).digest(), 'big') 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 @@ -377,34 +373,17 @@ def choice(self, seq): # raises IndexError if seq is empty 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 @@ -457,13 +436,8 @@ def sample(self, population, k, *, counts=None): # 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)) diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index 5354eddab69..c2dd50b981b 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -48,12 +48,11 @@ def __hash__(self): 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), []) @@ -105,15 +104,6 @@ def test_shuffle(self): 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): @@ -164,7 +154,7 @@ def test_sample_on_dicts(self): 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) diff --git a/Misc/NEWS.d/next/Library/2021-05-03-19-59-14.bpo-40465.1tB4Y0.rst b/Misc/NEWS.d/next/Library/2021-05-03-19-59-14.bpo-40465.1tB4Y0.rst new file mode 100644 index 00000000000..b8b63debdbc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-05-03-19-59-14.bpo-40465.1tB4Y0.rst @@ -0,0 +1 @@ +Remove random module features deprecated in Python 3.9.