Commit d9d3d14a authored by Raymond Hettinger's avatar Raymond Hettinger

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

parent 3dd98084
...@@ -43,6 +43,7 @@ class OrderedDict(dict, MutableMapping): ...@@ -43,6 +43,7 @@ class OrderedDict(dict, MutableMapping):
''' '''
if len(args) > 1: if len(args) > 1:
raise TypeError('expected at most 1 arguments, got %d' % len(args)) raise TypeError('expected at most 1 arguments, got %d' % len(args))
self.__in_repr = False # detects recursive repr
try: try:
self.__root self.__root
except AttributeError: except AttributeError:
...@@ -100,10 +101,10 @@ class OrderedDict(dict, MutableMapping): ...@@ -100,10 +101,10 @@ class OrderedDict(dict, MutableMapping):
def __reduce__(self): def __reduce__(self):
'Return state information for pickling' 'Return state information for pickling'
items = [[k, self[k]] for k in self] items = [[k, self[k]] for k in self]
tmp = self.__map, self.__root tmp = self.__map, self.__root, self.__in_repr
del self.__map, self.__root del self.__map, self.__root, self.__in_repr
inst_dict = vars(self).copy() inst_dict = vars(self).copy()
self.__map, self.__root = tmp self.__map, self.__root, self.__in_repr = tmp
if inst_dict: if inst_dict:
return (self.__class__, (items,), inst_dict) return (self.__class__, (items,), inst_dict)
return self.__class__, (items,) return self.__class__, (items,)
...@@ -128,9 +129,16 @@ class OrderedDict(dict, MutableMapping): ...@@ -128,9 +129,16 @@ class OrderedDict(dict, MutableMapping):
def __repr__(self): def __repr__(self):
'od.__repr__() <==> repr(od)' 'od.__repr__() <==> repr(od)'
if self.__in_repr:
return '...'
if not self: if not self:
return '%s()' % (self.__class__.__name__,) 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): def copy(self):
'od.copy() -> a shallow copy of od' 'od.copy() -> a shallow copy of od'
......
...@@ -908,6 +908,13 @@ class TestOrderedDict(unittest.TestCase): ...@@ -908,6 +908,13 @@ class TestOrderedDict(unittest.TestCase):
self.assertEqual(eval(repr(od)), od) self.assertEqual(eval(repr(od)), od)
self.assertEqual(repr(OrderedDict()), "OrderedDict()") 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): def test_setdefault(self):
pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
shuffle(pairs) shuffle(pairs)
......
...@@ -122,6 +122,9 @@ Library ...@@ -122,6 +122,9 @@ Library
to fetch the original errno, or to filter timeout errors. Now the to fetch the original errno, or to filter timeout errors. Now the
original error is re-raised. 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, - 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 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. be updated back after the system call. Original patch by Brian Brazil.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment