HTTP headers, as a case-insensitive multi-dict.
| 137 | |
| 138 | |
| 139 | class Headers(typing.MutableMapping[str, str]): |
| 140 | class="st">""" |
| 141 | HTTP headers, as a case-insensitive multi-dict. |
| 142 | class="st">""" |
| 143 | |
| 144 | def __init__( |
| 145 | self, |
| 146 | headers: HeaderTypes | None = None, |
| 147 | encoding: str | None = None, |
| 148 | ) -> None: |
| 149 | self._list = [] class="cm"># type: typing.List[typing.Tuple[bytes, bytes, bytes]] |
| 150 | |
| 151 | if isinstance(headers, Headers): |
| 152 | self._list = list(headers._list) |
| 153 | elif isinstance(headers, Mapping): |
| 154 | for k, v in headers.items(): |
| 155 | bytes_key = _normalize_header_key(k, encoding) |
| 156 | bytes_value = _normalize_header_value(v, encoding) |
| 157 | self._list.append((bytes_key, bytes_key.lower(), bytes_value)) |
| 158 | elif headers is not None: |
| 159 | for k, v in headers: |
| 160 | bytes_key = _normalize_header_key(k, encoding) |
| 161 | bytes_value = _normalize_header_value(v, encoding) |
| 162 | self._list.append((bytes_key, bytes_key.lower(), bytes_value)) |
| 163 | |
| 164 | self._encoding = encoding |
| 165 | |
| 166 | @property |
| 167 | def encoding(self) -> str: |
| 168 | class="st">""" |
| 169 | Header encoding is mandated as ascii, but we allow fallbacks to utf-8 |
| 170 | or iso-8859-1. |
| 171 | class="st">""" |
| 172 | if self._encoding is None: |
| 173 | for encoding in [class="st">"ascii", class="st">"utf-8"]: |
| 174 | for key, value in self.raw: |
| 175 | try: |
| 176 | key.decode(encoding) |
| 177 | value.decode(encoding) |
| 178 | except UnicodeDecodeError: |
| 179 | break |
| 180 | else: |
| 181 | class="cm"># The else block runs if class="st">'break' did not occur, meaning |
| 182 | class="cm"># all values fitted the encoding. |
| 183 | self._encoding = encoding |
| 184 | break |
| 185 | else: |
| 186 | class="cm"># The ISO-8859-1 encoding covers all 256 code points in a byte, |
| 187 | class="cm"># so will never raise decode errors. |
| 188 | self._encoding = class="st">"iso-8859-1" |
| 189 | return self._encoding |
| 190 | |
| 191 | @encoding.setter |
| 192 | def encoding(self, value: str) -> None: |
| 193 | self._encoding = value |
| 194 | |
| 195 | @property |
| 196 | def raw(self) -> list[tuple[bytes, bytes]]: |
no outgoing calls
no test coverage detected