commands.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import distlib.scripts
  2. import io
  3. import os.path as osp
  4. import shutil
  5. from zipfile import ZipFile
  6. SCRIPT_TEMPLATE = u"""# -*- coding: utf-8 -*-
  7. import sys, os
  8. import site
  9. installdir = os.path.dirname(os.path.dirname(__file__))
  10. pkgdir = os.path.join(installdir, 'pkgs')
  11. sys.path.insert(0, pkgdir)
  12. # Ensure .pth files in pkgdir are handled properly
  13. site.addsitedir(pkgdir)
  14. os.environ['PYTHONPATH'] = pkgdir + os.pathsep + os.environ.get('PYTHONPATH', '')
  15. # Allowing .dll files in Python directory to be found
  16. os.environ['PATH'] += ';' + os.path.dirname(sys.executable)
  17. {extra_preamble}
  18. if __name__ == '__main__':
  19. from {module} import {func}
  20. sys.exit({func}())
  21. """
  22. def find_exe(bitness=32, console=True):
  23. distlib_dir = osp.dirname(distlib.scripts.__file__)
  24. name = 't' if console else 'w'
  25. return osp.join(distlib_dir, '{name}{bitness}.exe'.format(name=name, bitness=bitness))
  26. def prepare_bin_directory(target, commands, bitness=32):
  27. # Give the base launcher a .dat extension so it doesn't show up as an
  28. # executable command itself. During the installation it will be copied to
  29. # each launcher name, and the necessary data appended to it.
  30. shutil.copy(find_exe(bitness, True), str(target / 'launcher_exe.dat'))
  31. shutil.copy(find_exe(bitness, False), str(target / 'launcher_noconsole_exe.dat'))
  32. for name, command in commands.items():
  33. specified_preamble = command.get('extra_preamble', None)
  34. if isinstance(specified_preamble, str):
  35. # Filename
  36. extra_preamble = io.open(specified_preamble, encoding='utf-8')
  37. elif specified_preamble is None:
  38. extra_preamble = io.StringIO() # Empty
  39. else:
  40. # Passed a StringIO or similar object
  41. extra_preamble = specified_preamble
  42. module, func = command['entry_point'].split(':')
  43. script = SCRIPT_TEMPLATE.format(
  44. module=module, func=func,
  45. extra_preamble=extra_preamble.read().rstrip(),
  46. )
  47. if command.get('console', True):
  48. append = '-append.zip'
  49. else:
  50. append = '-append-noconsole.zip'
  51. with ZipFile(str(target / (name + append)), 'w') as zf:
  52. zf.writestr('__main__.py', script.encode('utf-8'))