Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1d879f6

Browse files
committed
Backport r87613 to make OrderedDict subclassing match dict subclassing.
1 parent db0ef2b commit 1d879f6

2 files changed

Lines changed: 49 additions & 5 deletions

File tree

Lib/collections.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
class _Link(object):
2222
__slots__ = 'prev', 'next', 'key', '__weakref__'
2323

24-
class OrderedDict(dict, MutableMapping):
24+
class OrderedDict(dict):
2525
'Dictionary that remembers insertion order'
2626
# An inherited dict maps keys to values.
2727
# The inherited dict provides __getitem__, __len__, __contains__, and get.
@@ -50,7 +50,7 @@ def __init__(self, *args, **kwds):
5050
self.__root = root = _Link() # sentinel node for the doubly linked list
5151
root.prev = root.next = root
5252
self.__map = {}
53-
self.update(*args, **kwds)
53+
self.__update(*args, **kwds)
5454

5555
def clear(self):
5656
'od.clear() -> None. Remove all items from od.'
@@ -109,13 +109,29 @@ def __reduce__(self):
109109
return (self.__class__, (items,), inst_dict)
110110
return self.__class__, (items,)
111111

112-
setdefault = MutableMapping.setdefault
113-
update = MutableMapping.update
114-
pop = MutableMapping.pop
112+
update = __update = MutableMapping.update
115113
keys = MutableMapping.keys
116114
values = MutableMapping.values
117115
items = MutableMapping.items
118116

117+
__marker = object()
118+
119+
def pop(self, key, default=__marker):
120+
if key in self:
121+
result = self[key]
122+
del self[key]
123+
return result
124+
if default is self.__marker:
125+
raise KeyError(key)
126+
return default
127+
128+
def setdefault(self, key, default=None):
129+
'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
130+
if key in self:
131+
return self[key]
132+
self[key] = default
133+
return default
134+
119135
def popitem(self, last=True):
120136
'''od.popitem() -> (k, v), return and remove a (key, value) pair.
121137
Pairs are returned in LIFO order if last is true or FIFO order if false.

Lib/test/test_collections.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,10 @@ def test_update(self):
792792
self.assertEqual(list(d.items()),
793793
[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
794794

795+
def test_abc(self):
796+
self.assertTrue(isinstance(OrderedDict(), MutableMapping))
797+
self.assertTrue(issubclass(OrderedDict, MutableMapping))
798+
795799
def test_clear(self):
796800
pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
797801
shuffle(pairs)
@@ -850,6 +854,17 @@ def test_pop(self):
850854
self.assertEqual(len(od), 0)
851855
self.assertEqual(od.pop(k, 12345), 12345)
852856

857+
# make sure pop still works when __missing__ is defined
858+
class Missing(OrderedDict):
859+
def __missing__(self, key):
860+
return 0
861+
m = Missing(a=1)
862+
self.assertEqual(m.pop('b', 5), 5)
863+
self.assertEqual(m.pop('a', 6), 1)
864+
self.assertEqual(m.pop('a', 6), 6)
865+
with self.assertRaises(KeyError):
866+
m.pop('a')
867+
853868
def test_equality(self):
854869
pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
855870
shuffle(pairs)
@@ -934,6 +949,12 @@ def test_setdefault(self):
934949
# make sure 'x' is added to the end
935950
self.assertEqual(list(od.items())[-1], ('x', 10))
936951

952+
# make sure setdefault still works when __missing__ is defined
953+
class Missing(OrderedDict):
954+
def __missing__(self, key):
955+
return 0
956+
self.assertEqual(Missing().setdefault(5, 9), 9)
957+
937958
def test_reinsert(self):
938959
# Given insert a, insert b, delete a, re-insert a,
939960
# verify that a is now later than b.
@@ -945,6 +966,13 @@ def test_reinsert(self):
945966
self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
946967

947968

969+
def test_override_update(self):
970+
# Verify that subclasses can override update() without breaking __init__()
971+
class MyOD(OrderedDict):
972+
def update(self, *args, **kwds):
973+
raise Exception()
974+
items = [('a', 1), ('c', 3), ('b', 2)]
975+
self.assertEqual(list(MyOD(items).items()), items)
948976

949977
class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
950978
type2test = OrderedDict

0 commit comments

Comments
 (0)