diff --git a/docs/changelog/3343.misc.rst b/docs/changelog/3343.misc.rst new file mode 100644 index 0000000000..1f8e3bedc5 --- /dev/null +++ b/docs/changelog/3343.misc.rst @@ -0,0 +1 @@ +Prepare ``Loader`` and ``MemoryLoader`` for TOML support - by :user:`ziima` diff --git a/src/tox/config/loader/memory.py b/src/tox/config/loader/memory.py index 59d47bd77d..fb9182d09e 100644 --- a/src/tox/config/loader/memory.py +++ b/src/tox/config/loader/memory.py @@ -5,7 +5,7 @@ from tox.config.types import Command, EnvList -from .api import Loader +from .api import Loader, Override from .section import Section from .str_convert import StrConvert @@ -14,9 +14,16 @@ class MemoryLoader(Loader[Any]): - def __init__(self, **kwargs: Any) -> None: - super().__init__(Section(prefix="", name=str(id(self))), []) - self.raw: dict[str, Any] = {**kwargs} + def __init__( + self, + raw: dict[str, Any], + *, + section: Section | None = None, + overrides: list[Override] | None = None, + ) -> None: + section = section or Section(prefix="", name=str(id(self))) + super().__init__(section, overrides or []) + self.raw = raw def load_raw(self, key: Any, conf: Config | None, env_name: str | None) -> Any: # noqa: ARG002 return self.raw[key] diff --git a/src/tox/provision.py b/src/tox/provision.py index 9e1e2bf8c8..e19bf21872 100644 --- a/src/tox/provision.py +++ b/src/tox/provision.py @@ -91,12 +91,14 @@ def add_tox_requires_min_version(reqs: list[Requirement]) -> list[Requirement]: deps = ", ".join(f"{p}{'' if v is None else f' ({v})'}" for p, v in missing) loader = MemoryLoader( # these configuration values are loaded from in-memory always (no file conf) - base=[], # disable inheritance for provision environments - package="skip", # no packaging for this please - # use our own dependency specification - deps=PythonDeps("\n".join(str(r) for r in requires), root=state.conf.core["tox_root"]), - pass_env=["*"], # do not filter environment variables, will be handled by provisioned tox - recreate=state.conf.options.recreate and not state.conf.options.no_recreate_provision, + { + "base": [], # disable inheritance for provision environments + "package": "skip", # no packaging for this please + # use our own dependency specification + "deps": PythonDeps("\n".join(str(r) for r in requires), root=state.conf.core["tox_root"]), + "pass_env": ["*"], # do not filter environment variables, will be handled by provisioned tox + "recreate": state.conf.options.recreate and not state.conf.options.no_recreate_provision, + } ) provision_tox_env: str = state.conf.core["provision_tox_env"] state.conf.memory_seed_loaders[provision_tox_env].append(loader) diff --git a/src/tox/session/cmd/devenv.py b/src/tox/session/cmd/devenv.py index c4754e5460..c5e11c2573 100644 --- a/src/tox/session/cmd/devenv.py +++ b/src/tox/session/cmd/devenv.py @@ -35,8 +35,10 @@ def devenv(state: State) -> int: opt.skip_pkg_install = False # always install a package in this case opt.no_test = True # do not run the test phase loader = MemoryLoader( # these configuration values are loaded from in-memory always (no file conf) - usedevelop=True, # dev environments must be of type dev - env_dir=opt.devenv_path, # move it in source + { + "usedevelop": True, # dev environments must be of type dev + "env_dir": opt.devenv_path, # move it in source + } ) state.conf.memory_seed_loaders[next(iter(opt.env))].append(loader) diff --git a/src/tox/session/cmd/exec_.py b/src/tox/session/cmd/exec_.py index 4ce3e947e4..3f94b53f70 100644 --- a/src/tox/session/cmd/exec_.py +++ b/src/tox/session/cmd/exec_.py @@ -34,9 +34,11 @@ def exec_(state: State) -> int: msg = f"exactly one target environment allowed in exec mode but found {', '.join(envs)}" raise HandledError(msg) loader = MemoryLoader( # these configuration values are loaded from in-memory always (no file conf) - commands_pre=[], - commands=[], - commands_post=[], + { + "commands_pre": [], + "commands": [], + "commands_post": [], + } ) conf = state.envs[envs[0]].conf conf.loaders.insert(0, loader) diff --git a/src/tox/session/cmd/legacy.py b/src/tox/session/cmd/legacy.py index a78d8bac78..05f122e2d4 100644 --- a/src/tox/session/cmd/legacy.py +++ b/src/tox/session/cmd/legacy.py @@ -129,7 +129,7 @@ def _handle_legacy_only_flags(option: Parsed, envs: EnvSelector) -> None: # noq for env in envs.iter(only_active=True, package=False): env_conf = envs[env].conf if override: - env_conf.loaders.insert(0, MemoryLoader(**override)) + env_conf.loaders.insert(0, MemoryLoader(override)) if set_env: cast(SetEnv, env_conf["set_env"]).update(set_env, override=True) if forced: diff --git a/tests/config/loader/test_memory_loader.py b/tests/config/loader/test_memory_loader.py index dfe8f9b8d9..114e92c2b0 100644 --- a/tests/config/loader/test_memory_loader.py +++ b/tests/config/loader/test_memory_loader.py @@ -12,7 +12,7 @@ def test_memory_loader_override() -> None: - loader = MemoryLoader(a=1) + loader = MemoryLoader({"a": 1}) loader.overrides["a"] = [Override("a=2")] args = ConfigLoadArgs([], "name", None) loaded = loader.load("a", of_type=int, conf=None, factory=None, args=args) @@ -48,7 +48,7 @@ def test_memory_loader_override() -> None: ], ) def test_memory_loader(value: Any, of_type: type[Any], outcome: Any) -> None: - loader = MemoryLoader(a=value, kwargs={}) + loader = MemoryLoader({"a": value, "kwargs": {}}) args = ConfigLoadArgs([], "name", None) loaded = loader.load("a", of_type=of_type, conf=None, factory=None, args=args) assert loaded == outcome @@ -68,18 +68,18 @@ def test_memory_loader(value: Any, of_type: type[Any], outcome: Any) -> None: ], ) def test_memory_loader_fails_invalid(value: Any, of_type: type[Any], exception: Exception, msg: str) -> None: - loader = MemoryLoader(a=value, kwargs={}) + loader = MemoryLoader({"a": value, "kwargs": {}}) args = ConfigLoadArgs([], "name", None) with pytest.raises(exception, match=msg): # type: ignore[call-overload] loader.load("a", of_type=of_type, conf=None, factory=None, args=args) def test_memory_found_keys() -> None: - loader = MemoryLoader(a=1, c=2) + loader = MemoryLoader({"a": 1, "c": 2}) assert loader.found_keys() == {"a", "c"} def test_memory_loader_contains() -> None: - loader = MemoryLoader(a=1) + loader = MemoryLoader({"a": 1}) assert "a" in loader assert "b" not in loader diff --git a/tests/config/test_main.py b/tests/config/test_main.py index 853ef9bb44..070702e71e 100644 --- a/tests/config/test_main.py +++ b/tests/config/test_main.py @@ -63,7 +63,7 @@ def test_config_overrides(tox_ini_conf: ToxIniCreator) -> None: def test_config_override_wins_memory_loader(tox_ini_conf: ToxIniCreator) -> None: main_conf = tox_ini_conf("[testenv]", override=[Override("testenv.c=ok")]) - conf = main_conf.get_env("py", loaders=[MemoryLoader(c="something_else")]) + conf = main_conf.get_env("py", loaders=[MemoryLoader({"c": "something_else"})]) conf.add_config("c", of_type=str, default="d", desc="desc") assert conf["c"] == "ok" diff --git a/tests/config/test_sets.py b/tests/config/test_sets.py index 91aec92c15..5db2d7ee23 100644 --- a/tests/config/test_sets.py +++ b/tests/config/test_sets.py @@ -181,7 +181,7 @@ def test_do_not_allow_create_config_set(mocker: MockerFixture) -> None: def test_set_env_raises_on_non_str(mocker: MockerFixture) -> None: env_set = EnvConfigSet(mocker.create_autospec(Config), Section("a", "b"), "b") - env_set.loaders.insert(0, MemoryLoader(set_env=1)) + env_set.loaders.insert(0, MemoryLoader({"set_env": 1})) with pytest.raises(TypeError, match="1"): assert env_set["set_env"] diff --git a/tests/plugin/test_plugin.py b/tests/plugin/test_plugin.py index 32a8e9fdc9..a066c65efb 100644 --- a/tests/plugin/test_plugin.py +++ b/tests/plugin/test_plugin.py @@ -131,7 +131,7 @@ def test_plugin_can_set_core_conf( ) -> None: @impl def tox_add_core_config(core_conf: CoreConfigSet, state: State) -> None: # noqa: ARG001 - core_conf.loaders.insert(0, MemoryLoader(**{dir_name: tmp_path})) + core_conf.loaders.insert(0, MemoryLoader({dir_name: tmp_path})) register_inline_plugin(mocker, tox_add_core_config) @@ -186,7 +186,7 @@ def tox_add_core_config(core_conf: CoreConfigSet, state: State) -> None: # noqa def test_plugin_injects_invalid_python_run(tox_project: ToxProjectCreator, mocker: MockerFixture) -> None: @impl def tox_add_env_config(env_conf: EnvConfigSet, state: State) -> None: # noqa: ARG001 - env_conf.loaders.insert(0, MemoryLoader(deps=[1])) + env_conf.loaders.insert(0, MemoryLoader({"deps": [1]})) with pytest.raises(TypeError, match="1"): assert env_conf["deps"]