Class that works a bit like a dictionary but can validate keys and has some extra features.
Source code in navis/plotting/settings.py
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 | @dataclass
class Settings:
"""Class that works a bit like a dictionary but can validate keys and has some extra features."""
# We can define synonyms for arguments, so that they can be used interchangeably
_synonyms: List[Tuple] = field(default_factory=list)
_name = "Settings"
def __setattr__(self, key, value, check_valid=False):
if check_valid and key not in self.properties:
raise AttributeError(
f"The '{key}' argument is invalid for {self._name}. Valid arguments are: {', '.join(self.properties)}"
)
self.__dict__[key] = value
def __contains__(self, key):
return key in self.properties
@property
def properties(self):
return tuple(
[
p
for p in dir(self)
if not p.startswith("_")
and (p != "properties") # we need this to avoid infinite recursion
and not callable(getattr(self, p, None))
]
)
def update_settings(self, **kwargs):
# Deal with synonyms
for syn in self._synonyms:
present = [s for s in syn if s in kwargs]
if len(present) > 1:
raise ValueError(f"Multiple synonyms for the same argument: {present}")
for s in syn[1:]:
if s in kwargs:
kwargs[syn[0]] = kwargs.pop(s)
for k, v in kwargs.items():
self.__setattr__(k, v, check_valid=VALIDATE_SETTINGS)
# For method chaining
return self
def to_dict(self):
return {k: v for k, v in self.__dict__.items() if not k.startswith("_")}
def get(self, key, default=None):
value = self.__dict__.get(key, default)
if value is None:
value = default
return value
def pop(self, key, default=None):
return self.__dict__.pop(key, default)
|