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
44
45
46
|
"""Locate and invoke the pipx executable (ADR-0024). No pipx Python library."""
from __future__ import annotations
import os
import shutil
import subprocess
from collections.abc import Mapping
from pathlib import Path
from lpip.errors import PipxNotFoundError
def find_pipx_executable(*, environ: Mapping[str, str] | None = None) -> Path | None:
env = environ if environ is not None else os.environ
found = shutil.which("pipx", path=env.get("PATH"))
return Path(found) if found else None
def require_pipx(*, environ: Mapping[str, str] | None = None) -> Path:
found = find_pipx_executable(environ=environ)
if found is None:
raise PipxNotFoundError()
return found
def pipx_install_argv(pipx: str, requirement: str) -> list[str]:
"""Replace an existing pipx app of this name; do not call pipx upgrade."""
return [pipx, "install", "--force", requirement]
def format_pipx_install_command(pipx: str, requirement: str) -> str:
return f'{pipx} install --force "{requirement}"'
def run_pipx_install(
pipx: str,
requirement: str,
*,
environ: Mapping[str, str] | None = None,
) -> int:
completed = subprocess.run( # nosec B603
pipx_install_argv(pipx, requirement),
env=dict(environ) if environ is not None else None,
)
return completed.returncode
|