Преглед изворни кода

Add a shebang patcher to site hooks

Valentin Niess пре 5 година
родитељ
комит
15a34b71ab
1 измењених фајлова са 54 додато и 5 уклоњено
  1. 54 5
      python_appimage/data/sitecustomize.py

+ 54 - 5
python_appimage/data/sitecustomize.py

@@ -1,18 +1,21 @@
-"""Hook for cleaning the paths detected by Python
-"""
+'''Hooks for isloating the AppImage Python and making it relocatable
+'''
+import atexit
 import os
 import sys
 
 
 def clean_path():
-    site_packages = "/usr/local/lib/python{:}.{:}/site-packages".format(
+    '''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"
+    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(":")]
+        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)):
@@ -24,3 +27,49 @@ def clean_path():
 
 
 clean_path()
+
+
+def patch_pip_install():
+    '''Change absolute shebangs to relative ones following a `pip` install
+    '''
+    if ('pip' in sys.modules) and ('install' in sys.argv[1:]):
+        for exe in os.listdir(sys.prefix + '/bin'):
+            path = os.path.join(sys.prefix, 'bin', exe)
+
+            if (not os.path.isfile(path)) or (not os.access(path, os.X_OK)) or \
+               exe.startswith('python') or os.path.islink(path):
+                continue
+
+            with open(path, 'r') as f:
+                header = f.read(2)
+                if header != '#!':
+                    continue
+                content = f.read()
+
+            shebang, body = content.split(os.linesep, 1)
+            shebang = shebang.split()
+            python_x_y = os.path.basename(shebang.pop(0))
+            if not python_x_y.startswith('python'):
+                continue
+
+            relpath = os.path.relpath(
+                sys.prefix + '/../../usr/bin/' + python_x_y,
+                sys.prefix + '/bin')
+            shebang.append('"$@"')
+            cmd = (
+                '"exec"',
+                '"$(dirname $(readlink -f ${0}))/' + relpath + '"',
+                '"$0"',
+                ' '.join(shebang)
+            )
+
+            try:
+                with open(path, 'w') as f:
+                    f.write('#! /bin/sh\n')
+                    f.write(' '.join(cmd) + '\n')
+                    f.write(body)
+            except IOError:
+                pass
+
+
+atexit.register(patch_pip_install)