_pypy_collections.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. from __pypy__ import reversed_dict, move_to_end, objects_in_repr
  2. from _operator import eq as _eq
  3. import _collections_abc
  4. class OrderedDict(dict):
  5. '''Dictionary that remembers insertion order.
  6. In PyPy all dicts are ordered anyway. This is mostly useful as a
  7. placeholder to mean "this dict must be ordered even on CPython".
  8. Known difference: iterating over an OrderedDict which is being
  9. concurrently modified raises RuntimeError in PyPy. In CPython
  10. instead we get some behavior that appears reasonable in some
  11. cases but is nonsensical in other cases. This is officially
  12. forbidden by the CPython docs, so we forbid it explicitly for now.
  13. '''
  14. def __init__(*args, **kwds):
  15. '''Initialize an ordered dictionary. The signature is the same as
  16. regular dictionaries, but keyword arguments are not recommended because
  17. their insertion order is arbitrary.
  18. '''
  19. if not args:
  20. raise TypeError("descriptor '__init__' of 'OrderedDict' object "
  21. "needs an argument")
  22. self, *args = args
  23. if len(args) > 1:
  24. raise TypeError('expected at most 1 arguments, got %d' % len(args))
  25. self.__update(*args, **kwds)
  26. update = __update = _collections_abc.MutableMapping.update
  27. def __reversed__(self):
  28. return reversed_dict(self)
  29. def popitem(self, last=True):
  30. '''od.popitem() -> (k, v), return and remove a (key, value) pair.
  31. Pairs are returned in LIFO order if last is true or FIFO order if false.
  32. '''
  33. if last:
  34. return dict.popitem(self)
  35. else:
  36. it = dict.__iter__(self)
  37. try:
  38. k = next(it)
  39. except StopIteration:
  40. raise KeyError('dictionary is empty')
  41. return (k, self.pop(k))
  42. def move_to_end(self, key, last=True):
  43. '''Move an existing element to the end (or beginning if last==False).
  44. Raises KeyError if the element does not exist.
  45. When last=True, acts like a fast version of self[key]=self.pop(key).
  46. '''
  47. return move_to_end(self, key, last)
  48. def __repr__(self):
  49. 'od.__repr__() <==> repr(od)'
  50. if not self:
  51. return '%s()' % (self.__class__.__name__,)
  52. currently_in_repr = objects_in_repr()
  53. if self in currently_in_repr:
  54. return '...'
  55. currently_in_repr[self] = 1
  56. try:
  57. return '%s(%r)' % (self.__class__.__name__, list(self.items()))
  58. finally:
  59. try:
  60. del currently_in_repr[self]
  61. except:
  62. pass
  63. def __reduce__(self):
  64. 'Return state information for pickling'
  65. inst_dict = vars(self).copy()
  66. return self.__class__, (), inst_dict or None, None, iter(self.items())
  67. def copy(self):
  68. 'od.copy() -> a shallow copy of od'
  69. return self.__class__(self)
  70. def __eq__(self, other):
  71. '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
  72. while comparison to a regular mapping is order-insensitive.
  73. '''
  74. if isinstance(other, OrderedDict):
  75. return dict.__eq__(self, other) and all(map(_eq, self, other))
  76. return dict.__eq__(self, other)
  77. __ne__ = object.__ne__
  78. def keys(self):
  79. "D.keys() -> a set-like object providing a view on D's keys"
  80. return _OrderedDictKeysView(self)
  81. def items(self):
  82. "D.items() -> a set-like object providing a view on D's items"
  83. return _OrderedDictItemsView(self)
  84. def values(self):
  85. "D.values() -> an object providing a view on D's values"
  86. return _OrderedDictValuesView(self)
  87. class _OrderedDictKeysView(_collections_abc.KeysView):
  88. def __reversed__(self):
  89. yield from reversed_dict(self._mapping)
  90. class _OrderedDictItemsView(_collections_abc.ItemsView):
  91. def __reversed__(self):
  92. for key in reversed_dict(self._mapping):
  93. yield (key, self._mapping[key])
  94. class _OrderedDictValuesView(_collections_abc.ValuesView):
  95. def __reversed__(self):
  96. for key in reversed_dict(self._mapping):
  97. yield self._mapping[key]