[Python-checkins] cpython (merge 3.5 -> default): Merge

raymond.hettinger python-checkins at python.org
Wed Aug 31 18:01:40 EDT 2016


https://hg.python.org/cpython/rev/f23fc0f48ebe
changeset:   102978:f23fc0f48ebe
parent:      102975:fcf65749ef71
parent:      102977:5ae941fef3be
user:        Raymond Hettinger <python at rcn.com>
date:        Wed Aug 31 15:01:28 2016 -0700
summary:
  Merge

files:
  Lib/random.py           |   7 +++++++
  Lib/test/test_random.py |  18 ++++++++++++++++++
  Misc/NEWS               |   5 +++++
  3 files changed, 30 insertions(+), 0 deletions(-)


diff --git a/Lib/random.py b/Lib/random.py
--- a/Lib/random.py
+++ b/Lib/random.py
@@ -112,6 +112,13 @@
                 import time
                 a = int(time.time() * 256) # use fractional seconds
 
+        if version == 1 and isinstance(a, (str, bytes)):
+            x = ord(a[0]) << 7 if a else 0
+            for c in a:
+                x = ((1000003 * x) ^ ord(c)) & 0xFFFFFFFFFFFFFFFF
+            x ^= len(a)
+            a = -2 if x == -1 else x
+
         if version == 2:
             if isinstance(a, (str, bytes, bytearray)):
                 if isinstance(a, str):
diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py
--- a/Lib/test/test_random.py
+++ b/Lib/test/test_random.py
@@ -326,6 +326,24 @@
             ['0x1.1239ddfb11b7cp-3', '0x1.b3cbb5c51b120p-4',
              '0x1.8c4f55116b60fp-1', '0x1.63eb525174a27p-1'])
 
+    def test_bug_27706(self):
+        # Verify that version 1 seeds are unaffected by hash randomization
+
+        self.gen.seed('nofar', version=1)   # hash('nofar') == 5990528763808513177
+        self.assertEqual([self.gen.random().hex() for i in range(4)],
+            ['0x1.8645314505ad7p-1', '0x1.afb1f82e40a40p-5',
+             '0x1.2a59d2285e971p-1', '0x1.56977142a7880p-6'])
+
+        self.gen.seed('rachel', version=1)  # hash('rachel') == -9091735575445484789
+        self.assertEqual([self.gen.random().hex() for i in range(4)],
+            ['0x1.0b294cc856fcdp-1', '0x1.2ad22d79e77b8p-3',
+             '0x1.3052b9c072678p-2', '0x1.578f332106574p-3'])
+
+        self.gen.seed('', version=1)        # hash('') == 0
+        self.assertEqual([self.gen.random().hex() for i in range(4)],
+            ['0x1.b0580f98a7dbep-1', '0x1.84129978f9c1ap-1',
+             '0x1.aeaa51052e978p-2', '0x1.092178fb945a6p-2'])
+
     def test_setstate_first_arg(self):
         self.assertRaises(ValueError, self.gen.setstate, (1, None, None))
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -72,6 +72,11 @@
 
 - Issue #19884: Avoid spurious output on OS X with Gnu Readline.
 
+- Issue #27706: Restore deterministic behavior of random.Random().seed()
+  for string seeds using seeding version 1.  Allows sequences of calls
+  to random() to exactly match those obtained in Python 2.
+  Patch by Nofar Schnider.
+
 - Issue #10513: Fix a regression in Connection.commit().  Statements should
   not be reset after a commit.
 

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list