Skip to content

Commit 0fd074a

Browse files
committed
Replace key if not identical to old key
1 parent 586b24d commit 0fd074a

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

Lib/test/test_dict.py

+15
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,21 @@ def __hash__(self):
618618
with self.assertRaises(Exc):
619619
d1 == d2
620620

621+
def test_eq_replace(self):
622+
class AlwaysEqualCmp(object):
623+
def __eq__(self, other):
624+
return True
625+
626+
def __hash__(self):
627+
return 1
628+
629+
o1 = AlwaysEqualCmp()
630+
d3 = {}
631+
d3[o1] = 1
632+
o2 = AlwaysEqualCmp()
633+
d3[o2] = 2
634+
assert tuple(d3.keys())[0] is o2
635+
621636
def test_keys_contained(self):
622637
self.helper_keys_contained(lambda x: x.keys())
623638
self.helper_keys_contained(lambda x: x.items())

Lib/test/test_weakref.py

+13
Original file line numberDiff line numberDiff line change
@@ -1797,6 +1797,19 @@ def test_weak_keyed_bad_delitem(self):
17971797
self.assertRaises(TypeError, d.__getitem__, 13)
17981798
self.assertRaises(TypeError, d.__setitem__, 13, 13)
17991799

1800+
def test_weak_keyed_equal_replacement(self):
1801+
d = weakref.WeakKeyDictionary()
1802+
o1 = Object('1')
1803+
o2 = Object('1')
1804+
d[o1] = 1
1805+
d[o2] = 2
1806+
assert len(d) == 1
1807+
assert d[o2] == 2
1808+
assert tuple(d.keys())[0] is o2
1809+
del o1
1810+
assert len(d) == 1
1811+
assert tuple(d.keys())[0] is o2
1812+
18001813
def test_weak_keyed_cascading_deletes(self):
18011814
# SF bug 742860. For some reason, before 2.3 __delitem__ iterated
18021815
# over the keys via self.data.iterkeys(). If things vanished from

Objects/dictobject.c

+10
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,7 @@ Consumes key and value references.
12221222
static int
12231223
insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
12241224
{
1225+
PyObject *old_key;
12251226
PyObject *old_value;
12261227

12271228
if (DK_IS_UNICODE(mp->ma_keys) && !PyUnicode_CheckExact(key)) {
@@ -1279,6 +1280,15 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
12791280
return 0;
12801281
}
12811282

1283+
if (!DK_IS_UNICODE(mp->ma_keys)) {
1284+
PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[ix];
1285+
old_key = ep->me_key;
1286+
if (old_key != key) {
1287+
ep->me_key = key;
1288+
key = old_key;
1289+
}
1290+
}
1291+
12821292
if (old_value != value) {
12831293
if (_PyDict_HasSplitTable(mp)) {
12841294
mp->ma_values->values[ix] = value;

0 commit comments

Comments
 (0)