]> granicus.if.org Git - python/commitdiff
Issue 9826: OrderedDict.__repr__ did not play well with self-referencing dicts.
authorRaymond Hettinger <python@rcn.com>
Mon, 13 Sep 2010 22:14:36 +0000 (22:14 +0000)
committerRaymond Hettinger <python@rcn.com>
Mon, 13 Sep 2010 22:14:36 +0000 (22:14 +0000)
Lib/collections.py
Lib/test/test_collections.py
Misc/NEWS

index b0c67a1825c10c9088399ef95dae69c8aa4c82aa..9b144317945343bb3627de91cb76fea9fbe92c58 100644 (file)
@@ -12,6 +12,32 @@ import sys as _sys
 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 @@ class OrderedDict(dict, MutableMapping):
         value = self.pop(key)
         return key, value
 
+    @_recursive_repr
     def __repr__(self):
         'od.__repr__() <==> repr(od)'
         if not self:
index 16c4552e1d3089421447401fa0f994db80b20c1b..3f240089509c66114f452b5dfe5832ee2dafbdbd 100644 (file)
@@ -926,6 +926,13 @@ class TestOrderedDict(unittest.TestCase):
         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)
index 0ee1605433ab27c9296a05d7ff50e6d8bca1e130..657e99114894b4a3f7f7ded7ab7a2e385181c01b 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -43,6 +43,9 @@ Core and Builtins
 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).