17
17
from PIL import Image
18
18
19
19
20
- path = os .environ ['PATH' ]
21
- os .environ ['PATH' ] = ';' .join ([path , os .path .join (path .split (';' )[0 ], 'Scripts' )])
20
+ # path = os.environ['PATH']
21
+ # os.environ['PATH'] = ';'.join([path, os.path.join(path.split(';')[0], 'Scripts')])
22
22
23
23
24
- class Build ():
24
+ class BuildBase ():
25
25
26
- @classmethod
27
- def run (self , run_installer = True ):
28
- self .make_icon ()
29
- self .set_version ()
30
- self .set_appname ()
31
- self .set_api_ms_win_crt_path ()
32
- self .remove_build ()
33
- self .make_build ()
34
- # self.run_build()
35
- self .make_installer ()
36
- self .compress_installer ()
37
- if run_installer :
38
- self .run_installer ()
39
-
40
- @classmethod
41
- def make_icon (self ):
42
- directory = os .path .join ('assets' , 'icon' )
43
- src_path = os .path .join (directory , 'icon.png' )
44
- dst_path = os .path .join (directory , 'icon.ico' )
45
- icon_sizes = [(v , v ) for v in (16 , 24 , 32 , 48 , 64 , 96 , 128 , 256 ,)]
46
- img = Image .open (src_path )
47
- if os .path .exists (dst_path ):
48
- os .remove (dst_path )
49
- img .save (dst_path , sizes = icon_sizes )
26
+ class path ():
27
+ dist = 'dist'
28
+ build = 'build'
29
+ icondir = os .path .join ('assets' , 'icon' )
30
+ iconsrc = os .path .join (icondir , 'icon.png' )
31
+ icondst = os .path .join (icondir , 'icon.ico' )
32
+ mainsrc = os .path .join ('source' , 'main.py' )
33
+ spec = 'makebuild.spec'
34
+ iss = 'makeinstaller.iss'
35
+ winsxs = 'C:\\ Windows\\ WinSxS'
36
+ issc = r'C:\\Program Files (x86)\\Inno Setup 5\\ISCC.exe'
50
37
51
38
@classmethod
52
39
def remove_build (self ):
53
- remove_paths = ['dist' , 'build' ]
54
- for path in remove_paths :
40
+ for path in [self .path .build , self .path .dist ]:
55
41
path = os .path .abspath (path )
56
42
if os .path .isdir (path ):
57
43
try :
@@ -60,6 +46,14 @@ def remove_build(self):
60
46
except Exception :
61
47
print ('removing failed %s' % (path ))
62
48
49
+ @classmethod
50
+ def make_icon (self ):
51
+ icon_sizes = [(v , v ) for v in (16 , 24 , 32 , 48 , 64 , 96 , 128 , 256 ,)]
52
+ img = Image .open (self .path .iconsrc )
53
+ if os .path .exists (self .path .icondst ):
54
+ os .remove (self .path .icondst )
55
+ img .save (self .path .icondst , sizes = icon_sizes )
56
+
63
57
@classmethod
64
58
def subfile (self , ptrn , repl , path , ** kwargs ):
65
59
if not os .path .exists (path ):
@@ -75,54 +69,23 @@ def subfile(self, ptrn, repl, path, **kwargs):
75
69
return content
76
70
77
71
@classmethod
78
- def make_build (self ):
79
- proc = subprocess .Popen ('pyinstaller makebuild.spec' , shell = True )
80
- proc .communicate ()
81
-
82
- @classmethod
83
- def get_appname (self ):
84
- ptrn = (r'''[_]{0,2}appname[_]{0,2}[\s]{1,}[=]{1}[\s]{1,}'''
85
- r'''['"]{1}([a-zA-Z\s]{1,})['"]{1}''' )
86
- with open (os .path .join ('source' , 'main.py' ), 'r' ) as file :
87
- content = file .read ()
88
- m = re .search (ptrn , content )
89
- if m :
90
- return m .group (1 )
91
-
92
- @classmethod
93
- def set_appname (self ):
94
- ptrn = (r'''(__appname__[\s]{1,}=[\s]{1,}[\'\"]{1})'''
95
- r'''[\w\d\s\-\_\.]{0,}([\'\"]{1})''' )
96
- appname = self .get_appname ()
97
- if appname :
98
- self .subfile (ptrn , r'\g<1>{}\g<2>' .format (appname ), 'makebuild.spec' )
99
-
100
- @classmethod
101
- def get_version (self ):
102
- ptrn = (r'''[_]{0,2}version[_]{0,2}[\s]{1,}[=]{1}[\s]{1,}'''
103
- r'''['"]{1}([\d]{1,}\.[\d]{1,}\.[\d]{1,})['"]{1}''' )
104
- with open (os .path .join ('source' , 'main.py' ), 'r' ) as file :
72
+ def get_info_from_source (self , key ):
73
+ ptrn = (r'''[_]{0,2}%s[_]{0,2}[\s]{1,}[=]{1}[\s]{1,}'''
74
+ r'''['"]{1}([\w\d\.\-\s]{1,})['"]{1}''' ) % (key )
75
+ with open (self .path .mainsrc , 'r' ) as file :
105
76
content = file .read ()
106
77
m = re .search (ptrn , content )
107
78
if m :
108
79
return m .group (1 )
109
80
110
- @classmethod
111
- def set_version (self ):
112
- ptrn = r'''([\d]{1,}\.[\d]{1,}\.[\d]{1,})'''
113
- version = self .get_version ()
114
- if version :
115
- self .subfile (ptrn , version , 'makeinstaller.iss' )
116
-
117
81
@classmethod
118
82
def set_api_ms_win_crt_path (self , architecture = 'amd64' ):
119
83
# 'x86' or 'amd64'
120
84
existing_dirs = []
121
- basedir = 'C:\\ Windows\\ WinSxS'
122
- for dirname in os .listdir (basedir ):
85
+ for dirname in os .listdir (self .path .winsxs ):
123
86
if not dirname .startswith (architecture ):
124
87
continue
125
- absdir = os .path .join (basedir , dirname )
88
+ absdir = os .path .join (self . path . winsxs , dirname )
126
89
if not os .path .isdir (absdir ):
127
90
continue
128
91
@@ -135,59 +98,142 @@ def set_api_ms_win_crt_path(self, architecture='amd64'):
135
98
ptrn = (r'''(__api_ms_win_crt_path__[\s]{1,}=[\s]{1,}[\'\"]{1})'''
136
99
r'''[\w\d\s\-\_\.\:\\]{0,}([\'\"]{1})''' )
137
100
path = path .replace ('\\ ' , '\\ \\ \\ \\ ' )
138
- self .subfile (ptrn , r'\g<1>{}\g<2>' .format (path ), 'makebuild. spec' )
101
+ self .subfile (ptrn , r'\g<1>{}\g<2>' .format (path ), self . path . spec )
139
102
140
103
@classmethod
141
- def run_build (self ):
142
- name = self .get_appname ()
143
- command = '"{}"' .format (os .path .join ('dist' , '{}.exe' .format (name )))
104
+ def make_build (self ):
105
+ command = 'pyinstaller {}' .format (self .path .spec )
144
106
proc = subprocess .Popen (command , shell = True )
145
107
proc .communicate ()
146
108
147
109
@classmethod
148
110
def make_installer (self ):
149
- for name in os .listdir (' dist' ):
111
+ for name in os .listdir (self . path . dist ):
150
112
if os .path .splitext (name )[0 ][- 1 ].isdigit ():
151
- os .remove (os .path .join ('dist' , name ))
113
+ os .remove (os .path .join (self .path .dist , name ))
114
+ command = '"{}" "{}"' .format (self .path .issc , self .path .iss )
115
+ proc = subprocess .Popen (command , shell = True )
116
+ proc .communicate ()
152
117
153
- issc = r'''"C:\\Program Files (x86)\\Inno Setup 5\\ISCC.exe"'''
154
- command = '''%s "makeinstaller.iss"''' % (issc )
118
+ @classmethod
119
+ def run_build (self ):
120
+ name = self .get_appname ()
121
+ command = '"{}"' .format (os .path .join (self .path .dist , '{}.exe' .format (name )))
155
122
proc = subprocess .Popen (command , shell = True )
156
123
proc .communicate ()
157
124
158
125
@classmethod
159
126
def get_installer_name (self ):
160
- with open ('makeinstaller. iss' , 'r' ) as file :
127
+ with open (self . path . iss , 'r' ) as file :
161
128
for line in file .read ().split ('\n ' ):
162
- if line . startswith ( 'OutputBaseFilename' ) :
163
- return line .split ('=' )[- 1 ].strip ()
129
+ if 'OutputBaseFilename' in line :
130
+ return line .split ('=' )[- 1 ].strip ('" ' )
164
131
165
132
@classmethod
166
133
def compress_installer (self ):
167
134
name = self .get_installer_name ()
168
135
if not name :
169
136
return
170
137
src_name = '{}.exe' .format (name )
171
- src_path = os .path .join (' dist' , src_name )
172
- dst_path = os .path .join (' dist' , '{}.zip' .format (name ))
138
+ src_path = os .path .join (self . path . dist , src_name )
139
+ dst_path = os .path .join (self . path . dist , '{}.zip' .format (name ))
173
140
file = zipfile .ZipFile (dst_path , 'w' , zipfile .ZIP_DEFLATED )
174
141
file .write (src_path , src_name )
175
- # zipdir('tmp/', zipf)
176
142
file .close ()
177
- # for root, dirs, files in os.walk(path):
178
- # for file in files:
179
- # ziph.write(os.path.join(root, file))
180
143
181
144
@classmethod
182
145
def run_installer (self ):
183
146
name = self .get_installer_name ()
184
147
if not name :
185
148
return
186
- command = '"{}"' .format (os .path .join (' dist' , name ))
149
+ command = '"{}"' .format (os .path .join (self . path . dist , name ))
187
150
proc = subprocess .Popen (command , shell = True )
188
151
proc .communicate ()
189
152
190
153
154
+ class Build (BuildBase ):
155
+
156
+ @classmethod
157
+ def run (self , auto_build_info = True , run_installer = True ):
158
+
159
+ self .make_icon ()
160
+
161
+ if auto_build_info :
162
+
163
+ self .set_dist ()
164
+ self .set_author ()
165
+ self .set_appname ()
166
+ self .set_version ()
167
+
168
+ self .set_api_ms_win_crt_path ()
169
+ self .remove_build ()
170
+ self .make_build ()
171
+ # self.run_build()
172
+ self .make_installer ()
173
+ self .compress_installer ()
174
+
175
+ if run_installer :
176
+ self .run_installer ()
177
+
178
+ @classmethod
179
+ def get_appname (self ):
180
+ return self .get_info_from_source ('appname' )
181
+
182
+ @classmethod
183
+ def get_version (self ):
184
+ return self .get_info_from_source ('version' )
185
+
186
+ @classmethod
187
+ def get_author (self ):
188
+ return self .get_info_from_source ('author' )
189
+
190
+ @classmethod
191
+ def set_appname (self ):
192
+ appname = self .get_appname ()
193
+ if appname :
194
+ ptrn = (r'''(__appname__[\s]{1,}=[\s]{1,}[\'\"]{1})'''
195
+ r'''[\w\d\s\-\_\.]{0,}([\'\"]{1})''' )
196
+ self .subfile (ptrn , r'\g<1>{}\g<2>' .format (appname ), self .path .spec )
197
+
198
+ keys = r'|' .join ([
199
+ 'AppName' , 'AppVerName' ,
200
+ 'DefaultDirName' , 'DefaultGroupName' ,
201
+ 'UninstallDisplayIcon' , 'OutputBaseFilename' , 'Name' , 'Filename' ])
202
+ version_ptrn = r'[\d]{1,}\.[\d]{1,}\.[\d]{1,}'
203
+ ptrn = (r'(%s)'
204
+ r'([\s]{1,}[\=\:]{1}[\s]{1,}\")'
205
+ r'(\{[a-z]{1,}\}\\){0,1}'
206
+ r'[\w\d\s]{1,}'
207
+ r'(|\.exe|[\s\-\_\.]{1}%s[\s\-\_\.]{0,}[\w\d]{0,})'
208
+ r'(\")' ) % (keys , version_ptrn )
209
+ self .subfile (ptrn , r'\g<1>\g<2>\g<3>{}\g<4>\g<5>' .format (appname ), self .path .iss )
210
+
211
+ @classmethod
212
+ def set_version (self ):
213
+ version = self .get_version ()
214
+ if version :
215
+ ptrn = r'([\d]{1,}\.[\d]{1,}\.[\d]{1,})'
216
+ self .subfile (ptrn , version , self .path .iss )
217
+
218
+ @classmethod
219
+ def set_author (self ):
220
+ author = self .get_author ()
221
+ if author :
222
+ keys = r'|' .join ([
223
+ 'AppCopyright' , 'AppPublisher' ,
224
+ 'VersionInfoCompany' , 'VersionInfoCopyright' ])
225
+ ptrn = r'(%s)([\s]{1,}=[\s]{1,}\")[\w\d\s\.\-\_]{1,}(\")' % (keys )
226
+ self .subfile (ptrn , r'\g<1>\g<2>{}\g<3>' .format (author ), self .path .iss )
227
+
228
+ @classmethod
229
+ def set_dist (self ):
230
+ ptrn = (r'(Source|OutputDir)'
231
+ r'([\s]{0,}\:[\s]{0,}\")'
232
+ r'[\w\d\s\.\-\_]{1,}'
233
+ r'(\\\*){0,}'
234
+ r'(\")' )
235
+ self .subfile (ptrn , r'\g<1>\g<2>{}\g<3>\g<4>' .format (self .path .dist ), self .path .iss )
236
+
191
237
if __name__ == '__main__' :
192
238
from io import TextIOWrapper
193
239
sys .stdout = TextIOWrapper (sys .stdout .buffer , encoding = 'utf-8' , errors = 'replace' )
0 commit comments