__init__.py 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. from __future__ import annotations
  2. import subprocess
  3. from shlex import quote
  4. from typing import TYPE_CHECKING
  5. if TYPE_CHECKING:
  6. from collections.abc import Mapping
  7. CREATE_NO_WINDOW = 0x80000000
  8. class LogCmd:
  9. def __init__(self, cmd: list[str], env: Mapping[str, str] | None = None) -> None:
  10. self.cmd = cmd
  11. self.env = env
  12. def __repr__(self) -> str:
  13. cmd_repr = " ".join(quote(str(c)) for c in self.cmd)
  14. if self.env is not None:
  15. cmd_repr = f"{cmd_repr} env of {self.env!r}"
  16. return cmd_repr
  17. def run_cmd(cmd: list[str]) -> tuple[int, str, str]:
  18. try:
  19. process = subprocess.Popen(
  20. cmd,
  21. universal_newlines=True,
  22. stdin=subprocess.PIPE,
  23. stderr=subprocess.PIPE,
  24. stdout=subprocess.PIPE,
  25. encoding="utf-8",
  26. )
  27. out, err = process.communicate() # input disabled
  28. code = process.returncode
  29. except OSError as error:
  30. code, out, err = error.errno, "", error.strerror
  31. if code == 2 and err is not None and "file" in err: # noqa: PLR2004
  32. err = str(error) # FileNotFoundError in Python >= 3.3
  33. return code, out, err # ty: ignore[invalid-return-type]
  34. __all__ = (
  35. "CREATE_NO_WINDOW",
  36. "LogCmd",
  37. "run_cmd",
  38. )