-
Notifications
You must be signed in to change notification settings - Fork 4
/
frozendict.py
124 lines (100 loc) · 3.68 KB
/
frozendict.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
from typing import Any, Callable, Optional, Union, Tuple, Hashable, Sequence
try:
from collections import Mapping
except ImportError:
# For python > 3.10
from collections.abc import Mapping
from gelidum.exceptions import FrozenException
from gelidum.frozen import FrozenBase
from gelidum.typing import FrozenType, FrozenDict
__all__ = [
"frozendict"
]
class frozendict(dict, FrozenBase): # noqa
def __raise_immutable_exception(self, *args, **kwargs):
raise FrozenException("'frozendict' object is immutable")
def __init__(
self,
seq: Optional[Union[Mapping, Sequence, Tuple[Hashable, Any]]] = None,
freeze_func: Optional[Callable[[Any], FrozenBase]] = None,
**kwargs
):
if freeze_func is None:
def freeze_func(item: Any) -> FrozenType:
from gelidum.freeze import freeze
return freeze(item, on_update="exception", on_freeze="copy")
if seq is not None:
items = None
if isinstance(seq, Mapping):
items = seq.items()
elif isinstance(seq, Sequence):
items = seq
if items is not None:
super().__init__(
{key: freeze_func(value) for key, value in items},
**{key: freeze_func(value) for key, value in kwargs.items()}
)
else:
super().__init__(
{key: freeze_func(value) for key, value in seq}
)
elif kwargs:
super().__init__(
{key: freeze_func(value) for key, value in kwargs.items()}
)
else:
super().__init__()
@classmethod
def _gelidum_on_update(cls, *args, **kwargs):
raise FrozenException("'frozendict' object is immutable")
@classmethod
def get_gelidum_hot_class_name(cls) -> str:
return "dict"
@classmethod
def get_gelidum_hot_class_module(cls) -> str:
return "builtins.dict"
def __hash__(self) -> int:
return hash(tuple((k, v) for k, v in self.items()))
def __getitem__(self, key) -> Any:
if type(key) is slice:
return frozendict(
super().__getitem__(key)
)
try:
return super().__getitem__(key)
except IndexError:
raise IndexError("frozendict index out of range")
def __add__(self, other: FrozenDict) -> FrozenDict:
joined_dict = self | other
return frozendict(joined_dict)
def __or__(self, other: FrozenDict) -> FrozenDict:
if hasattr(super, "__or__"):
return super().__or__(other)
# Python version < 3.9
result_dict = dict()
result_dict.update(self)
result_dict.update(other)
return frozendict(result_dict)
def __sub__(self, other: FrozenDict) -> FrozenDict:
return frozendict({k: v
for k, v in self.items()
if k not in other})
def remove(self, x):
self.__raise_immutable_exception()
def pop(self, items):
self.__raise_immutable_exception()
def popitem(self, *args, **kwarg):
self.__raise_immutable_exception()
def __setitem__(self, key, val, *args, **kwargs):
self.__raise_immutable_exception()
def __delitem__(self, key, *args, **kwargs):
self.__raise_immutable_exception()
def clear(self):
self.__raise_immutable_exception()
def update(self, *args, **kwarg):
self.__raise_immutable_exception()
def copy(self) -> "frozendict":
"""
frozendict objects are only shallow-copied.
"""
return self