Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/requests/structures.py: 64%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2requests.structures
3~~~~~~~~~~~~~~~~~~~
5Data structures that power Requests.
6"""
8from __future__ import annotations
10from collections import OrderedDict
11from collections.abc import Iterable, Iterator, Mapping
12from typing import Any, Generic, TypeVar, overload
14from .compat import MutableMapping
16_VT = TypeVar("_VT")
17_D = TypeVar("_D")
20class CaseInsensitiveDict(MutableMapping[str, _VT], Generic[_VT]):
21 """A case-insensitive ``dict``-like object.
23 Implements all methods and operations of
24 ``MutableMapping`` as well as dict's ``copy``. Also
25 provides ``lower_items``.
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::
33 cid = CaseInsensitiveDict()
34 cid['Accept'] = 'application/json'
35 cid['aCCEPT'] == 'application/json' # True
36 list(cid) == ['Accept'] # True
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.
42 If the constructor, ``.update``, or equality comparison
43 operations are given keys that have equal ``.lower()``s, the
44 behavior is undefined.
45 """
47 _store: OrderedDict[str, tuple[str, _VT]]
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)
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)
64 def __getitem__(self, key: str) -> _VT:
65 return self._store[key.lower()][1]
67 def __delitem__(self, key: str) -> None:
68 del self._store[key.lower()]
70 def __iter__(self) -> Iterator[str]:
71 return (casedkey for casedkey, _ in self._store.values())
73 def __len__(self) -> int:
74 return len(self._store)
76 def lower_items(self) -> Iterator[tuple[str, _VT]]:
77 """Like iteritems(), but with all lowercase keys."""
78 return ((lowerkey, keyval[1]) for (lowerkey, keyval) in self._store.items())
80 def __eq__(self, other: object) -> bool:
81 if isinstance(other, Mapping):
82 other_dict: CaseInsensitiveDict[Any] = CaseInsensitiveDict(other) # type: ignore[reportUnknownArgumentType]
83 else:
84 return NotImplemented
85 # Compare insensitively
86 return dict(self.lower_items()) == dict(other_dict.lower_items())
88 # Copy is required
89 def copy(self) -> CaseInsensitiveDict[_VT]:
90 return CaseInsensitiveDict(self._store.values())
92 def __repr__(self) -> str:
93 return str(dict(self.items()))
96class LookupDict(dict[str, _VT]):
97 """Dictionary lookup object."""
99 name: Any
101 def __init__(self, name: Any = None) -> None:
102 self.name = name
103 super().__init__()
105 def __repr__(self) -> str:
106 return f"<lookup '{self.name}'>"
108 def __getattr__(self, key: str) -> _VT | None:
109 # We need this for type checkers to infer typing
110 # on attribute access with status_codes.py
111 if key in self.__dict__:
112 return self.__dict__[key]
113 else:
114 raise AttributeError(
115 f"'{type(self).__name__}' object has no attribute '{key}'"
116 )
118 def __getitem__(self, key: str) -> _VT | None: # type: ignore[override]
119 # We allow fall-through here, so values default to None
121 return self.__dict__.get(key, None)
123 @overload
124 def get(self, key: str, default: None = None) -> _VT | None: ...
126 @overload
127 def get(self, key: str, default: _D | _VT) -> _D | _VT: ...
129 def get(self, key: str, default: _D | None = None) -> _VT | _D | None:
130 return self.__dict__.get(key, default)