Skip to content

fix(cookbook): recognize runtime --user installs by replaying user-site .pth hooks#4811

Open
devpedrobarbosa wants to merge 2 commits into
pewdiepie-archdaemon:devfrom
devpedrobarbosa:fix/cookbook-runtime-user-install-pth-hooks
Open

fix(cookbook): recognize runtime --user installs by replaying user-site .pth hooks#4811
devpedrobarbosa wants to merge 2 commits into
pewdiepie-archdaemon:devfrom
devpedrobarbosa:fix/cookbook-runtime-user-install-pth-hooks

Conversation

@devpedrobarbosa

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #4694. The Real-ESRGAN build now succeeds, but the dependency was still shown as not installed in Cookbook → Dependencies, and a browser hard refresh never fixed it — only a full container restart did.

Root cause: the local optional-dep probe in list_packages decides "installed" by importing the package in-process. Cookbook installs optional deps with pip install --user, so the package lands in user-site along with setuptools' distutils-precedence.pth. On Python 3.12+ distutils is gone from the stdlib and is only restored by that .pth. When the dep is installed into an already-running server, user-site was never processed by site; the recovery used sys.path.append(user_site), which makes modules importable but does not execute user-site .pth files. So import basicsr (a realesrgan dep) → import distutils raised ModuleNotFoundError: No module named 'distutils', the probe caught it as ImportError, and realesrgan read as not-installed until a process restart.

Fix: use site.addsitedir(user_site) instead of sys.path.append(user_site) so user-site .pth hooks (incl. the setuptools distutils shim) are replayed when a package is installed into a running process.

Target branch

  • This PR targets dev, not main.

Linked Issue

Fixes #4810

Type of Change

  • Bug fix (non-breaking — fixes a confirmed issue)
  • New feature (non-breaking — adds new behaviour)
  • Breaking change (changes or removes existing behaviour)
  • Refactor / cleanup (behaviour unchanged)
  • Documentation only
  • CI / tooling / configuration

Checklist

  • I searched open issues and open PRs — this is not a duplicate.
  • This PR targets dev
  • My changes are limited to the scope described above — no unrelated refactors or whitespace changes mixed in.
  • I actually ran the app (docker compose up) and verified the change works end-to-end. Type-checks and unit tests are not enough.

How to Test

On the python:3.14 image (docker compose up -d --build):

  1. Reproduce (before this PR): with the server already running, install realesrgan from Cookbook → Dependencies. It builds/installs (importlib.metadata.version("realesrgan") == "0.3.0"), but the panel still shows it not installed, and a hard refresh doesn't help. Confirmed the in-process probe path fails:
    docker compose exec -u odysseus odysseus python -s -c \
      'import sys,site; sys.path.append(site.getusersitepackages()); import realesrgan'
    # ModuleNotFoundError: No module named 'distutils'
  2. With this PR: the same probe path uses site.addsitedir(...) and resolves:
    docker compose exec -u odysseus odysseus python -s -c \
      'import sys,site; site.addsitedir(site.getusersitepackages()); import realesrgan; print("ok")'
    # ok
  3. Verify recognition: reload the Dependencies panel — realesrgan shows installed without a restart. Confirmed via the exact local-probe path:
    docker compose exec -u odysseus odysseus python -c \
      'from src.optional_deps import prepare_optional_dependency_import as p; \
       import importlib, importlib.metadata as m; p("realesrgan"); \
       importlib.import_module("realesrgan"); print(m.version("realesrgan"))'
    # 0.3.0
  4. Confirm the .pth is user-site only: distutils-precedence.pth exists in /app/.local/lib/python3.14/site-packages/ but not in the main site-packages — which is why a plain sys.path.append left distutils unavailable.

Visual / UI changes — REQUIRED if you touched anything that renders

N/A — no UI/rendering changes. Touches only routes/shell_routes.py (one line in the list_packages user-site prologue, plus an explanatory comment).

Local optional-dep probing in `list_packages` decides "installed" by
importing the package in-process. When a dep is installed at runtime via
Cookbook -> Dependencies (`pip install --user`) into a long-lived server
that started before the install, user-site was never processed by `site`.

The recovery used `sys.path.append(user_site)`, which makes modules
importable but does NOT execute user-site `.pth` files. On Python 3.12+
`distutils` is gone from the stdlib and is only restored by setuptools'
`distutils-precedence.pth` (shipped in user-site). basicsr (a realesrgan
dep) does `import distutils` at import time, so the probe failed with
`ModuleNotFoundError: No module named 'distutils'` and reported realesrgan
as not installed until a full restart.

Use `site.addsitedir(user_site)` instead so user-site `.pth` hooks are
replayed and the distutils shim activates. Verified end-to-end on the
python:3.14 image: realesrgan now probes as installed without a restart.

Fixes pewdiepie-archdaemon#4810

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added the ready for review Description complete — ready for maintainer review label Jun 24, 2026
The regression test pinned the old `sys.path.append(user_site)` source
text. Update it to assert the new `site.addsitedir(user_site)` guarantee
that user-site `.pth` hooks are replayed for runtime --user installs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@alteixeira20 alteixeira20 added the bug Something isn't working label Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working ready for review Description complete — ready for maintainer review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cookbook: realesrgan installs but is not recognized — runtime --user installs don't replay user-site .pth hooks (distutils shim)

2 participants