# Path: tldap/dict.py
# 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
# 
#     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)
# 
#     def get(self, key: str, default: any = None):
#         key = self.fix_key(key)
#         return self._dict.get(key, default)
# 
#     def keys(self) -> KeysView[str]:
#         return self._dict.keys()
# 
#     def items(self) -> ItemsView[str, any]:
#         return self._dict.items()
# 
#     def to_dict(self) -> dict:
#         return self._dict
# 
# 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)
# 
#     def fix_key(self, key: str) -> str:
#         return self._dict.fix_key(key)
# 
#     def __getitem__(self, key: str):
#         return self._dict.__getitem__(key)
# 
#     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)
# 
#     def keys(self) -> KeysView[str]:
#         return self._dict.keys()
# 
#     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
# 
#     def merge(self: ImmutableDictEntity, d: dict) -> ImmutableDictEntity:
#         clone = self.__copy__()
#         for key, value in d.items():
#             clone._set(key, value)
#         return clone
# 
#     def set(self: ImmutableDictEntity, key: str, value: any) -> ImmutableDictEntity:
#         clone = self.__copy__()
#         clone._set(key, value)
#         return clone
# 
#     def to_dict(self) -> dict:
#         return self._dict.to_dict()


import pytest
from tldap.dict import CaseInsensitiveDict, ImmutableDict



@pytest.fixture
def ci():
    """ Get group 1. """
    allowed_values = {'NumberOfPenguins', 'NumberOfSharks'}
    return CaseInsensitiveDict(allowed_values)


@pytest.fixture
def immutable():
    """ Get group 1. """
    allowed_values = {'NumberOfPenguins', 'NumberOfSharks'}
    return ImmutableDict(allowed_values)


class TestCaseInsensitive:
    def test_init_lowercase(self):
        allowed_values = {'NumberOfPenguins', 'NumberOfSharks'}
        ci = CaseInsensitiveDict(allowed_values, {'numberofpenguins': 10})
        assert ci.keys() == {'NumberOfPenguins'}

    def test_init_mixedcase(self, ci):
        allowed_values = {'NumberOfPenguins', 'NumberOfSharks'}
        ci = CaseInsensitiveDict(allowed_values, {'numberOFpenguins': 10})
        assert ci.keys() == {'NumberOfPenguins'}

    def test_init_uppercase(self, ci):
        allowed_values = {'NumberOfPenguins', 'NumberOfSharks'}

# Path: tldap/dict.py
# 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
# 
#     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)
# 
#     def get(self, key: str, default: any = None):
#         key = self.fix_key(key)
#         return self._dict.get(key, default)
# 
#     def keys(self) -> KeysView[str]:
#         return self._dict.keys()
# 
#     def items(self) -> ItemsView[str, any]:
#         return self._dict.items()
# 
#     def to_dict(self) -> dict:
#         return self._dict
# 
# 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)
# 
#     def fix_key(self, key: str) -> str:
#         return self._dict.fix_key(key)
# 
#     def __getitem__(self, key: str):
#         return self._dict.__getitem__(key)
# 
#     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)
# 
#     def keys(self) -> KeysView[str]:
#         return self._dict.keys()
# 
#     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
# 
#     def merge(self: ImmutableDictEntity, d: dict) -> ImmutableDictEntity:
#         clone = self.__copy__()
#         for key, value in d.items():
#             clone._set(key, value)
#         return clone
# 
#     def set(self: ImmutableDictEntity, key: str, value: any) -> ImmutableDictEntity:
#         clone = self.__copy__()
#         clone._set(key, value)
#         return clone
# 
#     def to_dict(self) -> dict:
#         return self._dict.to_dict()


# Path: tests/a_unit/test_dict.py
import pytest
from tldap.dict import CaseInsensitiveDict, ImmutableDict




@pytest.fixture
def ci():
    """ Get group 1. """
    allowed_values = {'NumberOfPenguins', 'NumberOfSharks'}
    return CaseInsensitiveDict(allowed_values)


@pytest.fixture
def immutable():
    """ Get group 1. """
    allowed_values = {'NumberOfPenguins', 'NumberOfSharks'}
    return ImmutableDict(allowed_values)


class TestCaseInsensitive:
    def test_init_lowercase(self):
        allowed_values = {'NumberOfPenguins', 'NumberOfSharks'}
        ci = CaseInsensitiveDict(allowed_values, {'numberofpenguins': 10})
        assert ci.keys() == {'NumberOfPenguins'}

    def test_init_mixedcase(self, ci):
        allowed_values = {'NumberOfPenguins', 'NumberOfSharks'}
        ci = CaseInsensitiveDict(allowed_values, {'numberOFpenguins': 10})
        assert ci.keys() == {'NumberOfPenguins'}

    def test_init_uppercase(self, ci):
        allowed_values = {'NumberOfPenguins', 'NumberOfSharks'}

        ci = CaseInsensitiveDict(allowed_values, {'NUMBEROFPENGUINS': 10})