]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-46624: Defer to 3.12: "Remove deprecated support for non-integer values" (GH...
authorMiro Hrončok <miro@hroncok.cz>
Thu, 3 Feb 2022 13:48:13 +0000 (14:48 +0100)
committerGitHub <noreply@github.com>
Thu, 3 Feb 2022 13:48:13 +0000 (07:48 -0600)
Doc/library/random.rst
Lib/random.py
Lib/test/test_random.py
Misc/NEWS.d/next/Library/2022-02-03-12-07-41.bpo-46624.f_Qqh0.rst [new file with mode: 0644]

index 36f232dc319e4048de928525b277ec6c99ea9b4e..da4a4f61e456776bb41d3915548482e7eab9c5d0 100644 (file)
@@ -135,10 +135,15 @@ Functions for integers
       values.  Formerly it used a style like ``int(random()*n)`` which could produce
       slightly uneven distributions.
 
-   .. versionchanged:: 3.11
-      Automatic conversion of non-integer types is no longer supported.
-      Calls such as ``randrange(10.0)`` and ``randrange(Fraction(10, 1))``
-      now raise a :exc:`TypeError`.
+   .. deprecated:: 3.10
+      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)
 
index e8bc9416fcd9418ad6eb6f3a6b64ddb424cb4bf7..6d7b617e33a3002ffc5a4fca757d97e31835a2cc 100644 (file)
@@ -282,17 +282,27 @@ class Random(_random.Random):
     ## -------------------- integer methods  -------------------
 
     def randrange(self, start, stop=None, step=_ONE):
-        """Choose a random item from range(stop) or range(start, stop[, step]).
+        """Choose a random item from range(start, stop[, step]).
 
-        Roughly equivalent to ``choice(range(start, stop, step))``
-        but supports arbitrarily large ranges and is optimized
-        for common cases.
+        This fixes the problem with randint() which includes the
+        endpoint; in Python this is usually not what you want.
 
         """
 
         # This code is a bit messy to make it fast for the
         # common case while still doing adequate error checking.
-        istart = _index(start)
+        try:
+            istart = _index(start)
+        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 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.
@@ -302,15 +312,37 @@ class Random(_random.Random):
                 return self._randbelow(istart)
             raise ValueError("empty range for randrange()")
 
-        # Stop argument supplied.
-        istop = _index(stop)
+        # stop argument supplied.
+        try:
+            istop = _index(stop)
+        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 arguments to randrange() have been deprecated '
+                  'since Python 3.10 and will be removed in a subsequent '
+                  'version',
+                  DeprecationWarning, 2)
         width = istop - istart
-        istep = _index(step)
+        try:
+            istep = _index(step)
+        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 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)
-            raise ValueError(f"empty range in randrange({start}, {stop}, {step})")
+            raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width))
 
         # Non-unit step argument supplied.
         if istep > 0:
@@ -320,7 +352,7 @@ class Random(_random.Random):
         else:
             raise ValueError("zero step for randrange()")
         if n <= 0:
-            raise ValueError(f"empty range in randrange({start}, {stop}, {step})")
+            raise ValueError("empty range for randrange()")
         return istart + istep * self._randbelow(n)
 
     def randint(self, a, b):
index f980c5b8df0d20ac84a6ef64deb3c8d01ffe2c0d..5b066d23dd3fd6737155d7813436696323e15026 100644 (file)
@@ -481,44 +481,50 @@ class SystemRandom_TestBasicOps(TestBasicOps, unittest.TestCase):
         self.assertEqual(rint, 0)
 
     def test_randrange_errors(self):
-        raises_value_error = partial(self.assertRaises, ValueError, self.gen.randrange)
-        raises_type_error = partial(self.assertRaises, TypeError, self.gen.randrange)
-
+        raises = partial(self.assertRaises, ValueError, self.gen.randrange)
         # Empty range
-        raises_value_error(3, 3)
-        raises_value_error(-721)
-        raises_value_error(0, 100, -12)
-
-        # Zero step
-        raises_value_error(0, 42, 0)
-        raises_type_error(0, 42, 0.0)
-        raises_type_error(0, 0, 0.0)
-
-        # Non-integer stop
-        raises_type_error(3.14159)
-        raises_type_error(3.0)
-        raises_type_error(Fraction(3, 1))
-        raises_type_error('3')
-        raises_type_error(0, 2.71827)
-        raises_type_error(0, 2.0)
-        raises_type_error(0, Fraction(2, 1))
-        raises_type_error(0, '2')
-        raises_type_error(0, 2.71827, 2)
-
-        # Non-integer start
-        raises_type_error(2.71827, 5)
-        raises_type_error(2.0, 5)
-        raises_type_error(Fraction(2, 1), 5)
-        raises_type_error('2', 5)
-        raises_type_error(2.71827, 5, 2)
-
-        # Non-integer step
-        raises_type_error(0, 42, 3.14159)
-        raises_type_error(0, 42, 3.0)
-        raises_type_error(0, 42, Fraction(3, 1))
-        raises_type_error(0, 42, '3')
-        raises_type_error(0, 42, 1.0)
-        raises_type_error(0, 0, 1.0)
+        raises(3, 3)
+        raises(-721)
+        raises(0, 100, -12)
+        # Non-integer start/stop
+        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)
+        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
+        with self.assertWarns(DeprecationWarning):
+            randrange(10.0, 20, 2)
+        with self.assertWarns(DeprecationWarning):
+            randrange(10, 20.0, 2)
+        with self.assertWarns(DeprecationWarning):
+            randrange(10, 20, 1.0)
+        with self.assertWarns(DeprecationWarning):
+            randrange(10, 20, 2.0)
+        with self.assertWarns(DeprecationWarning):
+            with self.assertRaises(ValueError):
+                randrange(10.5)
+        with self.assertWarns(DeprecationWarning):
+            with self.assertRaises(ValueError):
+                randrange(10, 20.5)
+        with self.assertWarns(DeprecationWarning):
+            with self.assertRaises(ValueError):
+                randrange(10, 20, 1.5)
 
     def test_randrange_step(self):
         # bpo-42772: When stop is None, the step argument was being ignored.
diff --git a/Misc/NEWS.d/next/Library/2022-02-03-12-07-41.bpo-46624.f_Qqh0.rst b/Misc/NEWS.d/next/Library/2022-02-03-12-07-41.bpo-46624.f_Qqh0.rst
new file mode 100644 (file)
index 0000000..b0203b9
--- /dev/null
@@ -0,0 +1 @@
+Restore support for non-integer arguments of :func:`random.randrange` and :func:`random.randint`.