Source code for swh.model.collections

# Copyright (C) 2020 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information

"""Utility data structures."""

from collections.abc import Mapping
from typing import Dict, Generic, Iterable, Optional, Tuple, TypeVar, Union

KT = TypeVar("KT")
VT = TypeVar("VT")


[docs]class ImmutableDict(Mapping, Generic[KT, VT]): """A frozen dictionary. This class behaves like a dictionary, but internally stores objects in a tuple, so it is both immutable and hashable.""" data: Tuple[Tuple[KT, VT], ...] def __init__( self, data: Union[ Iterable[Tuple[KT, VT]], "ImmutableDict[KT, VT]", Dict[KT, VT] ] = {}, ): if isinstance(data, dict): self.data = tuple(item for item in data.items()) elif isinstance(data, ImmutableDict): self.data = data.data else: self.data = tuple(data) def __repr__(self): return f"ImmutableDict({dict(self.data)!r})" def __getitem__(self, key): for (k, v) in self.data: if k == key: return v raise KeyError(key) def __iter__(self): for (k, v) in self.data: yield k def __len__(self): return len(self.data)
[docs] def items(self): yield from self.data
def __hash__(self): return hash(tuple(sorted(self.data)))
[docs] def copy_pop(self, popped_key) -> Tuple[Optional[VT], "ImmutableDict[KT, VT]"]: """Returns a copy of this ImmutableDict without the given key, as well as the value associated to the key.""" popped_value = None new_items = [] for (key, value) in self.data: if key == popped_key: popped_value = value else: new_items.append((key, value)) return (popped_value, ImmutableDict(new_items))