diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2018-05-08 15:45:15 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-08 15:45:15 +0300 |
commit | ec1622d56c80d15740f7f8459c9a79fd55f5d3c7 (patch) | |
tree | 746876d28f338443003d4de44d8d8ddaaada016b /Lib/test/test_random.py | |
parent | d54cfb160c626626394e2f171d3ccfe03309f34e (diff) | |
download | cpython-git-ec1622d56c80d15740f7f8459c9a79fd55f5d3c7.tar.gz |
bpo-33144: Fix choosing random.Random._randbelow implementation. (GH-6563)
random() takes precedence over getrandbits() if defined later
in the class tree.
Diffstat (limited to 'Lib/test/test_random.py')
-rw-r--r-- | Lib/test/test_random.py | 78 |
1 files changed, 64 insertions, 14 deletions
diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index d91908b03d..e7ef68ba3d 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -5,7 +5,6 @@ import os import time import pickle import warnings -import logging from functools import partial from math import log, exp, pi, fsum, sin, factorial from test import support @@ -940,6 +939,7 @@ class TestDistributions(unittest.TestCase): gammavariate_mock.return_value = 0.0 self.assertEqual(0.0, random.betavariate(2.71828, 3.14159)) + class TestRandomSubclassing(unittest.TestCase): def test_random_subclass_with_kwargs(self): # SF bug #1486663 -- this used to erroneously raise a TypeError @@ -958,30 +958,80 @@ class TestRandomSubclassing(unittest.TestCase): # randrange class SubClass1(random.Random): def random(self): - return super().random() + called.add('SubClass1.random') + return random.Random.random(self) def getrandbits(self, n): - logging.getLogger('getrandbits').info('used getrandbits') - return super().getrandbits(n) - with self.assertLogs('getrandbits'): - SubClass1().randrange(42) + called.add('SubClass1.getrandbits') + return random.Random.getrandbits(self, n) + called = set() + SubClass1().randrange(42) + self.assertEqual(called, {'SubClass1.getrandbits'}) # subclass providing only random => can only use random for randrange class SubClass2(random.Random): def random(self): - logging.getLogger('random').info('used random') - return super().random() - with self.assertLogs('random'): - SubClass2().randrange(42) + called.add('SubClass2.random') + return random.Random.random(self) + called = set() + SubClass2().randrange(42) + self.assertEqual(called, {'SubClass2.random'}) # subclass defining getrandbits to complement its inherited random # => can now rely on getrandbits for randrange again class SubClass3(SubClass2): def getrandbits(self, n): - logging.getLogger('getrandbits').info('used getrandbits') - return super().getrandbits(n) - with self.assertLogs('getrandbits'): - SubClass3().randrange(42) + called.add('SubClass3.getrandbits') + return random.Random.getrandbits(self, n) + called = set() + SubClass3().randrange(42) + self.assertEqual(called, {'SubClass3.getrandbits'}) + + # subclass providing only random and inherited getrandbits + # => random takes precedence + class SubClass4(SubClass3): + def random(self): + called.add('SubClass4.random') + return random.Random.random(self) + called = set() + SubClass4().randrange(42) + self.assertEqual(called, {'SubClass4.random'}) + + # Following subclasses don't define random or getrandbits directly, + # but inherit them from classes which are not subclasses of Random + class Mixin1: + def random(self): + called.add('Mixin1.random') + return random.Random.random(self) + class Mixin2: + def getrandbits(self, n): + called.add('Mixin2.getrandbits') + return random.Random.getrandbits(self, n) + + class SubClass5(Mixin1, random.Random): + pass + called = set() + SubClass5().randrange(42) + self.assertEqual(called, {'Mixin1.random'}) + + class SubClass6(Mixin2, random.Random): + pass + called = set() + SubClass6().randrange(42) + self.assertEqual(called, {'Mixin2.getrandbits'}) + + class SubClass7(Mixin1, Mixin2, random.Random): + pass + called = set() + SubClass7().randrange(42) + self.assertEqual(called, {'Mixin1.random'}) + + class SubClass8(Mixin2, Mixin1, random.Random): + pass + called = set() + SubClass8().randrange(42) + self.assertEqual(called, {'Mixin2.getrandbits'}) + class TestModule(unittest.TestCase): def testMagicConstants(self): |