From 4eb7011425448655061731a8db158e5de918416a Mon Sep 17 00:00:00 2001 From: Valentin Niess Date: Mon, 30 Mar 2020 00:34:15 +0200 Subject: [PATCH] Add install command & reorganize --- python_appimage/__main__.py | 33 ++++++++++++------- .../{actions => appimage}/__init__.py | 0 .../{actions => appimage}/build.py | 0 .../{actions => appimage}/relocate.py | 0 .../{builders => commands}/__init__.py | 0 python_appimage/commands/install.py | 26 +++++++++++++++ .../{builders => commands}/local.py | 6 ++-- .../{builders => commands}/manylinux.py | 6 ++-- python_appimage/utils/deps.py | 8 +++-- 9 files changed, 60 insertions(+), 19 deletions(-) rename python_appimage/{actions => appimage}/__init__.py (100%) rename python_appimage/{actions => appimage}/build.py (100%) rename python_appimage/{actions => appimage}/relocate.py (100%) rename python_appimage/{builders => commands}/__init__.py (100%) create mode 100644 python_appimage/commands/install.py rename python_appimage/{builders => commands}/local.py (88%) rename python_appimage/{builders => commands}/manylinux.py (96%) diff --git a/python_appimage/__main__.py b/python_appimage/__main__.py index 9e55e21..9a2471b 100644 --- a/python_appimage/__main__.py +++ b/python_appimage/__main__.py @@ -11,24 +11,34 @@ __all__ = ['main'] def main(): # Parse arguments parser = argparse.ArgumentParser( - description='Bundle a Python install into an AppImage') - subparsers = parser.add_subparsers(title='builder', - help='Appimage builder', - dest='builder') + prog='python-appimage', + description='Bundle a Python installation into an AppImage') + subparsers = parser.add_subparsers(title='command', + help='Build or install command', + dest='command') parser.add_argument('-q', '--quiet', help='disable logging', dest='verbosity', action='store_const', const=logging.ERROR) parser.add_argument('-v', '--verbose', help='print extra information', dest='verbosity', action='store_const', const=logging.DEBUG) - local_parser = subparsers.add_parser('local') + install_parser = subparsers.add_parser('install', + description='Install binary dependencies') + install_parser.add_argument('binary', nargs='+', + choices=('appimagetool', 'patchelf'), help='one or more binary name') + + local_parser = subparsers.add_parser('local', + description='Bundle a local Python installation') local_parser.add_argument('-d', '--destination', help='AppImage destination') local_parser.add_argument('-p', '--python', help='python executable') - manylinux_parser = subparsers.add_parser('manylinux') - manylinux_parser.add_argument('tag', help='manylinux image tag') - manylinux_parser.add_argument('abi', help='python ABI') + manylinux_parser = subparsers.add_parser('manylinux', + description='Bundle a manylinux Python installation using docker') + manylinux_parser.add_argument('tag', + help='manylinux image tag (e.g. 2010_x86_64)') + manylinux_parser.add_argument('abi', + help='python ABI (e.g. cp37-cp37m)') manylinux_parser.add_argument('--contained', help=argparse.SUPPRESS, action='store_true', default=False) @@ -39,9 +49,10 @@ def main(): if args.verbosity: logging.getLogger().setLevel(args.verbosity) - # Call the AppImage builder - builder = import_module('.builders.' + args.builder, package=__package__) - builder.build(*builder._unpack_args(args)) + # Call the requested command + command = import_module('.commands.' + + args.command, package=__package__) + command.execute(*command._unpack_args(args)) if __name__ == "__main__": diff --git a/python_appimage/actions/__init__.py b/python_appimage/appimage/__init__.py similarity index 100% rename from python_appimage/actions/__init__.py rename to python_appimage/appimage/__init__.py diff --git a/python_appimage/actions/build.py b/python_appimage/appimage/build.py similarity index 100% rename from python_appimage/actions/build.py rename to python_appimage/appimage/build.py diff --git a/python_appimage/actions/relocate.py b/python_appimage/appimage/relocate.py similarity index 100% rename from python_appimage/actions/relocate.py rename to python_appimage/appimage/relocate.py diff --git a/python_appimage/builders/__init__.py b/python_appimage/commands/__init__.py similarity index 100% rename from python_appimage/builders/__init__.py rename to python_appimage/commands/__init__.py diff --git a/python_appimage/commands/install.py b/python_appimage/commands/install.py new file mode 100644 index 0000000..d5fce3b --- /dev/null +++ b/python_appimage/commands/install.py @@ -0,0 +1,26 @@ +import os + +from ..utils import deps +from ..utils.log import log + + + + +__all__ = ['execute'] + + +def _unpack_args(args): + '''Unpack command line arguments + ''' + return args.binary + + +def execute(*args): + '''Install the requested dependencies + ''' + bindir = os.path.dirname(deps.PATCHELF) + for binary in args: + installed = getattr(deps, 'ensure_' + binary)() + words = 'has been' if installed else 'already' + log('INSTALL', + '{:} {:} installed in {:}'.format(binary, words, bindir)) diff --git a/python_appimage/builders/local.py b/python_appimage/commands/local.py similarity index 88% rename from python_appimage/builders/local.py rename to python_appimage/commands/local.py index 8696b12..04a07c2 100644 --- a/python_appimage/builders/local.py +++ b/python_appimage/commands/local.py @@ -2,11 +2,11 @@ import glob import os import shutil -from ..actions import build_appimage, relocate_python +from ..appimage import build_appimage, relocate_python from ..utils.tmp import TemporaryDirectory -__all__ = ['build'] +__all__ = ['execute'] def _unpack_args(args): @@ -15,7 +15,7 @@ def _unpack_args(args): return args.python, args.destination -def build(python=None, destination=None): +def execute(python=None, destination=None): '''Build a Python AppImage using a local installation ''' pwd = os.getcwd() diff --git a/python_appimage/builders/manylinux.py b/python_appimage/commands/manylinux.py similarity index 96% rename from python_appimage/builders/manylinux.py rename to python_appimage/commands/manylinux.py index 6f6a766..f9bd4d6 100644 --- a/python_appimage/builders/manylinux.py +++ b/python_appimage/commands/manylinux.py @@ -4,13 +4,13 @@ import platform import shutil import sys -from ..actions import build_appimage, relocate_python +from ..appimage import build_appimage, relocate_python from ..utils.docker import docker_run from ..utils.fs import copy_tree from ..utils.tmp import TemporaryDirectory -__all__ = ['build'] +__all__ = ['execute'] def _unpack_args(args): @@ -31,7 +31,7 @@ def _get_appimage_name(abi, tag): fullversion, abi, tag) -def build(tag, abi, contained=False): +def execute(tag, abi, contained=False): '''Build a Python AppImage using a manylinux docker image ''' diff --git a/python_appimage/utils/deps.py b/python_appimage/utils/deps.py index e96a605..045361b 100644 --- a/python_appimage/utils/deps.py +++ b/python_appimage/utils/deps.py @@ -33,7 +33,7 @@ def ensure_appimagetool(): '''Fetch appimagetool from the web if not available locally ''' if os.path.exists(APPIMAGETOOL): - return + return False appimage = 'appimagetool-{0:}.AppImage'.format(_ARCH) baseurl = 'https://github.com/AppImage/AppImageKit/releases/' \ @@ -53,6 +53,8 @@ def ensure_appimagetool(): if not os.path.exists(APPIMAGETOOL): os.symlink(appdir_name + '/AppRun', APPIMAGETOOL) + return True + # Installers for dependencies def ensure_excludelist(): @@ -72,7 +74,7 @@ def ensure_patchelf(): '''Fetch PatchELF from the web if not available locally ''' if os.path.exists(PATCHELF): - return + return False iarch = 'i386' if _ARCH == 'i686' else _ARCH appimage = 'patchelf-{0:}.AppImage'.format(iarch) @@ -88,3 +90,5 @@ def ensure_patchelf(): system('./' + appimage, '--appimage-extract') copy_file('squashfs-root/usr/bin/patchelf', patchelf) os.chmod(patchelf, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) + + return True