|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
| 3 | +import inspect |
3 | 4 | import logging |
4 | 5 | from pathlib import Path |
5 | 6 | from typing import TYPE_CHECKING, Dict, Iterator, List, Mapping, TypeVar, cast |
6 | 7 |
|
7 | 8 | from tox.config.loader.api import ConfigLoadArgs, Loader, Override |
| 9 | +from tox.config.set_env import SetEnv |
8 | 10 | from tox.config.types import Command, EnvList |
| 11 | +from tox.report import HandledError |
9 | 12 |
|
10 | 13 | from ._api import TomlTypes |
11 | 14 | from ._replace import Unroll |
@@ -55,15 +58,34 @@ def load_raw_from_root(self, path: str) -> TomlTypes: |
55 | 58 |
|
56 | 59 | def build( # noqa: PLR0913 |
57 | 60 | self, |
58 | | - key: str, # noqa: ARG002 |
| 61 | + key: str, |
59 | 62 | of_type: type[_T], |
60 | 63 | factory: Factory[_T], |
61 | 64 | conf: Config | None, |
62 | 65 | raw: TomlTypes, |
63 | 66 | args: ConfigLoadArgs, |
64 | 67 | ) -> _T: |
| 68 | + delay_replace = inspect.isclass(of_type) and issubclass(of_type, SetEnv) |
| 69 | + |
| 70 | + def replacer(raw_: str, args_: ConfigLoadArgs) -> str: |
| 71 | + if conf is None: |
| 72 | + replaced = raw_ # no replacement supported in the core section |
| 73 | + else: |
| 74 | + reference_replacer = Unroll(conf, self, args) |
| 75 | + try: |
| 76 | + replaced = str(reference_replacer(raw_)) # do replacements |
| 77 | + except Exception as exception: |
| 78 | + if isinstance(exception, HandledError): |
| 79 | + raise |
| 80 | + msg = f"replace failed in {args_.env_name}.{key} with {exception!r}" |
| 81 | + raise HandledError(msg) from exception |
| 82 | + return replaced |
| 83 | + |
65 | 84 | exploded = Unroll(conf=conf, loader=self, args=args)(raw) |
66 | | - return self.to(exploded, of_type, factory) |
| 85 | + refactoried = self.to(exploded, of_type, factory) |
| 86 | + if delay_replace: |
| 87 | + refactoried.use_replacer(replacer, args=args) # type: ignore[attr-defined] # issubclass(to_type, SetEnv) |
| 88 | + return refactoried |
67 | 89 |
|
68 | 90 | def found_keys(self) -> set[str]: |
69 | 91 | return set(self.content.keys()) - self._unused_exclude |
|
0 commit comments