python-dictattr 0.0.2__tar.gz → 0.0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_dictattr-0.0.2 → python_dictattr-0.0.4}/PKG-INFO +1 -1
- {python_dictattr-0.0.2 → python_dictattr-0.0.4}/dictattr/__init__.py +54 -22
- {python_dictattr-0.0.2 → python_dictattr-0.0.4}/pyproject.toml +1 -1
- {python_dictattr-0.0.2 → python_dictattr-0.0.4}/LICENSE +0 -0
- {python_dictattr-0.0.2 → python_dictattr-0.0.4}/dictattr/py.typed +0 -0
- {python_dictattr-0.0.2 → python_dictattr-0.0.4}/readme.md +0 -0
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
6
|
__author__ = "ChenyangGao <https://chenyanggao.github.io>"
|
|
7
|
-
__version__ = (0, 0,
|
|
7
|
+
__version__ = (0, 0, 4)
|
|
8
8
|
__all__ = [
|
|
9
|
-
"odict", "AttrDict", "MapAttr", "MuMapAttr",
|
|
10
|
-
"
|
|
9
|
+
"odict", "AttrDict", "MapAttr", "MuMapAttr", "DictAttr",
|
|
10
|
+
"ChainDictAttr", "UserDictAttr", "PriorityUserDictAttr",
|
|
11
11
|
]
|
|
12
12
|
|
|
13
13
|
from collections import UserDict
|
|
@@ -25,6 +25,12 @@ class odict(dict[K, V]):
|
|
|
25
25
|
__setattr__ = dict.__setitem__ # type: ignore
|
|
26
26
|
__delattr__ = dict.__delitem__ # type: ignore
|
|
27
27
|
|
|
28
|
+
def __hash__(self, /) -> int: # type: ignore
|
|
29
|
+
return id(self)
|
|
30
|
+
|
|
31
|
+
def __eq__(self, value, /) -> bool:
|
|
32
|
+
return self is value or super().__eq__(value)
|
|
33
|
+
|
|
28
34
|
|
|
29
35
|
class AttrDict(dict[K, V]):
|
|
30
36
|
|
|
@@ -32,14 +38,19 @@ class AttrDict(dict[K, V]):
|
|
|
32
38
|
super().__init__(*args, **kwds)
|
|
33
39
|
self.__dict__ = self # type: ignore
|
|
34
40
|
|
|
41
|
+
def __hash__(self, /) -> int: # type: ignore
|
|
42
|
+
return id(self)
|
|
43
|
+
|
|
44
|
+
def __eq__(self, value, /) -> bool:
|
|
45
|
+
return self is value or super().__eq__(value)
|
|
46
|
+
|
|
35
47
|
|
|
36
48
|
@Mapping.register
|
|
37
49
|
class MapAttr(Generic[K, V]):
|
|
38
50
|
|
|
39
|
-
def __init__(self,
|
|
51
|
+
def __init__(self, /, *args, **kwds):
|
|
40
52
|
self.__dict__: dict[K, V] # type: ignore
|
|
41
|
-
|
|
42
|
-
self.__dict__ = d
|
|
53
|
+
self.__dict__.update(*args, **kwds)
|
|
43
54
|
|
|
44
55
|
def __contains__(self, key, /) -> bool:
|
|
45
56
|
return key in self.__dict__
|
|
@@ -61,8 +72,16 @@ class MapAttr(Generic[K, V]):
|
|
|
61
72
|
return f"{mod}.{cls.__qualname__}({self.__dict__})"
|
|
62
73
|
|
|
63
74
|
@classmethod
|
|
64
|
-
def of(
|
|
65
|
-
|
|
75
|
+
def of(
|
|
76
|
+
cls,
|
|
77
|
+
d: None | dict[K, V] = None,
|
|
78
|
+
/,
|
|
79
|
+
) -> Self:
|
|
80
|
+
if d is None:
|
|
81
|
+
return cls()
|
|
82
|
+
self = __class__.__new__(cls) # type: ignore
|
|
83
|
+
self.__dict__ = d
|
|
84
|
+
return self
|
|
66
85
|
|
|
67
86
|
|
|
68
87
|
@MutableMapping.register
|
|
@@ -105,25 +124,41 @@ class ChainDictAttr(DictAttr[K, V | "ChainDictAttr"]):
|
|
|
105
124
|
return d
|
|
106
125
|
|
|
107
126
|
|
|
108
|
-
class UserDictAttr(UserDict
|
|
127
|
+
class UserDictAttr(UserDict):
|
|
128
|
+
|
|
129
|
+
def __getattr__(self, attr, /):
|
|
130
|
+
try:
|
|
131
|
+
return self[attr]
|
|
132
|
+
except KeyError as e:
|
|
133
|
+
raise AttributeError(attr) from e
|
|
134
|
+
|
|
135
|
+
def __getitem__(self, key, /):
|
|
136
|
+
d = super().__getitem__(key)
|
|
137
|
+
if isinstance(d, Mapping) and not isinstance(d, __class__): # type: ignore
|
|
138
|
+
return type(self)(d)
|
|
139
|
+
return d
|
|
140
|
+
|
|
141
|
+
def __repr__(self, /) -> str:
|
|
142
|
+
cls = type(self)
|
|
143
|
+
name = cls.__qualname__
|
|
144
|
+
if (module := cls.__module__) != "__main__":
|
|
145
|
+
name = f"{module}.{name}"
|
|
146
|
+
return f"{name}.of({self.data!r})"
|
|
109
147
|
|
|
110
148
|
@classmethod
|
|
111
149
|
def of(cls, m: Mapping, /) -> Self:
|
|
112
150
|
self = cls()
|
|
113
|
-
self.__dict__["data"] = m
|
|
151
|
+
self.__dict__["data"] = m
|
|
114
152
|
return self
|
|
115
153
|
|
|
154
|
+
|
|
155
|
+
class PriorityUserDictAttr(UserDictAttr):
|
|
156
|
+
|
|
116
157
|
def __delattr__(self, attr, /):
|
|
117
158
|
try:
|
|
118
159
|
del self[attr]
|
|
119
160
|
except KeyError:
|
|
120
|
-
|
|
121
|
-
super().__delattr__(attr)
|
|
122
|
-
except KeyError:
|
|
123
|
-
raise AttributeError(attr)
|
|
124
|
-
|
|
125
|
-
def __getattr__(self, attr, /):
|
|
126
|
-
return getattr(self.data, attr)
|
|
161
|
+
super().__delattr__(attr)
|
|
127
162
|
|
|
128
163
|
def __getattribute__(self, attr, /):
|
|
129
164
|
if attr in ("__dict__", "data") or attr == f"__{attr.strip('_')}__":
|
|
@@ -133,11 +168,8 @@ class UserDictAttr(UserDict[K, V]):
|
|
|
133
168
|
except KeyError:
|
|
134
169
|
return super().__getattribute__(attr)
|
|
135
170
|
|
|
136
|
-
def
|
|
137
|
-
|
|
138
|
-
if type(d) is dict:
|
|
139
|
-
return type(self)(d)
|
|
140
|
-
return d
|
|
171
|
+
def __getattr__(self, attr, /):
|
|
172
|
+
raise AttributeError(attr)
|
|
141
173
|
|
|
142
174
|
def __setattr__(self, attr, val, /):
|
|
143
175
|
if attr == "data" and "data" not in self.__dict__:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|