Skip to content

Runner

runner

Subprocess runner that targets the audited project's venv.

When auditing an external project, tools (ruff, mypy, pytest, etc.) must execute in that project's virtual environment, not axm-audit's own.

run_in_project(cmd, project_path, *, timeout=_DEFAULT_TIMEOUT, with_packages=None, **kwargs)

Run a command in the target project's environment.

Locates the nearest .venv/ — either in project_path itself or in an ancestor directory (for uv monorepo workspace members). Uses uv run --directory to execute the command within the correct environment. Falls back to running the command directly with cwd set when no virtual environment is found.

Parameters:

Name Type Description Default
cmd list[str]

Command and arguments to run.

required
project_path Path

Root of the project being audited.

required
timeout int

Maximum seconds to wait before killing the subprocess. Defaults to 300 (5 minutes).

_DEFAULT_TIMEOUT
with_packages list[str] | None

Optional packages to inject at runtime via uv run --with <pkg>. Only effective when a .venv/ is found (i.e. when uv run is used). Allows audit tools to be available in the target project without requiring them as declared dependencies.

None
**kwargs Any

Extra arguments forwarded to subprocess.run.

{}

Returns:

Type Description
CompletedProcess[str]

CompletedProcess result. On timeout, returns a synthetic result

CompletedProcess[str]

with returncode=124 and the timeout message in stderr.

Source code in packages/axm-audit/src/axm_audit/core/runner.py
def run_in_project(
    cmd: list[str],
    project_path: Path,
    *,
    timeout: int = _DEFAULT_TIMEOUT,
    with_packages: list[str] | None = None,
    **kwargs: Any,
) -> subprocess.CompletedProcess[str]:
    """Run a command in the target project's environment.

    Locates the nearest ``.venv/`` — either in ``project_path`` itself
    or in an ancestor directory (for uv monorepo workspace members).
    Uses ``uv run --directory`` to execute the command within the
    correct environment.  Falls back to running the command directly
    with ``cwd`` set when no virtual environment is found.

    Args:
        cmd: Command and arguments to run.
        project_path: Root of the project being audited.
        timeout: Maximum seconds to wait before killing the subprocess.
            Defaults to 300 (5 minutes).
        with_packages: Optional packages to inject at runtime via
            ``uv run --with <pkg>``.  Only effective when a ``.venv/``
            is found (i.e. when ``uv run`` is used).  Allows audit tools
            to be available in the target project without requiring
            them as declared dependencies.
        **kwargs: Extra arguments forwarded to ``subprocess.run``.

    Returns:
        CompletedProcess result.  On timeout, returns a synthetic result
        with ``returncode=124`` and the timeout message in ``stderr``.
    """
    venv = _find_venv(project_path)

    if venv is not None:
        with_flags: list[str] = []
        for pkg in with_packages or []:
            with_flags.extend(["--with", pkg])
        full_cmd = ["uv", "run", *with_flags, "--directory", str(project_path), *cmd]
    else:
        full_cmd = cmd
        kwargs.setdefault("cwd", str(project_path))

    try:
        return subprocess.run(full_cmd, timeout=timeout, **kwargs)  # noqa: S603
    except subprocess.TimeoutExpired:
        cmd_str = " ".join(full_cmd)
        logger.warning("Command timed out after %ds: %s", timeout, cmd_str)
        return subprocess.CompletedProcess(
            args=full_cmd,
            returncode=124,
            stdout="",
            stderr=f"Command timed out after {timeout}s: {cmd_str}",
        )