mirror of
https://github.com/valentderah/totk-pc-recomp.git
synced 2026-11-11 01:41:02 +00:00
Merge pull request #990: Linux AppImage: ignore the user site-packages so installer.gui imports (jay23606)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
35968c1efb
2 files changed
+59
No files matched your search
@@ -0,0 +1,57 @@
|
||||
"""The AppImage entry must ignore the user's site-packages (issue 985).
|
||||
|
||||
AppRun starts the bundled Python with `-m installer.gui`. Without PYTHONNOUSERSITE, a PyPI package named `installer`
|
||||
in the user site shadows the project's own installer package and the window fails with "No module named installer.gui".
|
||||
|
||||
The test reads the export lines from AppRun, then runs Python with that environment against a fake user site holding
|
||||
a shadowing `installer` package (no `gui`) and a fake bundle holding the real layout. The bundle is added the way
|
||||
totk-release.pth adds it, after the user site, so the user site wins unless AppRun turns it off.
|
||||
"""
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
sys.path.insert(0, str(ROOT / 'tools'))
|
||||
|
||||
import make_release_linux # noqa: E402
|
||||
|
||||
line = 'export PYTHONNOUSERSITE=1'
|
||||
lines = make_release_linux.APPRUN.splitlines()
|
||||
|
||||
# Environment from AppRun's export lines. Values that refer to $HERE point into the mount and are not needed here.
|
||||
env = dict(os.environ)
|
||||
env.pop('PYTHONNOUSERSITE', None)
|
||||
for text in lines:
|
||||
if text.startswith('export ') and '=' in text and '$' not in text:
|
||||
name, value = text[len('export '):].split('=', 1)
|
||||
env[name] = value
|
||||
env.pop('PYTHONPATH', None)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
tmp = Path(tmp)
|
||||
user_base = tmp / 'userbase'
|
||||
env['PYTHONUSERBASE'] = str(user_base)
|
||||
user_site = Path(subprocess.run(
|
||||
[sys.executable, '-c', 'import site; print(site.getusersitepackages())'],
|
||||
env=env, capture_output=True, text=True, check=True, cwd=tmp).stdout.strip())
|
||||
shadow = user_site / 'installer'
|
||||
shadow.mkdir(parents=True)
|
||||
(shadow / '__init__.py').write_text('# stands in for the PyPI "installer" package: no gui submodule\n')
|
||||
|
||||
bundle = tmp / 'bundle'
|
||||
(bundle / 'installer').mkdir(parents=True)
|
||||
(bundle / 'installer' / '__init__.py').write_text('')
|
||||
(bundle / 'installer' / 'gui.py').write_text('print("gui imported")\n')
|
||||
|
||||
code = 'import site, sys; site.addsitedir(sys.argv[1]); import installer.gui'
|
||||
result = subprocess.run([sys.executable, '-c', code, str(bundle)],
|
||||
env=env, capture_output=True, text=True, cwd=tmp)
|
||||
assert result.returncode == 0, f'installer.gui not importable with AppRun env: {result.stderr.strip()}'
|
||||
|
||||
# Checked last so the import behaviour is what fails on the base commit; this line guards the mechanism.
|
||||
assert line in lines, f'AppRun does not set {line!r}; AppRun lines: {lines}'
|
||||
|
||||
print('AppRun sets PYTHONNOUSERSITE=1 and bundled installer.gui imports past a user-site shadow')
|
||||
@@ -426,6 +426,8 @@ APPRUN = '''#!/bin/sh
|
||||
# The AppImage entry: the setup window, run by the bundled Python from the read-only mount (no bytecode written there).
|
||||
HERE="$(dirname "$(readlink -f "$0")")"
|
||||
export PYTHONDONTWRITEBYTECODE=1
|
||||
# Ignore ~/.local/lib/pythonX.Y/site-packages: a user-installed package such as PyPI's `installer` would shadow ours
|
||||
export PYTHONNOUSERSITE=1
|
||||
export TCL_LIBRARY="$HERE/python/lib/tcl9.0"
|
||||
export TK_LIBRARY="$HERE/python/lib/tk9.0"
|
||||
exec "$HERE/python/bin/python3" -m installer.gui "$@"
|
||||
|
||||
Reference in new issue
Block a user