|
2 | 2 |
|
3 | 3 | import dataclasses |
4 | 4 | from collections.abc import Mapping |
| 5 | +from types import MappingProxyType |
5 | 6 | from typing import TYPE_CHECKING |
6 | 7 | from urllib.parse import _NetlocResultMixinStr, parse_qsl, urlsplit |
7 | 8 |
|
|
12 | 13 |
|
13 | 14 | @dataclasses.dataclass(frozen=True, init=False) |
14 | 15 | class _FrozenDictStrStr(Mapping[str, str]): |
15 | | - _data: tuple[tuple[str, str], ...] |
| 16 | + _data: MappingProxyType[str, str] |
16 | 17 |
|
17 | 18 | def __init__(self, **kwargs): |
18 | | - object.__setattr__(self, "_data", tuple(sorted(kwargs.items()))) |
| 19 | + object.__setattr__( |
| 20 | + self, "_data", MappingProxyType(dict(sorted(kwargs.items()))) |
| 21 | + ) |
19 | 22 |
|
20 | 23 | def __getitem__(self, key: str) -> str: |
21 | | - return dict(self._data)[key] |
| 24 | + return self._data[key] |
22 | 25 |
|
23 | 26 | def __iter__(self): |
24 | | - return (x[0] for x in self._data) |
| 27 | + return iter(self._data) |
25 | 28 |
|
26 | 29 | def __len__(self): |
27 | 30 | return len(self._data) |
28 | 31 |
|
| 32 | + def __hash__(self) -> int: |
| 33 | + return hash(frozenset(self._data.items())) |
| 34 | + |
| 35 | + def __getstate__(self) -> object: |
| 36 | + return dict(self._data) |
| 37 | + |
| 38 | + def __setstate__(self, state: object) -> None: |
| 39 | + if not isinstance(state, dict): |
| 40 | + msg = "Invalid state for _FrozenDictStrStr" |
| 41 | + raise TypeError(msg) |
| 42 | + object.__setattr__(self, "_data", MappingProxyType(state)) |
| 43 | + |
29 | 44 |
|
30 | 45 | @dataclasses.dataclass(frozen=True) |
31 | 46 | class _HeaderData: |
|
0 commit comments