sitecustomize.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. '''Hooks for isloating the AppImage Python and making it relocatable
  2. '''
  3. import atexit
  4. import os
  5. import sys
  6. def clean_path():
  7. '''Remove system locations from the packages search path
  8. '''
  9. site_packages = '/usr/local/lib/python{:}.{:}/site-packages'.format(
  10. *sys.version_info[:2])
  11. binaries_path = '/usr/local/bin'
  12. env_path = os.getenv("PYTHONPATH")
  13. if env_path is None:
  14. env_path = []
  15. else:
  16. env_path = [os.path.realpath(path) for path in env_path.split(':')]
  17. if ((os.path.dirname(sys.executable) != binaries_path) and
  18. (site_packages not in env_path)):
  19. # Remove the builtin site-packages from the path
  20. try:
  21. sys.path.remove(site_packages)
  22. except ValueError:
  23. pass
  24. clean_path()
  25. _bin_at_start = os.listdir(sys.prefix + '/bin')
  26. '''Initial content of the bin/ directory
  27. '''
  28. def patch_pip_install():
  29. '''Change absolute shebangs to relative ones following a `pip` install
  30. '''
  31. if not 'pip' in sys.modules:
  32. return
  33. args = sys.argv[1:]
  34. if 'install' in args:
  35. for exe in os.listdir(sys.prefix + '/bin'):
  36. path = os.path.join(sys.prefix, 'bin', exe)
  37. if (not os.path.isfile(path)) or (not os.access(path, os.X_OK)) or \
  38. exe.startswith('python') or os.path.islink(path) or \
  39. exe.endswith('.pyc') or exe.endswith('.pyo'):
  40. continue
  41. try:
  42. with open(path, 'r') as f:
  43. header = f.read(2)
  44. if header != '#!':
  45. continue
  46. content = f.read()
  47. except:
  48. continue
  49. shebang, body = content.split(os.linesep, 1)
  50. shebang = shebang.split()
  51. python_x_y = os.path.basename(shebang.pop(0))
  52. if not python_x_y.startswith('python'):
  53. head, altbody = body.split(os.linesep, 1)
  54. if head.startswith("'''exec' /"): # Patch for alt shebang
  55. body = altbody.split(os.linesep, 1)[1]
  56. python_x_y = os.path.basename(head.split()[1])
  57. else:
  58. continue
  59. relpath = os.path.relpath(
  60. sys.prefix + '/../../usr/bin/' + python_x_y,
  61. sys.prefix + '/bin')
  62. shebang.append('"$@"')
  63. cmd = (
  64. '"exec"',
  65. '"$(dirname $(readlink -f ${0}))/' + relpath + '"',
  66. '"$0"',
  67. ' '.join(shebang)
  68. )
  69. try:
  70. with open(path, 'w') as f:
  71. f.write('#! /bin/sh\n')
  72. f.write(' '.join(cmd) + '\n')
  73. f.write(body)
  74. except IOError:
  75. continue
  76. if exe in _bin_at_start:
  77. continue
  78. usr_dir = os.path.join(sys.prefix, '../../usr/bin')
  79. usr_exe = os.path.join(usr_dir, exe)
  80. if not os.path.exists(usr_exe):
  81. relpath = os.path.relpath(path, usr_dir)
  82. os.symlink(relpath, usr_exe)
  83. elif 'uninstall' in args:
  84. usr_dir = os.path.join(sys.prefix, '../../usr/bin')
  85. for exe in os.listdir(usr_dir):
  86. path = os.path.join(usr_dir, exe)
  87. if (not os.path.islink(path)) or \
  88. os.path.exists(os.path.realpath(path)):
  89. continue
  90. os.remove(path)
  91. atexit.register(patch_pip_install)