summaryrefslogtreecommitdiff
path: root/src/test_stages/cmd.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/test_stages/cmd.py')
-rw-r--r--src/test_stages/cmd.py33
1 files changed, 29 insertions, 4 deletions
diff --git a/src/test_stages/cmd.py b/src/test_stages/cmd.py
index 68e9723..4c90cdb 100644
--- a/src/test_stages/cmd.py
+++ b/src/test_stages/cmd.py
@@ -65,9 +65,10 @@ class Config:
filename: pathlib.Path
get_all_envs: Callable[[Config], list[TestEnv]]
+ match_spec: parse.BoolExpr | None = None
stages: list[Stage] = dataclasses.field(default_factory=list)
utf8_env: dict[str, str] = dataclasses.field(
- default_factory=lambda: utf8_locale.UTF8Detect().detect().env
+ default_factory=lambda: utf8_locale.UTF8Detect().detect().env,
)
@@ -93,7 +94,8 @@ def select_stages(cfg: Config, all_stages: list[TestEnv]) -> list[TestStage]:
"""Group the stages as specified."""
def process_stage(
- acc: tuple[list[TestStage], list[TestEnv]], stage: Stage
+ acc: tuple[list[TestStage], list[TestEnv]],
+ stage: Stage,
) -> tuple[list[TestStage], list[TestEnv]]:
"""Stash the environments matched by a stage specification."""
res, current = acc
@@ -106,7 +108,19 @@ def select_stages(cfg: Config, all_stages: list[TestEnv]) -> list[TestStage]:
return res, left
res_init: Final[list[TestStage]] = []
- return functools.reduce(process_stage, cfg.stages, (res_init, list(all_stages)))[0]
+ selected: Final = functools.reduce(process_stage, cfg.stages, (res_init, list(all_stages)))[0]
+ match_spec: Final = cfg.match_spec
+ if match_spec is None:
+ return selected
+
+ matched_all: Final = [
+ stage._replace(envlist=[env for env in stage.envlist if match_spec.evaluate(env)])
+ for stage in selected
+ ]
+ matched: Final = [stage for stage in matched_all if stage.envlist]
+ if not matched:
+ sys.exit("None of the selected environments satisfied the additional match condition")
+ return matched
def extract_cfg(ctx: click.Context) -> Config:
@@ -175,6 +189,12 @@ def click_run() -> Callable[[Callable[[Config, list[TestStage], list[str]], None
),
)
@click.option(
+ "-m",
+ "--match-spec",
+ type=str,
+ help="additional stage specifications for the tests to run",
+ )
+ @click.option(
"-p",
"--parallel",
type=StagesList,
@@ -183,7 +203,11 @@ def click_run() -> Callable[[Callable[[Config, list[TestStage], list[str]], None
@click.argument("stages_spec", nargs=-1, required=False, type=str)
@click.pass_context
def real_run(
- ctx: click.Context, arg: list[str], parallel: StagesList | None, stages_spec: list[str]
+ ctx: click.Context,
+ arg: list[str],
+ match_spec: str | None,
+ parallel: StagesList | None,
+ stages_spec: list[str],
) -> None:
"""Run the test environments in stages."""
cfg_base: Final = extract_cfg(ctx)
@@ -196,6 +220,7 @@ def click_run() -> Callable[[Callable[[Config, list[TestStage], list[str]], None
pstages: Final = set(range(len(stages_spec))) if parallel is None else parallel.stages
cfg: Final = dataclasses.replace(
cfg_base,
+ match_spec=parse.parse_spec(match_spec) if match_spec is not None else None,
stages=[
Stage(spec, parse.parse_spec(spec), idx in pstages)
for idx, spec in enumerate(stages_spec)