core: better support for ad-hoc configs
properly reload/unload the relevant modules so hopefully no more weird hacks should be required relevant - https://github.com/karlicoss/promnesia/issues/340 - https://github.com/karlicoss/HPI/issues/46
This commit is contained in:
parent
fb0c1289f0
commit
5ac5636e7f
4 changed files with 104 additions and 8 deletions
|
@ -44,12 +44,53 @@ def override_config(config: F) -> Iterator[F]:
|
|||
delattr(config, k)
|
||||
|
||||
|
||||
# helper for tests? not sure if could be useful elsewhere
|
||||
import importlib
|
||||
import sys
|
||||
from typing import Optional, Set
|
||||
ModuleRegex = str
|
||||
@contextmanager
|
||||
def tmp_config():
|
||||
import my.config as C
|
||||
with override_config(C):
|
||||
yield C # todo not sure?
|
||||
def _reload_modules(modules: ModuleRegex) -> Iterator[None]:
|
||||
def loaded_modules() -> Set[str]:
|
||||
return {name for name in sys.modules if re.fullmatch(modules, name)}
|
||||
|
||||
modules_before = loaded_modules()
|
||||
|
||||
for m in modules_before:
|
||||
importlib.reload(sys.modules[m])
|
||||
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
modules_after = loaded_modules()
|
||||
for m in modules_after:
|
||||
if m in modules_before:
|
||||
# was previously loaded, so need to reload to pick up old config
|
||||
importlib.reload(sys.modules[m])
|
||||
else:
|
||||
# wasn't previously loaded, so need to unload it
|
||||
# otherwise it might fail due to missing config etc
|
||||
sys.modules.pop(m, None)
|
||||
|
||||
|
||||
from contextlib import ExitStack
|
||||
import re
|
||||
@contextmanager
|
||||
def tmp_config(*, modules: Optional[ModuleRegex]=None, config=None):
|
||||
if modules is None:
|
||||
assert config is None
|
||||
if modules is not None:
|
||||
assert config is not None
|
||||
|
||||
import my.config
|
||||
with ExitStack() as module_reload_stack, override_config(my.config) as new_config:
|
||||
if config is not None:
|
||||
overrides = {k: v for k, v in vars(config).items() if not k.startswith('__')}
|
||||
for k, v in overrides.items():
|
||||
setattr(new_config, k, v)
|
||||
|
||||
if modules is not None:
|
||||
module_reload_stack.enter_context(_reload_modules(modules))
|
||||
yield new_config
|
||||
|
||||
|
||||
def test_tmp_config() -> None:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue