Skip to content

Commit 1398699

Browse files
committed
Fix test_type_lookup_mro_reference
If specialization fails, `X.mykey` will be performed again using the new mro set by __eq__. Check that the process doesn't crash, since that's what we care about.
1 parent cdf8eb5 commit 1398699

File tree

1 file changed

+26
-6
lines changed

1 file changed

+26
-6
lines changed

Lib/test/test_descr.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import random
88
import string
99
import sys
10+
import textwrap
1011
import types
1112
import unittest
1213
import warnings
@@ -15,6 +16,7 @@
1516
from copy import deepcopy
1617
from contextlib import redirect_stdout
1718
from test import support
19+
from test.support.script_helper import assert_python_ok
1820

1921
try:
2022
import _testcapi
@@ -5230,6 +5232,7 @@ def test_type_lookup_mro_reference(self):
52305232
# Issue #14199: _PyType_Lookup() has to keep a strong reference to
52315233
# the type MRO because it may be modified during the lookup, if
52325234
# __bases__ is set during the lookup for example.
5235+
code = textwrap.dedent("""
52335236
class MyKey(object):
52345237
def __hash__(self):
52355238
return hash('mykey')
@@ -5245,12 +5248,29 @@ class Base2(object):
52455248
mykey = 'from Base2'
52465249
mykey2 = 'from Base2'
52475250
5248-
with self.assertWarnsRegex(RuntimeWarning, 'X'):
5249-
X = type('X', (Base,), {MyKey(): 5})
5250-
# mykey is read from Base
5251-
self.assertEqual(X.mykey, 'from Base')
5252-
# mykey2 is read from Base2 because MyKey.__eq__ has set __bases__
5253-
self.assertEqual(X.mykey2, 'from Base2')
5251+
X = type('X', (Base,), {MyKey(): 5})
5252+
5253+
bases_before = ",".join([c.__name__ for c in X.__bases__])
5254+
print(f"before={bases_before}")
5255+
5256+
# mykey is initially read from Base, however, the lookup will be perfomed
5257+
# again if specialization fails. The second lookup will use the new
5258+
# mro set by __eq__.
5259+
print(X.mykey)
5260+
5261+
bases_after = ",".join([c.__name__ for c in X.__bases__])
5262+
print(f"after={bases_after}")
5263+
5264+
# mykey2 is read from Base2 because MyKey.__eq__ has set __bases_
5265+
print(f"mykey2={X.mykey2}")
5266+
""")
5267+
_, out, err = assert_python_ok("-c", code)
5268+
err = err.decode()
5269+
self.assertRegex(err, "RuntimeWarning: .*X")
5270+
out = out.decode()
5271+
self.assertRegex(out, "before=Base")
5272+
self.assertRegex(out, "after=Base2")
5273+
self.assertRegex(out, "mykey2=from Base2")
52545274

52555275

52565276
class PicklingTests(unittest.TestCase):

0 commit comments

Comments
 (0)