diff options
author | Brian Harring <ferringb@gmail.com> | 2023-01-17 00:22:28 -0800 |
---|---|---|
committer | Arthur Zamarin <arthurzam@gentoo.org> | 2023-02-05 20:08:21 +0200 |
commit | cc4b8915fd71d09715011b6dadbe9c86e28e0b11 (patch) | |
tree | d722b078a92059cbd7293468ff0f9a14d7b8c864 | |
parent | refactor(config): remove the notion of config layer incremental prepend/append. (diff) | |
download | pkgcore-cc4b8915fd71d09715011b6dadbe9c86e28e0b11.tar.gz pkgcore-cc4b8915fd71d09715011b6dadbe9c86e28e0b11.tar.bz2 pkgcore-cc4b8915fd71d09715011b6dadbe9c86e28e0b11.zip |
refactor(config): remove prepend/append incremental return signature fully.
The previous commit disabled the logic to generate prepend/val/append- nothing used it-
this commit realigns the client consumers to expect a single value unless they're invoked
arg_type="repr".
Essentially, now if you ask the config layer for a value, you don't have to know if it's
a value that is considered 'incremental'- you just get back a python object for what you asked,
ready for usage.
Signed-off-by: Brian Harring <ferringb@gmail.com>
Signed-off-by: Arthur Zamarin <arthurzam@gentoo.org>
-rw-r--r-- | src/pkgcore/config/basics.py | 108 | ||||
-rw-r--r-- | src/pkgcore/config/central.py | 58 | ||||
-rw-r--r-- | src/pkgcore/scripts/pconfig.py | 37 | ||||
-rw-r--r-- | tests/config/test_cparser.py | 4 | ||||
-rw-r--r-- | tests/scripts/test_pconfig.py | 9 |
5 files changed, 32 insertions, 184 deletions
diff --git a/src/pkgcore/config/basics.py b/src/pkgcore/config/basics.py index 3ab3e73f..ba968ef9 100644 --- a/src/pkgcore/config/basics.py +++ b/src/pkgcore/config/basics.py @@ -269,111 +269,9 @@ class DictConfigSection(ConfigSection): def keys(self) -> list[str]: 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:"): - 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 - # return all three. - # - # (we do not get called for separate reprs for the - # .prepend or .append because those are filtered from - # .keys(). If we do not filter those from .keys() - # central gets upset because it does not know their - # type. Perhaps this means we should have a separate - # .keys() used together with repr, not sure yet - # --marienz) - # - # The problem here is that we may get unsuitable for - # incremental or differing types for the three reprs - # we run, so we need to convert to a suitable common - # kind. - if result[0] is None and result[2] is None: - # Simple case: no extra data, so no need for any - # conversions. - kind, val = result[1] - if kind in ("list", "str") or kind == "refs": - # Caller expects a three-tuple. - return kind, (None, val, None) - else: - # non-incremental, just return as-is. - return kind, val - # We have more than one return value. Figure out what - # target to convert to. Choices are list, str and refs. - kinds = set(v[0] for v in result if v is not None) - if "refs" in kinds or "ref" in kinds: - # If we have any refs we have to convert to refs. - target_kind = "refs" - elif kinds == set(["str"]): - # If we have only str we can just use that. - target_kind = "str" - else: - # Convert to list. May not make any sense, but is - # the best we can do. - target_kind = "list" - converted = [] - for val in result: - if val is None: - converted.append(None) - continue - kind, val = val - if kind == "ref": - if target_kind != "refs": - raise ValueError( - "Internal issue detected: kind(ref), " - f"target_kind({target_kind!r}), name({name!r}), " - f"val({val!r}), arg_type({arg_type!r})" - ) - converted.append([val]) - elif kind == "refs": - if target_kind != "refs": - raise ValueError( - "Internal issue detected: kind(refs), " - f"target_kind({target_kind!r}), name({name!r}), " - f"val({val!r}), arg_type({arg_type!r})" - ) - converted.append(val) - elif kind == "list": - if target_kind == "str": - raise ValueError( - "Internal issue detected: kind(str), " - f"target_kind({target_kind!r}), name({name!r}), " - f"val({val!r}), arg_type({arg_type!r})" - ) - converted.append(val) - else: - # Everything else gets converted to a string first. - if kind == "callable": - val = "%s.%s" % (val.__module__, val.__name__) - elif kind in ("bool", "int", "str"): - val = str(val) - else: - raise errors.ConfigurationError(f"unsupported type {kind!r}") - # Then convert the str to list if needed. - if target_kind == "str": - converted.append(val) - else: - converted.append([val]) - return target_kind, converted - # simple types. + def render_value( + self, central, name: str, arg_type: str + ) -> typing.Union[typing.Any, tuple[str, typing.Any]]: try: return self.func(central, self.dict[name], arg_type) except IGNORED_EXCEPTIONS: diff --git a/src/pkgcore/config/central.py b/src/pkgcore/config/central.py index 350e25f5..0cd2f392 100644 --- a/src/pkgcore/config/central.py +++ b/src/pkgcore/config/central.py @@ -8,11 +8,9 @@ __all__ = ( "ConfigManager", ) -import functools import typing import weakref from collections import defaultdict, deque, namedtuple -from itertools import chain from snakeoil import klass, mappings from snakeoil.compatibility import IGNORED_EXCEPTIONS @@ -69,43 +67,14 @@ class _ConfigStack(defaultdict[str, list[typing.Any]]): def __init__(self) -> None: super().__init__(list) - def render_vals( + def render_value( self, manager, key: str, type_name: str - ) -> typing.Iterator[typing.Any]: + ) -> typing.Optional[typing.Any]: for data in self.get(key, ()): if key in data.section: - yield data.section.render_value(manager, key, type_name) - - def render_val( - self, manager, key: str, type_name: str - ) -> typing.Optional[typing.Any]: - for val in self.render_vals(manager, key, type_name): - return val + return data.section.render_value(manager, key, type_name) return None - def render_prepends(self, manager, key: str, type_name: str) -> list[typing.Any]: - results = [] - # keep in mind that the sequence we get is a top -> bottom walk of the config - # as such for this operation we have to reverse it when building the content- - # specifically, reverse the ordering, but not the content of each item. - data = [] - for content in self.render_vals(manager, key, type_name): - data.append(content) - if content[1]: - break - - for prepend, this_content, append in reversed(data): - if this_content: - results = [this_content] - if prepend: - results = [prepend] + results - if append: - results += [append] - - if type_name != "str": - results = list(chain.from_iterable(results)) - return results - class CollapsedConfig: @@ -463,13 +432,7 @@ class ConfigManager: current_conf = section_stack[0] if "inherit" not in current_conf: continue - prepend, inherits, append = current_conf.render_value( - self, "inherit", "list" - ) - if prepend is not None or append is not None: - raise errors.ConfigurationError( - "Prepending or appending to the inherit list makes no sense" - ) + inherits = current_conf.render_value(self, "inherit", "list") for inherit in inherits: if inherit == current_section: # self-inherit. Mkae use of section_stack to handle this. @@ -516,11 +479,11 @@ class ConfigManager: for key in data.section.keys(): config_stack[key].append(data) - kls = config_stack.render_val(self, "class", "callable") + kls = config_stack.render_value(self, "class", "callable") if kls is None: raise errors.ConfigurationError("no class specified") type_obj = basics.ConfigType(kls) - is_default = bool(config_stack.render_val(self, "default", "bool")) + is_default = bool(config_stack.render_value(self, "default", "bool")) for key in ("inherit", "inherit-only", "class", "default"): config_stack.pop(key, None) @@ -561,14 +524,7 @@ class ConfigManager: if typename.startswith("lazy_"): typename = typename[5:] - if typename.startswith("refs:") or typename in ("list", "str"): - result = config_stack.render_prepends(self, key, typename) - if typename == "str": - # TODO: figure out why this is needed and likely remove it. - # it's likely just doing ' '.join([item]) - result = " ".join(result) - else: - result = config_stack.render_val(self, key, typename) + result = config_stack.render_value(self, key, typename) if is_ref: result = [result] diff --git a/src/pkgcore/scripts/pconfig.py b/src/pkgcore/scripts/pconfig.py index 00b70a4e..75bb0017 100644 --- a/src/pkgcore/scripts/pconfig.py +++ b/src/pkgcore/scripts/pconfig.py @@ -319,29 +319,24 @@ def _dump_uncollapsed_section(config, out, err, section): kind, value = section.render_value(config, key, "repr") out.write(f"# type: {kind}") if kind == "list": - for name, val in zip((key + ".prepend", key, key + ".append"), value): - if val: - out.write(repr(name), " = ", " ".join(repr(v) for v in val)) + out.write(repr(key), " = ", " ".join(repr(v) for v in value)) continue if kind in ("refs", "str"): - for name, val in zip((key + ".prepend", key, key + ".append"), value): - if not val: - continue - out.write(repr(name), " = ", autoline=False) - if kind == "str": - out.write(repr(val)) - else: - out.write() - out.first_prefix.append(" ") - try: - for subnr, subsection in enumerate(val): - subname = f"nested section {subnr + 1}" - out.write(subname) - out.write("=" * len(subname)) - _dump_uncollapsed_section(config, out, err, subsection) - out.write() - finally: - out.first_prefix.pop() + out.write(repr(key), " = ", autoline=False) + if kind == "str": + out.write(repr(value)) + else: + out.write() + out.first_prefix.append(" ") + try: + for subnr, subsection in enumerate(value): + subname = f"nested section {subnr + 1}" + out.write(subname) + out.write("=" * len(subname)) + _dump_uncollapsed_section(config, out, err, subsection) + out.write() + finally: + out.first_prefix.pop() continue out.write(f"{key!r} = ", autoline=False) if kind == "callable": diff --git a/tests/config/test_cparser.py b/tests/config/test_cparser.py index a9082adb..bf407e62 100644 --- a/tests/config/test_cparser.py +++ b/tests/config/test_cparser.py @@ -43,11 +43,11 @@ class TestConfigFromIni: assert list(config.keys()) == ["test"] section = config["test"] for key, arg_type, value in ( - ("string", "str", [None, "hi I am a string", None]), + ("string", "str", "hi I am a string"), ( "list", "list", - [None, ["foo", "bar", "baz"], None], + ["foo", "bar", "baz"], ), ("true", "bool", True), ("false", "bool", False), diff --git a/tests/scripts/test_pconfig.py b/tests/scripts/test_pconfig.py index c9cd40eb..68543361 100644 --- a/tests/scripts/test_pconfig.py +++ b/tests/scripts/test_pconfig.py @@ -296,11 +296,10 @@ class WeirdSection(basics.ConfigSection): raise KeyError(name) if arg_type != "repr": raise errors.ConfigurationError(f"{arg_type!r} unsupported") - return "refs", [ + return ( + "refs", ["spork", basics.HardCodedConfigSection({"foo": "bar"})], - None, - None, - ] + ) class TestDumpUncollapsed(ArgParseMixin): @@ -337,7 +336,7 @@ class TestDumpUncollapsed(ArgParseMixin): " nested section 2", " ================", " # type: refs", - " 'sects.prepend' = ", + " 'sects' = ", " nested section 1", " ================", " named section 'spork'", |