Files
pkgmgr/src/pkgmgr/actions/install/installers/nix/runner.py
T
Kevin Veen-BirkenbachandClaude Opus 5 b4e0594901 style: modernise typing and clean up lint findings
Repository-wide mechanical cleanup so `ruff check src tests` has a chance
of passing; no behavioural changes.

- Add `from __future__ import annotations` where PEP 604 unions are used.
  This has to come first: pyproject declares requires-python >= 3.9, where
  `X | None` is not evaluable at runtime unless annotations are stringified.
- Replace typing.List/Dict/Tuple/Set with the builtin generics and
  Optional[X] with X | None, then drop the imports that became unused.
  The four actions/*/__init__.py files needed this by hand because ruff
  leaves unused imports in __init__.py alone (possible re-exports).
- Strip shebangs from 72 importable modules. None of them are executable
  or invoked directly; the entry points are console_scripts and runpy.
- Flatten nested `with` blocks, collapse needless-bool returns, and apply
  the remaining mechanical ruff fixes (PIE810, FLY002, PERF102, FURB192,
  RUF059, I001).
- Pass check=False explicitly to the four subprocess.run() calls that
  inspect returncode themselves. That is the existing default.

Two rewrites are visible to mocks, so their tests move with them:
subprocess.run(stdout=PIPE, stderr=PIPE) became capture_output=True, and
open(path, "r", ...) lost the redundant mode.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 16:47:13 +02:00

66 lines
1.9 KiB
Python

from __future__ import annotations
import subprocess
from typing import TYPE_CHECKING
from .types import RunResult
if TYPE_CHECKING:
from pkgmgr.actions.install.context import RepoContext
class CommandRunner:
"""
Executes commands (shell=True) inside a repository directory (if provided).
Supports preview mode and compact failure output logging.
"""
def run(self, ctx: RepoContext, cmd: str, allow_failure: bool) -> RunResult:
repo_dir = getattr(ctx, "repo_dir", None) or getattr(ctx, "repo_path", None)
preview = bool(getattr(ctx, "preview", False))
quiet = bool(getattr(ctx, "quiet", False))
if preview:
if not quiet:
print(f"[preview] {cmd}")
return RunResult(returncode=0, stdout="", stderr="")
try:
p = subprocess.run(
cmd,
shell=True,
cwd=repo_dir,
check=False,
capture_output=True,
text=True,
)
except Exception as e:
if not allow_failure:
raise
return RunResult(returncode=1, stdout="", stderr=str(e))
res = RunResult(
returncode=p.returncode, stdout=p.stdout or "", stderr=p.stderr or ""
)
if res.returncode != 0 and not quiet:
self._print_compact_failure(res)
if res.returncode != 0 and not allow_failure:
raise SystemExit(res.returncode)
return res
@staticmethod
def _print_compact_failure(res: RunResult) -> None:
out = (res.stdout or "").strip()
err = (res.stderr or "").strip()
if out:
print("[nix] stdout (last lines):")
print("\n".join(out.splitlines()[-20:]))
if err:
print("[nix] stderr (last lines):")
print("\n".join(err.splitlines()[-40:]))