Skip to content

Commit c98939a

Browse files
authored
Update seq tests from 3.14.4 (#7606)
* Update seq related tests
1 parent 9f1429d commit c98939a

File tree

5 files changed

+210
-11
lines changed

5 files changed

+210
-11
lines changed

Lib/test/seq_tests.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -261,23 +261,20 @@ def test_minmax(self):
261261
self.assertEqual(min(u), 0)
262262
self.assertEqual(max(u), 2)
263263

264-
def test_addmul(self):
264+
def test_add(self):
265265
u1 = self.type2test([0])
266266
u2 = self.type2test([0, 1])
267267
self.assertEqual(u1, u1 + self.type2test())
268268
self.assertEqual(u1, self.type2test() + u1)
269269
self.assertEqual(u1 + self.type2test([1]), u2)
270270
self.assertEqual(self.type2test([-1]) + u1, self.type2test([-1, 0]))
271-
self.assertEqual(self.type2test(), u2*0)
272-
self.assertEqual(self.type2test(), 0*u2)
271+
272+
def test_mul(self):
273+
u2 = self.type2test([0, 1])
273274
self.assertEqual(self.type2test(), u2*0)
274275
self.assertEqual(self.type2test(), 0*u2)
275276
self.assertEqual(u2, u2*1)
276277
self.assertEqual(u2, 1*u2)
277-
self.assertEqual(u2, u2*1)
278-
self.assertEqual(u2, 1*u2)
279-
self.assertEqual(u2+u2, u2*2)
280-
self.assertEqual(u2+u2, 2*u2)
281278
self.assertEqual(u2+u2, u2*2)
282279
self.assertEqual(u2+u2, 2*u2)
283280
self.assertEqual(u2+u2+u2, u2*3)
@@ -286,8 +283,9 @@ def test_addmul(self):
286283
class subclass(self.type2test):
287284
pass
288285
u3 = subclass([0, 1])
289-
self.assertEqual(u3, u3*1)
290-
self.assertIsNot(u3, u3*1)
286+
r = u3*1
287+
self.assertEqual(r, u3)
288+
self.assertIsNot(r, u3)
291289

292290
def test_iadd(self):
293291
u = self.type2test([0, 1])
@@ -348,6 +346,21 @@ def test_subscript(self):
348346
self.assertRaises(ValueError, a.__getitem__, slice(0, 10, 0))
349347
self.assertRaises(TypeError, a.__getitem__, 'x')
350348

349+
def _assert_cmp(self, a, b, r):
350+
self.assertIs(a == b, r == 0)
351+
self.assertIs(a != b, r != 0)
352+
self.assertIs(a > b, r > 0)
353+
self.assertIs(a <= b, r <= 0)
354+
self.assertIs(a < b, r < 0)
355+
self.assertIs(a >= b, r >= 0)
356+
357+
def test_cmp(self):
358+
a = self.type2test([0, 1])
359+
self._assert_cmp(a, a, 0)
360+
self._assert_cmp(a, self.type2test([0, 1]), 0)
361+
self._assert_cmp(a, self.type2test([0]), 1)
362+
self._assert_cmp(a, self.type2test([0, 2]), -1)
363+
351364
def test_count(self):
352365
a = self.type2test([0, 1, 2])*3
353366
self.assertEqual(a.count(0), 3)

Lib/test/test_dict.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,26 @@ def make_pairs():
15741574
self.assertEqual(d.get(key3_3), 44)
15751575
self.assertGreaterEqual(eq_count, 1)
15761576

1577+
def test_overwrite_managed_dict(self):
1578+
# GH-130327: Overwriting an object's managed dictionary with another object's
1579+
# skipped traversal in favor of inline values, causing the GC to believe that
1580+
# the __dict__ wasn't reachable.
1581+
import gc
1582+
1583+
class Shenanigans:
1584+
pass
1585+
1586+
to_be_deleted = Shenanigans()
1587+
to_be_deleted.attr = "whatever"
1588+
holds_reference = Shenanigans()
1589+
holds_reference.__dict__ = to_be_deleted.__dict__
1590+
holds_reference.ref = {"circular": to_be_deleted, "data": 42}
1591+
1592+
del to_be_deleted
1593+
gc.collect()
1594+
self.assertEqual(holds_reference.ref['data'], 42)
1595+
self.assertEqual(holds_reference.attr, "whatever")
1596+
15771597
@unittest.expectedFailure # TODO: RUSTPYTHON
15781598
def test_unhashable_key(self):
15791599
d = {'a': 1}
@@ -1686,6 +1706,69 @@ def test_hash_collision_remove_add(self):
16861706
self.assertEqual(len(d), len(items), d)
16871707
self.assertEqual(d, dict(items))
16881708

1709+
def test_clear_reentrant_embedded(self):
1710+
# gh-130555: dict.clear() must be safe when values are embedded
1711+
# in an object and a destructor mutates the dict.
1712+
class MyObj: pass
1713+
class ClearOnDelete:
1714+
def __del__(self):
1715+
nonlocal x
1716+
del x
1717+
1718+
x = MyObj()
1719+
x.a = ClearOnDelete()
1720+
1721+
d = x.__dict__
1722+
d.clear()
1723+
1724+
def test_clear_reentrant_cycle(self):
1725+
# gh-130555: dict.clear() must be safe for embedded dicts when the
1726+
# object is part of a reference cycle and the last reference to the
1727+
# dict is via the cycle.
1728+
class MyObj: pass
1729+
obj = MyObj()
1730+
obj.f = obj
1731+
obj.attr = "attr"
1732+
1733+
d = obj.__dict__
1734+
del obj
1735+
1736+
d.clear()
1737+
1738+
def test_clear_reentrant_force_combined(self):
1739+
# gh-130555: dict.clear() must be safe when a destructor forces the
1740+
# dict from embedded/split to combined (setting ma_values to NULL).
1741+
class MyObj: pass
1742+
class ForceConvert:
1743+
def __del__(self):
1744+
d[1] = "trigger"
1745+
1746+
x = MyObj()
1747+
x.a = ForceConvert()
1748+
x.b = "other"
1749+
1750+
d = x.__dict__
1751+
d.clear()
1752+
1753+
def test_clear_reentrant_delete(self):
1754+
# gh-130555: dict.clear() must be safe when a destructor deletes
1755+
# a key from the same embedded dict.
1756+
class MyObj: pass
1757+
class DelKey:
1758+
def __del__(self):
1759+
try:
1760+
del d['b']
1761+
except KeyError:
1762+
pass
1763+
1764+
x = MyObj()
1765+
x.a = DelKey()
1766+
x.b = "value_b"
1767+
x.c = "value_c"
1768+
1769+
d = x.__dict__
1770+
d.clear()
1771+
16891772

16901773
class CAPITest(unittest.TestCase):
16911774

Lib/test/test_listcomps.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,18 @@ def test_references___class___defined(self):
180180
code, outputs={"res": [2]}, scopes=["module", "function"])
181181
self._check_in_scopes(code, raises=NameError, scopes=["class"])
182182

183+
def test_references___classdict__(self):
184+
code = """
185+
class i: [__classdict__ for x in y]
186+
"""
187+
self._check_in_scopes(code, raises=NameError)
188+
189+
def test_references___conditional_annotations__(self):
190+
code = """
191+
class i: [__conditional_annotations__ for x in y]
192+
"""
193+
self._check_in_scopes(code, raises=NameError)
194+
183195
def test_references___class___enclosing(self):
184196
code = """
185197
__class__ = 2

Lib/test/test_set.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1969,7 +1969,6 @@ def check_set_op_does_not_crash(self, function):
19691969
self.assertIn("changed size during iteration", str(e))
19701970

19711971

1972-
@unittest.skip("TODO: RUSTPYTHON; segfault")
19731972
class TestBinaryOpsMutating(TestOperationsMutating):
19741973

19751974
def test_eq_with_mutation(self):
@@ -2058,7 +2057,6 @@ class TestBinaryOpsMutating_Subclass_Set(TestBinaryOpsMutating, unittest.TestCas
20582057
constructor2 = set
20592058

20602059

2061-
@unittest.skip("TODO: RUSTPYTHON; segfault")
20622060
class TestMethodsMutating(TestOperationsMutating):
20632061

20642062
def test_issubset_with_mutation(self):

Lib/test/test_userdict.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
# Check every path through every method of UserDict
22

3+
from collections import UserDict
34
from test import mapping_tests
45
import unittest
56
import collections
7+
import types
8+
9+
10+
class UserDictSubclass(UserDict):
11+
pass
12+
13+
class UserDictSubclass2(UserDict):
14+
pass
15+
616

717
d0 = {}
818
d1 = {"one": 1}
@@ -155,6 +165,25 @@ def test_init(self):
155165
self.assertRaises(TypeError, collections.UserDict, (), ())
156166
self.assertRaises(TypeError, collections.UserDict.__init__)
157167

168+
def test_data(self):
169+
u = UserDict()
170+
self.assertEqual(u.data, {})
171+
self.assertIs(type(u.data), dict)
172+
d = {'a': 1, 'b': 2}
173+
u = UserDict(d)
174+
self.assertEqual(u.data, d)
175+
self.assertIsNot(u.data, d)
176+
self.assertIs(type(u.data), dict)
177+
u = UserDict(u)
178+
self.assertEqual(u.data, d)
179+
self.assertIs(type(u.data), dict)
180+
u = UserDict([('a', 1), ('b', 2)])
181+
self.assertEqual(u.data, d)
182+
self.assertIs(type(u.data), dict)
183+
u = UserDict(a=1, b=2)
184+
self.assertEqual(u.data, d)
185+
self.assertIs(type(u.data), dict)
186+
158187
def test_update(self):
159188
for kw in 'self', 'dict', 'other', 'iterable':
160189
d = collections.UserDict()
@@ -215,6 +244,70 @@ class G(collections.UserDict):
215244

216245
test_repr_deep = mapping_tests.TestHashMappingProtocol.test_repr_deep
217246

247+
@unittest.expectedFailure # TODO: RUSTPYTHON; TypeError: unsupported operand type(s) for |: 'UserDict' and 'mappingproxy'
248+
def test_mixed_or(self):
249+
for t in UserDict, dict, types.MappingProxyType:
250+
with self.subTest(t.__name__):
251+
u = UserDict({0: 'a', 1: 'b'}) | t({1: 'c', 2: 'd'})
252+
self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'})
253+
self.assertIs(type(u), UserDict)
254+
255+
u = t({0: 'a', 1: 'b'}) | UserDict({1: 'c', 2: 'd'})
256+
self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'})
257+
self.assertIs(type(u), UserDict)
258+
259+
u = UserDict({0: 'a', 1: 'b'}) | UserDictSubclass({1: 'c', 2: 'd'})
260+
self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'})
261+
self.assertIs(type(u), UserDict)
262+
263+
u = UserDictSubclass({0: 'a', 1: 'b'}) | UserDict({1: 'c', 2: 'd'})
264+
self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'})
265+
self.assertIs(type(u), UserDictSubclass)
266+
267+
u = UserDictSubclass({0: 'a', 1: 'b'}) | UserDictSubclass2({1: 'c', 2: 'd'})
268+
self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'})
269+
self.assertIs(type(u), UserDictSubclass)
270+
271+
u = UserDict({1: 'c', 2: 'd'}).__ror__(UserDict({0: 'a', 1: 'b'}))
272+
self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'})
273+
self.assertIs(type(u), UserDict)
274+
275+
u = UserDictSubclass({1: 'c', 2: 'd'}).__ror__(UserDictSubclass2({0: 'a', 1: 'b'}))
276+
self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'})
277+
self.assertIs(type(u), UserDictSubclass)
278+
279+
def test_mixed_ior(self):
280+
for t in UserDict, dict, types.MappingProxyType:
281+
with self.subTest(t.__name__):
282+
u = u2 = UserDict({0: 'a', 1: 'b'})
283+
u |= t({1: 'c', 2: 'd'})
284+
self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'})
285+
self.assertIs(type(u), UserDict)
286+
self.assertIs(u, u2)
287+
288+
u = dict({0: 'a', 1: 'b'})
289+
u |= UserDict({1: 'c', 2: 'd'})
290+
self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'})
291+
self.assertIs(type(u), dict)
292+
293+
u = u2 = UserDict({0: 'a', 1: 'b'})
294+
u |= UserDictSubclass({1: 'c', 2: 'd'})
295+
self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'})
296+
self.assertIs(type(u), UserDict)
297+
self.assertIs(u, u2)
298+
299+
u = u2 = UserDictSubclass({0: 'a', 1: 'b'})
300+
u |= UserDict({1: 'c', 2: 'd'})
301+
self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'})
302+
self.assertIs(type(u), UserDictSubclass)
303+
self.assertIs(u, u2)
304+
305+
u = u2 = UserDictSubclass({0: 'a', 1: 'b'})
306+
u |= UserDictSubclass2({1: 'c', 2: 'd'})
307+
self.assertEqual(u, {0: 'a', 1: 'c', 2: 'd'})
308+
self.assertIs(type(u), UserDictSubclass)
309+
self.assertIs(u, u2)
310+
218311

219312
if __name__ == "__main__":
220313
unittest.main()

0 commit comments

Comments
 (0)