From 9f81ab8b1161ac7f8c5eb0fe42501e5fa903dffb Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 22 Jun 2019 10:11:43 +0300 Subject: [PATCH 1/6] Use index() instead of int() to check args of randrange(). --- Lib/random.py | 35 +++++++++++++++-------------------- Lib/test/test_random.py | 9 ++++++--- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/Lib/random.py b/Lib/random.py index e24737d4508a8f..e8fbe2f52d90bc 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -44,6 +44,7 @@ from _collections_abc import Set as _Set, Sequence as _Sequence from itertools import accumulate as _accumulate, repeat as _repeat from bisect import bisect as _bisect +from operator import index as _index import os as _os try: @@ -208,7 +209,7 @@ def __reduce__(self): ## -------------------- integer methods ------------------- - def randrange(self, start, stop=None, step=1, _int=int): + def randrange(self, start, stop=None, step=1, _index=_index): """Choose a random item from range(start, stop[, step]). This fixes the problem with randint() which includes the @@ -218,39 +219,33 @@ def randrange(self, start, stop=None, step=1, _int=int): # This code is a bit messy to make it fast for the # common case while still doing adequate error checking. - istart = _int(start) - if istart != start: - raise ValueError("non-integer arg 1 for randrange()") + start = _index(start) if stop is None: - if istart > 0: - return self._randbelow(istart) + if start > 0: + return self._randbelow(start) raise ValueError("empty range for randrange()") # stop argument supplied. - istop = _int(stop) - if istop != stop: - raise ValueError("non-integer stop for randrange()") - width = istop - istart + stop = _index(stop) + width = stop - start if step == 1 and width > 0: - return istart + self._randbelow(width) + return start + self._randbelow(width) if step == 1: - raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width)) + raise ValueError("empty range for randrange() (%d, %d, %d)" % (start, stop, width)) # Non-unit step argument supplied. - istep = _int(step) - if istep != step: - raise ValueError("non-integer step for randrange()") - if istep > 0: - n = (width + istep - 1) // istep - elif istep < 0: - n = (width + istep + 1) // istep + step = _index(step) + if step > 0: + n = (width + step - 1) // step + elif step < 0: + n = (width + step + 1) // step else: raise ValueError("zero step for randrange()") if n <= 0: raise ValueError("empty range for randrange()") - return istart + istep*self._randbelow(n) + return start + step*self._randbelow(n) def randint(self, a, b): """Return random integer in range [a, b], including both end points. diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index c147105376199a..09878959981108 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -368,11 +368,14 @@ def test_randrange_errors(self): raises(-721) raises(0, 100, -12) # Non-integer start/stop - raises(3.14159) - raises(0, 2.71828) + self.assertRaises(TypeError, self.gen.randrange, 3.0) + self.assertRaises(TypeError, self.gen.randrange, Fraction(3, 1)) + self.assertRaises(TypeError, self.gen.randrange, 0, 2.0) + self.assertRaises(TypeError, self.gen.randrange, 0, Fraction(2, 1)) # Zero and non-integer step raises(0, 42, 0) - raises(0, 42, 3.14159) + self.assertRaises(TypeError, self.gen.randrange, 0, 42, 3.0) + self.assertRaises(TypeError, self.gen.randrange, 0, 42, Fraction(3, 1)) def test_genrandbits(self): # Verify ranges From ccff52ec138142d4825ea9d1a9a377f1440b01f7 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 22 Mar 2020 21:25:22 +0200 Subject: [PATCH 2/6] Fallaback to int(). --- Doc/library/random.rst | 4 ++ Doc/whatsnew/3.9.rst | 3 + Lib/random.py | 56 +++++++++++++------ Lib/test/test_random.py | 19 +++++-- .../2020-03-22-21-33-31.bpo-37319.BrIAir.rst | 1 + 5 files changed, 60 insertions(+), 23 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst diff --git a/Doc/library/random.rst b/Doc/library/random.rst index 1eb39bbda42e81..aa92bff0f29a9b 100644 --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -130,6 +130,10 @@ Functions for integers values. Formerly it used a style like ``int(random()*n)`` which could produce slightly uneven distributions. + .. deprecated:: 3.9 + Accepting non-integer arguments is deprecated. + + .. function:: randint(a, b) Return a random integer *N* such that ``a <= N <= b``. Alias for diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index b11c29bdf090fa..447505b74d3d36 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -612,6 +612,9 @@ Deprecated by :c:func:`Py_Initialize()` since Python 3.7. (Contributed by Victor Stinner in :issue:`39877`.) +* Deprecated support of non-integer arguments in :func:`random.randrange`. + (Contributed by Serhiy Storchaka in :issue:`37319`.) + Removed ======= diff --git a/Lib/random.py b/Lib/random.py index e8fbe2f52d90bc..7bd1c3b1773e7b 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -68,7 +68,7 @@ SG_MAGICCONST = 1.0 + _log(4.5) BPF = 53 # Number of bits in a float RECIP_BPF = 2**-BPF - +_ONE = 1 # Translated by Guido van Rossum from C source provided by # Adrian Baddeley. Adapted by Raymond Hettinger for use with @@ -209,7 +209,7 @@ def __reduce__(self): ## -------------------- integer methods ------------------- - def randrange(self, start, stop=None, step=1, _index=_index): + def randrange(self, start, stop=None, step=_ONE, _index=_index, _int=int): """Choose a random item from range(start, stop[, step]). This fixes the problem with randint() which includes the @@ -219,33 +219,55 @@ def randrange(self, start, stop=None, step=1, _index=_index): # This code is a bit messy to make it fast for the # common case while still doing adequate error checking. - start = _index(start) + try: + istart = _index(start) + except TypeError: + istart = _int(start) + if istart != start: + raise ValueError("non-integer arg 1 for randrange()") + _warn('non-integer arg 1 for randrange()', + DeprecationWarning, 2) if stop is None: - if start > 0: - return self._randbelow(start) + if istart > 0: + return self._randbelow(istart) raise ValueError("empty range for randrange()") # stop argument supplied. - stop = _index(stop) - width = stop - start - if step == 1 and width > 0: - return start + self._randbelow(width) - if step == 1: - raise ValueError("empty range for randrange() (%d, %d, %d)" % (start, stop, width)) + try: + istop = _index(stop) + except TypeError: + istop = _int(stop) + if istop != stop: + raise ValueError("non-integer stop for randrange()") + _warn('non-integer stop for randrange()', + DeprecationWarning, 2) + width = istop - istart + # Fast path. + if step is _ONE: + if width > 0: + return istart + self._randbelow(width) + raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width)) # Non-unit step argument supplied. - step = _index(step) - if step > 0: - n = (width + step - 1) // step - elif step < 0: - n = (width + step + 1) // step + try: + istep = _index(step) + except TypeError: + istep = _int(step) + if istep != step: + raise ValueError("non-integer step for randrange()") + _warn('non-integer step for randrange()', + DeprecationWarning, 2) + if istep > 0: + n = (width + istep - 1) // istep + elif istep < 0: + n = (width + istep + 1) // istep else: raise ValueError("zero step for randrange()") if n <= 0: raise ValueError("empty range for randrange()") - return start + step*self._randbelow(n) + return istart + istep*self._randbelow(n) def randint(self, a, b): """Return random integer in range [a, b], including both end points. diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index 09878959981108..6c562cedbf36a5 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -367,15 +367,22 @@ def test_randrange_errors(self): raises(3, 3) raises(-721) raises(0, 100, -12) + self.assertWarns(DeprecationWarning, raises, 3, 3, 1.0) # Non-integer start/stop - self.assertRaises(TypeError, self.gen.randrange, 3.0) - self.assertRaises(TypeError, self.gen.randrange, Fraction(3, 1)) - self.assertRaises(TypeError, self.gen.randrange, 0, 2.0) - self.assertRaises(TypeError, self.gen.randrange, 0, Fraction(2, 1)) + raises(3.14159) + self.assertWarns(DeprecationWarning, self.gen.randrange, 3.0) + self.assertWarns(DeprecationWarning, self.gen.randrange, Fraction(3, 1)) + raises('3') + raises(0, 2.71828) + self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 2.0) + self.assertWarns(DeprecationWarning, self.gen.randrange, 0, Fraction(2, 1)) + raises(0, '2') # Zero and non-integer step raises(0, 42, 0) - self.assertRaises(TypeError, self.gen.randrange, 0, 42, 3.0) - self.assertRaises(TypeError, self.gen.randrange, 0, 42, Fraction(3, 1)) + raises(0, 42, 3.14159) + self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, 3.0) + self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, Fraction(3, 1)) + raises(0, 42, '3') def test_genrandbits(self): # Verify ranges diff --git a/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst b/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst new file mode 100644 index 00000000000000..5c1f4e3bc4a423 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst @@ -0,0 +1 @@ +Deprecated support of non-integer arguments in :func:`random.randrange`. From fcd65492fcaaa65b9e4dc1b6fc581ab2d8dbb86e Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 31 Oct 2020 22:50:26 +0200 Subject: [PATCH 3/6] Remove _ONE. --- Lib/random.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Lib/random.py b/Lib/random.py index 01d582e27c1d8e..d504aa92f2ee3d 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -96,7 +96,6 @@ SG_MAGICCONST = 1.0 + _log(4.5) BPF = 53 # Number of bits in a float RECIP_BPF = 2 ** -BPF -_ONE = 1 class Random(_random.Random): @@ -289,7 +288,7 @@ def randbytes(self, n): ## -------------------- integer methods ------------------- - def randrange(self, start, stop=None, step=_ONE): + def randrange(self, start, stop=None, step=1): """Choose a random item from range(start, stop[, step]). This fixes the problem with randint() which includes the @@ -322,13 +321,6 @@ def randrange(self, start, stop=None, step=_ONE): _warn('non-integer stop for randrange()', DeprecationWarning, 2) width = istop - istart - # Fast path. - if step is _ONE: - if width > 0: - return istart + self._randbelow(width) - raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width)) - - # Non-unit step argument supplied. try: istep = _index(step) except TypeError: @@ -337,6 +329,13 @@ def randrange(self, start, stop=None, step=_ONE): raise ValueError("non-integer step for randrange()") _warn('non-integer step for randrange()', DeprecationWarning, 2) + # Fast path. + if istep == 1: + if width > 0: + return istart + self._randbelow(width) + raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width)) + + # Non-unit step argument supplied. if istep > 0: n = (width + istep - 1) // istep elif istep < 0: From 2e8cfda3f88732ef03b6002ed23eef536826321b Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 31 Oct 2020 23:03:02 +0200 Subject: [PATCH 4/6] Raise TypeError instead of ValueError. --- Doc/library/random.rst | 4 ++ Lib/random.py | 6 +-- Lib/test/test_random.py | 38 ++++++++++++------- .../2020-03-22-21-33-31.bpo-37319.BrIAir.rst | 2 + 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/Doc/library/random.rst b/Doc/library/random.rst index 019af2b56f410a..c95691af5456db 100644 --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -135,6 +135,10 @@ Functions for integers values. Formerly it used a style like ``int(random()*n)`` which could produce slightly uneven distributions. + .. versionchanged:: 3.10 + Formerly :exc:`ValueError` could be raised for non-integer arguments + instead of :exc:`TypeError`. + .. deprecated:: 3.10 Accepting non-integer arguments is deprecated. diff --git a/Lib/random.py b/Lib/random.py index d504aa92f2ee3d..d16caafbffac64 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -303,7 +303,7 @@ def randrange(self, start, stop=None, step=1): except TypeError: istart = int(start) if istart != start: - raise ValueError("non-integer arg 1 for randrange()") + raise TypeError("non-integer arg 1 for randrange()") _warn('non-integer arg 1 for randrange()', DeprecationWarning, 2) if stop is None: @@ -317,7 +317,7 @@ def randrange(self, start, stop=None, step=1): except TypeError: istop = int(stop) if istop != stop: - raise ValueError("non-integer stop for randrange()") + raise TypeError("non-integer stop for randrange()") _warn('non-integer stop for randrange()', DeprecationWarning, 2) width = istop - istart @@ -326,7 +326,7 @@ def randrange(self, start, stop=None, step=1): except TypeError: istep = int(step) if istep != step: - raise ValueError("non-integer step for randrange()") + raise TypeError("non-integer step for randrange()") _warn('non-integer step for randrange()', DeprecationWarning, 2) # Fast path. diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index 467d0fd2d5f21a..dbcbc2b178199a 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -504,28 +504,40 @@ def test_randrange_nonunit_step(self): rint = self.gen.randrange(0, 2, 2) self.assertEqual(rint, 0) + def test_randrange_non_integers(self): + randrange = self.gen.randrange + with self.assertWarns(DeprecationWarning): + self.assertIn(randrange(3.0), range(3)) + with self.assertWarns(DeprecationWarning): + self.assertIn(randrange(0, 3.0), range(0, 3)) + with self.assertWarns(DeprecationWarning): + self.assertIn(randrange(0, 42, 1.0), range(0, 42, 1)) + with self.assertWarns(DeprecationWarning): + self.assertIn(randrange(0, 42, 3.0), range(0, 42, 3)) + def test_randrange_errors(self): - raises = partial(self.assertRaises, ValueError, self.gen.randrange) + randrange = self.gen.randrange + raises = partial(self.assertRaises, ValueError, randrange) # Empty range raises(3, 3) raises(-721) raises(0, 100, -12) self.assertWarns(DeprecationWarning, raises, 3, 3, 1.0) # Non-integer start/stop - raises(3.14159) - self.assertWarns(DeprecationWarning, self.gen.randrange, 3.0) - self.assertWarns(DeprecationWarning, self.gen.randrange, Fraction(3, 1)) - raises('3') - raises(0, 2.71828) - self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 2.0) - self.assertWarns(DeprecationWarning, self.gen.randrange, 0, Fraction(2, 1)) - raises(0, '2') + self.assertRaises(TypeError, randrange, 3.14159) + self.assertWarns(DeprecationWarning, randrange, 3.0) + self.assertWarns(DeprecationWarning, randrange, Fraction(3, 1)) + self.assertRaises(TypeError, randrange, '3') + self.assertRaises(TypeError, randrange, 0, 2.71828) + self.assertWarns(DeprecationWarning, randrange, 0, 2.0) + self.assertWarns(DeprecationWarning, randrange, 0, Fraction(2, 1)) + self.assertRaises(TypeError, randrange, 0, '2') # Zero and non-integer step raises(0, 42, 0) - raises(0, 42, 3.14159) - self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, 3.0) - self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, Fraction(3, 1)) - raises(0, 42, '3') + self.assertRaises(TypeError, randrange, 0, 42, 3.14159) + self.assertWarns(DeprecationWarning, randrange, 0, 42, 3.0) + self.assertWarns(DeprecationWarning, randrange, 0, 42, Fraction(3, 1)) + self.assertRaises(TypeError, randrange, 0, 42, '3') def test_randbelow_logic(self, _log=log, int=int): # check bitcount transition points: 2**i and 2**(i+1)-1 diff --git a/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst b/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst index 5c1f4e3bc4a423..7ea1e28309664a 100644 --- a/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst +++ b/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst @@ -1 +1,3 @@ Deprecated support of non-integer arguments in :func:`random.randrange`. +:exc:`TypeError` is now always raised for wrong type of arguments +(formerly :exc:`ValueError` could be raised for some non-integer arguments). From 6ff20ab2e58dd6164a5fbf136edacad0a7893c7d Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 24 Dec 2020 13:52:08 +0200 Subject: [PATCH 5/6] Revert "Raise TypeError instead of ValueError." This reverts commit 2e8cfda3f88732ef03b6002ed23eef536826321b. --- Doc/library/random.rst | 4 -- Lib/random.py | 6 +-- Lib/test/test_random.py | 38 +++++++------------ .../2020-03-22-21-33-31.bpo-37319.BrIAir.rst | 2 - 4 files changed, 16 insertions(+), 34 deletions(-) diff --git a/Doc/library/random.rst b/Doc/library/random.rst index b9e85f41853e5f..f62e8e949534b2 100644 --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -135,10 +135,6 @@ Functions for integers values. Formerly it used a style like ``int(random()*n)`` which could produce slightly uneven distributions. - .. versionchanged:: 3.10 - Formerly :exc:`ValueError` could be raised for non-integer arguments - instead of :exc:`TypeError`. - .. deprecated:: 3.10 Accepting non-integer arguments is deprecated. diff --git a/Lib/random.py b/Lib/random.py index ca0b4775d94406..c64adca1b4edda 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -303,7 +303,7 @@ def randrange(self, start, stop=None, step=1): except TypeError: istart = int(start) if istart != start: - raise TypeError("non-integer arg 1 for randrange()") + raise ValueError("non-integer arg 1 for randrange()") _warn('non-integer arg 1 for randrange()', DeprecationWarning, 2) if stop is None: @@ -317,7 +317,7 @@ def randrange(self, start, stop=None, step=1): except TypeError: istop = int(stop) if istop != stop: - raise TypeError("non-integer stop for randrange()") + raise ValueError("non-integer stop for randrange()") _warn('non-integer stop for randrange()', DeprecationWarning, 2) width = istop - istart @@ -326,7 +326,7 @@ def randrange(self, start, stop=None, step=1): except TypeError: istep = int(step) if istep != step: - raise TypeError("non-integer step for randrange()") + raise ValueError("non-integer step for randrange()") _warn('non-integer step for randrange()', DeprecationWarning, 2) # Fast path. diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index 76249f29b0375f..2a8f5e54594c25 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -529,40 +529,28 @@ def test_randrange_nonunit_step(self): rint = self.gen.randrange(0, 2, 2) self.assertEqual(rint, 0) - def test_randrange_non_integers(self): - randrange = self.gen.randrange - with self.assertWarns(DeprecationWarning): - self.assertIn(randrange(3.0), range(3)) - with self.assertWarns(DeprecationWarning): - self.assertIn(randrange(0, 3.0), range(0, 3)) - with self.assertWarns(DeprecationWarning): - self.assertIn(randrange(0, 42, 1.0), range(0, 42, 1)) - with self.assertWarns(DeprecationWarning): - self.assertIn(randrange(0, 42, 3.0), range(0, 42, 3)) - def test_randrange_errors(self): - randrange = self.gen.randrange - raises = partial(self.assertRaises, ValueError, randrange) + raises = partial(self.assertRaises, ValueError, self.gen.randrange) # Empty range raises(3, 3) raises(-721) raises(0, 100, -12) self.assertWarns(DeprecationWarning, raises, 3, 3, 1.0) # Non-integer start/stop - self.assertRaises(TypeError, randrange, 3.14159) - self.assertWarns(DeprecationWarning, randrange, 3.0) - self.assertWarns(DeprecationWarning, randrange, Fraction(3, 1)) - self.assertRaises(TypeError, randrange, '3') - self.assertRaises(TypeError, randrange, 0, 2.71828) - self.assertWarns(DeprecationWarning, randrange, 0, 2.0) - self.assertWarns(DeprecationWarning, randrange, 0, Fraction(2, 1)) - self.assertRaises(TypeError, randrange, 0, '2') + raises(3.14159) + self.assertWarns(DeprecationWarning, self.gen.randrange, 3.0) + self.assertWarns(DeprecationWarning, self.gen.randrange, Fraction(3, 1)) + raises('3') + raises(0, 2.71828) + self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 2.0) + self.assertWarns(DeprecationWarning, self.gen.randrange, 0, Fraction(2, 1)) + raises(0, '2') # Zero and non-integer step raises(0, 42, 0) - self.assertRaises(TypeError, randrange, 0, 42, 3.14159) - self.assertWarns(DeprecationWarning, randrange, 0, 42, 3.0) - self.assertWarns(DeprecationWarning, randrange, 0, 42, Fraction(3, 1)) - self.assertRaises(TypeError, randrange, 0, 42, '3') + raises(0, 42, 3.14159) + self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, 3.0) + self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, Fraction(3, 1)) + raises(0, 42, '3') def test_randbelow_logic(self, _log=log, int=int): # check bitcount transition points: 2**i and 2**(i+1)-1 diff --git a/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst b/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst index 7ea1e28309664a..5c1f4e3bc4a423 100644 --- a/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst +++ b/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst @@ -1,3 +1 @@ Deprecated support of non-integer arguments in :func:`random.randrange`. -:exc:`TypeError` is now always raised for wrong type of arguments -(formerly :exc:`ValueError` could be raised for some non-integer arguments). From 3ad3c36b61ee3fc9e4a43c8b03de30c30177ffa7 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Thu, 24 Dec 2020 14:53:03 +0200 Subject: [PATCH 6/6] Update docs and emit deprecation warning for ValueError. --- Doc/library/random.rst | 9 ++++++++- Doc/whatsnew/3.10.rst | 5 +++-- Lib/random.py | 18 +++++++++++++++--- Lib/test/test_random.py | 12 ++++++------ .../2020-03-22-21-33-31.bpo-37319.BrIAir.rst | 8 +++++++- 5 files changed, 39 insertions(+), 13 deletions(-) diff --git a/Doc/library/random.rst b/Doc/library/random.rst index f62e8e949534b2..109e895fe8ec4a 100644 --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -136,7 +136,14 @@ Functions for integers slightly uneven distributions. .. deprecated:: 3.10 - Accepting non-integer arguments is deprecated. + The automatic conversion of non-integer types to equivalent integers is + deprecated. Currently ``randrange(10.0)`` is losslessly converted to + ``randrange(10)``. In the future, this will raise a :exc:`TypeError`. + + .. deprecated:: 3.10 + The exception raised for non-integral values such as ``randrange(10.5)`` + or ``randrange('10')`` will be changed from :exc:`ValueError` to + :exc:`TypeError`. .. function:: randint(a, b) diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index 593e5346fecfba..68bb9cf07be788 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -442,8 +442,9 @@ Deprecated as appropriate to help identify code which needs updating during this transition. -* Deprecated support of non-integer arguments in :func:`random.randrange`. - (Contributed by Serhiy Storchaka in :issue:`37319`.) +* Non-integer arguments to :func:`random.randrange` are deprecated. + The :exc:`ValueError` is deprecated in favor of a :exc:`TypeError`. + (Contributed by Serhiy Storchaka and Raymond Hettinger in :issue:`37319`.) * The various ``load_module()`` methods of :mod:`importlib` have been documented as deprecated since Python 3.6, but will now also trigger diff --git a/Lib/random.py b/Lib/random.py index c64adca1b4edda..cc8229ab625e82 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -303,8 +303,12 @@ def randrange(self, start, stop=None, step=1): except TypeError: istart = int(start) if istart != start: + _warn('randrange() will raise TypeError in the future', + DeprecationWarning, 2) raise ValueError("non-integer arg 1 for randrange()") - _warn('non-integer arg 1 for randrange()', + _warn('non-integer arguments to randrange() have been deprecated ' + 'since Python 3.10 and will be removed in a subsequent ' + 'version', DeprecationWarning, 2) if stop is None: if istart > 0: @@ -317,8 +321,12 @@ def randrange(self, start, stop=None, step=1): except TypeError: istop = int(stop) if istop != stop: + _warn('randrange() will raise TypeError in the future', + DeprecationWarning, 2) raise ValueError("non-integer stop for randrange()") - _warn('non-integer stop for randrange()', + _warn('non-integer arguments to randrange() have been deprecated ' + 'since Python 3.10 and will be removed in a subsequent ' + 'version', DeprecationWarning, 2) width = istop - istart try: @@ -326,8 +334,12 @@ def randrange(self, start, stop=None, step=1): except TypeError: istep = int(step) if istep != step: + _warn('randrange() will raise TypeError in the future', + DeprecationWarning, 2) raise ValueError("non-integer step for randrange()") - _warn('non-integer step for randrange()', + _warn('non-integer arguments to randrange() have been deprecated ' + 'since Python 3.10 and will be removed in a subsequent ' + 'version', DeprecationWarning, 2) # Fast path. if istep == 1: diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index 2a8f5e54594c25..b38dc271393f7a 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -537,20 +537,20 @@ def test_randrange_errors(self): raises(0, 100, -12) self.assertWarns(DeprecationWarning, raises, 3, 3, 1.0) # Non-integer start/stop - raises(3.14159) + self.assertWarns(DeprecationWarning, raises, 3.14159) self.assertWarns(DeprecationWarning, self.gen.randrange, 3.0) self.assertWarns(DeprecationWarning, self.gen.randrange, Fraction(3, 1)) - raises('3') - raises(0, 2.71828) + self.assertWarns(DeprecationWarning, raises, '3') + self.assertWarns(DeprecationWarning, raises, 0, 2.71828) self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 2.0) self.assertWarns(DeprecationWarning, self.gen.randrange, 0, Fraction(2, 1)) - raises(0, '2') + self.assertWarns(DeprecationWarning, raises, 0, '2') # Zero and non-integer step raises(0, 42, 0) - raises(0, 42, 3.14159) + self.assertWarns(DeprecationWarning, raises, 0, 42, 3.14159) self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, 3.0) self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, Fraction(3, 1)) - raises(0, 42, '3') + self.assertWarns(DeprecationWarning, raises, 0, 42, '3') def test_randbelow_logic(self, _log=log, int=int): # check bitcount transition points: 2**i and 2**(i+1)-1 diff --git a/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst b/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst index 5c1f4e3bc4a423..423bf10632ac94 100644 --- a/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst +++ b/Misc/NEWS.d/next/Library/2020-03-22-21-33-31.bpo-37319.BrIAir.rst @@ -1 +1,7 @@ -Deprecated support of non-integer arguments in :func:`random.randrange`. +Harmonized :func:`random.randrange` argument handling to better match +that used by :func:`range`. + +* The integer test/conversion in ``randrange()`` now uses :func:`operator.index`. +* Non-integer arguments to ``randrange()`` are deprecated. +* The ``ValueError`` is deprecated in favor of a ``TypeError``. +* It now runs a little faster than before. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy