diff options
author | Raymond Hettinger <python@rcn.com> | 2011-01-02 01:03:26 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2011-01-02 01:03:26 (GMT) |
commit | 8ebebd8f7e0d4f9e11a76687ce797bb78a219c34 (patch) | |
tree | 3de25541c18916b80f96ef57861b3db15a414d7f /Lib | |
parent | fe0263d36feb014557df4a3e30702f0691848ddd (diff) | |
download | cpython-8ebebd8f7e0d4f9e11a76687ce797bb78a219c34.zip cpython-8ebebd8f7e0d4f9e11a76687ce797bb78a219c34.tar.gz cpython-8ebebd8f7e0d4f9e11a76687ce797bb78a219c34.tar.bz2 |
Raymond-Hettingers-MacBook-Pro:py27 raymondhettinger$ cat svn-commit.tmp
Backport r87594 r87611 and r87612 so that OrderedDict subclassing behavior
better matches dict subclassing (i.e. adding __missing__ works and
extending/overriding the update() methods doesn't break __init__()).
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/collections.py | 26 | ||||
-rw-r--r-- | Lib/test/test_collections.py | 28 |
2 files changed, 49 insertions, 5 deletions
diff --git a/Lib/collections.py b/Lib/collections.py index a49ecc7..17fc012 100644 --- a/Lib/collections.py +++ b/Lib/collections.py @@ -43,7 +43,7 @@ def _recursive_repr(user_function): ### OrderedDict ################################################################################ -class OrderedDict(dict, MutableMapping): +class OrderedDict(dict): 'Dictionary that remembers insertion order' # An inherited dict maps keys to values. # The inherited dict provides __getitem__, __len__, __contains__, and get. @@ -71,7 +71,7 @@ class OrderedDict(dict, MutableMapping): NEXT = 1 root[PREV] = root[NEXT] = root self.__map = {} - self.update(*args, **kwds) + self.__update(*args, **kwds) def __setitem__(self, key, value, PREV=0, NEXT=1, dict_setitem=dict.__setitem__): 'od.__setitem__(i, y) <==> od[i]=y' @@ -134,9 +134,7 @@ class OrderedDict(dict, MutableMapping): pass dict.clear(self) - setdefault = MutableMapping.setdefault - update = MutableMapping.update - pop = MutableMapping.pop + update = __update = MutableMapping.update keys = MutableMapping.keys values = MutableMapping.values items = MutableMapping.items @@ -157,6 +155,24 @@ class OrderedDict(dict, MutableMapping): "od.viewitems() -> a set-like object providing a view on od's items" return ItemsView(self) + __marker = object() + + def pop(self, key, default=__marker): + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + def popitem(self, last=True): '''od.popitem() -> (k, v), return and remove a (key, value) pair. Pairs are returned in LIFO order if last is true or FIFO order if false. diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index 2d2319f..f6a43fc 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -812,6 +812,10 @@ class TestOrderedDict(unittest.TestCase): self.assertEqual(list(d.items()), [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)]) + def test_abc(self): + self.assertIsInstance(OrderedDict(), MutableMapping) + self.assertTrue(issubclass(OrderedDict, MutableMapping)) + def test_clear(self): pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) @@ -873,6 +877,17 @@ class TestOrderedDict(unittest.TestCase): self.assertEqual(len(od), 0) self.assertEqual(od.pop(k, 12345), 12345) + # make sure pop still works when __missing__ is defined + class Missing(OrderedDict): + def __missing__(self, key): + return 0 + m = Missing(a=1) + self.assertEqual(m.pop('b', 5), 5) + self.assertEqual(m.pop('a', 6), 1) + self.assertEqual(m.pop('a', 6), 6) + with self.assertRaises(KeyError): + m.pop('a') + def test_equality(self): pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) @@ -956,6 +971,12 @@ class TestOrderedDict(unittest.TestCase): # make sure 'x' is added to the end self.assertEqual(list(od.items())[-1], ('x', 10)) + # make sure setdefault still works when __missing__ is defined + class Missing(OrderedDict): + def __missing__(self, key): + return 0 + self.assertEqual(Missing().setdefault(5, 9), 9) + def test_reinsert(self): # Given insert a, insert b, delete a, re-insert a, # verify that a is now later than b. @@ -973,6 +994,13 @@ class TestOrderedDict(unittest.TestCase): self.assertEqual(list(od.viewvalues()), [None for k in s]) self.assertEqual(list(od.viewitems()), [(k, None) for k in s]) + def test_override_update(self): + # Verify that subclasses can override update() without breaking __init__() + class MyOD(OrderedDict): + def update(self, *args, **kwds): + raise Exception() + items = [('a', 1), ('c', 3), ('b', 2)] + self.assertEqual(list(MyOD(items).items()), items) class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol): type2test = OrderedDict |