-
Notifications
You must be signed in to change notification settings - Fork 59
/
cfg.py
65 lines (56 loc) 路 1.97 KB
/
cfg.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
from typing import TypeVar, Type, Callable, Dict, Any
Attrs = Dict[str, Any]
C = TypeVar('C')
# todo not sure about it, could be overthinking...
# but short enough to change later
# TODO document why it's necessary?
def make_config(cls: Type[C], migration: Callable[[Attrs], Attrs]=lambda x: x) -> C:
user_config = cls.__base__
old_props = {
# NOTE: deliberately use gettatr to 'force' class properties here
k: getattr(user_config, k) for k in vars(user_config)
}
new_props = migration(old_props)
from dataclasses import fields
params = {
k: v
for k, v in new_props.items()
if k in {f.name for f in fields(cls)}
}
# todo maybe return type here?
return cls(**params) # type: ignore[call-arg]
F = TypeVar('F')
from contextlib import contextmanager
from typing import Iterator
@contextmanager
def override_config(config: F) -> Iterator[F]:
'''
Temporary override for config's parameters, useful for testing/fake data/etc.
'''
orig_properties = {k: v for k, v in vars(config).items() if not k.startswith('__')}
try:
yield config
finally:
# ugh. __dict__ of type objects isn't writable..
for k, v in orig_properties.items():
setattr(config, k, v)
added = {k for k in set(vars(config).keys()).difference(set(orig_properties.keys())) if not k.startswith('__')}
for k in added:
delattr(config, k)
# helper for tests? not sure if could be useful elsewhere
@contextmanager
def tmp_config():
import my.config as C
with override_config(C):
yield C # todo not sure?
def test_tmp_config() -> None:
class extra:
data_path = '/path/to/data'
with tmp_config() as c:
assert c.google != 'whatever'
assert not hasattr(c, 'extra')
c.extra = extra
c.google = 'whatever'
# todo hmm. not sure what should do about new properties??
assert not hasattr(c, 'extra')
assert c.google != 'whatever'