Source code for tldap.dict

# Copyright 2018 Brian May
#
# This file is part of python-tldap.
#
# python-tldap is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# python-tldap is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with python-tldap  If not, see <http://www.gnu.org/licenses/>.
""" Dictionary related classes. """
from typing import Dict, ItemsView, KeysView, Optional, Set, TypeVar


Entity = TypeVar('Entity', bound='CaseInsensitiveDict')


[docs] class CaseInsensitiveDict: """ Case insensitve dictionary for searches however preserves the case for retrieval. Needs to be supplied with a set of allowed keys. """ def __init__(self, allowed_keys: Set[str], d: Optional[dict] = None) -> None: self._lc: Dict[str, str] = { value.lower(): value for value in allowed_keys } self._dict = dict() if d is not None: for k, v in d.items(): self[k] = v
[docs] def fix_key(self, key: str) -> str: key = key.lower() if key not in self._lc: raise KeyError(key) return self._lc[key.lower()]
def __setitem__(self, key: str, value: any): key = self.fix_key(key) self._dict.__setitem__(key, value) def __delitem__(self, key: str): key = self.fix_key(key) del self._lc[key] self._dict.__delitem__(key) def __getitem__(self, key: str): key = self.fix_key(key) return self._dict.__getitem__(key) def __contains__(self, key: str): key = self.fix_key(key) return self._dict.__contains__(key)
[docs] def get(self, key: str, default: any = None): key = self.fix_key(key) return self._dict.get(key, default)
[docs] def keys(self) -> KeysView[str]: return self._dict.keys()
[docs] def items(self) -> ItemsView[str, any]: return self._dict.items()
[docs] def to_dict(self) -> dict: return self._dict
ImmutableDictEntity = TypeVar('ImmutableDictEntity', bound='ImmutableDict')
[docs] class ImmutableDict: """ Immutable dictionary that cannot be changed without creating a new instance. """ def __init__(self, allowed_keys: Optional[Set[str]] = None, d: Optional[dict] = None) -> None: self._allowed_keys = allowed_keys self._dict = CaseInsensitiveDict(allowed_keys) if d is not None: for key, value in d.items(): self._set(key, value)
[docs] def fix_key(self, key: str) -> str: return self._dict.fix_key(key)
def __getitem__(self, key: str): return self._dict.__getitem__(key)
[docs] def get(self, key: str, default: any = None): key = self.fix_key(key) try: return self._dict.get(key, default) except KeyError: return default
def __contains__(self, key: str): return self._dict.__contains__(key)
[docs] def keys(self) -> KeysView[str]: return self._dict.keys()
[docs] def items(self) -> ItemsView[str, any]: return self._dict.items()
def __copy__(self: ImmutableDictEntity) -> ImmutableDictEntity: return self.__class__(self._allowed_keys, self._dict) def _set(self, key: str, value: any) -> None: self._dict[key] = value
[docs] def merge(self: ImmutableDictEntity, d: dict) -> ImmutableDictEntity: clone = self.__copy__() for key, value in d.items(): clone._set(key, value) return clone
[docs] def set(self: ImmutableDictEntity, key: str, value: any) -> ImmutableDictEntity: clone = self.__copy__() clone._set(key, value) return clone
[docs] def to_dict(self) -> dict: return self._dict.to_dict()