forked from rackspace/runway
-
Notifications
You must be signed in to change notification settings - Fork 0
/
runway.folder.spec
147 lines (126 loc) · 4.76 KB
/
runway.folder.spec
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
145
146
147
"""pyinstaller spec file to build a single-binary distribution of runway.
This file should be considered a python file and linted as such.
"""
# pylint: disable=undefined-variable,wrong-import-order,invalid-name
# pylint: disable=wrong-import-position,import-self
import os
import pkgutil
from pkg_resources import get_distribution, get_entry_info
from PyInstaller.utils.hooks import collect_data_files, copy_metadata
# distutils not included with virtualenv < 20 so we have to import it here
# can be removed once we can upgrade virtualenv and pyinstaller
import distutils
if getattr(distutils, "distutils_path", "").endswith("__init__.py"):
distutils.distutils_path = os.path.dirname(distutils.distutils_path)
CLI_PATH = os.path.join(os.path.dirname(os.path.dirname(workpath)), "runway") # noqa
def get_submodules(package):
"""Get submodules of a package to add to hiddenimports.
Package must be installed and imported for this to be used.
This is needed for dependencies that do not have a
native pyinstaller hook. This may not find everything that
needs to be included.
Args:
package: An import package to inspect.
Returns:
List of submodules.
"""
return [
name
for _, name, _ in pkgutil.walk_packages(
path=package.__path__, prefix=package.__name__ + ".", onerror=lambda x: None
)
]
def Entrypoint(dist, group, name, **kwargs): # noqa
"""Get entrypoint info for packages using setuptools."""
ep = get_entry_info(dist, group, name)
# script name must not be a valid module name to avoid name clashes on import
script_path = os.path.join(workpath, name + "-script.py") # noqa: F821
print("creating script for entry point", dist, group, name)
with open(script_path, "w") as fh:
print("import", ep.module_name, file=fh)
print("%s.%s()" % (ep.module_name, ".".join(ep.attrs)), file=fh)
return Analysis([script_path] + kwargs.get("scripts", []), **kwargs) # noqa: F821
# files that are not explicitly imported but consumed at runtime
# need to be included as data_files.
data_files = [
(os.path.join(CLI_PATH, "blueprints"), "./runway/blueprints"),
(os.path.join(CLI_PATH, "cfngin/hooks"), "./runway/cfngin/hooks"),
(os.path.join(CLI_PATH, "templates"), "./runway/templates"),
]
data_files.append(
("{}/yamllint/conf".format(get_distribution("yamllint").location), "yamllint/conf/")
)
data_files.append(
("{}/cfnlint/rules".format(get_distribution("cfn-lint").location), "cfnlint/rules/")
)
data_files.append(
("{}/botocore/data".format(get_distribution("botocore").location), "botocore/data/")
)
data_files.extend(collect_data_files("cfnlint"))
data_files.extend(collect_data_files("distutils"))
data_files.extend(collect_data_files("hcl2"))
data_files.extend(collect_data_files("pip"))
data_files.extend(collect_data_files("wheel"))
data_files.append(copy_metadata("runway")[0]) # support scm version
# pyinstaller is not able to find dependencies of dependencies
# unless a hook already exists for pyinstaller so we have to
# add their dependencies here.
hiddenimports = []
# these packages do not have pyinstaller hooks so we need to import
# them to collect a list of submodules to include as hidden imports.
import runway # noqa
import troposphere # noqa
import awacs # noqa
import botocore # noqa
import pip # noqa
import wheel # noqa
import yamllint # noqa
import cfnlint # noqa
hiddenimports.extend(get_submodules(runway))
hiddenimports.extend(get_submodules(troposphere))
hiddenimports.extend(get_submodules(awacs))
hiddenimports.extend(get_submodules(botocore))
hiddenimports.extend(get_submodules(pip))
hiddenimports.extend(get_submodules(wheel))
hiddenimports.extend(get_submodules(distutils))
hiddenimports.extend(get_submodules(yamllint))
hiddenimports.extend(get_submodules(cfnlint))
# needed due to pkg_resources dropping python2 support
# can be removed on the next pyinstaller release
# https://github.com/pypa/setuptools/issues/1963#issuecomment-582084099
hiddenimports.append("pkg_resources.py2_warn")
a = Entrypoint(
"runway",
"console_scripts",
"runway",
pathex=[CLI_PATH],
datas=data_files,
hiddenimports=hiddenimports,
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=None,
noarchive=False,
binaries=[],
)
pyz = PYZ(a.pure, a.zipped_data, cipher=None) # noqa: F821
exe = EXE(
pyz, # noqa: F821
a.scripts,
[],
exclude_binaries=True,
# for some reason pyinstaller won't create the correct dir
# structure if this is the same name as a dir used in datas
name="runway-cli",
strip=False,
upx=True,
console=True,
)
coll = COLLECT(
exe, # noqa: F821
a.binaries,
a.zipfiles,
a.datas,
name="runway",
strip=False,
upx=True,
)