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

raymond.hettinger python-checkins at python.org
Sun Sep 12 07:28:42 CEST 2010


Author: raymond.hettinger
Date: Sun Sep 12 07:28:42 2010
New Revision: 84729

Log:
Issue #9826:  Handle recursive repr in collections.OrderedDict.

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

Modified: python/branches/release31-maint/Lib/collections.py
==============================================================================
--- python/branches/release31-maint/Lib/collections.py	(original)
+++ python/branches/release31-maint/Lib/collections.py	Sun Sep 12 07:28:42 2010
@@ -43,6 +43,7 @@
         '''
         if len(args) > 1:
             raise TypeError('expected at most 1 arguments, got %d' % len(args))
+        self.__in_repr = False              # detects recursive repr
         try:
             self.__root
         except AttributeError:
@@ -100,10 +101,10 @@
     def __reduce__(self):
         'Return state information for pickling'
         items = [[k, self[k]] for k in self]
-        tmp = self.__map, self.__root
-        del self.__map, self.__root
+        tmp = self.__map, self.__root, self.__in_repr
+        del self.__map, self.__root, self.__in_repr
         inst_dict = vars(self).copy()
-        self.__map, self.__root = tmp
+        self.__map, self.__root, self.__in_repr = tmp
         if inst_dict:
             return (self.__class__, (items,), inst_dict)
         return self.__class__, (items,)
@@ -128,9 +129,16 @@
 
     def __repr__(self):
         'od.__repr__() <==> repr(od)'
+        if self.__in_repr:
+            return '...'
         if not self:
             return '%s()' % (self.__class__.__name__,)
-        return '%s(%r)' % (self.__class__.__name__, list(self.items()))
+        self.__in_repr = True
+        try:
+            result = '%s(%r)' % (self.__class__.__name__, list(self.items()))
+        finally:
+            self.__in_repr = False
+        return result
 
     def copy(self):
         'od.copy() -> a shallow copy of od'

Modified: python/branches/release31-maint/Lib/test/test_collections.py
==============================================================================
--- python/branches/release31-maint/Lib/test/test_collections.py	(original)
+++ python/branches/release31-maint/Lib/test/test_collections.py	Sun Sep 12 07:28:42 2010
@@ -908,6 +908,13 @@
         self.assertEqual(eval(repr(od)), od)
         self.assertEqual(repr(OrderedDict()), "OrderedDict()")
 
+    def test_repr_recursive(self):
+        # See issue #9826
+        od = OrderedDict.fromkeys('abc')
+        od['x'] = od
+        self.assertEqual(repr(od),
+            "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
+
     def test_setdefault(self):
         pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
         shuffle(pairs)

Modified: python/branches/release31-maint/Misc/NEWS
==============================================================================
--- python/branches/release31-maint/Misc/NEWS	(original)
+++ python/branches/release31-maint/Misc/NEWS	Sun Sep 12 07:28:42 2010
@@ -122,6 +122,9 @@
   to fetch the original errno, or to filter timeout errors.  Now the
   original error is re-raised.
 
+- Issue #9826: OrderedDict.__repr__ can now handle self-referential
+  values:   d['x'] = d.
+
 - Issue #9758: When fcntl.ioctl() was called with mutable_flag set to True,
   and the passed buffer was exactly 1024 bytes long, the buffer wouldn't
   be updated back after the system call.  Original patch by Brian Brazil.


More information about the Python-checkins mailing list