The dependency-install fallback chain unconditionally ran 'pip install --user', which fails inside a virtualenv (and as root in LXC/containers) with 'Can not perform a --user install. User site-packages are not visible in this virtualenv.' — even though the function's docstring already noted --user is invalid in venvs. Guard the --user fallback with a venv check so it only runs outside a venv (where --user is actually valid for PEP-668 system Pythons). Derive the venv probe interpreter from the install command (python for 'pip', python3 for 'pip3'/'python3 -m pip') so the check runs in pip's own environment. System PEP-668 installs keep the --user fallback; venv/LXC-root installs no longer hit the --user error. Updated the unit test for the new chain. Closes #388
This commit is contained in:
@@ -152,13 +152,25 @@ def _pip_install_fallback_chain(package: str, *, python_cmd: str = "python3 -m p
|
||||
"""Build a bash pip install fallback chain.
|
||||
|
||||
Try the active interpreter/environment first. `--user` is invalid inside
|
||||
many venvs, so keep the user-site fallback for PEP-668 system Pythons only
|
||||
after the venv-safe attempt has failed.
|
||||
many venvs, so only attempt the --user fallback when NOT inside a venv.
|
||||
"""
|
||||
upgrade_flag = " -U" if upgrade else ""
|
||||
base = f"{python_cmd} install -q{upgrade_flag} {package} 2>/dev/null"
|
||||
user = f"{python_cmd} install --user --break-system-packages -q{upgrade_flag} {package} 2>/dev/null"
|
||||
return f"{base} || {user}"
|
||||
# Derive the python executable for the venv detection check.
|
||||
# Must use the same interpreter that pip belongs to; hardcoding
|
||||
# python3 breaks when pip lives in a venv that only has "python".
|
||||
if " -m pip" in python_cmd:
|
||||
python_exe = python_cmd.replace(" -m pip", "")
|
||||
elif python_cmd.strip() == "pip":
|
||||
python_exe = "python"
|
||||
elif python_cmd.strip() == "pip3":
|
||||
python_exe = "python3"
|
||||
else:
|
||||
python_exe = "python3"
|
||||
venv_check = f'{python_exe} -c "import sys; sys.exit(0 if sys.prefix != sys.base_prefix else 1)"'
|
||||
# venv_check exits 0 (true) when IN a venv; --user is only valid outside one.
|
||||
return f"{base} || {{ {venv_check} || {user}; }}"
|
||||
|
||||
|
||||
def _cached_model_scan_script(model_dirs: list[str] | None = None) -> str:
|
||||
|
||||
@@ -92,8 +92,9 @@ def test_pip_install_fallback_chain_prefers_venv_safe_install():
|
||||
def test_pip_install_fallback_chain_allows_custom_python_command():
|
||||
chain = _pip_install_fallback_chain("hf_transfer", python_cmd="pip", upgrade=False)
|
||||
assert chain == (
|
||||
"pip install -q hf_transfer 2>/dev/null || "
|
||||
"pip install --user --break-system-packages -q hf_transfer 2>/dev/null"
|
||||
'pip install -q hf_transfer 2>/dev/null || { '
|
||||
'python -c "import sys; sys.exit(0 if sys.prefix != sys.base_prefix else 1)"'
|
||||
' || pip install --user --break-system-packages -q hf_transfer 2>/dev/null; }'
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user