Repository: RustPython/RustPython (language: rust)

Issue:
int.from_bytes can omit byte_order parameter
## Feature

<!-- What Python feature is missing from RustPython? Give a short description of the feature and how you ran into its absence. -->
Changed in version 3.11: Added default argument value for byteorder.
Remove unnecessary parameter in "random.py"
```python
a = int.from_bytes(a + _sha512(a).digest())
```

TypeError: Expected at least 1 arguments (2 given)
## Python Documentation

<!-- Give a link to the feature in the CPython documentation (https://docs.python.org/3/) in order to assist in its implementation. -->
documentation: [CPython v3.11.2 from_bytes issue](https://docs.python.org/3.11/library/stdtypes.html?highlight=from_bytes#int.from_bytes) 
source code: [ref](https://github.com/RustPython/RustPython/pull/4748/commits/822c764d6d8754d738daa4ba2608ac80fafe98e1#diff-851cf2d8d99b6d8dee26acc31319431dce51dbe26e3e56494d9b4c45edd8e11fL170) 


Discussion / hints:

Fix patch:
diff --git a/Lib/random.py b/Lib/random.py
index f8735d42a1..85bad08d57 100644
--- a/Lib/random.py
+++ b/Lib/random.py
@@ -167,15 +167,11 @@ def seed(self, a=None, version=2):
         elif version == 2 and isinstance(a, (str, bytes, bytearray)):
             if isinstance(a, str):
                 a = a.encode()
-            a = int.from_bytes(a + _sha512(a).digest(), 'big')
+            a = int.from_bytes(a + _sha512(a).digest())
 
         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
@@ -250,10 +246,8 @@ def __init_subclass__(cls, /, **kwargs):
                 break
 
     def _randbelow_with_getrandbits(self, n):
-        "Return a random int in the range [0,n).  Returns 0 if n==0."
+        "Return a random int in the range [0,n).  Defined for n > 0."
 
-        if not n:
-            return 0
         getrandbits = self.getrandbits
         k = n.bit_length()  # don't use (n-1) here because n can be 1
         r = getrandbits(k)  # 0 <= r < 2**k
@@ -262,7 +256,7 @@ def _randbelow_with_getrandbits(self, n):
         return r
 
     def _randbelow_without_getrandbits(self, n, maxsize=1<<BPF):
-        """Return a random int in the range [0,n).  Returns 0 if n==0.
+        """Return a random int in the range [0,n).  Defined for n > 0.
 
         The implementation does not use getrandbits, but only random.
         """
@@ -273,8 +267,6 @@ def _randbelow_without_getrandbits(self, n, maxsize=1<<BPF):
                 "enough bits to choose from a population range this large.\n"
                 "To remove the range limitation, add a getrandbits() method.")
             return _floor(random() * n)
-        if n == 0:
-            return 0
         rem = maxsize % n
         limit = (maxsize - rem) / maxsize   # int(limit * maxsize) % n == 0
         r = random()
@@ -303,10 +295,10 @@ def randbytes(self, n):
     ## -------------------- integer methods  -------------------
 
     def randrange(self, start, stop=None, step=_ONE):
-        """Choose a random item from range(start, stop[, step]).
+        """Choose a random item from range(stop) or range(start, stop[, step]).
 
-        This fixes the problem with randint() which includes the
-        endpoint; in Python this is usually not what you want.
+        Roughly equivalent to ``choice(range(start, stop, step))`` but
+        supports arbitrarily large ranges and is optimized for common cases.
 
         """
 
@@ -387,37 +379,24 @@ def randint(self, a, b):
 
     def choice(self, seq):
         """Choose a random element from a non-empty sequence."""
-        # 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.
 
-        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.
+        # As an accommodation for NumPy, we don't use "if not seq"
+        # because bool(numpy.array()) raises a ValueError.
+        if not len(seq):
+            raise IndexError('Cannot choose from an empty sequence')
+        return seq[self._randbelow(len(seq))]
 
-        """
+    def shuffle(self, x):
+        """Shuffle list x in place, and return None."""
 
-        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
@@ -470,13 +449,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))
@@ -580,7 +554,7 @@ def triangular(self, low=0.0, high=1.0, mode=None):
             low, high = high, low
         return low + (high - low) * _sqrt(u * c)
 
-    def normalvariate(self, mu, sigma):
+    def normalvariate(self, mu=0.0, sigma=1.0):
         """Normal distribution.
 
         mu is the mean, and sigma is the standard deviation.
@@ -601,7 +575,7 @@ def normalvariate(self, mu, sigma):
                 break
         return mu + z * sigma
 
-    def gauss(self, mu, sigma):
+    def gauss(self, mu=0.0, sigma=1.0):
         """Gaussian distribution.
 
         mu is the mean, and sigma is the standard deviation.  This is
@@ -833,15 +807,15 @@ class SystemRandom(Random):
     """
 
     def random(self):
-        """Get the next random number in the range [0.0, 1.0)."""
-        return (int.from_bytes(_urandom(7), 'big') >> 3) * RECIP_BPF
+        """Get the next random number in the range 0.0 <= X < 1.0."""
+        return (int.from_bytes(_urandom(7)) >> 3) * RECIP_BPF
 
     def getrandbits(self, k):
         """getrandbits(k) -> x.  Generates an int with k random bits."""
         if k < 0:
             raise ValueError('number of bits must be non-negative')
         numbytes = (k + 7) // 8                       # bits / 8 and rounded up
-        x = int.from_bytes(_urandom(numbytes), 'big')
+        x = int.from_bytes(_urandom(numbytes))
         return x >> (numbytes * 8 - k)                # trim excess bits
 
     def randbytes(self, n):
diff --git a/vm/src/builtins/int.rs b/vm/src/builtins/int.rs
index f46047f67e..0ad9949c6a 100644
--- a/vm/src/builtins/int.rs
+++ b/vm/src/builtins/int.rs
@@ -794,6 +794,7 @@ pub struct IntOptions {
 #[derive(FromArgs)]
 struct IntFromByteArgs {
     bytes: PyBytesInner,
+    #[pyarg(any, default = "ArgByteOrder::Big")]
     byteorder: ArgByteOrder,
     #[pyarg(named, optional)]
     signed: OptionalArg<ArgIntoBool>,


Test patch:
diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py
index e7028504ea..4bf00d5dbb 100644
--- a/Lib/test/test_random.py
+++ b/Lib/test/test_random.py
@@ -52,12 +52,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), [])
 
@@ -110,15 +109,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):
@@ -126,6 +116,21 @@ def test_choice(self):
         self.assertEqual(choice([50]), 50)
         self.assertIn(choice([25, 75]), [25, 75])
 
+    def test_choice_with_numpy(self):
+        # Accommodation for NumPy arrays which have disabled __bool__().
+        # See: https://github.com/python/cpython/issues/100805
+        choice = self.gen.choice
+
+        class NA(list):
+            "Simulate numpy.array() behavior"
+            def __bool__(self):
+                raise RuntimeError
+
+        with self.assertRaises(IndexError):
+            choice(NA([]))
+        self.assertEqual(choice(NA([50])), 50)
+        self.assertIn(choice(NA([25, 75])), [25, 75])
+
     def test_sample(self):
         # For the entire allowable range of 0 <= k <= N, validate that
         # the sample is of the correct length and contains only unique items
@@ -169,7 +174,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)
 
@@ -391,23 +396,6 @@ def test_pickling(self):
             restoredseq = [newgen.random() for i in range(10)]
             self.assertEqual(origseq, restoredseq)
 
-    @test.support.cpython_only
-    def test_bug_41052(self):
-        # _random.Random should not be allowed to serialization
-        import _random
-        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
-            r = _random.Random()
-            self.assertRaises(TypeError, pickle.dumps, r, proto)
-
-    @test.support.cpython_only
-    def test_bug_42008(self):
-        # _random.Random should call seed with first element of arg tuple
-        import _random
-        r1 = _random.Random()
-        r1.seed(8675309)
-        r2 = _random.Random(8675309)
-        self.assertEqual(r1.random(), r2.random())
-
     # TODO: RUSTPYTHON AttributeError: 'super' object has no attribute 'getstate'
     @unittest.expectedFailure
     def test_bug_1727780(self):
@@ -445,6 +433,10 @@ def test_randbytes(self):
         self.assertRaises(ValueError, self.gen.randbytes, -1)
         self.assertRaises(TypeError, self.gen.randbytes, 1.0)
 
+    def test_mu_sigma_default_args(self):
+        self.assertIsInstance(self.gen.normalvariate(), float)
+        self.assertIsInstance(self.gen.gauss(), float)
+
 
 try:
     random.SystemRandom().random()
@@ -592,6 +584,25 @@ def test_randbelow_logic(self, _log=log, int=int):
             self.assertTrue(2**k > n > 2**(k-1))   # note the stronger assertion
 
 
+class TestRawMersenneTwister(unittest.TestCase):
+    @test.support.cpython_only
+    def test_bug_41052(self):
+        # _random.Random should not be allowed to serialization
+        import _random
+        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+            r = _random.Random()
+            self.assertRaises(TypeError, pickle.dumps, r, proto)
+
+    @test.support.cpython_only
+    def test_bug_42008(self):
+        # _random.Random should call seed with first element of arg tuple
+        import _random
+        r1 = _random.Random()
+        r1.seed(8675309)
+        r2 = _random.Random(8675309)
+        self.assertEqual(r1.random(), r2.random())
+
+
 class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase):
     gen = random.Random()
 
@@ -846,10 +857,6 @@ def test_randbelow_without_getrandbits(self):
                 maxsize+1, maxsize=maxsize
             )
         self.gen._randbelow_without_getrandbits(5640, maxsize=maxsize)
-        # issue 33203: test that _randbelow returns zero on
-        # n == 0 also in its getrandbits-independent branch.
-        x = self.gen._randbelow_without_getrandbits(0, maxsize=maxsize)
-        self.assertEqual(x, 0)
 
         # This might be going too far to test a single line, but because of our
         # noble aim of achieving 100% test coverage we need to write a case in
@@ -1331,7 +1338,7 @@ def test__all__(self):
         # tests validity but not completeness of the __all__ list
         self.assertTrue(set(random.__all__) <= set(dir(random)))
 
-    @unittest.skipUnless(hasattr(os, "fork"), "fork() required")
+    @test.support.requires_fork()
     def test_after_fork(self):
         # Test the global Random instance gets reseeded in child
         r, w = os.pipe()