def test_argparse_docopt_config(monkeypatch, obj, usage, brief, invocations): from copy import copy for invocation in invocations: print(invocation) test_obj = copy(obj) test_argv = invocation['argv'] test_expected = invocation['expected'] # Clear `sys.argv` so that if the command-line is accessed prematurely, # e.g. in `init()` rather than `load()`, an error is raised. Note that # `sys.argv[0]` needs to be present, because `argparse` checks this # when generating usage text. monkeypatch.setattr(sys, 'argv', ['app']) # These attributes should be available even before `init()` is called. # Note that accessing these attributes may trigger `init()`, e.g. if # the usage text contains default values based on BYOC-managed # attributes. assert test_obj.usage == usage assert test_obj.brief == brief # Make sure that calling `init()` (if it wasn't implicitly called # above) doesn't cause the command line to be read. byoc.init(test_obj) monkeypatch.setattr(sys, 'argv', test_argv) byoc.load(test_obj) for attr, value in test_expected.items(): assert getattr(test_obj, attr) == value
def test_appdirs_config(tmp_chdir, monkeypatch, obj, slug, author, version, files, layers): import appdirs class AppDirs: def __init__(self, slug, author, version): self.slug = slug self.author = author self.version = version self.user_config_dir = 'user' self.site_config_dir = 'site' monkeypatch.setattr(appdirs, 'AppDirs', AppDirs) for name, content in files.items(): path = tmp_chdir / name path.parent.mkdir(parents=True, exist_ok=True) path.write_text(content) assert obj.dirs.slug == slug assert obj.dirs.author == author assert obj.dirs.version == version assert list(obj.config_paths) == unordered([Path(x) for x in files.keys()]) byoc.init(obj) assert collect_layers(obj)[0] == layers
def test_file_config(tmp_chdir, obj, files, layers): for name, content in files.items(): path = tmp_chdir / name path.parent.mkdir(parents=True, exist_ok=True) path.write_text(content) byoc.init(obj) assert collect_layers(obj)[0] == layers
def test_values_iter(obj, param, getters, default, expected, log): with_obj = with_byoc.exec(obj) obj = get_obj(with_obj) param = find_param(obj, param) getters = [with_obj.eval(x) for x in getters] default = with_py.eval(default) if default else UNSPECIFIED byoc.init(obj) bound_getters = [ x.bind(obj, param) for x in getters ] values = byoc.pickers.ValuesIter(bound_getters, default, Log()) assert list(values) == expected assert values.log._err.info_strs == log
def test_init_load_reload(obj, init_layers, load_layers, reload_layers): if not reload_layers: reload_layers = load_layers byoc.init(obj) assert collect_layers(obj) == init_layers try: obj.load() except AttributeError: byoc.load(obj) assert collect_layers(obj) == load_layers try: obj.reload() except AttributeError: byoc.reload(obj) assert collect_layers(obj) == reload_layers
def test_on_load_inheritance(): class DummyConfig(byoc.Config): def load(self): yield byoc.DictLayer(values={}) class P: __config__ = [DummyConfig] def __init__(self): self.calls = set() @byoc.on_load def a(self): self.calls.add('P/a') @byoc.on_load def b(self): self.calls.add('P/b') @byoc.on_load def c(self): self.calls.add('P/c') class F1(P): @byoc.on_load def a(self): self.calls.add('F1/a') @byoc.on_load def b(self): self.calls.add('F1/b') class F2(F1): @byoc.on_load def a(self): self.calls.add('F2/a') p = P() f1 = F1() f2 = F2() byoc.init(p) byoc.init(f1) byoc.init(f2) assert p.calls == { 'P/a', 'P/b', 'P/c'} assert f1.calls == {'F1/a', 'F1/b', 'P/c'} assert f2.calls == {'F2/a', 'F1/b', 'P/c'}