1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
#!/usr/bin/env python
"""Script to create a pyinstaller executable.
This exe can then be wrapped in a platform specific installer for each
supported platform.
"""
import argparse
import json
import os
import shutil
import sys
from distutils.dir_util import copy_tree
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from install_deps import install_packages
from utils import run, save_to_zip, tmp_dir, update_metadata
ROOT = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
)
EXE_DIR = os.path.join(ROOT, 'exe')
PYINSTALLER_DIR = os.path.join(EXE_DIR, 'pyinstaller')
ASSETS_DIR = os.path.join(EXE_DIR, 'assets')
DEFAULT_OUTPUT_ZIP = 'awscli-exe.zip'
AC_INDEX_INTERNAL_PATH = os.path.join('awscli', 'data', 'ac.index')
DISTRIBUTION_SOURCE = 'exe'
def make_exe(exe_zipfile, cleanup=True, ac_index=None):
with tmp_dir() as workdir:
delete_existing_exe_build()
do_make_exe(workdir, exe_zipfile, ac_index)
if cleanup:
cleanup_build()
print('Exe build is available at: %s' % exe_zipfile)
def do_make_exe(workdir, exe_zipfile, ac_index):
exe_dir = os.path.join(workdir, 'aws')
output_exe_dist_dir = os.path.join(exe_dir, 'dist')
aws_exe_build = pyinstaller('aws.spec')
if ac_index:
full_internal_ac_index_path = os.path.join(
aws_exe_build, AC_INDEX_INTERNAL_PATH
)
copy_file(ac_index, full_internal_ac_index_path)
copy_directory(aws_exe_build, output_exe_dist_dir)
aws_complete_exe_build = pyinstaller('aws_completer.spec')
update_metadata(
aws_complete_exe_build, distribution_source=DISTRIBUTION_SOURCE
)
copy_directory_contents_into(aws_complete_exe_build, output_exe_dist_dir)
copy_directory_contents_into(ASSETS_DIR, exe_dir)
save_to_zip(workdir, exe_zipfile)
def delete_existing_exe_build():
build_dir = os.path.join(PYINSTALLER_DIR, 'dist')
if os.path.isdir(build_dir):
shutil.rmtree(build_dir)
def pyinstaller(specfile):
aws_spec_path = os.path.join(PYINSTALLER_DIR, specfile)
print(run('pyinstaller %s' % (aws_spec_path), cwd=PYINSTALLER_DIR))
return os.path.join(PYINSTALLER_DIR, 'dist', os.path.splitext(specfile)[0])
def copy_directory(src, dst):
print('Copying %s -> %s' % (src, dst))
shutil.copytree(src, dst)
def copy_directory_contents_into(src, dst):
print('Copying contents of %s into %s' % (src, dst))
copy_tree(src, dst)
def copy_file(src, dst):
print('Copying file %s -> %s' % (src, dst))
shutil.copy2(src, dst)
def cleanup_build():
locations = [
os.path.join(PYINSTALLER_DIR, 'build'),
os.path.join(PYINSTALLER_DIR, 'dist'),
]
for location in locations:
shutil.rmtree(location)
print('Deleted build directory: %s' % location)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
'--output',
default=os.path.join(ROOT, 'dist', DEFAULT_OUTPUT_ZIP),
help=(
'The name of the file to save the exe zip. By default, '
'this will be saved in "dist/%s" directory in the root of the '
'awscli.' % DEFAULT_OUTPUT_ZIP
),
)
parser.add_argument(
'--no-cleanup',
dest='cleanup',
action='store_false',
default=True,
help=(
'Leave the build folder produced by pyinstaller. This can be '
'useful for debugging.'
),
)
parser.add_argument(
'--src-dir',
default=None,
help=(
'Source directory for pinned installation dependencies. This '
'provides the ability to do offline builds without PyPI.'
),
)
parser.add_argument(
'--ac-index-path',
default=None,
help=('Path to ac.index file to include in the exe.'),
)
args = parser.parse_args()
output = os.path.abspath(args.output)
if args.src_dir:
print(f'Installing dependencies from local directory: {args.src_dir}')
install_packages(args.src_dir)
else:
run('pip install -r requirements-dev-lock.txt')
run('pip install .')
make_exe(output, cleanup=args.cleanup, ac_index=args.ac_index_path)
if __name__ == "__main__":
main()
|