Skip to content

bpo-37319: Deprecated support of non-integer arguments in random.randrange(). #19112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jan 25, 2021
5 changes: 3 additions & 2 deletions Doc/library/random.rst
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,9 @@ Functions for integers
``randrange(10)``. In the future, this will raise a :exc:`TypeError`.

.. deprecated:: 3.10
The exception raised for non-integral values such as ``range(10.5)``
will be changed from :exc:`ValueError` to :exc:`TypeError`.
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)

Expand Down
4 changes: 4 additions & 0 deletions Doc/whatsnew/3.10.rst
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,10 @@ Deprecated
as appropriate to help identify code which needs updating during
this transition.

* 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
a :exc:`DeprecationWarning`. Use
Expand Down
44 changes: 20 additions & 24 deletions Lib/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,17 +303,15 @@ def randrange(self, start, stop=None, step=_ONE):
try:
istart = _index(start)
except TypeError:
if int(start) == start:
istart = int(start)
_warn('Float arguments to randrange() have been deprecated\n'
'since Python 3.10 and will be removed in a subsequent '
'version.',
DeprecationWarning, 2)
else:
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 arguments to randrange() have been deprecated '
'since Python 3.10 and will be removed in a subsequent '
'version',
DeprecationWarning, 2)
if stop is None:
# We don't check for "step != 1" because it hasn't been
# type checked and converted to an integer yet.
Expand All @@ -327,31 +325,29 @@ def randrange(self, start, stop=None, step=_ONE):
try:
istop = _index(stop)
except TypeError:
if int(stop) == stop:
istop = int(stop)
_warn('Float arguments to randrange() have been deprecated\n'
'since Python 3.10 and will be removed in a subsequent '
'version.',
DeprecationWarning, 2)
else:
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 arguments to randrange() have been deprecated '
'since Python 3.10 and will be removed in a subsequent '
'version',
DeprecationWarning, 2)
width = istop - istart
try:
istep = _index(step)
except TypeError:
if int(step) == step:
istep = int(step)
_warn('Float arguments to randrange() have been deprecated\n'
'since Python 3.10 and will be removed in a subsequent '
'version.',
DeprecationWarning, 2)
else:
istep = int(step)
if istep != step:
_warn('randrange() will raise TypeError in the future',
DeprecationWarning, 2)
raise ValueError("non-integer step for randrange()")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we're at it, the exception type should be converted to TypeError.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we raise it with custom message or reraise the exception raised by index()?

width = istop - istart
_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:
if width > 0:
return istart + self._randbelow(width)
Expand Down
19 changes: 16 additions & 3 deletions Lib/test/test_random.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,11 +509,24 @@ def test_randrange_errors(self):
raises(-721)
raises(0, 100, -12)
# Non-integer start/stop
raises(3.14159)
raises(0, 2.71828)
self.assertWarns(DeprecationWarning, raises, 3.14159)
self.assertWarns(DeprecationWarning, self.gen.randrange, 3.0)
self.assertWarns(DeprecationWarning, self.gen.randrange, Fraction(3, 1))
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))
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, 0.0)
self.assertWarns(DeprecationWarning, raises, 0, 0, 0.0)
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))
self.assertWarns(DeprecationWarning, raises, 0, 42, '3')
self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, 1.0)
self.assertWarns(DeprecationWarning, raises, 0, 0, 1.0)

def test_randrange_argument_handling(self):
randrange = self.gen.randrange
Expand Down
10 changes: 5 additions & 5 deletions Misc/NEWS.d/3.10.0a4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -605,12 +605,12 @@ deprecated in Python 3.7. Patch by Erlend E. Aasland
.. nonce: Cfl1eR
.. section: Library

Harmonized random.randrange() argument handling to match range().
Harmonized :func:`random.randrange` argument handling to match :func:`range`.

* The integer test and conversion in randrange() now uses
operator.index().
* Non-integer arguments to randrange() are deprecated.
* The *ValueError* is deprecated in favor of a *TypeError*.
* The integer test and 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.

(Contributed by Raymond Hettinger and Serhiy Storchaka.)
Expand Down