From 05c4fcf9347e87ee06d9d799fff53e0249ff70cd Mon Sep 17 00:00:00 2001 From: jfh Date: Thu, 4 Nov 2021 15:23:06 +0200 Subject: [PATCH] Allow any object as an argument for random.seed --- Lib/test/test_random.py | 8 ++------ stdlib/src/random.rs | 13 +++++++++---- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index cee28f283..594bfb62a 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -40,8 +40,6 @@ class TestBasicOps: self.gen.setstate(state) # should regenerate the same sequence self.assertEqual(randseq, self.randomlist(N)) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_seedargs(self): # Seed value with a negative hash. class MySeed(object): @@ -55,8 +53,6 @@ class TestBasicOps: self.assertRaises(TypeError, self.gen.seed, 1, 2, 3, 4) self.assertRaises(TypeError, type(self.gen), []) - # TODO: RUSTPYTHON Success for SystemRandom, failure for MersenneTwister - @unittest.skip @unittest.mock.patch('random._urandom') # os.urandom def test_seed_when_randomness_source_not_found(self, urandom_mock): # Random.seed() uses time.time() when an operating system specific @@ -887,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): @@ -900,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): 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]