-
Notifications
You must be signed in to change notification settings - Fork 2
/
mixins.py
86 lines (67 loc) · 1.97 KB
/
mixins.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
from abc import ABC, abstractmethod
def assign_self(func):
"""
Set the received object the value of the key in the mapping container
"""
def wrapper(container, key):
new_object = func(container, key)
container[key] = new_object
return container[key]
return wrapper
__all__ = ["MapMixin"]
class MapMixin(ABC):
@abstractmethod
def _valid_key(self, key):
pass
@abstractmethod
def _attrify(self, key):
pass
@assign_self
def __call__(self, key):
"""
Access value through object call
eg. att(key)
"""
obj = self[key]
return self._attrify(obj)
@assign_self
def __getattr__(self, key):
"""
Accesss value via attribute
"""
if not self._valid_key(key):
raise AttributeError(
"invalid key, '{key}'".format(key=key)
)
if key not in self:
raise AttributeError(
"key does not exist, '{key}'".format(key=key)
)
obj = self[key]
return self._attrify(obj)
def __setattr__(self, key, value):
if not self._valid_key(key):
raise AttributeError(
"invalid key, '{key}'".format(key=key)
)
self[key] = value
def __delattr__(self, key):
del self[key]
def __add__(self, other):
"""
Add a dict, or its child to an attridict object
"""
if not isinstance(other, dict):
raise TypeError(
"'{other}' is not a mapping object".format(other=other)
)
return type(self)({**self, **other})
def __radd__(self, other):
"""
Add an attridict object to a dict, or its child
"""
if not isinstance(other, dict):
raise TypeError(
"'{other}' is not a mapping object".format(other=other)
)
return type(self)({**other, **self})