Skip to content

Commit ac94948

Browse files
committed
[GR-23219] Make test_dict pass - change during iteration.
PullRequest: graalpython/1043
2 parents 16580ad + 9b60a76 commit ac94948

20 files changed

+386
-162
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_dict.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -853,4 +853,49 @@ def __eq__(self, o):
853853
raised = True
854854
assert raised
855855

856-
assert 'kw' not in d
856+
assert 'kw' not in d
857+
858+
def test_iter_changed_size():
859+
def just_iterate(it):
860+
for i in it:
861+
pass
862+
863+
def iterate_and_update(it):
864+
for i in it:
865+
d.update({3:3})
866+
867+
# dict
868+
d = {1:1, 2:2}
869+
it = iter(d)
870+
del d[1]
871+
assert_raises(RuntimeError, just_iterate, it)
872+
873+
d = {1:1, 2:2}
874+
assert_raises(RuntimeError, iterate_and_update, d)
875+
876+
# keys
877+
d = {1:1, 2:2}
878+
it = iter(d.keys())
879+
del d[1]
880+
assert_raises(RuntimeError, just_iterate, it)
881+
882+
d = {1:1}
883+
assert_raises(RuntimeError, iterate_and_update, d.keys())
884+
885+
# values
886+
d = {1:1, 2:2}
887+
it = iter(d.values())
888+
del d[1]
889+
assert_raises(RuntimeError, just_iterate, it)
890+
891+
d = {1:1}
892+
assert_raises(RuntimeError, iterate_and_update, d.values())
893+
894+
# items
895+
d = {1:1, 2:2}
896+
it = iter(d.items())
897+
del d[1]
898+
assert_raises(RuntimeError, just_iterate, it)
899+
900+
d = {1:1}
901+
assert_raises(RuntimeError, iterate_and_update, d.items())

graalpython/com.oracle.graal.python.test/src/tests/test_mappingproxy.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -129,3 +129,16 @@ def test_iter():
129129
mp_keys = set([k for k in mp])
130130
assert d.keys() == mp_keys
131131

132+
def test_iter_changed_size():
133+
class A:
134+
pass
135+
136+
def foo():
137+
pass
138+
139+
try:
140+
for i in A.__dict__:
141+
setattr(A, 'foo', foo)
142+
except RuntimeError:
143+
raised = True
144+
assert raised

graalpython/com.oracle.graal.python.test/src/tests/test_set.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,4 +460,21 @@ def __len__(self):
460460
assert {10, 11}.isdisjoint(NonSetWithIter())
461461
assert {10, 11, 12, 13, 14}.isdisjoint(NonSetWithIter())
462462
assert not {1, 2}.isdisjoint(NonSetWithIter())
463-
assert not {1, 2, 3, 4, 5}.isdisjoint(NonSetWithIter())
463+
assert not {1, 2, 3, 4, 5}.isdisjoint(NonSetWithIter())
464+
465+
def test_iter_changed_size():
466+
def just_iterate(it):
467+
for i in it:
468+
pass
469+
470+
def iterate_and_update(it):
471+
for i in it:
472+
s.add(3)
473+
474+
s = {1, 2}
475+
it = iter(s)
476+
s.pop()
477+
assert_raises(RuntimeError, just_iterate, it)
478+
479+
s = {1, 2}
480+
assert_raises(RuntimeError, iterate_and_update, s)

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_dict.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
*graalpython.lib-python.3.test.test_dict.DictTest.test_mutating_lookup
3838
*graalpython.lib-python.3.test.test_dict.DictTest.test_object_set_item_single_instance_non_str_key
3939
*graalpython.lib-python.3.test.test_dict.DictTest.test_pop
40+
*graalpython.lib-python.3.test.test_dict.DictTest.test_popitem
4041
*graalpython.lib-python.3.test.test_dict.DictTest.test_reentrant_insertion
4142
*graalpython.lib-python.3.test.test_dict.DictTest.test_repr
4243
*graalpython.lib-python.3.test.test_dict.DictTest.test_repr_deep
@@ -61,19 +62,29 @@
6162
*graalpython.lib-python.3.test.test_dict.DictTest.test_values
6263
*graalpython.lib-python.3.test.test_dict.GeneralMappingTests.test_bool
6364
*graalpython.lib-python.3.test.test_dict.GeneralMappingTests.test_constructor
65+
*graalpython.lib-python.3.test.test_dict.GeneralMappingTests.test_get
6466
*graalpython.lib-python.3.test.test_dict.GeneralMappingTests.test_getitem
6567
*graalpython.lib-python.3.test.test_dict.GeneralMappingTests.test_items
68+
*graalpython.lib-python.3.test.test_dict.GeneralMappingTests.test_keys
6669
*graalpython.lib-python.3.test.test_dict.GeneralMappingTests.test_len
70+
*graalpython.lib-python.3.test.test_dict.GeneralMappingTests.test_pop
6771
*graalpython.lib-python.3.test.test_dict.GeneralMappingTests.test_popitem
72+
*graalpython.lib-python.3.test.test_dict.GeneralMappingTests.test_read
6873
*graalpython.lib-python.3.test.test_dict.GeneralMappingTests.test_setdefault
6974
*graalpython.lib-python.3.test.test_dict.GeneralMappingTests.test_update
7075
*graalpython.lib-python.3.test.test_dict.GeneralMappingTests.test_values
76+
*graalpython.lib-python.3.test.test_dict.GeneralMappingTests.test_write
7177
*graalpython.lib-python.3.test.test_dict.SubclassMappingTests.test_bool
7278
*graalpython.lib-python.3.test.test_dict.SubclassMappingTests.test_constructor
79+
*graalpython.lib-python.3.test.test_dict.SubclassMappingTests.test_get
7380
*graalpython.lib-python.3.test.test_dict.SubclassMappingTests.test_getitem
7481
*graalpython.lib-python.3.test.test_dict.SubclassMappingTests.test_items
82+
*graalpython.lib-python.3.test.test_dict.SubclassMappingTests.test_keys
7583
*graalpython.lib-python.3.test.test_dict.SubclassMappingTests.test_len
84+
*graalpython.lib-python.3.test.test_dict.SubclassMappingTests.test_pop
7685
*graalpython.lib-python.3.test.test_dict.SubclassMappingTests.test_popitem
86+
*graalpython.lib-python.3.test.test_dict.SubclassMappingTests.test_read
7787
*graalpython.lib-python.3.test.test_dict.SubclassMappingTests.test_setdefault
7888
*graalpython.lib-python.3.test.test_dict.SubclassMappingTests.test_update
7989
*graalpython.lib-python.3.test.test_dict.SubclassMappingTests.test_values
90+
*graalpython.lib-python.3.test.test_dict.SubclassMappingTests.test_write

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/DynamicObjectStorage.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,9 @@ private static Object runNode(DynamicObjectStorage self, Object key, Object acc,
341341
@ExportMessage
342342
@TruffleBoundary
343343
public HashingStorage clear() {
344-
return new DynamicObjectStorage();
344+
store.setShapeAndResize(store.getShape(), EMPTY_SHAPE);
345+
store.updateShape();
346+
return this;
345347
}
346348

347349
@Override

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/EconomicMapStorage.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -372,16 +372,17 @@ static HashingStorage delItemWithStateWithSideEffect(EconomicMapStorage self, Ob
372372
static class Clear {
373373

374374
@Specialization(guards = "!hasSideEffect(self)")
375-
static HashingStorage clear(@SuppressWarnings("unused") EconomicMapStorage self) {
376-
return create();
375+
static HashingStorage clear(EconomicMapStorage self) {
376+
self.map.clear();
377+
return self;
377378
}
378379

379380
@Specialization
380381
static HashingStorage clearWithSideEffect(EconomicMapStorage self,
381382
@Exclusive @Cached LookupInheritedAttributeNode.Dynamic lookup,
382383
@Exclusive @Cached CallUnaryMethodNode callNode) {
383384
if (self.map.size() == 0) {
384-
return create();
385+
return self;
385386
}
386387
Object[] entries = new Object[self.map.size() * 2];
387388
MapCursor<DictKey, Object> cursor = self.map.getEntries();
@@ -398,7 +399,7 @@ static HashingStorage clearWithSideEffect(EconomicMapStorage self,
398399
callNode.executeObject(lookup.execute(o, __DEL__), o);
399400
}
400401
}
401-
return create();
402+
return self;
402403
}
403404

404405
}

0 commit comments

Comments
 (0)