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

raymond.hettinger python-checkins at python.org
Tue Sep 14 00:14:37 CEST 2010


Author: raymond.hettinger
Date: Tue Sep 14 00:14:36 2010
New Revision: 84793

Log:
Issue 9826: OrderedDict.__repr__ did not play well with self-referencing dicts.

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	Tue Sep 14 00:14:36 2010
@@ -12,6 +12,32 @@
 import heapq as _heapq
 from itertools import repeat as _repeat, chain as _chain, starmap as _starmap, \
                       ifilter as _ifilter, imap as _imap
+try:
+    from thread import get_ident
+except AttributeError:
+    from dummy_thread import get_ident
+
+def _recursive_repr(user_function):
+    'Decorator to make a repr function return "..." for a recursive call'
+    repr_running = set()
+
+    def wrapper(self):
+        key = id(self), get_ident()
+        if key in repr_running:
+            return '...'
+        repr_running.add(key)
+        try:
+            result = user_function(self)
+        finally:
+            repr_running.discard(key)
+        return result
+
+    # Can't use functools.wraps() here because of bootstrap issues
+    wrapper.__module__ = getattr(user_function, '__module__')
+    wrapper.__doc__ = getattr(user_function, '__doc__')
+    wrapper.__name__ = getattr(user_function, '__name__')
+    return wrapper
+
 
 ################################################################################
 ### OrderedDict
@@ -142,6 +168,7 @@
         value = self.pop(key)
         return key, value
 
+    @_recursive_repr
     def __repr__(self):
         'od.__repr__() <==> repr(od)'
         if not self:

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	Tue Sep 14 00:14:36 2010
@@ -926,6 +926,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/release27-maint/Misc/NEWS
==============================================================================
--- python/branches/release27-maint/Misc/NEWS	(original)
+++ python/branches/release27-maint/Misc/NEWS	Tue Sep 14 00:14:36 2010
@@ -43,6 +43,9 @@
 Library
 -------
 
+- Issue #9826: OrderedDict.__repr__ can now handle self-referential
+  values:   d['x'] = d.
+
 - Issue #767645: Set os.path.supports_unicode_filenames to True on Mac OS X
   (macpath module).
 


More information about the Python-checkins mailing list