summaryrefslogtreecommitdiff
path: root/src/tox/session/cmd/exec_.py
blob: 891189b76211b0db9676581bb1f9ad2c4df9e3de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
"""
Execute a command in a tox environment.
"""
from __future__ import annotations

from pathlib import Path

from tox.config.cli.parser import ToxParser
from tox.config.loader.memory import MemoryLoader
from tox.config.types import Command
from tox.plugin import impl
from tox.report import HandledError
from tox.session.cmd.run.common import env_run_create_flags
from tox.session.cmd.run.sequential import run_sequential
from tox.session.env_select import CliEnv, register_env_select_flags
from tox.session.state import State


@impl
def tox_add_option(parser: ToxParser) -> None:
    our = parser.add_command("exec", ["e"], "execute an arbitrary command within a tox environment", exec_)
    our.epilog = "For example: tox exec -e py39 -- python --version"
    register_env_select_flags(our, default=CliEnv("py"), multiple=False)
    env_run_create_flags(our, mode="exec")


def exec_(state: State) -> int:
    envs = list(state.envs.iter())
    if len(envs) != 1:
        raise HandledError(f"exactly one target environment allowed in exec mode but found {', '.join(envs)}")
    loader = MemoryLoader(  # these configuration values are loaded from in-memory always (no file conf)
        commands_pre=[],
        commands=[],
        commands_post=[],
    )
    conf = state.envs[envs[0]].conf
    conf.loaders.insert(0, loader)
    to_path: Path | None = conf["change_dir"] if conf["args_are_paths"] else None
    pos_args = state.conf.pos_args(to_path)
    if not pos_args:
        raise HandledError("You must specify a command as positional arguments, use -- <command>")
    loader.raw["commands"] = [Command(list(pos_args))]
    return run_sequential(state)