diff --git a/CHANGES/448.feature.rst b/CHANGES/448.feature.rst new file mode 100644 index 000000000..b47c0fabb --- /dev/null +++ b/CHANGES/448.feature.rst @@ -0,0 +1 @@ +Added support for reversing keys, values, and items views via ``reversed()`` -- implements :issue:`448`. diff --git a/multidict/_multidict_py.py b/multidict/_multidict_py.py index ef6c03c7f..dc24cc8fd 100644 --- a/multidict/_multidict_py.py +++ b/multidict/_multidict_py.py @@ -101,6 +101,15 @@ def _iter(self, version: int) -> Iterator[tuple[str, _V]]: raise RuntimeError("Dictionary changed during iteration") yield self._md._key(e.key), e.value + def __reversed__(self) -> Iterator[tuple[str, _V]]: + return _Iter(len(self), self._iter_reversed(self._md._version)) + + def _iter_reversed(self, version: int) -> Iterator[tuple[str, _V]]: + for e in self._md._keys.iter_entries_reverse(): + if version != self._md._version: + raise RuntimeError("Dictionary changed during iteration") + yield self._md._key(e.key), e.value + @reprlib.recursive_repr() def __repr__(self) -> str: lst = [] @@ -272,6 +281,15 @@ def _iter(self, version: int) -> Iterator[_V]: raise RuntimeError("Dictionary changed during iteration") yield e.value + def __reversed__(self) -> Iterator[_V]: + return _Iter(len(self), self._iter_reversed(self._md._version)) + + def _iter_reversed(self, version: int) -> Iterator[_V]: + for e in self._md._keys.iter_entries_reverse(): + if version != self._md._version: + raise RuntimeError("Dictionary changed during iteration") + yield e.value + @reprlib.recursive_repr() def __repr__(self) -> str: lst = [] @@ -301,6 +319,15 @@ def _iter(self, version: int) -> Iterator[str]: raise RuntimeError("Dictionary changed during iteration") yield self._md._key(e.key) + def __reversed__(self) -> Iterator[str]: + return _Iter(len(self), self._iter_reversed(self._md._version)) + + def _iter_reversed(self, version: int) -> Iterator[str]: + for e in self._md._keys.iter_entries_reverse(): + if version != self._md._version: + raise RuntimeError("Dictionary changed during iteration") + yield self._md._key(e.key) + def __repr__(self) -> str: lst = [] for e in self._md._keys.iter_entries(): @@ -595,6 +622,9 @@ def del_idx(self, hash_: int, idx: int) -> None: def iter_entries(self) -> Iterator[_Entry[_V]]: return filter(None, self.entries) + def iter_entries_reverse(self) -> Iterator[_Entry[_V]]: + return filter(None, reversed(self.entries)) + def restore_hash(self, hash_: int) -> None: mask = self.mask indices = self.indices