|
1 | 1 | import weakref
|
2 | 2 | from collections import defaultdict
|
3 |
| -from typing import TYPE_CHECKING, Generic, MutableMapping, TypeVar, cast |
| 3 | +from typing import ( |
| 4 | + TYPE_CHECKING, |
| 5 | + Generic, |
| 6 | + Optional, |
| 7 | + Protocol, |
| 8 | + TypeVar, |
| 9 | + Union, |
| 10 | + cast, |
| 11 | +) |
4 | 12 |
|
5 | 13 | __all__ = (
|
6 | 14 | "KeyFoldDict",
|
|
10 | 18 | )
|
11 | 19 |
|
12 | 20 |
|
13 |
| -K = TypeVar("K", bound=str) |
| 21 | +K_contra = TypeVar("K_contra", bound=str, contravariant=True) |
14 | 22 | V = TypeVar("V")
|
| 23 | +T = TypeVar("T") |
| 24 | + |
15 | 25 |
|
16 | 26 | if TYPE_CHECKING:
|
17 | 27 |
|
18 |
| - class MapBase(MutableMapping[K, V]): |
19 |
| - ... |
| 28 | + class MapBase(Protocol[K_contra, V]): |
| 29 | + def __getitem__(self, item: K_contra) -> V: |
| 30 | + ... |
| 31 | + |
| 32 | + def __delitem__(self, item: K_contra) -> None: |
| 33 | + ... |
| 34 | + |
| 35 | + def __setitem__(self, item: K_contra, value: V) -> None: |
| 36 | + ... |
| 37 | + |
| 38 | + def get(self, item: K_contra, default: V = None) -> Optional[V]: |
| 39 | + ... |
| 40 | + |
| 41 | + def setdefault( |
| 42 | + self, key: K_contra, default: Union[V, T] = None |
| 43 | + ) -> Union[V, T]: |
| 44 | + ... |
| 45 | + |
| 46 | + def pop( |
| 47 | + self, key: K_contra, default: Union[V, T] = None |
| 48 | + ) -> Union[V, T]: |
| 49 | + ... |
20 | 50 |
|
21 | 51 | else:
|
22 | 52 |
|
23 |
| - class MapBase(Generic[K, V]): |
| 53 | + class MapBase(Generic[K_contra, V]): |
24 | 54 | ...
|
25 | 55 |
|
26 | 56 |
|
27 |
| -class KeyFoldMixin(MapBase[K, V]): |
| 57 | +class KeyFoldMixin(MapBase[K_contra, V]): |
28 | 58 | """
|
29 | 59 | A mixin for Mapping to allow for case-insensitive keys
|
30 | 60 | """
|
31 | 61 |
|
32 |
| - def __getitem__(self, item: K) -> V: |
33 |
| - return super().__getitem__(cast(K, item.casefold())) |
| 62 | + def __getitem__(self, item: K_contra) -> V: |
| 63 | + return super().__getitem__(cast(K_contra, item.casefold())) |
34 | 64 |
|
35 |
| - def __setitem__(self, key: K, value: V) -> None: |
36 |
| - return super().__setitem__(cast(K, key.casefold()), value) |
| 65 | + def __setitem__(self, key: K_contra, value: V) -> None: |
| 66 | + return super().__setitem__(cast(K_contra, key.casefold()), value) |
37 | 67 |
|
38 |
| - def __delitem__(self, key: K) -> None: |
39 |
| - return super().__delitem__(cast(K, key.casefold())) |
| 68 | + def __delitem__(self, key: K_contra) -> None: |
| 69 | + return super().__delitem__(cast(K_contra, key.casefold())) |
40 | 70 |
|
41 |
| - def pop(self, key: K, *args) -> V: |
| 71 | + def pop(self, key: K_contra, *args) -> V: |
42 | 72 | """
|
43 | 73 | Wraps `dict.pop`
|
44 | 74 | """
|
45 |
| - return super().pop(cast(K, key.casefold()), *args) |
| 75 | + return super().pop(cast(K_contra, key.casefold()), *args) |
46 | 76 |
|
47 |
| - def get(self, key: K, default=None): |
| 77 | + def get(self, key: K_contra, default=None): |
48 | 78 | """
|
49 | 79 | Wrap `dict.get`
|
50 | 80 | """
|
51 |
| - return super().get(cast(K, key.casefold()), default) |
| 81 | + return super().get(cast(K_contra, key.casefold()), default) |
52 | 82 |
|
53 |
| - def setdefault(self, key: K, default=None): |
| 83 | + def setdefault(self, key: K_contra, default=None): |
54 | 84 | """
|
55 | 85 | Wrap `dict.setdefault`
|
56 | 86 | """
|
57 |
| - return super().setdefault(cast(K, key.casefold()), default) |
| 87 | + return super().setdefault(cast(K_contra, key.casefold()), default) |
58 | 88 |
|
59 | 89 | def update(self, *args, **kwargs):
|
60 | 90 | """
|
|
0 commit comments