mirror of
https://github.com/python/cpython.git
synced 2025-08-24 10:45:53 +00:00
Closes #21173: Fix len() on a WeakKeyDictionary when .clear() was called with an iterator alive.
This commit is contained in:
commit
414e15a88d
3 changed files with 52 additions and 0 deletions
|
@ -1310,6 +1310,36 @@ class MappingTestCase(TestBase):
|
|||
dict.clear()
|
||||
self.assertEqual(len(dict), 0)
|
||||
|
||||
def check_weak_del_and_len_while_iterating(self, dict, testcontext):
|
||||
# Check that len() works when both iterating and removing keys
|
||||
# explicitly through various means (.pop(), .clear()...), while
|
||||
# implicit mutation is deferred because an iterator is alive.
|
||||
# (each call to testcontext() should schedule one item for removal
|
||||
# for this test to work properly)
|
||||
o = Object(123456)
|
||||
with testcontext():
|
||||
n = len(dict)
|
||||
dict.popitem()
|
||||
self.assertEqual(len(dict), n - 1)
|
||||
dict[o] = o
|
||||
self.assertEqual(len(dict), n)
|
||||
with testcontext():
|
||||
self.assertEqual(len(dict), n - 1)
|
||||
dict.pop(next(dict.keys()))
|
||||
self.assertEqual(len(dict), n - 2)
|
||||
with testcontext():
|
||||
self.assertEqual(len(dict), n - 3)
|
||||
del dict[next(dict.keys())]
|
||||
self.assertEqual(len(dict), n - 4)
|
||||
with testcontext():
|
||||
self.assertEqual(len(dict), n - 5)
|
||||
dict.popitem()
|
||||
self.assertEqual(len(dict), n - 6)
|
||||
with testcontext():
|
||||
dict.clear()
|
||||
self.assertEqual(len(dict), 0)
|
||||
self.assertEqual(len(dict), 0)
|
||||
|
||||
def test_weak_keys_destroy_while_iterating(self):
|
||||
# Issue #7105: iterators shouldn't crash when a key is implicitly removed
|
||||
dict, objects = self.make_weak_keyed_dict()
|
||||
|
@ -1331,6 +1361,10 @@ class MappingTestCase(TestBase):
|
|||
it = None # should commit all removals
|
||||
gc.collect()
|
||||
self.check_weak_destroy_and_mutate_while_iterating(dict, testcontext)
|
||||
# Issue #21173: len() fragile when keys are both implicitly and
|
||||
# explicitly removed.
|
||||
dict, objects = self.make_weak_keyed_dict()
|
||||
self.check_weak_del_and_len_while_iterating(dict, testcontext)
|
||||
|
||||
def test_weak_values_destroy_while_iterating(self):
|
||||
# Issue #7105: iterators shouldn't crash when a key is implicitly removed
|
||||
|
@ -1354,6 +1388,8 @@ class MappingTestCase(TestBase):
|
|||
it = None # should commit all removals
|
||||
gc.collect()
|
||||
self.check_weak_destroy_and_mutate_while_iterating(dict, testcontext)
|
||||
dict, objects = self.make_weak_valued_dict()
|
||||
self.check_weak_del_and_len_while_iterating(dict, testcontext)
|
||||
|
||||
def test_make_weak_keyed_dict_from_dict(self):
|
||||
o = Object(3)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue