_initappimage in site.py

This commit is contained in:
Valentin Niess
2022-06-11 16:22:07 +02:00
parent d947ae8afb
commit cd5df332f1
6 changed files with 69 additions and 56 deletions

View File

@@ -106,6 +106,32 @@ def patch_binary(path, libdir, recursive=True):
patch_binary(target, libdir, recursive=True)
def patch_site(path, patch):
'''Patch the site.py module for running Python from an AppImage
'''
with open(path) as f:
source = f.read()
if '_initappimage' in source: return
lines = source.split(os.linesep)
for i, line in enumerate(lines):
if line.startswith('def main('): break
else:
return
with open(patch) as f:
patch = f.read()
lines.insert(i, patch)
lines.insert(i + 1, '')
source = os.linesep.join(lines)
with open(path, 'w') as f:
f.write(source)
def relocate_python(python=None, appdir=None):
'''Bundle a Python install inside an AppDir
'''
@@ -258,8 +284,14 @@ def relocate_python(python=None, appdir=None):
os.symlink('pip3', pip)
# Patch the site.py module
log('PATCH', '%s site.py', PYTHON_X_Y)
sitepath = PYTHON_PKG + '/site.py'
patch_site(sitepath, PREFIX + '/data/site-patch.py')
# Set a hook in Python for cleaning the path detection
log('HOOK', '%s site packages', PYTHON_X_Y)
log('HOOK', '%s site-packages', PYTHON_X_Y)
sitepkgs = PYTHON_PKG + '/site-packages'
make_tree(sitepkgs)

View File

@@ -1,9 +1,16 @@
{{ shebang }}
# Export APPRUN if running from an extracted image
self="$(readlink -f -- $0)"
here="${self%/*}"
APPDIR="${APPDIR:-${here}}"
# If running from an extracted image, then export ARGV0 and APPDIR
if [ -z "${APPIMAGE}" ]; then
export ARGV0=$0
self="$(readlink -f -- $0)"
here="${self%/*}"
export APPDIR="${APPDIR:-${here}}"
fi
# Resolve the calling command (preserving symbolic links).
export APPIMAGE_COMMAND="$(command -v -- $ARGV0)"
{{ tcltk-env }}
{{ cert-file }}

View File

@@ -1,25 +1 @@
for opt in "$@"
do
[ "${opt:0:1}" != "-" ] && break
if [[ "${opt}" =~ "I" ]] || [[ "${opt}" =~ "E" ]]; then
# Environment variables are disabled ($PYTHONHOME). Let's run in a safe
# mode from the raw Python binary inside the AppImage
"$APPDIR/opt/{{ python }}/bin/{{ python }}" "$@"
exit "$?"
fi
done
# Get the executable name, i.e. the AppImage or the python binary if running from an
# extracted image
executable="${APPDIR}/opt/{{ python }}/bin/{{ python }}"
if [[ "${ARGV0}" =~ "/" ]]; then
executable="$(cd $(dirname ${ARGV0}) && pwd)/$(basename ${ARGV0})"
elif [[ "${ARGV0}" != "" ]]; then
executable=$(which "${ARGV0}")
fi
# Wrap the call to Python in order to mimic a call from the source
# executable ($ARGV0), but potentially located outside of the Python
# install ($PYTHONHOME)
(PYTHONHOME="${APPDIR}/opt/{{ python }}" exec -a "${executable}" "$APPDIR/opt/{{ python }}/bin/{{ python }}" "$@")
exit "$?"
"$APPDIR/opt/{{ python }}/bin/{{ python }}" "$@"

View File

@@ -0,0 +1,16 @@
# This is a site.py patch when calling Python from an AppImage.
def _initappimage():
"""Initialise executable name for running from an AppImage."""
env = os.environ
try:
command = env["APPIMAGE_COMMAND"]
except KeyError:
return
if command and ("APPDIR" in env):
command = os.path.abspath(command)
sys.executable = command
sys._base_executable = command
_initappimage()
del _initappimage

View File

@@ -1,34 +1,10 @@
'''Hooks for isloating the AppImage Python and making it relocatable
'''Python AppImage hooks
'''
import atexit
import os
import sys
def clean_path():
'''Remove system locations from the packages search path
'''
site_packages = '/usr/local/lib/python{:}.{:}/site-packages'.format(
*sys.version_info[:2])
binaries_path = '/usr/local/bin'
env_path = os.getenv("PYTHONPATH")
if env_path is None:
env_path = []
else:
env_path = [os.path.realpath(path) for path in env_path.split(':')]
if ((os.path.dirname(sys.executable) != binaries_path) and
(site_packages not in env_path)):
# Remove the builtin site-packages from the path
try:
sys.path.remove(site_packages)
except ValueError:
pass
clean_path()
_bin_at_start = os.listdir(sys.prefix + '/bin')
'''Initial content of the bin/ directory
'''
@@ -108,4 +84,8 @@ def patch_pip_install():
os.remove(path)
atexit.register(patch_pip_install)
if os.getenv('VIRTUAL_ENV') is None:
atexit.register(patch_pip_install)
else:
del _bin_at_start
del patch_pip_install

View File

@@ -46,4 +46,6 @@ def docker_run(image, extra_cmds):
p = subprocess.Popen(cmd, shell=True)
p.communicate()
if p.returncode != 0:
if p.returncode == 139:
sys.stderr.write("segmentation fault when running Docker (139)\n")
sys.exit(p.returncode)