A case-insensitive ``dict``-like object. Implements all methods and operations of ``MutableMapping`` as well as dict's ``copy``. Also provides ``lower_items``. All keys are expected to be strings. The structure remembers the case of the last key to be set, and ``iter(instance)`
| 18 | |
| 19 | |
| 20 | class CaseInsensitiveDict(MutableMapping[str, _VT], Generic[_VT]): |
| 21 | """A case-insensitive ``dict``-like object. |
| 22 | |
| 23 | Implements all methods and operations of |
| 24 | ``MutableMapping`` as well as dict's ``copy``. Also |
| 25 | provides ``lower_items``. |
| 26 | |
| 27 | All keys are expected to be strings. The structure remembers the |
| 28 | case of the last key to be set, and ``iter(instance)``, |
| 29 | ``keys()``, ``items()``, ``iterkeys()``, and ``iteritems()`` |
| 30 | will contain case-sensitive keys. However, querying and contains |
| 31 | testing is case insensitive:: |
| 32 | |
| 33 | cid = CaseInsensitiveDict() |
| 34 | cid['Accept'] = 'application/json' |
| 35 | cid['aCCEPT'] == 'application/json' # True |
| 36 | list(cid) == ['Accept'] # True |
| 37 | |
| 38 | For example, ``headers['content-encoding']`` will return the |
| 39 | value of a ``'Content-Encoding'`` response header, regardless |
| 40 | of how the header name was originally stored. |
| 41 | |
| 42 | If the constructor, ``.update``, or equality comparison |
| 43 | operations are given keys that have equal ``.lower()``s, the |
| 44 | behavior is undefined. |
| 45 | """ |
| 46 | |
| 47 | _store: OrderedDict[str, tuple[str, _VT]] |
| 48 | |
| 49 | def __init__( |
| 50 | self, |
| 51 | data: Mapping[str, _VT] | Iterable[tuple[str, _VT]] | None = None, |
| 52 | **kwargs: _VT, |
| 53 | ) -> None: |
| 54 | self._store = OrderedDict() |
| 55 | if data is None: |
| 56 | data = {} |
| 57 | self.update(data, **kwargs) |
| 58 | |
| 59 | def __setitem__(self, key: str, value: _VT) -> None: |
| 60 | # Use the lowercased key for lookups, but store the actual |
| 61 | # key alongside the value. |
| 62 | self._store[key.lower()] = (key, value) |
| 63 | |
| 64 | def __getitem__(self, key: str) -> _VT: |
| 65 | return self._store[key.lower()][1] |
| 66 | |
| 67 | def __delitem__(self, key: str) -> None: |
| 68 | del self._store[key.lower()] |
| 69 | |
| 70 | def __iter__(self) -> Iterator[str]: |
| 71 | return (casedkey for casedkey, _ in self._store.values()) |
| 72 | |
| 73 | def __len__(self) -> int: |
| 74 | return len(self._store) |
| 75 | |
| 76 | def lower_items(self) -> Iterator[tuple[str, _VT]]: |
| 77 | """Like iteritems(), but with all lowercase keys.""" |
no outgoing calls