Compare commits

...

1 commit

Author SHA1 Message Date
5d2eb8dde5 Prefer pipx over pip3 --break-system-packages for Python tools
The previous fallback chain (pip3 install → pip3 install
--break-system-packages) silently writes into the distro Python's
site-packages on PEP 668 systems (Debian 12+, Ubuntu 23.04+). The warn
message fires after the damage is done. Since the target audience is
engineers SSH-ing into Linux servers, the PEP 668 hit rate is high.

New order:
  1. pipx install   (isolated per-tool venvs)
  2. pip3 --user    (works on pre-PEP-668 Python)
  3. --break-system-packages  (gated behind CHOPSTICKS_ALLOW_BREAK_SYSTEM=1)
  4. fail with a remediation hint

Also:
- Bootstrap pipx via the system package manager if it's missing.
- Warn if $HOME/.local/bin is absent from PATH (pipx and pip --user
  both install there).

Closes #66
2026-05-16 22:42:56 +08:00
2 changed files with 37 additions and 7 deletions

View file

@ -23,6 +23,10 @@
### Fixed
- `install.sh` Python tools now prefer `pipx` and `pip3 --user` over
`pip3 install --break-system-packages`; the break-system path is gated
behind `CHOPSTICKS_ALLOW_BREAK_SYSTEM=1` so PEP 668 distros are no
longer silently polluted
- `g:loaded_logipat` typo → `g:loaded_logiPat` — logiPat was loading fully (0.478ms wasted)
- `get.sh` now refuses to update an existing `~/.vim` git repo unless its
origin is chopsticks

View file

@ -966,19 +966,45 @@ elif [[ $_I_PYTHON -lt 0 ]] || ! _selected "$_I_PYTHON"; then
skip "Python tool suite (skipped by user)"
SKIPPED+=("black" "isort" "flake8" "pylint" "yamllint" "sqlfluff")
else
# Prefer pipx (isolated per-tool venvs, the recommended path on PEP 668
# distros like Debian 12+/Ubuntu 23.04+). Bootstrap pipx via the system
# package manager if missing. Only fall back to --break-system-packages
# if the user explicitly opts in.
if ! command -v pipx >/dev/null 2>&1; then
if pkg_install pipx pipx python-pipx pipx 2>/dev/null; then
ok "pipx (recommended Python CLI installer)"
else
warn "pipx not available — falling back to pip3 --user"
fi
fi
case ":$PATH:" in
*":$HOME/.local/bin:"*) ;;
*) warn "\$HOME/.local/bin is not on PATH — pipx/pip --user tools will not be found"
info "Add to your shell rc: export PATH=\"\$HOME/.local/bin:\$PATH\"" ;;
esac
pip_install() {
local pkg="$1" check="${2:-$1}"
if command -v "$check" >/dev/null 2>&1; then
ok "$pkg (already installed)"; return
fi
if pip3 install --quiet "$pkg" 2>/dev/null; then
ok "$pkg"; INSTALLED+=("$pkg")
elif pip3 install --quiet --break-system-packages "$pkg" 2>/dev/null; then
warn "$pkg installed with --break-system-packages (consider using a virtualenv)"
ok "$pkg"; INSTALLED+=("$pkg")
else
fail "$pkg"; FAILED+=("$pkg")
if command -v pipx >/dev/null 2>&1 && pipx install --quiet "$pkg" 2>/dev/null; then
ok "$pkg (via pipx)"; INSTALLED+=("$pkg")
return
fi
if pip3 install --quiet --user "$pkg" 2>/dev/null; then
ok "$pkg (via pip --user)"; INSTALLED+=("$pkg")
return
fi
if [[ "${CHOPSTICKS_ALLOW_BREAK_SYSTEM:-0}" == "1" ]] && \
pip3 install --quiet --break-system-packages "$pkg" 2>/dev/null; then
warn "$pkg installed with --break-system-packages (CHOPSTICKS_ALLOW_BREAK_SYSTEM=1)"
INSTALLED+=("$pkg")
return
fi
fail "$pkg — install pipx, or set CHOPSTICKS_ALLOW_BREAK_SYSTEM=1 to bypass PEP 668"
FAILED+=("$pkg")
}
pip_install black
pip_install isort