__main__.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import argparse
  2. from importlib import import_module
  3. import os
  4. import sys
  5. __all__ = ['main']
  6. def exists(path):
  7. if not os.path.exists(path):
  8. raise argparse.ArgumentTypeError("could not find: {}".format(path))
  9. return os.path.abspath(path)
  10. def main():
  11. '''Entry point for the CLI
  12. '''
  13. # Binary dependencies
  14. binaries = ('appimagetool', 'patchelf')
  15. # Parse arguments
  16. parser = argparse.ArgumentParser(
  17. prog='python-appimage',
  18. description='Bundle a Python installation into an AppImage')
  19. subparsers = parser.add_subparsers(title='command',
  20. help='Command to execute',
  21. dest='command')
  22. parser.add_argument('-a', '--appimagetool-version',
  23. help='set appimagetool version')
  24. parser.add_argument('-q', '--quiet', help='disable logging',
  25. dest='verbosity', action='store_const', const='ERROR')
  26. parser.add_argument('-v', '--verbose', help='print extra information',
  27. dest='verbosity', action='store_const', const='DEBUG')
  28. install_parser = subparsers.add_parser('install',
  29. description='Install binary dependencies')
  30. install_parser.add_argument('binary', nargs='+',
  31. choices=binaries, help='one or more binary name')
  32. build_parser = subparsers.add_parser('build',
  33. description='Build a Python appimage')
  34. build_subparsers = build_parser.add_subparsers(
  35. title='type',
  36. help='Type of AppImage build',
  37. dest='sub_command')
  38. build_local_parser = build_subparsers.add_parser('local',
  39. description='Bundle a local Python installation')
  40. build_local_parser.add_argument('-d', '--destination',
  41. help='AppImage destination')
  42. build_local_parser.add_argument('-p', '--python', help='python executable')
  43. build_manylinux_parser = build_subparsers.add_parser('manylinux',
  44. description='Bundle a manylinux Python installation using docker')
  45. build_manylinux_parser.add_argument('tag',
  46. help='manylinux image tag (e.g. 2010_x86_64)')
  47. build_manylinux_parser.add_argument('abi',
  48. help='python ABI (e.g. cp37-cp37m)')
  49. build_app_parser = build_subparsers.add_parser('app',
  50. description='Build a Python application using a base AppImage')
  51. build_app_parser.add_argument('appdir',
  52. help='path to the application metadata')
  53. build_app_parser.add_argument('-b', '--base-image',
  54. help='path to a base image on disk')
  55. build_app_parser.add_argument('-l', '--linux-tag',
  56. help='linux compatibility tag (e.g. manylinux1_x86_64)')
  57. build_app_parser.add_argument('-n', '--name',
  58. help='application name')
  59. build_app_parser.add_argument('--python-tag',
  60. help='python compatibility tag (e.g. cp37-cp37m)')
  61. build_app_parser.add_argument('-p', '--python-version',
  62. help='python version (e.g. 3.8)')
  63. build_app_parser.add_argument('--in-tree-build',
  64. help='force pip in-tree-build',
  65. action='store_true',
  66. default=False)
  67. build_app_parser.add_argument('-x', '--extra-data', type=exists,
  68. help='extra application data (bundled under $APPDIR/)', nargs='+')
  69. list_parser = subparsers.add_parser('list',
  70. description='List Python versions installed in a manylinux image')
  71. list_parser.add_argument('tag',
  72. help='manylinux image tag (e.g. 2010_x86_64)')
  73. which_parser = subparsers.add_parser('which',
  74. description='Locate a binary dependency')
  75. which_parser.add_argument('binary', choices=binaries,
  76. help='name of the binary to locate')
  77. args = parser.parse_args()
  78. # Configure the verbosity
  79. if args.verbosity:
  80. from .utils import log
  81. log.set_level(args.verbosity)
  82. if args.appimagetool_version:
  83. from .utils import deps
  84. deps.APPIMAGETOOL_VERSION = args.appimagetool_version
  85. # check if no arguments are passed
  86. if args.command is None:
  87. parser.print_help()
  88. return
  89. # Call the requested command
  90. module = '.commands.' + args.command
  91. try:
  92. module += '.' + args.sub_command
  93. except AttributeError:
  94. pass
  95. command = import_module(module, package=__package__)
  96. # check if the module has a 'execute' subcommand
  97. # if not, display the help message
  98. if not hasattr(command, 'execute'):
  99. locals().get('{}_parser'.format(args.command)).print_help()
  100. return
  101. # execute the command
  102. command.execute(*command._unpack_args(args))
  103. if __name__ == "__main__":
  104. main()