[Python-checkins] r87613 - in python/branches/release27-maint: Lib/collections.py Lib/test/test_collections.py Misc/NEWS

raymond.hettinger python-checkins at python.org
Sun Jan 2 02:03:27 CET 2011


Author: raymond.hettinger
Date: Sun Jan  2 02:03:26 2011
New Revision: 87613

Log:
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__()).



Modified:
   python/branches/release27-maint/Lib/collections.py
   python/branches/release27-maint/Lib/test/test_collections.py
   python/branches/release27-maint/Misc/NEWS

Modified: python/branches/release27-maint/Lib/collections.py
==============================================================================
--- python/branches/release27-maint/Lib/collections.py	(original)
+++ python/branches/release27-maint/Lib/collections.py	Sun Jan  2 02:03:26 2011
@@ -43,7 +43,7 @@
 ### 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 @@
             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 @@
             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 @@
         "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.

Modified: python/branches/release27-maint/Lib/test/test_collections.py
==============================================================================
--- python/branches/release27-maint/Lib/test/test_collections.py	(original)
+++ python/branches/release27-maint/Lib/test/test_collections.py	Sun Jan  2 02:03:26 2011
@@ -812,6 +812,10 @@
         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 @@
         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 @@
         # 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 @@
         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

Modified: python/branches/release27-maint/Misc/NEWS
==============================================================================
--- python/branches/release27-maint/Misc/NEWS	(original)
+++ python/branches/release27-maint/Misc/NEWS	Sun Jan  2 02:03:26 2011
@@ -22,6 +22,8 @@
 Library
 -------
 
+- Subclasses of collections.OrderedDict now work correctly with __missing__.
+
 - Issue 10753 - Characters ';','=' and ',' in the PATH_INFO environment
   variable won't be quoted when the URI is constructed by the wsgiref.util 's
   request_uri method. According to RFC 3986, these characters can be a part of


More information about the Python-checkins mailing list