fix(install): avoid apt-package uninstall failure during web dep install (#371)

* fix(install): avoid apt-package uninstall failure on web deps

On a fresh Pi install, requests is installed via apt (python3-requests),
which ships no pip RECORD file. When pip later installs
google-api-python-client, its dependency tree pulls a newer requests and
attempts to uninstall the apt copy, failing with "uninstall-no-record-file"
and aborting the whole install at step 7 (web interface dependencies).

Add --ignore-installed to install_via_pip so pip lays the new version down
in /usr/local (shadowing the apt copy) instead of trying to remove an
apt-managed package. This resolves the failure for any transitive
dependency pip needs to upgrade over an apt-installed package, not just
requests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(install): also pass --ignore-installed for local rgbmatrix install

Keeps the rgbmatrix pip install consistent with install_via_pip so it
won't fail trying to uninstall an apt-managed dependency either.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ron Pierce
2026-06-15 11:06:56 -07:00
committed by GitHub
parent ab0cfd2362
commit 974d7ea57a

View File

@@ -75,12 +75,20 @@ def install_via_pip(package_name):
Debian/Ubuntu-based systems without a virtual environment. Debian/Ubuntu-based systems without a virtual environment.
--prefer-binary prefers pre-built wheels over source distributions to avoid --prefer-binary prefers pre-built wheels over source distributions to avoid
exhausting /tmp space during compilation. exhausting /tmp space during compilation.
--ignore-installed stops pip from trying to *uninstall* packages that were
installed by apt (e.g. python3-requests). Those Debian packages ship no
pip RECORD file, so an uninstall attempt fails with "uninstall-no-record-file"
and aborts the whole install. With --ignore-installed, pip lays the new
version down in /usr/local where it shadows the apt copy instead of removing
it. This matters when a pip dependency (google-api-python-client pulls a
newer requests) needs to upgrade an apt-managed package.
Returns (success, output). Returns (success, output).
""" """
print(f"Installing {package_name} via pip...") print(f"Installing {package_name} via pip...")
success, output = _run([ success, output = _run([
sys.executable, '-m', 'pip', 'install', '--break-system-packages', '--prefer-binary', package_name sys.executable, '-m', 'pip', 'install',
'--break-system-packages', '--prefer-binary', '--ignore-installed', package_name
]) ])
if success: if success:
print(f"Successfully installed {package_name} via pip") print(f"Successfully installed {package_name} via pip")
@@ -200,7 +208,7 @@ def main():
if setup_py.exists(): if setup_py.exists():
# Try installing - use regular install, not editable mode # Try installing - use regular install, not editable mode
# This is optional for web interface and should already be installed in Step 6 # This is optional for web interface and should already be installed in Step 6
ok, output = _run([sys.executable, '-m', 'pip', 'install', '--break-system-packages', str(rgbmatrix_path)]) ok, output = _run([sys.executable, '-m', 'pip', 'install', '--break-system-packages', '--ignore-installed', str(rgbmatrix_path)])
if ok: if ok:
print("rgbmatrix module installed successfully") print("rgbmatrix module installed successfully")
else: else: