Skip to content

Commit

Permalink
Add API for substitution and refs
Browse files Browse the repository at this point in the history
Signed-off-by: Bernát Gábor <[email protected]>
  • Loading branch information
gaborbernat committed Sep 30, 2024
1 parent edd352e commit cf49d2d
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
16 changes: 15 additions & 1 deletion src/tox/config/loader/toml/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
from pathlib import Path
from typing import TYPE_CHECKING, Dict, Iterator, List, Mapping, Set, TypeVar, cast

from tox.config.loader.api import Loader, Override
from tox.config.loader.api import ConfigLoadArgs, Loader, Override
from tox.config.types import Command, EnvList

from ._api import TomlTypes
from ._replace import unroll_refs_and_apply_substitutions
from ._validate import validate

if TYPE_CHECKING:
from tox.config.loader.convert import Factory
from tox.config.loader.section import Section
from tox.config.main import Config

Expand Down Expand Up @@ -37,6 +39,18 @@ def __repr__(self) -> str:
def load_raw(self, key: str, conf: Config | None, env_name: str | None) -> TomlTypes: # noqa: ARG002
return self.content[key]

def build( # noqa: PLR0913
self,
key: str, # noqa: ARG002
of_type: type[_T],
factory: Factory[_T],
conf: Config | None,
raw: TomlTypes,
args: ConfigLoadArgs,
) -> _T:
raw = unroll_refs_and_apply_substitutions(conf=conf, loader=self, value=raw, args=args)
return self.to(raw, of_type, factory)

def found_keys(self) -> set[str]:
return set(self.content.keys()) - self._unused_exclude

Expand Down
35 changes: 35 additions & 0 deletions src/tox/config/loader/toml/_replace.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from __future__ import annotations

from typing import TYPE_CHECKING, Final

if TYPE_CHECKING:
from tox.config.loader.api import ConfigLoadArgs
from tox.config.loader.toml import TomlLoader
from tox.config.main import Config

from ._api import TomlTypes

MAX_REPLACE_DEPTH: Final[int] = 100


class MatchRecursionError(ValueError):
"""Could not stabilize on replacement value."""


def unroll_refs_and_apply_substitutions(
conf: Config, # noqa: ARG001
loader: TomlLoader, # noqa: ARG001
value: TomlTypes,
args: ConfigLoadArgs, # noqa: ARG001
depth: int = 0,
) -> TomlTypes:
"""Replace all active tokens within value according to the config."""
if depth > MAX_REPLACE_DEPTH:
msg = f"Could not expand {value} after recursing {depth} frames"
raise MatchRecursionError(msg)
return value


__all__ = [
"unroll_refs_and_apply_substitutions",
]
2 changes: 1 addition & 1 deletion tests/config/source/test_toml_tox.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,5 @@ def test_config_in_toml_extra(tox_project: ToxProjectCreator) -> None:

def test_config_in_toml_replace(tox_project: ToxProjectCreator) -> None:
project = tox_project({"tox.toml": '[env_run_base]\ndescription = "Magic in {env_name}"'})
outcome = project.run("c", "-k", "commands")
outcome = project.run("c", "-k", "description")
outcome.assert_success()

0 comments on commit cf49d2d

Please sign in to comment.