Skip to content

Commit 97e85b2

Browse files
authored
Update test_{dict,weakref}.py from 3.13.5 (RustPython#5963)
* Update test_dict.py from 3.13.5 * Update `test_weakref.py` from 3.13.5
1 parent d42e8f0 commit 97e85b2

File tree

3 files changed

+226
-63
lines changed

3 files changed

+226
-63
lines changed

Lib/test/support/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2589,6 +2589,22 @@ def adjust_int_max_str_digits(max_digits):
25892589
finally:
25902590
sys.set_int_max_str_digits(current)
25912591

2592+
2593+
# From CPython 3.13.5
2594+
def get_c_recursion_limit():
2595+
try:
2596+
import _testcapi
2597+
return _testcapi.Py_C_RECURSION_LIMIT
2598+
except ImportError:
2599+
raise unittest.SkipTest('requires _testcapi')
2600+
2601+
2602+
# From CPython 3.13.5
2603+
def exceeds_recursion_limit():
2604+
"""For recursion tests, easily exceeds default recursion limit."""
2605+
return get_c_recursion_limit() * 3
2606+
2607+
25922608
#For recursion tests, easily exceeds default recursion limit
25932609
EXCEEDS_RECURSION_LIMIT = 5000
25942610

Lib/test/test_dict.py

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import unittest
99
import weakref
1010
from test import support
11-
from test.support import import_helper, C_RECURSION_LIMIT
11+
from test.support import import_helper, get_c_recursion_limit
1212

1313

1414
class DictTest(unittest.TestCase):
@@ -312,17 +312,34 @@ def __setitem__(self, key, value):
312312
self.assertRaises(Exc, baddict2.fromkeys, [1])
313313

314314
# test fast path for dictionary inputs
315+
res = dict(zip(range(6), [0]*6))
315316
d = dict(zip(range(6), range(6)))
316-
self.assertEqual(dict.fromkeys(d, 0), dict(zip(range(6), [0]*6)))
317-
317+
self.assertEqual(dict.fromkeys(d, 0), res)
318+
# test fast path for set inputs
319+
d = set(range(6))
320+
self.assertEqual(dict.fromkeys(d, 0), res)
321+
# test slow path for other iterable inputs
322+
d = list(range(6))
323+
self.assertEqual(dict.fromkeys(d, 0), res)
324+
325+
# test fast path when object's constructor returns large non-empty dict
318326
class baddict3(dict):
319327
def __new__(cls):
320328
return d
321-
d = {i : i for i in range(10)}
329+
d = {i : i for i in range(1000)}
322330
res = d.copy()
323331
res.update(a=None, b=None, c=None)
324332
self.assertEqual(baddict3.fromkeys({"a", "b", "c"}), res)
325333

334+
# test slow path when object is a proper subclass of dict
335+
class baddict4(dict):
336+
def __init__(self):
337+
dict.__init__(self, d)
338+
d = {i : i for i in range(1000)}
339+
res = d.copy()
340+
res.update(a=None, b=None, c=None)
341+
self.assertEqual(baddict4.fromkeys({"a", "b", "c"}), res)
342+
326343
def test_copy(self):
327344
d = {1: 1, 2: 2, 3: 3}
328345
self.assertIsNot(d.copy(), d)
@@ -596,10 +613,9 @@ def __repr__(self):
596613
d = {1: BadRepr()}
597614
self.assertRaises(Exc, repr, d)
598615

599-
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON Windows')
600616
def test_repr_deep(self):
601617
d = {}
602-
for i in range(C_RECURSION_LIMIT + 1):
618+
for i in range(get_c_recursion_limit() + 1):
603619
d = {1: d}
604620
self.assertRaises(RecursionError, repr, d)
605621

@@ -994,6 +1010,18 @@ class MyDict(dict):
9941010
pass
9951011
self._tracked(MyDict())
9961012

1013+
@support.cpython_only
1014+
def test_track_lazy_instance_dicts(self):
1015+
class C:
1016+
pass
1017+
o = C()
1018+
d = o.__dict__
1019+
self._not_tracked(d)
1020+
o.untracked = 42
1021+
self._not_tracked(d)
1022+
o.tracked = []
1023+
self._tracked(d)
1024+
9971025
def make_shared_key_dict(self, n):
9981026
class C:
9991027
pass
@@ -1108,10 +1136,8 @@ class C:
11081136
a = C()
11091137
a.x = 1
11101138
d = a.__dict__
1111-
before_resize = sys.getsizeof(d)
11121139
d[2] = 2 # split table is resized to a generic combined table
11131140

1114-
self.assertGreater(sys.getsizeof(d), before_resize)
11151141
self.assertEqual(list(d), ['x', 2])
11161142

11171143
def test_iterator_pickling(self):
@@ -1485,6 +1511,24 @@ def test_dict_items_result_gc_reversed(self):
14851511
gc.collect()
14861512
self.assertTrue(gc.is_tracked(next(it)))
14871513

1514+
def test_store_evilattr(self):
1515+
class EvilAttr:
1516+
def __init__(self, d):
1517+
self.d = d
1518+
1519+
def __del__(self):
1520+
if 'attr' in self.d:
1521+
del self.d['attr']
1522+
gc.collect()
1523+
1524+
class Obj:
1525+
pass
1526+
1527+
obj = Obj()
1528+
obj.__dict__ = {}
1529+
for _ in range(10):
1530+
obj.attr = EvilAttr(obj.__dict__)
1531+
14881532
def test_str_nonstr(self):
14891533
# cpython uses a different lookup function if the dict only contains
14901534
# `str` keys. Make sure the unoptimized path is used when a non-`str`
@@ -1591,8 +1635,8 @@ class CAPITest(unittest.TestCase):
15911635
# Test _PyDict_GetItem_KnownHash()
15921636
@support.cpython_only
15931637
def test_getitem_knownhash(self):
1594-
_testcapi = import_helper.import_module('_testcapi')
1595-
dict_getitem_knownhash = _testcapi.dict_getitem_knownhash
1638+
_testinternalcapi = import_helper.import_module('_testinternalcapi')
1639+
dict_getitem_knownhash = _testinternalcapi.dict_getitem_knownhash
15961640

15971641
d = {'x': 1, 'y': 2, 'z': 3}
15981642
self.assertEqual(dict_getitem_knownhash(d, 'x', hash('x')), 1)

0 commit comments

Comments
 (0)