mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	Issue #9826: Handle recursive repr in collections.OrderedDict.
This commit is contained in:
		
							parent
							
								
									fa11db0a02
								
							
						
					
					
						commit
						dc08a143e0
					
				
					 3 changed files with 22 additions and 4 deletions
				
			
		| 
						 | 
					@ -41,6 +41,7 @@ def __init__(self, *args, **kwds):
 | 
				
			||||||
        '''
 | 
					        '''
 | 
				
			||||||
        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:
 | 
				
			||||||
| 
						 | 
					@ -95,10 +96,10 @@ def __reversed__(self):
 | 
				
			||||||
    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,)
 | 
				
			||||||
| 
						 | 
					@ -167,9 +168,16 @@ def move_to_end(self, key, last=True):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -951,6 +951,13 @@ def test_repr(self):
 | 
				
			||||||
        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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,9 @@ Core and Builtins
 | 
				
			||||||
Library
 | 
					Library
 | 
				
			||||||
-------
 | 
					-------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Issue #9826: OrderedDict.__repr__ can now handle self-referential
 | 
				
			||||||
 | 
					  values:   d['x'] = d.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Issue #9825: Using __del__ in the definition of collections.OrderedDict made
 | 
					- Issue #9825: Using __del__ in the definition of collections.OrderedDict made
 | 
				
			||||||
  it possible for the user to create self-referencing ordered dictionaries
 | 
					  it possible for the user to create self-referencing ordered dictionaries
 | 
				
			||||||
  which become permanently uncollectable GC garbage. Reinstated the Py3.1
 | 
					  which become permanently uncollectable GC garbage. Reinstated the Py3.1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue