diff options
author | Brian Harring <ferringb@gmail.com> | 2022-12-25 11:26:31 -0800 |
---|---|---|
committer | Arthur Zamarin <arthurzam@gentoo.org> | 2022-12-25 21:32:26 +0200 |
commit | b17af120f9081aa30d6a368fd75a69c298cb70e0 (patch) | |
tree | 3de8bc1fba4fbd004b9b1703e67b1a9feb5ab6fc /tests/config | |
parent | Fix secondary exception from when an EBD fails to start. (diff) | |
download | pkgcore-b17af120f9081aa30d6a368fd75a69c298cb70e0.tar.gz pkgcore-b17af120f9081aa30d6a368fd75a69c298cb70e0.tar.bz2 pkgcore-b17af120f9081aa30d6a368fd75a69c298cb70e0.zip |
Reformat w/ black-22.12.0
Signed-off-by: Brian Harring <ferringb@gmail.com>
Signed-off-by: Arthur Zamarin <arthurzam@gentoo.org>
Diffstat (limited to 'tests/config')
-rw-r--r-- | tests/config/test_basics.py | 396 | ||||
-rw-r--r-- | tests/config/test_central.py | 1160 | ||||
-rw-r--r-- | tests/config/test_cparser.py | 70 | ||||
-rw-r--r-- | tests/config/test_init.py | 39 |
4 files changed, 1034 insertions, 631 deletions
diff --git a/tests/config/test_basics.py b/tests/config/test_basics.py index 825c1a0c..374fc135 100644 --- a/tests/config/test_basics.py +++ b/tests/config/test_basics.py @@ -9,15 +9,19 @@ def passthrough(*args, **kwargs): def test_invalid_config_types(): - for var in ('class', 'inherit'): - @configurable({var: 'str'}) + for var in ("class", "inherit"): + + @configurable({var: "str"}) def testtype(): pass + with pytest.raises(errors.TypeDefinitionError): basics.ConfigType(testtype) - @configurable(positional=['foo']) + + @configurable(positional=["foo"]) def test(*args): pass + with pytest.raises(errors.TypeDefinitionError): basics.ConfigType(test) @@ -25,9 +29,11 @@ def test_invalid_config_types(): # the docstrings aren't part of the test, but using 'pass' instead # makes trial's --coverage complain about them. + def argsfunc(*args): """Function taking a variable number of arguments.""" + def kwargsfunc(**kwargs): """Function taking keyword arguments.""" @@ -36,14 +42,12 @@ def nonopt(one, two): """Function taking two non-optional args.""" -def alltypes(alist=(), astr='astr', abool=True, aref=object(), anint=3, - along=int(3)): +def alltypes(alist=(), astr="astr", abool=True, aref=object(), anint=3, along=int(3)): """Function taking lots of kinds of args.""" class NewStyleStrClass: - - def __init__(self, one, two='two'): + def __init__(self, one, two="two"): """Newstyle testclass.""" def test_member(self, one): @@ -51,7 +55,6 @@ class NewStyleStrClass: class NewStyleClass: - def __init__(self, one, two=object()): """Newstyle testclass.""" @@ -60,7 +63,6 @@ class NewStyleClass: class OldStyleClass: - def __init__(self, one, two=object()): """Newstyle testclass.""" @@ -69,7 +71,6 @@ class OldStyleClass: class TestConfigTypeFromFunction: - def test_invalid(self): with pytest.raises(TypeError): basics.ConfigType(argsfunc) @@ -78,62 +79,68 @@ class TestConfigTypeFromFunction: def test_basic(self): nonopt_type = basics.ConfigType(nonopt) - assert nonopt_type.name == 'nonopt' - assert nonopt_type.types == {'one': 'str', 'two': 'str'} - assert nonopt_type.required == ('one', 'two') - assert nonopt_type.positional == ('one', 'two') + assert nonopt_type.name == "nonopt" + assert nonopt_type.types == {"one": "str", "two": "str"} + assert nonopt_type.required == ("one", "two") + assert nonopt_type.positional == ("one", "two") def test_default_types(self): test_type = basics.ConfigType(alltypes) assert test_type.types == { - 'alist': 'list', 'astr': 'str', 'abool': 'bool', - 'anint': 'int', 'along': 'int'} + "alist": "list", + "astr": "str", + "abool": "bool", + "anint": "int", + "along": "int", + } assert not test_type.required - @pytest.mark.parametrize('func', ( - pytest.param(NewStyleClass(1).member, id='newstyle_instance'), - pytest.param(OldStyleClass(1).member, id='oldstyle_instance'), - pytest.param(NewStyleClass.member, id='newstyle_class'), - pytest.param(OldStyleClass.member, id='oldstyle_class'), - )) + @pytest.mark.parametrize( + "func", + ( + pytest.param(NewStyleClass(1).member, id="newstyle_instance"), + pytest.param(OldStyleClass(1).member, id="oldstyle_instance"), + pytest.param(NewStyleClass.member, id="newstyle_class"), + pytest.param(OldStyleClass.member, id="oldstyle_class"), + ), + ) def test_class_member(self, func): test_type = basics.ConfigType(func) - assert test_type.name == 'member' - assert test_type.required == ('one',) + assert test_type.name == "member" + assert test_type.required == ("one",) class TestConfigTypeFromClass: - def _test_basics(self, klass, name, two_override=None): test_type = basics.ConfigType(klass) assert test_type.name == name - assert set(test_type.required) == {'one'} - target_types = {'one': 'str'} + assert set(test_type.required) == {"one"} + target_types = {"one": "str"} if two_override is not None: - target_types['two'] = two_override + target_types["two"] = two_override assert target_types == test_type.types assert test_type.name == name def test_oldstyle(self): - self._test_basics(OldStyleClass, 'OldStyleClass') + self._test_basics(OldStyleClass, "OldStyleClass") def test_newstyle(self): - self._test_basics(NewStyleClass, 'NewStyleClass') + self._test_basics(NewStyleClass, "NewStyleClass") def test_defaults_str(self): - self._test_basics(NewStyleStrClass, 'NewStyleStrClass', - two_override='str') + self._test_basics(NewStyleStrClass, "NewStyleStrClass", two_override="str") def test_config_hint(self): class Class(NewStyleClass): - pkgcore_config_type = ConfigHint( - types={'two':'bool'}, doc='interesting') - self._test_basics(Class, 'Class', two_override='bool') - assert 'interesting' == basics.ConfigType(Class).doc + pkgcore_config_type = ConfigHint(types={"two": "bool"}, doc="interesting") + + self._test_basics(Class, "Class", two_override="bool") + assert "interesting" == basics.ConfigType(Class).doc def test_object_init(self): class kls: pass + conf = basics.ConfigType(kls) assert not conf.types assert not conf.required @@ -151,12 +158,16 @@ class TestConfigTypeFromClass: # have to be accurate however class cls(dict): __slots__ = () + with pytest.raises(TypeError): basics.ConfigType(cls) - raw_hint = ConfigHint(types={"filename":"str", "mode":"r", - "buffering":"int"}, typename='file', - required=['filename'], positional=['filename']) + raw_hint = ConfigHint( + types={"filename": "str", "mode": "r", "buffering": "int"}, + typename="file", + required=["filename"], + positional=["filename"], + ) # make sure it still tries to introspect, and throws typeerror. # introspection is generally wanted- if it must be skipped, the @@ -166,41 +177,45 @@ class TestConfigTypeFromClass: basics.ConfigType(cls) cls.pkgcore_config_type = raw_hint.clone(authorative=True) conf = basics.ConfigType(cls) - assert conf.name == 'file' - assert list(conf.required) == ['filename'] - assert list(conf.positional) == ['filename'] - assert set(conf.types) == {'buffering', 'filename', 'mode'} + assert conf.name == "file" + assert list(conf.required) == ["filename"] + assert list(conf.positional) == ["filename"] + assert set(conf.types) == {"buffering", "filename", "mode"} -class TestConfigHint: +class TestConfigHint: def test_configurable_decorator(self): - @configurable(typename='spork', types={'foon': 'str'}) + @configurable(typename="spork", types={"foon": "str"}) def stuff(*args, **kwargs): return args, kwargs - assert 'spork' == stuff.pkgcore_config_type.typename - assert 'str' == basics.ConfigType(stuff).types['foon'] - assert (('spork',), {}) == stuff('spork') - + assert "spork" == stuff.pkgcore_config_type.typename + assert "str" == basics.ConfigType(stuff).types["foon"] + assert (("spork",), {}) == stuff("spork") def test_clone(self): - c = ConfigHint(types={'foo': 'list', 'one': 'str'}, - positional=['one'], required=['one'], - typename='barn', doc='orig doc') - c2 = c.clone(types={'foo': 'list', 'one': 'str', 'two': 'str'}, - required=['one', 'two']) - assert c2.types == {'foo': 'list', 'one': 'str', 'two': 'str'} + c = ConfigHint( + types={"foo": "list", "one": "str"}, + positional=["one"], + required=["one"], + typename="barn", + doc="orig doc", + ) + c2 = c.clone( + types={"foo": "list", "one": "str", "two": "str"}, required=["one", "two"] + ) + assert c2.types == {"foo": "list", "one": "str", "two": "str"} assert c2.positional == c.positional - assert c2.required == ['one', 'two'] + assert c2.required == ["one", "two"] assert c2.typename == c.typename assert c2.allow_unknowns == c.allow_unknowns assert c2.doc == c.doc -class TestConfigSection: +class TestConfigSection: def test_section_ref_collapse(self): # Silly testcase just to make something drop off the --coverage radar. - ref = basics.LazySectionRef(None, 'ref:foon') + ref = basics.LazySectionRef(None, "ref:foon") pytest.raises(NotImplementedError, ref._collapse) pytest.raises(NotImplementedError, ref.collapse) pytest.raises(NotImplementedError, ref.instantiate) @@ -209,108 +224,123 @@ class TestConfigSection: section = basics.ConfigSection() pytest.raises(NotImplementedError, section.__contains__, 42) pytest.raises(NotImplementedError, section.keys) - pytest.raises(NotImplementedError, section.render_value, None, 'a', 'str') + pytest.raises(NotImplementedError, section.render_value, None, "a", "str") class TestDictConfigSection: - def test_misc(self): def convert(central, value, arg_type): return central, value, arg_type - section = basics.DictConfigSection(convert, {'list': [1, 2]}) - assert 'foo' not in section - assert 'list' in section - assert ['list'] == list(section.keys()) - assert (None, [1, 2], 'spoon') == section.render_value(None, 'list', 'spoon') + + section = basics.DictConfigSection(convert, {"list": [1, 2]}) + assert "foo" not in section + assert "list" in section + assert ["list"] == list(section.keys()) + assert (None, [1, 2], "spoon") == section.render_value(None, "list", "spoon") def test_failure(self): def fail(central, value, arg_type): - raise errors.ConfigurationError('fail') - section = basics.DictConfigSection(fail, {'list': [1, 2]}) + raise errors.ConfigurationError("fail") + + section = basics.DictConfigSection(fail, {"list": [1, 2]}) with pytest.raises(errors.ConfigurationError): - section.render_value(None, 'list', 'spoon') + section.render_value(None, "list", "spoon") class TestFakeIncrementalDictConfigSection: - @staticmethod def _convert(central, value, arg_type): return central, value, arg_type @staticmethod def _fail(central, value, arg_type): - raise errors.ConfigurationError('fail') + raise errors.ConfigurationError("fail") def test_misc(self): section = basics.FakeIncrementalDictConfigSection( - self._convert, {'list': [1, 2]}) - assert 'foo' not in section - assert 'list' in section - assert ['list'] == list(section.keys()) + self._convert, {"list": [1, 2]} + ) + assert "foo" not in section + assert "list" in section + assert ["list"] == list(section.keys()) with pytest.raises(errors.ConfigurationError): - obj = basics.FakeIncrementalDictConfigSection(self._fail, {'a': 'b'}) - obj.render_value(None, 'a', 'str') + obj = basics.FakeIncrementalDictConfigSection(self._fail, {"a": "b"}) + obj.render_value(None, "a", "str") def test_fake_incrementals(self): section = basics.FakeIncrementalDictConfigSection( - self._convert, {'seq.append': [1, 2]}) + self._convert, {"seq.append": [1, 2]} + ) manager = object() - assert [None, None, (manager, [1, 2], 'list')] == section.render_value(manager, 'seq', 'list') + assert [None, None, (manager, [1, 2], "list")] == section.render_value( + manager, "seq", "list" + ) + def _repr(central, value, arg_type): - return 'list', ['thing'] - section = basics.FakeIncrementalDictConfigSection( - _repr, {'foo': None}) - assert ('list', (None, ['thing'], None)) == section.render_value(manager, 'foo', 'repr') + return "list", ["thing"] + + section = basics.FakeIncrementalDictConfigSection(_repr, {"foo": None}) + assert ("list", (None, ["thing"], None)) == section.render_value( + manager, "foo", "repr" + ) with pytest.raises(errors.ConfigurationError): - obj = basics.FakeIncrementalDictConfigSection(self._fail, {'a.prepend': 'b'}) - obj.render_value(None, 'a', 'list') + obj = basics.FakeIncrementalDictConfigSection( + self._fail, {"a.prepend": "b"} + ) + obj.render_value(None, "a", "list") def test_repr(self): def asis(central, value, arg_type): - assert arg_type == 'repr', arg_type + assert arg_type == "repr", arg_type return value + source_dict = { - 'seq.append': ('list', [1, 2]), - 'simple': ('bool', True), - 'multistr': ('str', 'body'), - 'multistr.prepend': ('str', 'head'), - 'refs': ('str', 'lost'), - 'refs.append': ('ref', 'main'), - 'refs.prepend': ('refs', ['a', 'b']), - 'strlist': ('callable', asis), - 'strlist.prepend': ('str', 'whatever'), - 'wrong.prepend': ('wrong', 'wrong'), + "seq.append": ("list", [1, 2]), + "simple": ("bool", True), + "multistr": ("str", "body"), + "multistr.prepend": ("str", "head"), + "refs": ("str", "lost"), + "refs.append": ("ref", "main"), + "refs.prepend": ("refs", ["a", "b"]), + "strlist": ("callable", asis), + "strlist.prepend": ("str", "whatever"), + "wrong.prepend": ("wrong", "wrong"), } section = basics.FakeIncrementalDictConfigSection(asis, source_dict) manager = object() with pytest.raises(KeyError): - section.render_value(manager, 'spoon', 'repr') - assert ('list', [None, None, [1, 2]]) == section.render_value(manager, 'seq', 'repr') - assert ('bool', True) == section.render_value(manager, 'simple', 'repr') - assert ('str', ['head', 'body', None]) == section.render_value(manager, 'multistr', 'repr') - assert ('refs', [['a', 'b'], ['lost'], ['main']]) == section.render_value(manager, 'refs', 'repr') - assert ('list', [ - ['whatever'], - ['tests.config.test_basics.asis'], - None]) == section.render_value(manager, 'strlist', 'repr') + section.render_value(manager, "spoon", "repr") + assert ("list", [None, None, [1, 2]]) == section.render_value( + manager, "seq", "repr" + ) + assert ("bool", True) == section.render_value(manager, "simple", "repr") + assert ("str", ["head", "body", None]) == section.render_value( + manager, "multistr", "repr" + ) + assert ("refs", [["a", "b"], ["lost"], ["main"]]) == section.render_value( + manager, "refs", "repr" + ) + assert ( + "list", + [["whatever"], ["tests.config.test_basics.asis"], None], + ) == section.render_value(manager, "strlist", "repr") with pytest.raises(errors.ConfigurationError): - section.render_value(manager, 'wrong', 'repr') + section.render_value(manager, "wrong", "repr") class TestConvertString: - def test_render_value(self): source = { - 'str': 'tests', - 'bool': 'yes', - 'list': '0 1 2', - 'callable': 'tests.config.test_basics.passthrough', + "str": "tests", + "bool": "yes", + "list": "0 1 2", + "callable": "tests.config.test_basics.passthrough", } destination = { - 'str': 'tests', - 'bool': True, - 'list': ['0', '1', '2'], - 'callable': passthrough, + "str": "tests", + "bool": True, + "list": ["0", "1", "2"], + "callable": passthrough, } # valid gets @@ -319,49 +349,59 @@ class TestConvertString: # reprs for typename, value in source.items(): - assert ('str', value) == basics.convert_string(None, source[typename], 'repr') + assert ("str", value) == basics.convert_string( + None, source[typename], "repr" + ) # invalid gets # not callable with pytest.raises(errors.ConfigurationError): - basics.convert_string(None, source['str'], 'callable') + basics.convert_string(None, source["str"], "callable") # not importable with pytest.raises(errors.ConfigurationError): - basics.convert_string(None, source['bool'], 'callable') + basics.convert_string(None, source["bool"], "callable") # Bogus type. with pytest.raises(errors.ConfigurationError): - basics.convert_string(None, source['bool'], 'frob') + basics.convert_string(None, source["bool"], "frob") def test_section_ref(self): def spoon(): """Noop.""" - target_config = central.CollapsedConfig( - basics.ConfigType(spoon), {}, None) + + target_config = central.CollapsedConfig(basics.ConfigType(spoon), {}, None) + class TestCentral: def collapse_named_section(self, section): try: - return {'target': target_config}[section] + return {"target": target_config}[section] except KeyError: raise errors.ConfigurationError(section) - assert basics.convert_string(TestCentral(), 'target', 'ref:spoon').collapse() == target_config + + assert ( + basics.convert_string(TestCentral(), "target", "ref:spoon").collapse() + == target_config + ) with pytest.raises(errors.ConfigurationError): - basics.convert_string(TestCentral(), 'missing', 'ref:spoon').instantiate() + basics.convert_string(TestCentral(), "missing", "ref:spoon").instantiate() def test_section_refs(self): def spoon(): """Noop.""" - config1 = central.CollapsedConfig( - basics.ConfigType(spoon), {}, None) - config2 = central.CollapsedConfig( - basics.ConfigType(spoon), {}, None) + + config1 = central.CollapsedConfig(basics.ConfigType(spoon), {}, None) + config2 = central.CollapsedConfig(basics.ConfigType(spoon), {}, None) + class TestCentral: def collapse_named_section(self, section): try: - return {'1': config1, '2': config2}[section] + return {"1": config1, "2": config2}[section] except KeyError: raise errors.ConfigurationError(section) - assert [config1, config2] == list(ref.collapse() for ref in basics.convert_string( - TestCentral(), '1 2', 'refs:spoon')) - lazy_refs = basics.convert_string(TestCentral(), '2 3', 'refs:spoon') + + assert [config1, config2] == list( + ref.collapse() + for ref in basics.convert_string(TestCentral(), "1 2", "refs:spoon") + ) + lazy_refs = basics.convert_string(TestCentral(), "2 3", "refs:spoon") assert len(lazy_refs) == 2 with pytest.raises(errors.ConfigurationError): lazy_refs[1].collapse() @@ -370,10 +410,10 @@ class TestConvertString: class TestConvertAsIs: source = { - 'str': 'tests', - 'bool': True, - 'list': ['0', '1', '2'], - 'callable': passthrough, + "str": "tests", + "bool": True, + "list": ["0", "1", "2"], + "callable": passthrough, } def test_render_value(self): @@ -388,91 +428,89 @@ class TestConvertAsIs: def test_repr(self): for typename, value in self.source.items(): - assert (typename, value) == basics.convert_asis(None, value, 'repr') + assert (typename, value) == basics.convert_asis(None, value, "repr") with pytest.raises(errors.ConfigurationError): - basics.convert_asis(None, object(), 'repr') + basics.convert_asis(None, object(), "repr") def test_section_ref(self): ref = basics.HardCodedConfigSection({}) with pytest.raises(errors.ConfigurationError): - basics.convert_asis(None, 42, 'ref:spoon') - assert ref is basics.convert_asis(None, ref, 'ref:spoon').section - assert ('ref', ref) == basics.convert_asis(None, ref, 'repr') + basics.convert_asis(None, 42, "ref:spoon") + assert ref is basics.convert_asis(None, ref, "ref:spoon").section + assert ("ref", ref) == basics.convert_asis(None, ref, "repr") def test_section_refs(self): ref = basics.HardCodedConfigSection({}) with pytest.raises(errors.ConfigurationError): - basics.convert_asis(None, [1, 2], 'refs:spoon') - assert ref is basics.convert_asis(None, [ref], 'refs:spoon')[0].section - assert ('refs', [ref]) == basics.convert_asis(None, [ref], 'repr') + basics.convert_asis(None, [1, 2], "refs:spoon") + assert ref is basics.convert_asis(None, [ref], "refs:spoon")[0].section + assert ("refs", [ref]) == basics.convert_asis(None, [ref], "repr") def test_alias(): def spoon(): """Noop.""" + foon = central.CollapsedConfig(basics.ConfigType(spoon), {}, None) + class MockManager: def collapse_named_section(self, name): - if name == 'foon': + if name == "foon": return foon return object() + manager = MockManager() - alias = basics.section_alias('foon', 'spoon') - type_obj = basics.ConfigType(alias.render_value(manager, 'class', - 'callable')) - assert 'spoon' == type_obj.name - assert foon is alias.render_value(manager, 'target', 'ref:spoon').collapse() + alias = basics.section_alias("foon", "spoon") + type_obj = basics.ConfigType(alias.render_value(manager, "class", "callable")) + assert "spoon" == type_obj.name + assert foon is alias.render_value(manager, "target", "ref:spoon").collapse() class TestParsers: - def test_str_to_bool(self): # abuse assert is to make sure we get actual booleans, not some # weird object that happens to be True or False when converted # to a bool for string, output in [ - ('True', True), - ('yes', True), - ('1', True), - ('False', False), - ('no', False), - ('0', False), - ]: + ("True", True), + ("yes", True), + ("1", True), + ("False", False), + ("no", False), + ("0", False), + ]: assert basics.str_to_bool(string) is output def test_str_to_int(self): - for string, output in [ - ('\t 1', 1), - ('1', 1), - ('-100', -100)]: + for string, output in [("\t 1", 1), ("1", 1), ("-100", -100)]: assert basics.str_to_int(string) == output with pytest.raises(errors.ConfigurationError): - basics.str_to_int('f') + basics.str_to_int("f") def test_str_to_str(self): for string, output in [ - ('\t ', ''), - (' foo ', 'foo'), - (' " foo " ', ' foo '), + ("\t ", ""), + (" foo ", "foo"), + (' " foo " ', " foo "), ('\t"', '"'), - ('\nfoo\t\n bar\t', 'foo bar'), - ('"a"', 'a'), + ("\nfoo\t\n bar\t", "foo bar"), + ('"a"', "a"), ("'a'", "a"), ("'a", "'a"), ('"a', '"a'), - ]: + ]: assert basics.str_to_str(string) == output def test_str_to_list(self): for string, output in [ - ('foo', ['foo']), - ('"f\'oo" \'b"ar\'', ["f'oo", 'b"ar']), - ('', []), - (' ', []), + ("foo", ["foo"]), + ("\"f'oo\" 'b\"ar'", ["f'oo", 'b"ar']), + ("", []), + (" ", []), ('\\"hi ', ['"hi']), - ('\'"hi\'', ['"hi']), + ("'\"hi'", ['"hi']), ('"\\"hi"', ['"hi']), - ]: + ]: assert basics.str_to_list(string) == output for string in ['"', "'foo", 'ba"r', 'baz"']: with pytest.raises(errors.QuoteInterpretationError): @@ -480,13 +518,15 @@ class TestParsers: # make sure this explodes instead of returning something # confusing so we explode much later with pytest.raises(TypeError): - basics.str_to_list(['no', 'string']) + basics.str_to_list(["no", "string"]) def test_parse_config_file(tmp_path): - (fp := tmp_path / 'file').write_text('foon') + (fp := tmp_path / "file").write_text("foon") with pytest.raises(errors.ConfigurationError): - basics.parse_config_file('/spork', None) + basics.parse_config_file("/spork", None) + def parser(f): return f.read() - assert 'foon' == basics.parse_config_file(fp, parser) + + assert "foon" == basics.parse_config_file(fp, parser) diff --git a/tests/config/test_central.py b/tests/config/test_central.py index 692cea04..f3fc1c70 100644 --- a/tests/config/test_central.py +++ b/tests/config/test_central.py @@ -8,10 +8,13 @@ from snakeoil.errors import walk_exception_chain # A bunch of functions used from various tests below. def repo(cache): return cache -@configurable({'content': 'ref:drawer', 'contents': 'refs:drawer'}) + + +@configurable({"content": "ref:drawer", "contents": "refs:drawer"}) def drawer(content=None, contents=None): return content, contents + # The exception checks here also check if the str value of the # exception is what we expect. This does not mean the wording of the # error messages used here is strictly required. It just makes sure @@ -22,12 +25,13 @@ def drawer(content=None, contents=None): # This makes sure the types are not unnecessarily queried (since # querying object() will blow up). + class RemoteSource: """Use this one for tests that do need the names but nothing more.""" def __iter__(self): - return iter(('remote',)) + return iter(("remote",)) def __getitem__(self, key): raise NotImplementedError() @@ -36,496 +40,748 @@ class RemoteSource: def _str_exc(exc): return ":\n".join(str(x) for x in walk_exception_chain(exc)) + def check_error(message, func, *args, **kwargs): """Like assertRaises but checks for the message string too.""" - klass = kwargs.pop('klass', errors.ConfigurationError) + klass = kwargs.pop("klass", errors.ConfigurationError) try: func(*args, **kwargs) except klass as exc: - assert message == _str_exc(exc), \ - f'\nGot:\n{_str_exc(exc)!r}\nExpected:\n{message!r}\n' + assert message == _str_exc( + exc + ), f"\nGot:\n{_str_exc(exc)!r}\nExpected:\n{message!r}\n" else: - pytest.fail('no exception raised') + pytest.fail("no exception raised") + def get_config_obj(manager, obj_type, obj_name): types = getattr(manager.objects, obj_type) return types[obj_name] + def test_sections(): - manager = central.ConfigManager([{ - 'fooinst': basics.HardCodedConfigSection({'class': repo}), - 'barinst': basics.HardCodedConfigSection({'class': drawer}), - }]) - assert ['barinst', 'fooinst'] == sorted(manager.sections()) - assert list(manager.objects.drawer.keys()) == ['barinst'] - assert manager.objects.drawer == {'barinst': (None, None)} + manager = central.ConfigManager( + [ + { + "fooinst": basics.HardCodedConfigSection({"class": repo}), + "barinst": basics.HardCodedConfigSection({"class": drawer}), + } + ] + ) + assert ["barinst", "fooinst"] == sorted(manager.sections()) + assert list(manager.objects.drawer.keys()) == ["barinst"] + assert manager.objects.drawer == {"barinst": (None, None)} + def test_contains(): manager = central.ConfigManager( - [{'spork': basics.HardCodedConfigSection({'class': drawer})}], - [RemoteSource()]) - assert 'spork' in manager.objects.drawer - assert 'foon' not in manager.objects.drawer + [{"spork": basics.HardCodedConfigSection({"class": drawer})}], [RemoteSource()] + ) + assert "spork" in manager.objects.drawer + assert "foon" not in manager.objects.drawer + def test_no_class(): - manager = central.ConfigManager( - [{'foo': basics.HardCodedConfigSection({})}]) + manager = central.ConfigManager([{"foo": basics.HardCodedConfigSection({})}]) check_error( - "Collapsing section named 'foo':\n" - 'no class specified', - manager.collapse_named_section, 'foo') + "Collapsing section named 'foo':\n" "no class specified", + manager.collapse_named_section, + "foo", + ) + def test_missing_section_ref(): - manager = central.ConfigManager([{ - 'rsync repo': basics.HardCodedConfigSection({'class': repo}), - }]) + manager = central.ConfigManager( + [ + { + "rsync repo": basics.HardCodedConfigSection({"class": repo}), + } + ] + ) check_error( "Collapsing section named 'rsync repo':\n" "type tests.config.test_central.repo needs settings for " "'cache'", - get_config_obj, manager, 'repo', 'rsync repo') + get_config_obj, + manager, + "repo", + "rsync repo", + ) + def test_unknown_type(): manager = central.ConfigManager( - [{'spork': basics.HardCodedConfigSection({'class': drawer, - 'foon': None})}]) + [{"spork": basics.HardCodedConfigSection({"class": drawer, "foon": None})}] + ) check_error( - "Collapsing section named 'spork':\n" - "Type of 'foon' unknown", - manager.collapse_named_section, 'spork') + "Collapsing section named 'spork':\n" "Type of 'foon' unknown", + manager.collapse_named_section, + "spork", + ) + def test_missing_inherit_target(): - manager = central.ConfigManager([{ - 'myrepo': basics.HardCodedConfigSection({ - 'class': repo, - 'inherit': ['baserepo'], - }), - }], [RemoteSource()]) + manager = central.ConfigManager( + [ + { + "myrepo": basics.HardCodedConfigSection( + { + "class": repo, + "inherit": ["baserepo"], + } + ), + } + ], + [RemoteSource()], + ) check_error( "Collapsing section named 'myrepo':\n" "Inherit target 'baserepo' cannot be found", - get_config_obj, manager, 'repo', 'myrepo') + get_config_obj, + manager, + "repo", + "myrepo", + ) + def test_inherit_unknown_type(): - manager = central.ConfigManager([{ - 'baserepo': basics.HardCodedConfigSection({ - 'cache': 'available', - }), - 'actual repo': basics.HardCodedConfigSection({ - 'class': drawer, - 'inherit': ['baserepo'], - }), - }]) + manager = central.ConfigManager( + [ + { + "baserepo": basics.HardCodedConfigSection( + { + "cache": "available", + } + ), + "actual repo": basics.HardCodedConfigSection( + { + "class": drawer, + "inherit": ["baserepo"], + } + ), + } + ] + ) check_error( - "Collapsing section named 'actual repo':\n" - "Type of 'cache' unknown", - get_config_obj, manager, 'repo', 'actual repo') + "Collapsing section named 'actual repo':\n" "Type of 'cache' unknown", + get_config_obj, + manager, + "repo", + "actual repo", + ) + def test_inherit(): - manager = central.ConfigManager([{ - 'baserepo': basics.HardCodedConfigSection({ - 'cache': 'available', - 'inherit': ['unneeded'], - }), - 'unneeded': basics.HardCodedConfigSection({ - 'cache': 'unavailable'}), - 'actual repo': basics.HardCodedConfigSection({ - 'class': repo, - 'inherit': ['baserepo'], - }), - }]) - - assert 'available' == manager.objects.repo['actual repo'] + manager = central.ConfigManager( + [ + { + "baserepo": basics.HardCodedConfigSection( + { + "cache": "available", + "inherit": ["unneeded"], + } + ), + "unneeded": basics.HardCodedConfigSection({"cache": "unavailable"}), + "actual repo": basics.HardCodedConfigSection( + { + "class": repo, + "inherit": ["baserepo"], + } + ), + } + ] + ) + + assert "available" == manager.objects.repo["actual repo"] + def test_no_object_returned(): def noop(): """Do not do anything.""" - manager = central.ConfigManager([{ - 'myrepo': basics.HardCodedConfigSection({'class': noop}), - }]) + + manager = central.ConfigManager( + [ + { + "myrepo": basics.HardCodedConfigSection({"class": noop}), + } + ] + ) check_error( "Failed instantiating section 'myrepo':\n" "'No object returned' instantiating " "tests.config.test_central.noop", - manager.collapse_named_section('myrepo').instantiate) + manager.collapse_named_section("myrepo").instantiate, + ) + def test_not_callable(): class myrepo: def __repr__(self): - return 'useless' - manager = central.ConfigManager([{ - 'myrepo': basics.HardCodedConfigSection({'class': myrepo()}), - }]) + return "useless" + + manager = central.ConfigManager( + [ + { + "myrepo": basics.HardCodedConfigSection({"class": myrepo()}), + } + ] + ) check_error( "Collapsing section named 'myrepo':\n" "Failed converting argument 'class' to callable:\n" "useless is not callable", - get_config_obj, manager, 'myrepo', 'myrepo') + get_config_obj, + manager, + "myrepo", + "myrepo", + ) + def test_raises_instantiationerror(): def myrepo(): - raise Exception('I raised') - manager = central.ConfigManager([{ - 'myrepo': basics.HardCodedConfigSection({'class': myrepo}), - }]) + raise Exception("I raised") + + manager = central.ConfigManager( + [ + { + "myrepo": basics.HardCodedConfigSection({"class": myrepo}), + } + ] + ) check_error( "Failed instantiating section 'myrepo':\n" "Failed instantiating section 'myrepo': exception caught from 'tests.config.test_central.myrepo':\n" "I raised", - get_config_obj, manager, 'myrepo', 'myrepo') + get_config_obj, + manager, + "myrepo", + "myrepo", + ) + def test_raises(): def myrepo(): - raise ValueError('I raised') - manager = central.ConfigManager([{ - 'myrepo': basics.HardCodedConfigSection({'class': myrepo}) - }]) + raise ValueError("I raised") + + manager = central.ConfigManager( + [{"myrepo": basics.HardCodedConfigSection({"class": myrepo})}] + ) check_error( "Failed instantiating section 'myrepo':\n" "Failed instantiating section 'myrepo': exception caught from 'tests.config.test_central.myrepo':\n" "I raised", - get_config_obj, manager, 'myrepo', 'myrepo') - manager = central.ConfigManager([{ - 'myrepo': basics.HardCodedConfigSection({'class': myrepo}) - }], debug=True) + get_config_obj, + manager, + "myrepo", + "myrepo", + ) + manager = central.ConfigManager( + [{"myrepo": basics.HardCodedConfigSection({"class": myrepo})}], debug=True + ) check_error( "Failed instantiating section 'myrepo':\n" "Failed instantiating section 'myrepo': exception caught from 'tests.config.test_central.myrepo':\n" "I raised", - get_config_obj, manager, 'myrepo', 'myrepo', - klass=errors.ConfigurationError) + get_config_obj, + manager, + "myrepo", + "myrepo", + klass=errors.ConfigurationError, + ) + def test_pargs(): - @configurable(types={'p': 'str', 'notp': 'str'}, - positional=['p'], required=['p']) + @configurable(types={"p": "str", "notp": "str"}, positional=["p"], required=["p"]) def myrepo(*args, **kwargs): return args, kwargs - manager = central.ConfigManager([{ - 'myrepo': basics.HardCodedConfigSection({ - 'class': myrepo, - 'p': 'pos', - 'notp': 'notpos', - }), - }]) - assert manager.objects.myrepo['myrepo'] == (('pos',), {'notp': 'notpos'}) + manager = central.ConfigManager( + [ + { + "myrepo": basics.HardCodedConfigSection( + { + "class": myrepo, + "p": "pos", + "notp": "notpos", + } + ), + } + ] + ) + + assert manager.objects.myrepo["myrepo"] == (("pos",), {"notp": "notpos"}) + def test_autoexec(): - @configurable(typename='configsection') + @configurable(typename="configsection") def autoloader(): - return {'spork': basics.HardCodedConfigSection({'class': repo, - 'cache': 'test'})} + return { + "spork": basics.HardCodedConfigSection({"class": repo, "cache": "test"}) + } + + manager = central.ConfigManager( + [ + { + "autoload-sub": basics.HardCodedConfigSection( + { + "class": autoloader, + } + ) + } + ] + ) + assert {"autoload-sub", "spork"} == set(manager.sections()) + assert ["spork"] == list(manager.objects.repo.keys()) + assert "test" == manager.collapse_named_section("spork").instantiate() - manager = central.ConfigManager([{ - 'autoload-sub': basics.HardCodedConfigSection({ - 'class': autoloader, - })}]) - assert {'autoload-sub', 'spork'} == set(manager.sections()) - assert ['spork'] == list(manager.objects.repo.keys()) - assert 'test' == manager.collapse_named_section('spork').instantiate() def test_reload(): - mod_dict = {'class': repo, 'cache': 'test'} + mod_dict = {"class": repo, "cache": "test"} - @configurable(typename='configsection') + @configurable(typename="configsection") def autoloader(): - return {'spork': basics.HardCodedConfigSection(mod_dict)} - - manager = central.ConfigManager([{ - 'autoload-sub': basics.HardCodedConfigSection({ - 'class': autoloader})}]) - - assert {'autoload-sub', 'spork'} == set(manager.sections()) - assert ['spork'] == list(manager.objects.repo.keys()) - collapsedspork = manager.collapse_named_section('spork') - assert 'test' == collapsedspork.instantiate() - mod_dict['cache'] = 'modded' - assert collapsedspork is manager.collapse_named_section('spork') - assert 'test' == collapsedspork.instantiate() + return {"spork": basics.HardCodedConfigSection(mod_dict)} + + manager = central.ConfigManager( + [{"autoload-sub": basics.HardCodedConfigSection({"class": autoloader})}] + ) + + assert {"autoload-sub", "spork"} == set(manager.sections()) + assert ["spork"] == list(manager.objects.repo.keys()) + collapsedspork = manager.collapse_named_section("spork") + assert "test" == collapsedspork.instantiate() + mod_dict["cache"] = "modded" + assert collapsedspork is manager.collapse_named_section("spork") + assert "test" == collapsedspork.instantiate() types = manager.types manager.reload() - newspork = manager.collapse_named_section('spork') + newspork = manager.collapse_named_section("spork") assert collapsedspork is not newspork - assert 'modded' == newspork.instantiate(), \ - 'it did not throw away the cached instance' + assert ( + "modded" == newspork.instantiate() + ), "it did not throw away the cached instance" assert types is not manager.types + def test_instantiate_default_ref(): - manager = central.ConfigManager([{ - 'spork': basics.HardCodedConfigSection({'class': drawer}), - }]) - assert (None, None) == manager.collapse_named_section('spork').instantiate() + manager = central.ConfigManager( + [ + { + "spork": basics.HardCodedConfigSection({"class": drawer}), + } + ] + ) + assert (None, None) == manager.collapse_named_section("spork").instantiate() + def test_allow_unknowns(): @configurable(allow_unknowns=True) def myrepo(**kwargs): return kwargs - manager = central.ConfigManager([{ - 'spork': basics.HardCodedConfigSection({ - 'class': myrepo, 'spork': 'foon'})}]) + manager = central.ConfigManager( + [{"spork": basics.HardCodedConfigSection({"class": myrepo, "spork": "foon"})}] + ) + + assert {"spork": "foon"} == manager.collapse_named_section("spork").instantiate() - assert {'spork': 'foon'} == manager.collapse_named_section('spork').instantiate() def test_reinstantiate_after_raise(): # The most likely bug this tests for is attempting to # reprocess already processed section_ref args. spork = object() - @configurable({'thing': 'ref:spork'}) + + @configurable({"thing": "ref:spork"}) def myrepo(thing): assert thing is spork - raise errors.ComplexInstantiationError('I suck') - @configurable(typename='spork') + raise errors.ComplexInstantiationError("I suck") + + @configurable(typename="spork") def spork_producer(): return spork - manager = central.ConfigManager([{ - 'spork': basics.HardCodedConfigSection({ - 'class': myrepo, - 'thing': basics.HardCodedConfigSection({ - 'class': spork_producer, - }), - })}]) - spork = manager.collapse_named_section('spork') + + manager = central.ConfigManager( + [ + { + "spork": basics.HardCodedConfigSection( + { + "class": myrepo, + "thing": basics.HardCodedConfigSection( + { + "class": spork_producer, + } + ), + } + ) + } + ] + ) + spork = manager.collapse_named_section("spork") for i in range(3): check_error( "Failed instantiating section 'spork':\n" "Failed instantiating section 'spork': exception caught from 'tests.config.test_central.myrepo':\n" "'I suck', callable unset!", - spork.instantiate) + spork.instantiate, + ) for i in range(3): check_error( "Failed instantiating section 'spork':\n" "Failed instantiating section 'spork': exception caught from 'tests.config.test_central.myrepo':\n" "'I suck', callable unset!", - manager.collapse_named_section('spork').instantiate) + manager.collapse_named_section("spork").instantiate, + ) + def test_instantiation_caching(): - @configurable(typename='drawer') + @configurable(typename="drawer") def myrepo(): return object() - manager = central.ConfigManager([{ - 'spork': basics.HardCodedConfigSection({'class': myrepo}), - 'drawer': basics.ConfigSectionFromStringDict({ - 'class': 'tests.config.test_central.drawer', - 'content': 'spork', - }), - }]) - - config = manager.collapse_named_section('spork') + manager = central.ConfigManager( + [ + { + "spork": basics.HardCodedConfigSection({"class": myrepo}), + "drawer": basics.ConfigSectionFromStringDict( + { + "class": "tests.config.test_central.drawer", + "content": "spork", + } + ), + } + ] + ) + + config = manager.collapse_named_section("spork") assert config.instantiate() is config.instantiate() - assert config.instantiate() is manager.collapse_named_section('drawer').instantiate()[0] + assert ( + config.instantiate() + is manager.collapse_named_section("drawer").instantiate()[0] + ) + def test_collapse_named_errors(): - manager = central.ConfigManager([{ - 'spork': basics.ConfigSectionFromStringDict({ - 'class': 'tests.config.test_central.drawer', - 'content': 'ref'}) - }], [RemoteSource()]) + manager = central.ConfigManager( + [ + { + "spork": basics.ConfigSectionFromStringDict( + {"class": "tests.config.test_central.drawer", "content": "ref"} + ) + } + ], + [RemoteSource()], + ) with pytest.raises(KeyError): - get_config_obj(manager, 'repo', 'foon') + get_config_obj(manager, "repo", "foon") check_error( "Collapsing section named 'spork':\n" "Failed collapsing section key 'content':\n" "no section called 'ref'", - get_config_obj, manager, 'repo', 'spork') + get_config_obj, + manager, + "repo", + "spork", + ) + def test_recursive_autoload(): - @configurable(typename='configsection') + @configurable(typename="configsection") def autoloader(): - return {'autoload-sub': basics.HardCodedConfigSection( - {'class': autoloader}), - 'spork': basics.HardCodedConfigSection({'class': repo, - 'cache': 'test'})} + return { + "autoload-sub": basics.HardCodedConfigSection({"class": autoloader}), + "spork": basics.HardCodedConfigSection({"class": repo, "cache": "test"}), + } check_error( "New config is trying to modify existing section(s) 'autoload-sub' " "that was already instantiated.", central.ConfigManager, - [{'autoload-sub': basics.HardCodedConfigSection({ - 'class': autoloader, - })}]) + [ + { + "autoload-sub": basics.HardCodedConfigSection( + { + "class": autoloader, + } + ) + } + ], + ) + def test_recursive_section_ref(): - manager = central.ConfigManager([{ - 'spork': basics.ConfigSectionFromStringDict({ - 'class': 'tests.config.test_central.drawer', - 'content': 'foon'}), - 'foon': basics.ConfigSectionFromStringDict({ - 'class': 'tests.config.test_central.drawer', - 'content': 'spork'}), - 'self': basics.ConfigSectionFromStringDict({ - 'class': 'tests.config.test_central.drawer', - 'content': 'self'}), - }]) + manager = central.ConfigManager( + [ + { + "spork": basics.ConfigSectionFromStringDict( + {"class": "tests.config.test_central.drawer", "content": "foon"} + ), + "foon": basics.ConfigSectionFromStringDict( + {"class": "tests.config.test_central.drawer", "content": "spork"} + ), + "self": basics.ConfigSectionFromStringDict( + {"class": "tests.config.test_central.drawer", "content": "self"} + ), + } + ] + ) check_error( "Collapsing section named 'self':\n" "Failed collapsing section key 'content':\n" "Reference to 'self' is recursive", - get_config_obj, manager, 'drawer', 'self') + get_config_obj, + manager, + "drawer", + "self", + ) check_error( "Collapsing section named 'spork':\n" "Failed collapsing section key 'content':\n" "Collapsing section named 'foon':\n" "Failed collapsing section key 'content':\n" "Reference to 'spork' is recursive", - get_config_obj, manager, 'drawer', 'spork') + get_config_obj, + manager, + "drawer", + "spork", + ) + def test_recursive_inherit(): - manager = central.ConfigManager([{ - 'spork': basics.ConfigSectionFromStringDict({ - 'class': 'tests.config.test_central.drawer', - 'inherit': 'foon'}), - 'foon': basics.ConfigSectionFromStringDict({ - 'class': 'tests.config.test_central.drawer', - 'inherit': 'spork'}), - }]) + manager = central.ConfigManager( + [ + { + "spork": basics.ConfigSectionFromStringDict( + {"class": "tests.config.test_central.drawer", "inherit": "foon"} + ), + "foon": basics.ConfigSectionFromStringDict( + {"class": "tests.config.test_central.drawer", "inherit": "spork"} + ), + } + ] + ) check_error( - "Collapsing section named 'spork':\n" - "Inherit 'spork' is recursive", - get_config_obj, manager, 'drawer', 'spork') + "Collapsing section named 'spork':\n" "Inherit 'spork' is recursive", + get_config_obj, + manager, + "drawer", + "spork", + ) + def test_alias(): def myspork(): return object - manager = central.ConfigManager([{ - 'spork': basics.HardCodedConfigSection({'class': myspork}), - 'foon': basics.section_alias('spork', 'myspork'), - }]) + + manager = central.ConfigManager( + [ + { + "spork": basics.HardCodedConfigSection({"class": myspork}), + "foon": basics.section_alias("spork", "myspork"), + } + ] + ) # This tests both the detected typename of foon and the caching. - assert manager.objects.myspork['spork'] is manager.objects.myspork['foon'] + assert manager.objects.myspork["spork"] is manager.objects.myspork["foon"] + def test_typecheck(): - @configurable({'myrepo': 'ref:repo'}, typename='repo') + @configurable({"myrepo": "ref:repo"}, typename="repo") def reporef(myrepo=None): return myrepo - @configurable({'myrepo': 'refs:repo'}, typename='repo') + + @configurable({"myrepo": "refs:repo"}, typename="repo") def reporefs(myrepo=None): return myrepo - @configurable(typename='repo') + + @configurable(typename="repo") def myrepo(): - return 'repo!' - manager = central.ConfigManager([{ - 'myrepo': basics.HardCodedConfigSection({'class': myrepo}), - 'drawer': basics.HardCodedConfigSection({'class': drawer}), - 'right': basics.AutoConfigSection({'class': reporef, - 'myrepo': 'myrepo'}), - 'wrong': basics.AutoConfigSection({'class': reporef, - 'myrepo': 'drawer'}), - }]) + return "repo!" + + manager = central.ConfigManager( + [ + { + "myrepo": basics.HardCodedConfigSection({"class": myrepo}), + "drawer": basics.HardCodedConfigSection({"class": drawer}), + "right": basics.AutoConfigSection( + {"class": reporef, "myrepo": "myrepo"} + ), + "wrong": basics.AutoConfigSection( + {"class": reporef, "myrepo": "drawer"} + ), + } + ] + ) check_error( "Collapsing section named 'wrong':\n" "Failed collapsing section key 'myrepo':\n" "reference 'drawer' should be of type 'repo', got 'drawer'", - get_config_obj, manager, 'repo', 'wrong') - assert 'repo!' == manager.objects.repo['right'] - - manager = central.ConfigManager([{ - 'myrepo': basics.HardCodedConfigSection({'class': myrepo}), - 'drawer': basics.HardCodedConfigSection({'class': drawer}), - 'right': basics.AutoConfigSection({'class': reporefs, - 'myrepo': 'myrepo'}), - 'wrong': basics.AutoConfigSection({'class': reporefs, - 'myrepo': 'drawer'}), - }]) + get_config_obj, + manager, + "repo", + "wrong", + ) + assert "repo!" == manager.objects.repo["right"] + + manager = central.ConfigManager( + [ + { + "myrepo": basics.HardCodedConfigSection({"class": myrepo}), + "drawer": basics.HardCodedConfigSection({"class": drawer}), + "right": basics.AutoConfigSection( + {"class": reporefs, "myrepo": "myrepo"} + ), + "wrong": basics.AutoConfigSection( + {"class": reporefs, "myrepo": "drawer"} + ), + } + ] + ) check_error( "Collapsing section named 'wrong':\n" "Failed collapsing section key 'myrepo':\n" "reference 'drawer' should be of type 'repo', got 'drawer'", - get_config_obj, manager, 'repo', 'wrong') - assert ['repo!'] == manager.objects.repo['right'] + get_config_obj, + manager, + "repo", + "wrong", + ) + assert ["repo!"] == manager.objects.repo["right"] + def test_default(): - manager = central.ConfigManager([{ - 'thing': basics.HardCodedConfigSection({'class': drawer, - 'default': True}), - 'bug': basics.HardCodedConfigSection({'class': None, - 'inherit-only':True, - 'default': True}), - 'ignore': basics.HardCodedConfigSection({'class': drawer}), - }]) - assert (None, None) == manager.get_default('drawer') - assert manager.collapse_named_section('thing').default - - manager = central.ConfigManager([{ - 'thing': basics.HardCodedConfigSection({'class': drawer, - 'default': True}), - 'thing2': basics.HardCodedConfigSection({'class': drawer, - 'default': True}), - }]) + manager = central.ConfigManager( + [ + { + "thing": basics.HardCodedConfigSection( + {"class": drawer, "default": True} + ), + "bug": basics.HardCodedConfigSection( + {"class": None, "inherit-only": True, "default": True} + ), + "ignore": basics.HardCodedConfigSection({"class": drawer}), + } + ] + ) + assert (None, None) == manager.get_default("drawer") + assert manager.collapse_named_section("thing").default + + manager = central.ConfigManager( + [ + { + "thing": basics.HardCodedConfigSection( + {"class": drawer, "default": True} + ), + "thing2": basics.HardCodedConfigSection( + {"class": drawer, "default": True} + ), + } + ] + ) check_error( "type drawer incorrectly has multiple default sections: 'thing', 'thing2'", - manager.get_default, 'drawer') + manager.get_default, + "drawer", + ) manager = central.ConfigManager([]) - assert manager.get_default('drawer') is None + assert manager.get_default("drawer") is None + def test_broken_default(): def broken(): - raise errors.ComplexInstantiationError('broken') - manager = central.ConfigManager([{ - 'thing': basics.HardCodedConfigSection({ - 'class': drawer, 'default': True, - 'content': basics.HardCodedConfigSection({ - 'class': 'spork'})}), - 'thing2': basics.HardCodedConfigSection({ - 'class': broken, 'default': True})}]) + raise errors.ComplexInstantiationError("broken") + + manager = central.ConfigManager( + [ + { + "thing": basics.HardCodedConfigSection( + { + "class": drawer, + "default": True, + "content": basics.HardCodedConfigSection({"class": "spork"}), + } + ), + "thing2": basics.HardCodedConfigSection( + {"class": broken, "default": True} + ), + } + ] + ) check_error( "Collapsing defaults for 'drawer':\n" "Collapsing section named 'thing':\n" "Failed collapsing section key 'content':\n" "Failed converting argument 'class' to callable:\n" "'spork' is not callable", - manager.get_default, 'drawer') + manager.get_default, + "drawer", + ) check_error( "Collapsing defaults for 'broken':\n" "Collapsing section named 'thing':\n" "Failed collapsing section key 'content':\n" "Failed converting argument 'class' to callable:\n" "'spork' is not callable", - manager.get_default, 'broken') + manager.get_default, + "broken", + ) + def test_instantiate_broken_ref(): - @configurable(typename='drawer') + @configurable(typename="drawer") def broken(): - raise errors.ComplexInstantiationError('broken') - manager = central.ConfigManager([{ - 'one': basics.HardCodedConfigSection({ - 'class': drawer, - 'content': basics.HardCodedConfigSection({ - 'class': broken})}), - 'multi': basics.HardCodedConfigSection({ - 'class': drawer, - 'contents': [basics.HardCodedConfigSection({ - 'class': broken})]}), - }]) + raise errors.ComplexInstantiationError("broken") + + manager = central.ConfigManager( + [ + { + "one": basics.HardCodedConfigSection( + { + "class": drawer, + "content": basics.HardCodedConfigSection({"class": broken}), + } + ), + "multi": basics.HardCodedConfigSection( + { + "class": drawer, + "contents": [basics.HardCodedConfigSection({"class": broken})], + } + ), + } + ] + ) check_error( "Failed instantiating section 'one':\n" "Instantiating reference 'content' pointing at None:\n" "Failed instantiating section None:\n" "Failed instantiating section None: exception caught from 'tests.config.test_central.broken':\n" "'broken', callable unset!", - manager.collapse_named_section('one').instantiate) + manager.collapse_named_section("one").instantiate, + ) check_error( "Failed instantiating section 'multi':\n" "Instantiating reference 'contents' pointing at None:\n" "Failed instantiating section None:\n" "Failed instantiating section None: exception caught from 'tests.config.test_central.broken':\n" "'broken', callable unset!", - manager.collapse_named_section('multi').instantiate) + manager.collapse_named_section("multi").instantiate, + ) + def test_autoload_instantiationerror(): - @configurable(typename='configsection') + @configurable(typename="configsection") def broken(): - raise errors.ComplexInstantiationError('broken') + raise errors.ComplexInstantiationError("broken") + check_error( "Failed loading autoload section 'autoload_broken':\n" "Failed instantiating section 'autoload_broken':\n" "Failed instantiating section 'autoload_broken': exception caught from 'tests.config.test_central.broken':\n" "'broken', callable unset!", - central.ConfigManager, [{ - 'autoload_broken': basics.HardCodedConfigSection({ - 'class': broken})}]) + central.ConfigManager, + [{"autoload_broken": basics.HardCodedConfigSection({"class": broken})}], + ) + def test_autoload_uncollapsable(): check_error( @@ -533,172 +789,266 @@ def test_autoload_uncollapsable(): "Collapsing section named 'autoload_broken':\n" "Failed converting argument 'class' to callable:\n" "'spork' is not callable", - central.ConfigManager, [{ - 'autoload_broken': basics.HardCodedConfigSection({ - 'class': 'spork'})}]) + central.ConfigManager, + [{"autoload_broken": basics.HardCodedConfigSection({"class": "spork"})}], + ) + def test_autoload_wrong_type(): check_error( "Section 'autoload_wrong' is marked as autoload but type is " - 'drawer, not configsection', - central.ConfigManager, [{ - 'autoload_wrong': basics.HardCodedConfigSection({ - 'class': drawer})}]) + "drawer, not configsection", + central.ConfigManager, + [{"autoload_wrong": basics.HardCodedConfigSection({"class": drawer})}], + ) + def test_lazy_refs(): - @configurable({'myrepo': 'lazy_ref:repo', 'thing': 'lazy_ref'}, - typename='repo') + @configurable({"myrepo": "lazy_ref:repo", "thing": "lazy_ref"}, typename="repo") def reporef(myrepo=None, thing=None): return myrepo, thing - @configurable({'myrepo': 'lazy_refs:repo', 'thing': 'lazy_refs'}, - typename='repo') + + @configurable({"myrepo": "lazy_refs:repo", "thing": "lazy_refs"}, typename="repo") def reporefs(myrepo=None, thing=None): return myrepo, thing - @configurable(typename='repo') + + @configurable(typename="repo") def myrepo(): - return 'repo!' - manager = central.ConfigManager([{ - 'myrepo': basics.HardCodedConfigSection({'class': myrepo}), - 'drawer': basics.HardCodedConfigSection({'class': drawer}), - 'right': basics.AutoConfigSection({'class': reporef, - 'myrepo': 'myrepo'}), - 'wrong': basics.AutoConfigSection({'class': reporef, - 'myrepo': 'drawer'}), - }]) + return "repo!" + + manager = central.ConfigManager( + [ + { + "myrepo": basics.HardCodedConfigSection({"class": myrepo}), + "drawer": basics.HardCodedConfigSection({"class": drawer}), + "right": basics.AutoConfigSection( + {"class": reporef, "myrepo": "myrepo"} + ), + "wrong": basics.AutoConfigSection( + {"class": reporef, "myrepo": "drawer"} + ), + } + ] + ) check_error( "reference 'drawer' should be of type 'repo', got 'drawer'", - manager.objects.repo['wrong'][0].collapse) - assert 'repo!' == manager.objects.repo['right'][0].instantiate() - - manager = central.ConfigManager([{ - 'myrepo': basics.HardCodedConfigSection({'class': myrepo}), - 'drawer': basics.HardCodedConfigSection({'class': drawer}), - 'right': basics.AutoConfigSection({'class': reporefs, - 'myrepo': 'myrepo'}), - 'wrong': basics.AutoConfigSection({'class': reporefs, - 'myrepo': 'drawer'}), - }]) + manager.objects.repo["wrong"][0].collapse, + ) + assert "repo!" == manager.objects.repo["right"][0].instantiate() + + manager = central.ConfigManager( + [ + { + "myrepo": basics.HardCodedConfigSection({"class": myrepo}), + "drawer": basics.HardCodedConfigSection({"class": drawer}), + "right": basics.AutoConfigSection( + {"class": reporefs, "myrepo": "myrepo"} + ), + "wrong": basics.AutoConfigSection( + {"class": reporefs, "myrepo": "drawer"} + ), + } + ] + ) check_error( "reference 'drawer' should be of type 'repo', got 'drawer'", - manager.objects.repo['wrong'][0][0].collapse) - assert ['repo!'] == [c.instantiate() for c in manager.objects.repo['right'][0]] + manager.objects.repo["wrong"][0][0].collapse, + ) + assert ["repo!"] == [c.instantiate() for c in manager.objects.repo["right"][0]] + def test_inherited_default(): - manager = central.ConfigManager([{ - 'default': basics.HardCodedConfigSection({ - 'default': True, - 'inherit': ['basic'], - }), - 'uncollapsable': basics.HardCodedConfigSection({ - 'default': True, - 'inherit': ['spork'], - 'inherit-only': True, - }), - 'basic': basics.HardCodedConfigSection({'class': drawer}), - }], [RemoteSource()]) - assert manager.get_default('drawer') + manager = central.ConfigManager( + [ + { + "default": basics.HardCodedConfigSection( + { + "default": True, + "inherit": ["basic"], + } + ), + "uncollapsable": basics.HardCodedConfigSection( + { + "default": True, + "inherit": ["spork"], + "inherit-only": True, + } + ), + "basic": basics.HardCodedConfigSection({"class": drawer}), + } + ], + [RemoteSource()], + ) + assert manager.get_default("drawer") + def test_section_names(): - manager = central.ConfigManager([{ - 'thing': basics.HardCodedConfigSection({'class': drawer}), - }], [RemoteSource()]) - collapsed = manager.collapse_named_section('thing') - assert 'thing' == collapsed.name + manager = central.ConfigManager( + [ + { + "thing": basics.HardCodedConfigSection({"class": drawer}), + } + ], + [RemoteSource()], + ) + collapsed = manager.collapse_named_section("thing") + assert "thing" == collapsed.name + def test_inherit_only(): - manager = central.ConfigManager([{ - 'source': basics.HardCodedConfigSection({ - 'class': drawer, - 'inherit-only': True, - }), - 'target': basics.HardCodedConfigSection({ - 'inherit': ['source'], - }) - }], [RemoteSource()]) + manager = central.ConfigManager( + [ + { + "source": basics.HardCodedConfigSection( + { + "class": drawer, + "inherit-only": True, + } + ), + "target": basics.HardCodedConfigSection( + { + "inherit": ["source"], + } + ), + } + ], + [RemoteSource()], + ) check_error( - "Collapsing section named 'source':\n" - 'cannot collapse inherit-only section', - manager.collapse_named_section, 'source') - assert manager.collapse_named_section('target') + "Collapsing section named 'source':\n" "cannot collapse inherit-only section", + manager.collapse_named_section, + "source", + ) + assert manager.collapse_named_section("target") + def test_self_inherit(): - section = basics.HardCodedConfigSection({'inherit': ['self']}) - manager = central.ConfigManager([{ - 'self': basics.ConfigSectionFromStringDict({ - 'class': 'tests.config.test_central.drawer', - 'inherit': 'self'}), - }], [RemoteSource()]) + section = basics.HardCodedConfigSection({"inherit": ["self"]}) + manager = central.ConfigManager( + [ + { + "self": basics.ConfigSectionFromStringDict( + {"class": "tests.config.test_central.drawer", "inherit": "self"} + ), + } + ], + [RemoteSource()], + ) check_error( - "Collapsing section named 'self':\n" - "Self-inherit 'self' cannot be found", - get_config_obj, manager, 'drawer', 'self') + "Collapsing section named 'self':\n" "Self-inherit 'self' cannot be found", + get_config_obj, + manager, + "drawer", + "self", + ) check_error( - "Self-inherit 'self' cannot be found", - manager.collapse_section, [section]) - - manager = central.ConfigManager([{ - 'self': basics.HardCodedConfigSection({ - 'inherit': ['self'], - })}, { - 'self': basics.HardCodedConfigSection({ - 'inherit': ['self'], - })}, { - 'self': basics.HardCodedConfigSection({ - 'class': drawer})}]) - assert manager.collapse_named_section('self') + "Self-inherit 'self' cannot be found", manager.collapse_section, [section] + ) + + manager = central.ConfigManager( + [ + { + "self": basics.HardCodedConfigSection( + { + "inherit": ["self"], + } + ) + }, + { + "self": basics.HardCodedConfigSection( + { + "inherit": ["self"], + } + ) + }, + {"self": basics.HardCodedConfigSection({"class": drawer})}, + ] + ) + assert manager.collapse_named_section("self") assert manager.collapse_section([section]) + def test_prepend_inherit(): - manager = central.ConfigManager([{ - 'sect': basics.HardCodedConfigSection({ - 'inherit.prepend': ['self']})}]) + manager = central.ConfigManager( + [{"sect": basics.HardCodedConfigSection({"inherit.prepend": ["self"]})}] + ) check_error( "Collapsing section named 'sect':\n" - 'Prepending or appending to the inherit list makes no sense', - manager.collapse_named_section, 'sect') + "Prepending or appending to the inherit list makes no sense", + manager.collapse_named_section, + "sect", + ) + def test_list_prepend(): - @configurable({'seq': 'list'}) + @configurable({"seq": "list"}) def seq(seq): return seq - manager = central.ConfigManager([{ - 'inh': basics.HardCodedConfigSection({ - 'inherit': ['sect'], - 'seq.prepend': ['pre'], - }), - 'sect': basics.HardCodedConfigSection({ - 'inherit': ['base'], - 'seq': ['1', '2'], - })}, { - 'base': basics.HardCodedConfigSection({ - 'class': seq, - 'seq.prepend': ['-1'], - 'seq.append': ['post'], - })}]) - assert ['-1', 'post'] == manager.objects.seq['base'] - assert ['1', '2'] == manager.objects.seq['sect'] - assert ['pre', '1', '2'] == manager.objects.seq['inh'] + + manager = central.ConfigManager( + [ + { + "inh": basics.HardCodedConfigSection( + { + "inherit": ["sect"], + "seq.prepend": ["pre"], + } + ), + "sect": basics.HardCodedConfigSection( + { + "inherit": ["base"], + "seq": ["1", "2"], + } + ), + }, + { + "base": basics.HardCodedConfigSection( + { + "class": seq, + "seq.prepend": ["-1"], + "seq.append": ["post"], + } + ) + }, + ] + ) + assert ["-1", "post"] == manager.objects.seq["base"] + assert ["1", "2"] == manager.objects.seq["sect"] + assert ["pre", "1", "2"] == manager.objects.seq["inh"] + def test_str_prepend(): - @configurable({'string': 'str'}) + @configurable({"string": "str"}) def sect(string): return string - manager = central.ConfigManager([{ - 'inh': basics.HardCodedConfigSection({ - 'inherit': ['sect'], - 'string.prepend': 'pre', - }), - 'sect': basics.HardCodedConfigSection({ - 'inherit': ['base'], - 'string': 'b', - }) - }, { - 'base': basics.HardCodedConfigSection({ - 'class': sect, - 'string.prepend': 'a', - 'string.append': 'c', - }) - }]) - assert 'a c' == manager.objects.sect['base'] - assert 'b' == manager.objects.sect['sect'] - assert 'pre b' == manager.objects.sect['inh'] + + manager = central.ConfigManager( + [ + { + "inh": basics.HardCodedConfigSection( + { + "inherit": ["sect"], + "string.prepend": "pre", + } + ), + "sect": basics.HardCodedConfigSection( + { + "inherit": ["base"], + "string": "b", + } + ), + }, + { + "base": basics.HardCodedConfigSection( + { + "class": sect, + "string.prepend": "a", + "string.append": "c", + } + ) + }, + ] + ) + assert "a c" == manager.objects.sect["base"] + assert "b" == manager.objects.sect["sect"] + assert "pre b" == manager.objects.sect["inh"] diff --git a/tests/config/test_cparser.py b/tests/config/test_cparser.py index 64809732..e7d0b0ea 100644 --- a/tests/config/test_cparser.py +++ b/tests/config/test_cparser.py @@ -7,23 +7,29 @@ from pkgcore.config import central, cparser, errors def test_case_sensitive_config_parser(): cp = cparser.CaseSensitiveConfigParser() - config = StringIO('\n'.join(( - '[header]', - 'foo=bar', - 'FOO=BAR', - '[HEADER]', - 'foo=notbar', - ))) + config = StringIO( + "\n".join( + ( + "[header]", + "foo=bar", + "FOO=BAR", + "[HEADER]", + "foo=notbar", + ) + ) + ) cp.read_file(config) - assert cp.get('header', 'foo') == 'bar' - assert cp.get('header', 'FOO') == 'BAR' - assert cp.get('HEADER', 'foo') == 'notbar' + assert cp.get("header", "foo") == "bar" + assert cp.get("header", "FOO") == "BAR" + assert cp.get("HEADER", "foo") == "notbar" class TestConfigFromIni: - def test_config_from_ini(self): - config = cparser.config_from_file(StringIO(textwrap.dedent('''\ + config = cparser.config_from_file( + StringIO( + textwrap.dedent( + """\ [test] string = 'hi I am a string' list = foo bar baz @@ -31,23 +37,37 @@ class TestConfigFromIni: list.append = post bits true = yes false = no - '''))) - assert list(config.keys()) == ['test'] - section = config['test'] + """ + ) + ) + ) + assert list(config.keys()) == ["test"] + section = config["test"] for key, arg_type, value in ( - ('string', 'str', [None, 'hi I am a string', None]), - ('list', 'list', [ - ['pre', 'bits'], ['foo', 'bar', 'baz'], ['post', 'bits']]), - ('true', 'bool', True), - ('false', 'bool', False), - ): + ("string", "str", [None, "hi I am a string", None]), + ( + "list", + "list", + [["pre", "bits"], ["foo", "bar", "baz"], ["post", "bits"]], + ), + ("true", "bool", True), + ("false", "bool", False), + ): assert section.render_value(None, key, arg_type) == value def test_missing_section_ref(self): - config = cparser.config_from_file(StringIO(textwrap.dedent('''\ + config = cparser.config_from_file( + StringIO( + textwrap.dedent( + """\ [test] ref = 'missing' - '''))) - section = config['test'] + """ + ) + ) + ) + section = config["test"] with pytest.raises(errors.ConfigurationError): - section.render_value(central.ConfigManager([]), 'ref', 'ref:drawer').collapse() + section.render_value( + central.ConfigManager([]), "ref", "ref:drawer" + ).collapse() diff --git a/tests/config/test_init.py b/tests/config/test_init.py index 1e2cc9cf..1ac35e8e 100644 --- a/tests/config/test_init.py +++ b/tests/config/test_init.py @@ -6,51 +6,44 @@ from pkgcore.config import basics, load_config from pkgcore.config.hint import configurable -@configurable(typename='foo') +@configurable(typename="foo") def passthrough(*args, **kwargs): return args, kwargs class TestConfigLoading: - @pytest.fixture def user_config(self, tmp_path): - user_config = tmp_path / 'user.conf' - user_config.write_text( - '[foo]\n' - 'class = tests.config.test_init.passthrough\n' - ) + user_config = tmp_path / "user.conf" + user_config.write_text("[foo]\n" "class = tests.config.test_init.passthrough\n") return str(user_config) @pytest.fixture def system_config(self, tmp_path): - system_config = tmp_path / 'system.conf' - system_config.write_text( - '[foo]\n' - 'class = also invalid\n' - ) + system_config = tmp_path / "system.conf" + system_config.write_text("[foo]\n" "class = also invalid\n") return str(system_config) def test_load_config(self, user_config): manager = load_config(user_conf_file=user_config) - assert manager.foo['foo'] == ((), {}) + assert manager.foo["foo"] == ((), {}) def test_user_config_override_system(self, user_config, system_config): manager = load_config( - user_conf_file=user_config, - system_conf_file=system_config) - assert manager.foo['foo'] == ((), {}) + user_conf_file=user_config, system_conf_file=system_config + ) + assert manager.foo["foo"] == ((), {}) def test_prepends(self, user_config): manager = load_config( user_conf_file=user_config, - prepend_sources=[{'myfoo': basics.HardCodedConfigSection({ - 'inherit': ['foo']})}]) - assert manager.foo['myfoo'] == ((), {}) + prepend_sources=[ + {"myfoo": basics.HardCodedConfigSection({"inherit": ["foo"]})} + ], + ) + assert manager.foo["myfoo"] == ((), {}) def test_disabling_loading(self, user_config): - manager = load_config( - user_conf_file=user_config, - skip_config_files=True) + manager = load_config(user_conf_file=user_config, skip_config_files=True) with pytest.raises(KeyError): - manager.foo['foo'] + manager.foo["foo"] |