diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index 4648e2742..594bfb62a 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -20,6 +20,8 @@ class TestBasicOps: """Helper function to make a list of random numbers""" return [self.gen.random() for i in range(n)] + # TODO: RUSTPYTHON AttributeError: 'super' object has no attribute 'getstate' + @unittest.expectedFailure def test_autoseed(self): self.gen.seed() state1 = self.gen.getstate() @@ -28,7 +30,7 @@ class TestBasicOps: state2 = self.gen.getstate() self.assertNotEqual(state1, state2) - # TODO: RUSTPYTHON + # TODO: RUSTPYTHON AttributeError: 'super' object has no attribute 'getstate' @unittest.expectedFailure def test_saverestore(self): N = 1000 @@ -254,6 +256,8 @@ class TestBasicOps: self.assertEqual(x1, x2) self.assertEqual(y1, y2) + # TODO: RUSTPYTHON AttributeError: 'super' object has no attribute 'getstate' + @unittest.expectedFailure def test_pickling(self): for proto in range(pickle.HIGHEST_PROTOCOL + 1): state = pickle.dumps(self.gen, proto) @@ -262,7 +266,7 @@ class TestBasicOps: restoredseq = [newgen.random() for i in range(10)] self.assertEqual(origseq, restoredseq) - # TODO: RUSTPYTHON + # TODO: RUSTPYTHON AttributeError: 'super' object has no attribute 'getstate' @unittest.expectedFailure def test_bug_1727780(self): # verify that version-2-pickles can be loaded @@ -412,26 +416,6 @@ class SystemRandom_TestBasicOps(TestBasicOps, unittest.TestCase): class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase): gen = random.Random() - # TODO: RUSTPYTHON - @unittest.expectedFailure - def test_autoseed(self): - super().test_autoseed() - - # TODO: RUSTPYTHON - @unittest.expectedFailure - def test_seedargs(self): - super().test_seedargs() - - # TODO: RUSTPYTHON - @unittest.expectedFailure - def test_pickling(self): - super().test_pickling() - - # TODO: RUSTPYTHON - @unittest.expectedFailure - def test_seed_when_randomness_source_not_found(self): - super().test_seed_when_randomness_source_not_found() - def test_guaranteed_stable(self): # These sequences are guaranteed to stay the same across versions of python self.gen.seed(3456147, version=1) @@ -502,7 +486,7 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase): def test_setstate_first_arg(self): self.assertRaises(ValueError, self.gen.setstate, (1, None, None)) - # TODO: RUSTPYTHON + # TODO: RUSTPYTHON AttributeError: 'super' object has no attribute 'getstate' @unittest.expectedFailure def test_setstate_middle_arg(self): start_state = self.gen.getstate() @@ -628,7 +612,7 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase): self.assertEqual(set(range(start,stop)), set([self.gen.randrange(start,stop) for i in range(100)])) - # TODO: RUSTPYTHON + # TODO: RUSTPYTHON @unittest.expectedFailure def test_genrandbits(self): # Verify cross-platform repeatability @@ -685,7 +669,7 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase): self.assertEqual(k, numbits) # note the stronger assertion self.assertTrue(2**k > n > 2**(k-1)) # note the stronger assertion - # TODO: RUSTPYTHON + # TODO: RUSTPYTHON AttributeError: 'Random' object has no attribute '_randbelow_without_getrandbits' @unittest.expectedFailure def test_randbelow_without_getrandbits(self): # Random._randbelow() can only use random() when the built-in one @@ -785,7 +769,7 @@ def gamma(z, sqrt2pi=(2.0*pi)**0.5): ]) class TestDistributions(unittest.TestCase): - # TODO: RUSTPYTHON + # TODO: RUSTPYTHON ValueError: math domain error @unittest.expectedFailure def test_zeroinputs(self): # Verify that distributions can handle a series of zero inputs' @@ -899,7 +883,7 @@ class TestDistributions(unittest.TestCase): returned_value = random.gammavariate(1.1, 2.3) self.assertAlmostEqual(returned_value, 2.53) - # TODO: RUSTPYTHON + # TODO: RUSTPYTHON assertAlmostEqual failure. @unittest.expectedFailure @unittest.mock.patch('random.Random.random') def test_gammavariate_alpha_equal_one(self, random_mock): @@ -912,7 +896,7 @@ class TestDistributions(unittest.TestCase): returned_value = random.gammavariate(1.0, 3.14) self.assertAlmostEqual(returned_value, 1.877208182372648) - # TODO: RUSTPYTHON + # TODO: RUSTPYTHON assertAlmostEqual failure. @unittest.expectedFailure @unittest.mock.patch('random.Random.random') def test_gammavariate_alpha_equal_one_equals_expovariate(self, random_mock): @@ -1004,7 +988,7 @@ class TestDistributions(unittest.TestCase): class TestRandomSubclassing(unittest.TestCase): - # TODO: RUSTPYTHON + # TODO: RUSTPYTHON Unexpected keyword argument newarg @unittest.expectedFailure def test_random_subclass_with_kwargs(self): # SF bug #1486663 -- this used to erroneously raise a TypeError @@ -1013,7 +997,7 @@ class TestRandomSubclassing(unittest.TestCase): random.Random.__init__(self) Subclass(newarg=1) - # TODO: RUSTPYTHON + # TODO: RUSTPYTHON AssertionError: items in the second set but not the first. @unittest.expectedFailure def test_subclasses_overriding_methods(self): # Subclasses with an overridden random, but only the original diff --git a/stdlib/src/random.rs b/stdlib/src/random.rs index 4fd7b3147..5e74e4310 100644 --- a/stdlib/src/random.rs +++ b/stdlib/src/random.rs @@ -6,7 +6,7 @@ pub(crate) use _random::make_module; mod _random { use crate::common::lock::PyMutex; use crate::vm::{ - builtins::{PyIntRef, PyTypeRef}, + builtins::{PyInt, PyTypeRef}, function::OptionalOption, types::Constructor, PyObjectRef, PyResult, PyValue, VirtualMachine, @@ -85,13 +85,17 @@ mod _random { mt19937::gen_res53(&mut *rng) } - // TODO: n can be a float, str, bytes, or bytearray #[pymethod] - fn seed(&self, n: OptionalOption) { + fn seed(&self, n: OptionalOption, vm: &VirtualMachine) -> PyResult<()> { let new_rng = match n.flatten() { None => PyRng::default(), Some(n) => { - let (_, mut key) = n.as_bigint().abs().to_u32_digits(); + // Fallback to using hash if object isn't Int-like. + let (_, mut key) = match n.downcast::() { + Ok(n) => n.as_bigint().abs(), + Err(obj) => BigInt::from(obj.hash(vm)?).abs(), + } + .to_u32_digits(); if cfg!(target_endian = "big") { key.reverse(); } @@ -101,6 +105,7 @@ mod _random { }; *self.rng.lock() = new_rng; + Ok(()) } #[pymethod]