diff options
author | Brian Harring <ferringb@gmail.com> | 2023-01-16 23:22:56 -0800 |
---|---|---|
committer | Arthur Zamarin <arthurzam@gentoo.org> | 2023-02-05 20:08:21 +0200 |
commit | 07602f09835ad21fed1603cd44923fe6e288c24a (patch) | |
tree | 607f266b4abaf220cdd9430fa95446e528535985 | |
parent | refactor(config): remove indirection of multiplex.config_tree for multiplex.tree (diff) | |
download | pkgcore-07602f09835ad21fed1603cd44923fe6e288c24a.tar.gz pkgcore-07602f09835ad21fed1603cd44923fe6e288c24a.tar.bz2 pkgcore-07602f09835ad21fed1603cd44923fe6e288c24a.zip |
refactor(config): remove the notion of config layer incremental prepend/append.
Many moons gone past the original config system tried to support the idea
of incrementally stacked values (x y -x z -y == z). This commit removes
the fundamental core of that functionality; the incremental logic is now implemented
in domain specific layers, rather than being a capability of the config layer.
Note: this just removes the logic. The signature of [before, mid, after] return
is still in place, and will be removed as the API is normalized. In particular,
pconfig still reports on .prepend/.apend, there just no longer is content there.
That behaviour (and signature) change will be a followon commit.
Signed-off-by: Brian Harring <ferringb@gmail.com>
Signed-off-by: Arthur Zamarin <arthurzam@gentoo.org>
-rw-r--r-- | src/pkgcore/config/basics.py | 95 | ||||
-rw-r--r-- | src/pkgcore/ebuild/portage_conf.py | 6 | ||||
-rw-r--r-- | tests/config/test_basics.py | 81 | ||||
-rw-r--r-- | tests/config/test_central.py | 86 | ||||
-rw-r--r-- | tests/config/test_cparser.py | 5 |
5 files changed, 24 insertions, 249 deletions
diff --git a/src/pkgcore/config/basics.py b/src/pkgcore/config/basics.py index 95792ea26..3ab3e73f7 100644 --- a/src/pkgcore/config/basics.py +++ b/src/pkgcore/config/basics.py @@ -10,7 +10,6 @@ __all__ = ( "LazyNamedSectionRef", "ConfigSection", "DictConfigSection", - "FakeIncrementalDictConfigSection", "convert_string", "convert_asis", "convert_hybrid", @@ -247,50 +246,12 @@ class DictConfigSection(ConfigSection): func: typing.Callable dict: dict[str, typing.Any] - def __init__(self, conversion_func, source_dict: dict[str, typing.Any]) -> None: - """Initialize. - - :type conversion_func: callable. - :param conversion_func: called with a ConfigManager, a value from - the dict and a type name. - :type source_dict: dict with string keys and arbitrary values. - """ - super().__init__() - self.func = conversion_func - self.dict = source_dict - - def __contains__(self, name: str) -> bool: - return name in self.dict - - def keys(self) -> list[str]: - return list(self.dict.keys()) - - def render_value(self, central, name: str, arg_type: str): - try: - return self.func(central, self.dict[name], arg_type) - except IGNORED_EXCEPTIONS: - raise - except Exception as e: - raise errors.ConfigurationError( - f"Failed converting argument {name!r} to {arg_type}" - ) from e - - -class FakeIncrementalDictConfigSection(ConfigSection): - """Turns a dict and a conversion function into a ConfigSection.""" - - func: typing.Callable - dict: dict[str, typing.Any] - def __init__( self, conversion_func: typing.Callable, source_dict: dict[str, typing.Any] ) -> None: """Initialize. - A request for a section of a list type will look for - name.prepend and name.append keys too, using those for values - prepended/appended to the inherited values. The conversion - func should return a single sequence for list types and in + The conversion func should return a single sequence for list types and in repr for list types. :type conversion_func: callable. @@ -303,47 +264,31 @@ class FakeIncrementalDictConfigSection(ConfigSection): self.dict = source_dict def __contains__(self, name: str) -> bool: - return ( - name in self.dict - or name + ".append" in self.dict - or name + ".prepend" in self.dict - ) + return name in self.dict def keys(self) -> list[str]: - keys = set() - for key in self.dict: - if key.endswith(".append"): - key = key[:-7] - elif key.endswith(".prepend"): - key = key[:-8] - keys.add(key) - return list(keys) + return list(self.dict.keys()) def render_value(self, central, name: str, arg_type: str): # Check if we need our special incremental magic. if arg_type in ("list", "str", "repr") or arg_type.startswith("refs:"): - result = [] - # Careful: None is a valid dict value, so use something else here. - missing = object() - for subname in (name + ".prepend", name, name + ".append"): - val = self.dict.get(subname, missing) - if val is missing: - val = None - else: - try: - val = self.func(central, val, arg_type) - except IGNORED_EXCEPTIONS: - raise - except Exception as e: - raise errors.ConfigurationError( - f"Failed converting argument {subname!r} to {arg_type}" - ) from e - result.append(val) - if result[0] is result[1] is result[2] is None: + try: + val = self.func(central, self.dict[name], arg_type) + except IGNORED_EXCEPTIONS: + raise + except Exception as e: + raise errors.ConfigurationError( + f"Failed converting argument {name!r} to {arg_type}" + ) from e + if val is None: raise KeyError(name) + result = [None, val, None] if arg_type != "repr": # Done. return result + # what follows is basically a type annotation shoved into this pathway, resulting + # in a differing signature from norms. repr arg_type needs to be removed for this reason. + # If "kind" is of some incremental-ish kind or we have # .prepend or .append for this key then we need to # convert everything we have to the same kind and @@ -428,7 +373,7 @@ class FakeIncrementalDictConfigSection(ConfigSection): else: converted.append([val]) return target_kind, converted - # Not incremental. + # simple types. try: return self.func(central, self.dict[name], arg_type) except IGNORED_EXCEPTIONS: @@ -597,9 +542,9 @@ def convert_hybrid(central, value, arg_type: str): # "Invalid name" (pylint thinks these are module-level constants) # pylint: disable-msg=C0103 -HardCodedConfigSection = partial(FakeIncrementalDictConfigSection, convert_asis) -ConfigSectionFromStringDict = partial(FakeIncrementalDictConfigSection, convert_string) -AutoConfigSection = partial(FakeIncrementalDictConfigSection, convert_hybrid) +HardCodedConfigSection = partial(DictConfigSection, convert_asis) +ConfigSectionFromStringDict = partial(DictConfigSection, convert_string) +AutoConfigSection = partial(DictConfigSection, convert_hybrid) def section_alias(target, typename: str) -> AutoConfigSection: diff --git a/src/pkgcore/ebuild/portage_conf.py b/src/pkgcore/ebuild/portage_conf.py index d33d2e37d..84f39ce27 100644 --- a/src/pkgcore/ebuild/portage_conf.py +++ b/src/pkgcore/ebuild/portage_conf.py @@ -213,7 +213,7 @@ class PortageConfig(DictMixin): self._make_repo_syncers(repos_conf, make_conf) if repos: - self["repo-stack"] = basics.FakeIncrementalDictConfigSection( + self["repo-stack"] = basics.DictConfigSection( my_convert_hybrid, { "class": "pkgcore.repository.multiplex.tree", @@ -248,9 +248,7 @@ class PortageConfig(DictMixin): } ) - self["livefs"] = basics.FakeIncrementalDictConfigSection( - my_convert_hybrid, make_conf - ) + self["livefs"] = basics.DictConfigSection(my_convert_hybrid, make_conf) def __setitem__(self, key, value): self._config[key] = value diff --git a/tests/config/test_basics.py b/tests/config/test_basics.py index e04cc7047..10f0841e1 100644 --- a/tests/config/test_basics.py +++ b/tests/config/test_basics.py @@ -248,87 +248,6 @@ class TestDictConfigSection: 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") - - 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()) - with pytest.raises(errors.ConfigurationError): - 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]} - ) - manager = object() - 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" - ) - with pytest.raises(errors.ConfigurationError): - 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 - 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"), - } - 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") - with pytest.raises(errors.ConfigurationError): - section.render_value(manager, "wrong", "repr") - - class TestConvertString: def test_render_value(self): source = { diff --git a/tests/config/test_central.py b/tests/config/test_central.py index 5ffb8072b..55b541f8f 100644 --- a/tests/config/test_central.py +++ b/tests/config/test_central.py @@ -970,89 +970,3 @@ def test_self_inherit(): ) assert manager.collapse_named_section("self") assert manager.collapse_section([section]) - - -def test_prepend_inherit(): - 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", - ) - - -def test_list_prepend(): - @configurable(types={"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"] - - -def test_str_prepend(): - @configurable(types={"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"] diff --git a/tests/config/test_cparser.py b/tests/config/test_cparser.py index e7d0b0ea5..a9082adbf 100644 --- a/tests/config/test_cparser.py +++ b/tests/config/test_cparser.py @@ -2,6 +2,7 @@ import textwrap from io import StringIO import pytest + from pkgcore.config import central, cparser, errors @@ -33,8 +34,6 @@ class TestConfigFromIni: [test] string = 'hi I am a string' list = foo bar baz - list.prepend = pre bits - list.append = post bits true = yes false = no """ @@ -48,7 +47,7 @@ class TestConfigFromIni: ( "list", "list", - [["pre", "bits"], ["foo", "bar", "baz"], ["post", "bits"]], + [None, ["foo", "bar", "baz"], None], ), ("true", "bool", True), ("false", "bool", False), |