-
Notifications
You must be signed in to change notification settings - Fork 11
/
Build.py
140 lines (127 loc) · 5.03 KB
/
Build.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
# -*- coding: utf-8 -*-
# Copyright (c) 2022-2024, Harry Huang
# @ BSD 3-Clause License
import os, configparser
import os.path as osp
def __get_venv_dir():
import re, subprocess
rst = subprocess.run(['poetry', 'env', 'info'], capture_output=True)
if rst.returncode == 0:
for l in rst.stdout.splitlines():
match = re.search(r'Path:\s+(.+)', str(l, encoding='UTF-8'))
if match:
path = match.group(1).strip()
if osp.isdir(path):
return path
print("× Failed to parse poetry output to query venv dir.")
else:
print(f"× Failed to run poetry to query venv dir. Returned code: {rst.returncode}")
print(f"- StdErr: {rst.stderr}")
print(f"- StdOut: {rst.stdout}")
print("- Please check the compatibility of poetry version.")
print("- Please check the poetry status and the venv info.")
raise Exception("venv dir not found or poetry config failed")
def __get_proj_info():
try:
parser = configparser.ConfigParser()
parser.read('pyproject.toml', encoding='UTF-8')
config = parser['tool.poetry']
return {
'name': config['name'].strip("'\""),
'version': config['version'].strip("'\""),
'description': config['description'].strip("'\""),
'author': config['authors'].strip("'\"[]").split('<')[0].strip(),
'license': config['license'].strip("'\"").replace('\\\\', '\\')
}
except KeyError as arg:
print(f"x Required field missing, {arg}")
raise arg
except Exception as arg:
print("× Failed to parse poetry project info.")
raise arg
def __get_build_def(proj_dir, venv_dir):
try:
parser = configparser.ConfigParser()
parser.read('pyproject.toml', encoding='UTF-8')
return {k: v.strip("'\"").replace('\\\\', '\\').replace('$project$', proj_dir).replace('$venv$', venv_dir) \
for k, v in parser['tool.build'].items()}
except Exception as arg:
print("× Failed to parse build definition fields.")
raise arg
def __main():
proj_dir = osp.dirname(osp.abspath(__file__))
venv_dir = __get_venv_dir()
proj_info = __get_proj_info()
build_def = __get_build_def(proj_dir, venv_dir)
print(f"Project: {proj_info['name']}|{proj_info['version']}|{proj_info['author']}|{proj_info['license']}")
print(f"Root: {proj_dir}")
print(f"Venv: {venv_dir}")
print("")
__build(proj_info, proj_dir, build_def)
exit(0)
def __exec(cmd):
rst = os.system(cmd)
if rst == 0:
print(f"\n[Done] <- {cmd}")
else:
print(f"\n[Error] <- {cmd}")
print(f"× Execution failed! Returned code: {rst}")
exit(1)
def __build(proj_info, proj_dir, build_def):
import time, shutil
t1 = time.time()
print(f"Removing build dir...")
os.chdir(proj_dir)
build_dir = build_def['build-dir']
if osp.exists(build_dir):
shutil.rmtree(build_dir, ignore_errors=False)
print(f"Creating build dir...")
os.mkdir(build_dir)
os.chdir(build_dir)
print(f"Creating version file...")
version_file = 'version.txt'
with open(version_file, 'w', encoding='UTF-8') as f:
f.write(f'''# UTF-8
VSVersionInfo(
ffi=FixedFileInfo(
filevers=({proj_info['version'].replace('.',',')},0),
prodvers=({proj_info['version'].replace('.',',')},0),
mask=0x3f,
flags=0x0,
OS=0x4,
fileType=0x1,
subtype=0x0,
date=(0,0)
),
kids=[
StringFileInfo([
StringTable(
u'040904B0',
[StringStruct(u'CompanyName', u'{proj_info['author']}'),
StringStruct(u'FileDescription', u'{proj_info['description']}'),
StringStruct(u'FileVersion', u'{proj_info['version']}'),
StringStruct(u'LegalCopyright', u'©{proj_info['author']} @{proj_info['license']} License'),
StringStruct(u'ProductName', u'{proj_info['name']}'),
StringStruct(u'ProductVersion', u'{proj_info['version']}')])
])
])
''') # End f.write
print('Running pyinstaller...')
cmd_pyinstaller = f"poetry run pyinstaller -F"
cmd_pyinstaller += f" --name \"{proj_info['name']}-v{proj_info['version']}\""
cmd_pyinstaller += f" --version-file {version_file}"
cmd_pyinstaller += f" --icon \"{build_def['icon']}\"" if 'icon' in build_def.keys() else ""
if 'add-binary' in build_def.keys():
for i in build_def['add-binary'].split('|'):
cmd_pyinstaller += f" --add-binary \"{i}\"" if i else ""
if 'add-data' in build_def.keys():
for i in build_def['add-data'].split('|'):
cmd_pyinstaller += f" --add-data \"{i}\"" if i else ""
cmd_pyinstaller += f" --hidden-import {build_def['hidden-import']}" if 'hidden-import' in build_def.keys() else ""
cmd_pyinstaller += f" --log-level {build_def['log-level']}" if 'log-level' in build_def.keys() else ""
cmd_pyinstaller += f" \"{build_def['entry']}\""
__exec(cmd_pyinstaller)
print(f"√ Build finished in {round(time.time() - t1, 1)}s!")
print(f"- Dist files see: {osp.join(build_dir, 'dist')}")
if __name__ == '__main__':
__main()