Skip to content

Commit 6baa98e

Browse files
authored
bpo-46624: Defer to 3.12: "Remove deprecated support for non-integer values" (GH-31098)
1 parent 674ab66 commit 6baa98e

File tree

4 files changed

+95
-51
lines changed

4 files changed

+95
-51
lines changed

Doc/library/random.rst

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,15 @@ Functions for integers
135135
values. Formerly it used a style like ``int(random()*n)`` which could produce
136136
slightly uneven distributions.
137137

138-
.. versionchanged:: 3.11
139-
Automatic conversion of non-integer types is no longer supported.
140-
Calls such as ``randrange(10.0)`` and ``randrange(Fraction(10, 1))``
141-
now raise a :exc:`TypeError`.
138+
.. deprecated:: 3.10
139+
The automatic conversion of non-integer types to equivalent integers is
140+
deprecated. Currently ``randrange(10.0)`` is losslessly converted to
141+
``randrange(10)``. In the future, this will raise a :exc:`TypeError`.
142+
143+
.. deprecated:: 3.10
144+
The exception raised for non-integral values such as ``randrange(10.5)``
145+
or ``randrange('10')`` will be changed from :exc:`ValueError` to
146+
:exc:`TypeError`.
142147

143148
.. function:: randint(a, b)
144149

Lib/random.py

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -282,17 +282,27 @@ def randbytes(self, n):
282282
## -------------------- integer methods -------------------
283283

284284
def randrange(self, start, stop=None, step=_ONE):
285-
"""Choose a random item from range(stop) or range(start, stop[, step]).
285+
"""Choose a random item from range(start, stop[, step]).
286286
287-
Roughly equivalent to ``choice(range(start, stop, step))``
288-
but supports arbitrarily large ranges and is optimized
289-
for common cases.
287+
This fixes the problem with randint() which includes the
288+
endpoint; in Python this is usually not what you want.
290289
291290
"""
292291

293292
# This code is a bit messy to make it fast for the
294293
# common case while still doing adequate error checking.
295-
istart = _index(start)
294+
try:
295+
istart = _index(start)
296+
except TypeError:
297+
istart = int(start)
298+
if istart != start:
299+
_warn('randrange() will raise TypeError in the future',
300+
DeprecationWarning, 2)
301+
raise ValueError("non-integer arg 1 for randrange()")
302+
_warn('non-integer arguments to randrange() have been deprecated '
303+
'since Python 3.10 and will be removed in a subsequent '
304+
'version',
305+
DeprecationWarning, 2)
296306
if stop is None:
297307
# We don't check for "step != 1" because it hasn't been
298308
# type checked and converted to an integer yet.
@@ -302,15 +312,37 @@ def randrange(self, start, stop=None, step=_ONE):
302312
return self._randbelow(istart)
303313
raise ValueError("empty range for randrange()")
304314

305-
# Stop argument supplied.
306-
istop = _index(stop)
315+
# stop argument supplied.
316+
try:
317+
istop = _index(stop)
318+
except TypeError:
319+
istop = int(stop)
320+
if istop != stop:
321+
_warn('randrange() will raise TypeError in the future',
322+
DeprecationWarning, 2)
323+
raise ValueError("non-integer stop for randrange()")
324+
_warn('non-integer arguments to randrange() have been deprecated '
325+
'since Python 3.10 and will be removed in a subsequent '
326+
'version',
327+
DeprecationWarning, 2)
307328
width = istop - istart
308-
istep = _index(step)
329+
try:
330+
istep = _index(step)
331+
except TypeError:
332+
istep = int(step)
333+
if istep != step:
334+
_warn('randrange() will raise TypeError in the future',
335+
DeprecationWarning, 2)
336+
raise ValueError("non-integer step for randrange()")
337+
_warn('non-integer arguments to randrange() have been deprecated '
338+
'since Python 3.10 and will be removed in a subsequent '
339+
'version',
340+
DeprecationWarning, 2)
309341
# Fast path.
310342
if istep == 1:
311343
if width > 0:
312344
return istart + self._randbelow(width)
313-
raise ValueError(f"empty range in randrange({start}, {stop}, {step})")
345+
raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width))
314346

315347
# Non-unit step argument supplied.
316348
if istep > 0:
@@ -320,7 +352,7 @@ def randrange(self, start, stop=None, step=_ONE):
320352
else:
321353
raise ValueError("zero step for randrange()")
322354
if n <= 0:
323-
raise ValueError(f"empty range in randrange({start}, {stop}, {step})")
355+
raise ValueError("empty range for randrange()")
324356
return istart + istep * self._randbelow(n)
325357

326358
def randint(self, a, b):

Lib/test/test_random.py

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -481,44 +481,50 @@ def test_randrange_nonunit_step(self):
481481
self.assertEqual(rint, 0)
482482

483483
def test_randrange_errors(self):
484-
raises_value_error = partial(self.assertRaises, ValueError, self.gen.randrange)
485-
raises_type_error = partial(self.assertRaises, TypeError, self.gen.randrange)
486-
484+
raises = partial(self.assertRaises, ValueError, self.gen.randrange)
487485
# Empty range
488-
raises_value_error(3, 3)
489-
raises_value_error(-721)
490-
raises_value_error(0, 100, -12)
491-
492-
# Zero step
493-
raises_value_error(0, 42, 0)
494-
raises_type_error(0, 42, 0.0)
495-
raises_type_error(0, 0, 0.0)
496-
497-
# Non-integer stop
498-
raises_type_error(3.14159)
499-
raises_type_error(3.0)
500-
raises_type_error(Fraction(3, 1))
501-
raises_type_error('3')
502-
raises_type_error(0, 2.71827)
503-
raises_type_error(0, 2.0)
504-
raises_type_error(0, Fraction(2, 1))
505-
raises_type_error(0, '2')
506-
raises_type_error(0, 2.71827, 2)
507-
508-
# Non-integer start
509-
raises_type_error(2.71827, 5)
510-
raises_type_error(2.0, 5)
511-
raises_type_error(Fraction(2, 1), 5)
512-
raises_type_error('2', 5)
513-
raises_type_error(2.71827, 5, 2)
514-
515-
# Non-integer step
516-
raises_type_error(0, 42, 3.14159)
517-
raises_type_error(0, 42, 3.0)
518-
raises_type_error(0, 42, Fraction(3, 1))
519-
raises_type_error(0, 42, '3')
520-
raises_type_error(0, 42, 1.0)
521-
raises_type_error(0, 0, 1.0)
486+
raises(3, 3)
487+
raises(-721)
488+
raises(0, 100, -12)
489+
# Non-integer start/stop
490+
self.assertWarns(DeprecationWarning, raises, 3.14159)
491+
self.assertWarns(DeprecationWarning, self.gen.randrange, 3.0)
492+
self.assertWarns(DeprecationWarning, self.gen.randrange, Fraction(3, 1))
493+
self.assertWarns(DeprecationWarning, raises, '3')
494+
self.assertWarns(DeprecationWarning, raises, 0, 2.71828)
495+
self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 2.0)
496+
self.assertWarns(DeprecationWarning, self.gen.randrange, 0, Fraction(2, 1))
497+
self.assertWarns(DeprecationWarning, raises, 0, '2')
498+
# Zero and non-integer step
499+
raises(0, 42, 0)
500+
self.assertWarns(DeprecationWarning, raises, 0, 42, 0.0)
501+
self.assertWarns(DeprecationWarning, raises, 0, 0, 0.0)
502+
self.assertWarns(DeprecationWarning, raises, 0, 42, 3.14159)
503+
self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, 3.0)
504+
self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, Fraction(3, 1))
505+
self.assertWarns(DeprecationWarning, raises, 0, 42, '3')
506+
self.assertWarns(DeprecationWarning, self.gen.randrange, 0, 42, 1.0)
507+
self.assertWarns(DeprecationWarning, raises, 0, 0, 1.0)
508+
509+
def test_randrange_argument_handling(self):
510+
randrange = self.gen.randrange
511+
with self.assertWarns(DeprecationWarning):
512+
randrange(10.0, 20, 2)
513+
with self.assertWarns(DeprecationWarning):
514+
randrange(10, 20.0, 2)
515+
with self.assertWarns(DeprecationWarning):
516+
randrange(10, 20, 1.0)
517+
with self.assertWarns(DeprecationWarning):
518+
randrange(10, 20, 2.0)
519+
with self.assertWarns(DeprecationWarning):
520+
with self.assertRaises(ValueError):
521+
randrange(10.5)
522+
with self.assertWarns(DeprecationWarning):
523+
with self.assertRaises(ValueError):
524+
randrange(10, 20.5)
525+
with self.assertWarns(DeprecationWarning):
526+
with self.assertRaises(ValueError):
527+
randrange(10, 20, 1.5)
522528

523529
def test_randrange_step(self):
524530
# bpo-42772: When stop is None, the step argument was being ignored.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Restore support for non-integer arguments of :func:`random.randrange` and :func:`random.randint`.

0 commit comments

Comments
 (0)