This repository has been archived by the owner on Jun 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathbuild_bin.py
192 lines (114 loc) · 4.42 KB
/
build_bin.py
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#!/usr/bin/env python3
# coding: utf-8
import sys
from pathlib import Path
import os
import importlib
import subprocess
import pyinstaller_cfg
def hidden_imports(search_path):
'''find the imports from the plugins
pyinstaller cannot find the imports from the plugins because they are only
loaded on demand at boot
Args:
search_path(str): path to plugin modules to search'''
pre_import_modules = set(sys.modules)
search_path = Path(search_path)
# find all modules in search_path that do not start with . or _
for i in search_path.glob('*'):
if not i.name[0] in ['.', '_']:
module = importlib.import_module(f"{'.'.join(search_path.parts)}.{i.name}")
post_import_modules = set(sys.modules)
imported_modules = post_import_modules - pre_import_modules
unique_modules = set()
for m in imported_modules:
unique_modules.add(m.split('.')[0])
return unique_modules
def build_pyinstaller_command():
'''build a command list for Popen'''
# calculate hidden imports
my_hidden = hidden_imports(pyinstaller_cfg.plugin_path)
cmd_list = ['pipenv', 'run', 'pyinstaller']
for o in pyinstaller_cfg.options:
if len(o) > 0:
cmd_list.append(o)
# calculated hidden imports
for h in my_hidden:
if len(h) > 0:
cmd_list.extend(['--hidden-import', h])
# explicit hidden imports from configuration file
for h in pyinstaller_cfg.hidden_imports:
cmd_list.extend(['--hidden-import', h])
# add specified datas that are internal to the project
for d in pyinstaller_cfg.datas:
if len(d) > 0:
cmd_list.extend(['--add-data', f'{pyinstaller_cfg.base_path}/{d[0]}:{d[1]}'])
# add datas that are external to the project (e.g. datas that should be covered by hook-foo.py files)
for d in pyinstaller_cfg.external_datas:
if len(d) > 0:
cmd_list.extend(['--add-data', f'{d[0]}:{d[1]}'])
for e in pyinstaller_cfg.exclude:
if len(e) > 0:
cmd_list.extend(['--exclude-module', e])
cmd_list.append(f'{pyinstaller_cfg.base_path}/{pyinstaller_cfg.base_script}')
return cmd_list
def run(command):
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while True:
line = process.stdout.readline().rstrip()
if not line:
break
yield line
def main():
exit_status = 0
pre_import_modules = set(sys.modules)
pyinstaller_command = build_pyinstaller_command()
# process = subprocess.Popen(pyinstaller_command, stdout=subprocess.PIPE)
# while True:
# output = process.stdout.readline()
# if output == '' and process.poll() is not None:
# break
# if output:
# print(output.strip())
# rc = process.poll()
# if rc > 0:
# print('pyinstaller exited with errors!')
# print('try running the build command manually from within a pipenv shell: ')
# print(" ".join(pyinstaller_command))
# print('pyinstaller exited with errors!')
# else:
# print('executable is stored in ./dist')
# return rc
timeout = 500
# print(pyinstaller_command)
proc = subprocess.Popen(pyinstaller_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(f'starting build -- will timeout after {timeout} seconds')
print(f'$ {pyinstaller_command}')
try:
outs, errs = proc.communicate(timeout=timeout)
except subprocess.TimeoutExpired:
proc.kill()
print('timeout exceeded! build failed!')
print(f'try running this command manually from within the pipenv shell:')
print(f'{" ".join(pyinstaller_command)}')
print('timeout exceeded! build failed!')
outs, errs = proc.communicate()
exit_status = 1
print(outs)
print(errs)
if exit_status == 0:
print(f'executable created in ./dist/')
return exit_status
if __name__ == '__main__':
exit_status = 0
build = True
for i in sys.argv:
if 'ipykernel' in i:
print('this should **NOT** be run from within jupyter notebook')
print('modules imported by jupyter can interfere with module discovery.')
build = False
exit_status = 1
if build:
exit_status = main()
exit(exit_status)
exit(0)