73 |
72 |
74 |
73 |
75 def _findExecutable(majorVersion): |
74 def _findExecutable(majorVersion): |
76 """ |
75 """ |
77 Restricted function to determine the names of the executable. |
76 Restricted function to determine the names of the executable. |
78 |
77 |
79 @param majorVersion major Python version of the executables |
78 @param majorVersion major Python version of the executables |
80 @type int |
79 @type int |
81 @return names of the executable |
80 @return names of the executable |
82 @rtype list of str |
81 @rtype list of str |
83 """ |
82 """ |
84 # Determine Python Version |
83 # Determine Python Version |
85 if majorVersion == 3: |
84 if majorVersion == 3: |
86 minorVersions = range(10) |
85 minorVersions = range(10) |
87 else: |
86 else: |
88 return [] |
87 return [] |
89 |
88 |
90 executables = set() |
89 executables = set() |
91 if Utilities.isWindowsPlatform(): |
90 if Utilities.isWindowsPlatform(): |
92 # |
91 # |
93 # Windows |
92 # Windows |
94 # |
93 # |
95 try: |
94 try: |
96 import winreg |
95 import winreg |
97 except ImportError: |
96 except ImportError: |
98 import _winreg as winreg # __IGNORE_WARNING__ |
97 import _winreg as winreg # __IGNORE_WARNING__ |
99 |
98 |
100 def getExePath(branch, access, versionStr): |
99 def getExePath(branch, access, versionStr): |
101 try: |
100 try: |
102 software = winreg.OpenKey(branch, 'Software', 0, access) |
101 software = winreg.OpenKey(branch, "Software", 0, access) |
103 python = winreg.OpenKey(software, 'Python', 0, access) |
102 python = winreg.OpenKey(software, "Python", 0, access) |
104 pcore = winreg.OpenKey(python, 'PythonCore', 0, access) |
103 pcore = winreg.OpenKey(python, "PythonCore", 0, access) |
105 version = winreg.OpenKey(pcore, versionStr, 0, access) |
104 version = winreg.OpenKey(pcore, versionStr, 0, access) |
106 installpath = winreg.QueryValue(version, 'InstallPath') |
105 installpath = winreg.QueryValue(version, "InstallPath") |
107 exe = os.path.join(installpath, 'Scripts', 'cxfreeze.bat') |
106 exe = os.path.join(installpath, "Scripts", "cxfreeze.bat") |
108 if os.access(exe, os.X_OK): |
107 if os.access(exe, os.X_OK): |
109 return exe |
108 return exe |
110 except WindowsError: # __IGNORE_WARNING__ |
109 except WindowsError: # __IGNORE_WARNING__ |
111 return None |
110 return None |
112 return None |
111 return None |
113 |
112 |
114 versionSuffixes = ["", "-32", "-64"] |
113 versionSuffixes = ["", "-32", "-64"] |
115 for minorVersion in minorVersions: |
114 for minorVersion in minorVersions: |
116 for versionSuffix in versionSuffixes: |
115 for versionSuffix in versionSuffixes: |
117 versionStr = '{0}.{1}{2}'.format(majorVersion, minorVersion, |
116 versionStr = "{0}.{1}{2}".format( |
118 versionSuffix) |
117 majorVersion, minorVersion, versionSuffix |
|
118 ) |
119 exePath = getExePath( |
119 exePath = getExePath( |
120 winreg.HKEY_CURRENT_USER, |
120 winreg.HKEY_CURRENT_USER, |
121 winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr) |
121 winreg.KEY_WOW64_32KEY | winreg.KEY_READ, |
|
122 versionStr, |
|
123 ) |
122 if exePath is not None: |
124 if exePath is not None: |
123 executables.add(exePath) |
125 executables.add(exePath) |
124 |
126 |
125 exePath = getExePath( |
127 exePath = getExePath( |
126 winreg.HKEY_LOCAL_MACHINE, |
128 winreg.HKEY_LOCAL_MACHINE, |
127 winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr) |
129 winreg.KEY_WOW64_32KEY | winreg.KEY_READ, |
|
130 versionStr, |
|
131 ) |
128 if exePath is not None: |
132 if exePath is not None: |
129 executables.add(exePath) |
133 executables.add(exePath) |
130 |
134 |
131 # Even on Intel 64-bit machines it's 'AMD64' |
135 # Even on Intel 64-bit machines it's 'AMD64' |
132 if platform.machine() == 'AMD64': |
136 if platform.machine() == "AMD64": |
133 exePath = getExePath( |
137 exePath = getExePath( |
134 winreg.HKEY_CURRENT_USER, |
138 winreg.HKEY_CURRENT_USER, |
135 winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr) |
139 winreg.KEY_WOW64_64KEY | winreg.KEY_READ, |
|
140 versionStr, |
|
141 ) |
136 if exePath is not None: |
142 if exePath is not None: |
137 executables.add(exePath) |
143 executables.add(exePath) |
138 |
144 |
139 exePath = getExePath( |
145 exePath = getExePath( |
140 winreg.HKEY_LOCAL_MACHINE, |
146 winreg.HKEY_LOCAL_MACHINE, |
141 winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr) |
147 winreg.KEY_WOW64_64KEY | winreg.KEY_READ, |
|
148 versionStr, |
|
149 ) |
142 if exePath is not None: |
150 if exePath is not None: |
143 executables.add(exePath) |
151 executables.add(exePath) |
144 |
152 |
145 if not executables and majorVersion >= 3: |
153 if not executables and majorVersion >= 3: |
146 # check the PATH environment variable if nothing was found |
154 # check the PATH environment variable if nothing was found |
147 # Python 3 only |
155 # Python 3 only |
148 path = Utilities.getEnvironmentEntry('PATH') |
156 path = Utilities.getEnvironmentEntry("PATH") |
149 if path: |
157 if path: |
150 dirs = path.split(os.pathsep) |
158 dirs = path.split(os.pathsep) |
151 for directory in dirs: |
159 for directory in dirs: |
152 for suffix in (".bat", ".exe"): |
160 for suffix in (".bat", ".exe"): |
153 exe = os.path.join(directory, "cxfreeze" + suffix) |
161 exe = os.path.join(directory, "cxfreeze" + suffix) |
154 if os.access(exe, os.X_OK): |
162 if os.access(exe, os.X_OK): |
155 executables.add(exe) |
163 executables.add(exe) |
156 else: |
164 else: |
157 # |
165 # |
158 # Linux, Unix ... |
166 # Linux, Unix ... |
159 cxfreezeScript = 'cxfreeze' |
167 cxfreezeScript = "cxfreeze" |
160 scriptSuffixes = ["", "-python{0}".format(majorVersion)] |
168 scriptSuffixes = ["", "-python{0}".format(majorVersion)] |
161 for minorVersion in minorVersions: |
169 for minorVersion in minorVersions: |
162 scriptSuffixes.append( |
170 scriptSuffixes.append("-python{0}.{1}".format(majorVersion, minorVersion)) |
163 "-python{0}.{1}".format(majorVersion, minorVersion)) |
|
164 # There could be multiple cxfreeze executables in the path |
171 # There could be multiple cxfreeze executables in the path |
165 # e.g. for different python variants |
172 # e.g. for different python variants |
166 path = Utilities.getEnvironmentEntry('PATH') |
173 path = Utilities.getEnvironmentEntry("PATH") |
167 # environment variable not defined |
174 # environment variable not defined |
168 if path is None: |
175 if path is None: |
169 return [] |
176 return [] |
170 |
177 |
171 # step 1: determine possible candidates |
178 # step 1: determine possible candidates |
172 exes = [] |
179 exes = [] |
173 dirs = path.split(os.pathsep) |
180 dirs = path.split(os.pathsep) |
174 for directory in dirs: |
181 for directory in dirs: |
175 for suffix in scriptSuffixes: |
182 for suffix in scriptSuffixes: |
176 exe = os.path.join(directory, cxfreezeScript + suffix) |
183 exe = os.path.join(directory, cxfreezeScript + suffix) |
177 if os.access(exe, os.X_OK): |
184 if os.access(exe, os.X_OK): |
178 exes.append(exe) |
185 exes.append(exe) |
179 |
186 |
180 # step 2: determine the Python variant |
187 # step 2: determine the Python variant |
181 _exePy3 = set() |
188 _exePy3 = set() |
182 versionArgs = ["-c", "import sys; print(sys.version_info[0])"] |
189 versionArgs = ["-c", "import sys; print(sys.version_info[0])"] |
183 for exe in exes: |
190 for exe in exes: |
184 with open(exe, "r") as f: |
191 with open(exe, "r") as f: |
187 process = QProcess() |
194 process = QProcess() |
188 process.start(program, versionArgs) |
195 process.start(program, versionArgs) |
189 process.waitForFinished(5000) |
196 process.waitForFinished(5000) |
190 # get a QByteArray of the output |
197 # get a QByteArray of the output |
191 versionBytes = process.readAllStandardOutput() |
198 versionBytes = process.readAllStandardOutput() |
192 versionStr = str(versionBytes, encoding='utf-8').strip() |
199 versionStr = str(versionBytes, encoding="utf-8").strip() |
193 if versionStr == "3": |
200 if versionStr == "3": |
194 _exePy3.add(exe) |
201 _exePy3.add(exe) |
195 |
202 |
196 executables = _exePy3 |
203 executables = _exePy3 |
197 |
204 |
198 # sort items, the probably newest topmost |
205 # sort items, the probably newest topmost |
199 executables = list(executables) |
206 executables = list(executables) |
200 executables.sort(reverse=True) |
207 executables.sort(reverse=True) |
201 return executables |
208 return executables |
202 |
209 |
203 |
210 |
204 def _checkProgram(): |
211 def _checkProgram(): |
205 """ |
212 """ |
206 Restricted function to check the availability of cxfreeze. |
213 Restricted function to check the availability of cxfreeze. |
207 |
214 |
208 @return flag indicating availability |
215 @return flag indicating availability |
209 @rtype bool |
216 @rtype bool |
210 """ |
217 """ |
211 global error, exePy3 |
218 global error, exePy3 |
212 |
219 |
213 exePy3 = _findExecutable(3) |
220 exePy3 = _findExecutable(3) |
214 if exePy3 == []: |
221 if exePy3 == []: |
215 if Utilities.isWindowsPlatform(): |
222 if Utilities.isWindowsPlatform(): |
216 error = QCoreApplication.translate( |
223 error = QCoreApplication.translate( |
217 "CxFreezePlugin", |
224 "CxFreezePlugin", |
218 "The cxfreeze.bat executable could not be found." |
225 "The cxfreeze.bat executable could not be found." |
219 "Did you run the cxfreeze-postinstall script?") |
226 "Did you run the cxfreeze-postinstall script?", |
|
227 ) |
220 else: |
228 else: |
221 error = QCoreApplication.translate( |
229 error = QCoreApplication.translate( |
222 "CxFreezePlugin", |
230 "CxFreezePlugin", "The cxfreeze executable could not be found." |
223 "The cxfreeze executable could not be found.") |
231 ) |
224 return False |
232 return False |
225 else: |
233 else: |
226 return True |
234 return True |
227 |
235 |
228 |
236 |
229 class CxFreezePlugin(QObject): |
237 class CxFreezePlugin(QObject): |
230 """ |
238 """ |
231 Class implementing the CxFreeze plugin. |
239 Class implementing the CxFreeze plugin. |
232 """ |
240 """ |
|
241 |
233 def __init__(self, ui): |
242 def __init__(self, ui): |
234 """ |
243 """ |
235 Constructor |
244 Constructor |
236 |
245 |
237 @param ui reference to the user interface object |
246 @param ui reference to the user interface object |
238 @type UserInterface |
247 @type UserInterface |
239 """ |
248 """ |
240 super().__init__(ui) |
249 super().__init__(ui) |
241 self.__ui = ui |
250 self.__ui = ui |
242 self.__initialize() |
251 self.__initialize() |
243 _checkProgram() |
252 _checkProgram() |
244 |
253 |
245 self.__translator = None |
254 self.__translator = None |
246 self.__loadTranslator() |
255 self.__loadTranslator() |
247 |
256 |
248 def __initialize(self): |
257 def __initialize(self): |
249 """ |
258 """ |
250 Private slot to (re)initialize the plugin. |
259 Private slot to (re)initialize the plugin. |
251 """ |
260 """ |
252 self.__projectAct = None |
261 self.__projectAct = None |
253 self.__projectSeparator = None |
262 self.__projectSeparator = None |
254 |
263 |
255 def activate(self): |
264 def activate(self): |
256 """ |
265 """ |
257 Public method to activate this plugin. |
266 Public method to activate this plugin. |
258 |
267 |
259 @return tuple of None and activation status |
268 @return tuple of None and activation status |
260 @rtype tuple of (None, bool) |
269 @rtype tuple of (None, bool) |
261 """ |
270 """ |
262 global error |
271 global error |
263 |
272 |
264 # There is already an error, don't activate |
273 # There is already an error, don't activate |
265 if error: |
274 if error: |
266 return None, False |
275 return None, False |
267 |
276 |
268 # cxfreeze is only activated if it is available |
277 # cxfreeze is only activated if it is available |
269 if not _checkProgram(): |
278 if not _checkProgram(): |
270 return None, False |
279 return None, False |
271 |
280 |
272 project = ericApp().getObject("Project") |
281 project = ericApp().getObject("Project") |
273 menu = project.getMenu("Packagers") |
282 menu = project.getMenu("Packagers") |
274 if menu: |
283 if menu: |
275 self.__projectAct = EricAction( |
284 self.__projectAct = EricAction( |
276 self.tr('Use cx_freeze'), |
285 self.tr("Use cx_freeze"), |
277 self.tr('Use cx_&freeze'), 0, 0, |
286 self.tr("Use cx_&freeze"), |
278 self, 'packagers_cxfreeze') |
287 0, |
|
288 0, |
|
289 self, |
|
290 "packagers_cxfreeze", |
|
291 ) |
279 self.__projectAct.setStatusTip( |
292 self.__projectAct.setStatusTip( |
280 self.tr('Generate a distribution package using cx_freeze')) |
293 self.tr("Generate a distribution package using cx_freeze") |
281 self.__projectAct.setWhatsThis(self.tr( |
294 ) |
282 """<b>Use cx_freeze</b>""" |
295 self.__projectAct.setWhatsThis( |
283 """<p>Generate a distribution package using cx_freeze.""" |
296 self.tr( |
284 """ The command is executed in the project path. All""" |
297 """<b>Use cx_freeze</b>""" |
285 """ files and directories must be given absolute or""" |
298 """<p>Generate a distribution package using cx_freeze.""" |
286 """ relative to the project directory.</p>""" |
299 """ The command is executed in the project path. All""" |
287 )) |
300 """ files and directories must be given absolute or""" |
|
301 """ relative to the project directory.</p>""" |
|
302 ) |
|
303 ) |
288 self.__projectAct.triggered.connect(self.__cxfreeze) |
304 self.__projectAct.triggered.connect(self.__cxfreeze) |
289 project.addEricActions([self.__projectAct]) |
305 project.addEricActions([self.__projectAct]) |
290 self.__projectSeparator = menu.addSeparator() |
306 self.__projectSeparator = menu.addSeparator() |
291 menu.addAction(self.__projectAct) |
307 menu.addAction(self.__projectAct) |
292 project.showMenu.connect(self.__projectShowMenu) |
308 project.showMenu.connect(self.__projectShowMenu) |
293 |
309 |
294 error = "" |
310 error = "" |
295 return None, True |
311 return None, True |
296 |
312 |
297 def deactivate(self): |
313 def deactivate(self): |
298 """ |
314 """ |
300 """ |
316 """ |
301 menu = ericApp().getObject("Project").getMenu("Packagers") |
317 menu = ericApp().getObject("Project").getMenu("Packagers") |
302 if menu: |
318 if menu: |
303 if self.__projectAct: |
319 if self.__projectAct: |
304 menu.removeAction(self.__projectAct) |
320 menu.removeAction(self.__projectAct) |
305 ericApp().getObject("Project").removeEricActions( |
321 ericApp().getObject("Project").removeEricActions([self.__projectAct]) |
306 [self.__projectAct]) |
|
307 if self.__projectSeparator: |
322 if self.__projectSeparator: |
308 menu.removeAction(self.__projectSeparator) |
323 menu.removeAction(self.__projectSeparator) |
309 |
324 |
310 self.__initialize() |
325 self.__initialize() |
311 |
326 |
312 def __projectShowMenu(self, menuName, menu): |
327 def __projectShowMenu(self, menuName, menu): |
313 """ |
328 """ |
314 Private slot called, when the the project menu or a submenu is |
329 Private slot called, when the the project menu or a submenu is |
315 about to be shown. |
330 about to be shown. |
316 |
331 |
317 @param menuName name of the menu to be shown |
332 @param menuName name of the menu to be shown |
318 @type str |
333 @type str |
319 @param menu reference to the menu |
334 @param menu reference to the menu |
320 @type QMenu |
335 @type QMenu |
321 """ |
336 """ |
322 if ( |
337 if menuName == "Packagers" and self.__projectAct is not None: |
323 menuName == "Packagers" and |
|
324 self.__projectAct is not None |
|
325 ): |
|
326 self.__projectAct.setEnabled( |
338 self.__projectAct.setEnabled( |
327 ericApp().getObject("Project").getProjectLanguage() == |
339 ericApp().getObject("Project").getProjectLanguage() == "Python3" |
328 "Python3" |
340 ) |
329 ) |
341 |
330 |
|
331 def __loadTranslator(self): |
342 def __loadTranslator(self): |
332 """ |
343 """ |
333 Private method to load the translation file. |
344 Private method to load the translation file. |
334 """ |
345 """ |
335 if self.__ui is not None: |
346 if self.__ui is not None: |
336 loc = self.__ui.getLocale() |
347 loc = self.__ui.getLocale() |
337 if loc and loc != "C": |
348 if loc and loc != "C": |
338 locale_dir = os.path.join(os.path.dirname(__file__), |
349 locale_dir = os.path.join(os.path.dirname(__file__), "CxFreeze", "i18n") |
339 "CxFreeze", "i18n") |
|
340 translation = "cxfreeze_{0}".format(loc) |
350 translation = "cxfreeze_{0}".format(loc) |
341 translator = QTranslator(None) |
351 translator = QTranslator(None) |
342 loaded = translator.load(translation, locale_dir) |
352 loaded = translator.load(translation, locale_dir) |
343 if loaded: |
353 if loaded: |
344 self.__translator = translator |
354 self.__translator = translator |
345 ericApp().installTranslator(self.__translator) |
355 ericApp().installTranslator(self.__translator) |
346 else: |
356 else: |
347 print("Warning: translation file '{0}' could not be" |
357 print( |
348 " loaded.".format(translation)) |
358 "Warning: translation file '{0}' could not be" |
|
359 " loaded.".format(translation) |
|
360 ) |
349 print("Using default.") |
361 print("Using default.") |
350 |
362 |
351 def __cxfreeze(self): |
363 def __cxfreeze(self): |
352 """ |
364 """ |
353 Private slot to handle the cxfreeze execution. |
365 Private slot to handle the cxfreeze execution. |
354 """ |
366 """ |
355 project = ericApp().getObject("Project") |
367 project = ericApp().getObject("Project") |
358 EricMessageBox.critical( |
370 EricMessageBox.critical( |
359 self.__ui, |
371 self.__ui, |
360 self.tr("cxfreeze"), |
372 self.tr("cxfreeze"), |
361 self.tr( |
373 self.tr( |
362 """There is no main script defined for the current""" |
374 """There is no main script defined for the current""" |
363 """ project."""), |
375 """ project.""" |
364 EricMessageBox.StandardButtons(EricMessageBox.Abort)) |
376 ), |
|
377 EricMessageBox.StandardButtons(EricMessageBox.Abort), |
|
378 ) |
365 return |
379 return |
366 |
380 |
367 majorVersionStr = project.getProjectLanguage() |
381 majorVersionStr = project.getProjectLanguage() |
368 exe = {"Python3": exePy3}.get(majorVersionStr) |
382 exe = {"Python3": exePy3}.get(majorVersionStr) |
369 if exe == []: |
383 if exe == []: |
370 EricMessageBox.critical( |
384 EricMessageBox.critical( |
371 self.__ui, |
385 self.__ui, |
372 self.tr("cxfreeze"), |
386 self.tr("cxfreeze"), |
373 self.tr("""The cxfreeze executable could not be found.""")) |
387 self.tr("""The cxfreeze executable could not be found."""), |
|
388 ) |
374 return |
389 return |
375 |
390 |
376 # check if all files saved and errorfree before continue |
391 # check if all files saved and errorfree before continue |
377 if not project.checkAllScriptsDirty(reportSyntaxErrors=True): |
392 if not project.checkAllScriptsDirty(reportSyntaxErrors=True): |
378 return |
393 return |
379 |
394 |
380 from CxFreeze.CxfreezeConfigDialog import CxfreezeConfigDialog |
395 from CxFreeze.CxfreezeConfigDialog import CxfreezeConfigDialog |
381 parms = project.getData('PACKAGERSPARMS', "CXFREEZE") |
396 |
|
397 parms = project.getData("PACKAGERSPARMS", "CXFREEZE") |
382 dlg = CxfreezeConfigDialog(project, exe, parms) |
398 dlg = CxfreezeConfigDialog(project, exe, parms) |
383 if dlg.exec() == QDialog.DialogCode.Accepted: |
399 if dlg.exec() == QDialog.DialogCode.Accepted: |
384 args, parms = dlg.generateParameters() |
400 args, parms = dlg.generateParameters() |
385 project.setData('PACKAGERSPARMS', "CXFREEZE", parms) |
401 project.setData("PACKAGERSPARMS", "CXFREEZE", parms) |
386 |
402 |
387 # now do the call |
403 # now do the call |
388 from CxFreeze.CxfreezeExecDialog import CxfreezeExecDialog |
404 from CxFreeze.CxfreezeExecDialog import CxfreezeExecDialog |
|
405 |
389 dia = CxfreezeExecDialog("cxfreeze") |
406 dia = CxfreezeExecDialog("cxfreeze") |
390 dia.show() |
407 dia.show() |
391 res = dia.start(args, parms, project.ppath, |
408 res = dia.start(args, parms, project.ppath, project.getMainScript()) |
392 project.getMainScript()) |
|
393 if res: |
409 if res: |
394 dia.exec() |
410 dia.exec() |
395 |
411 |
396 |
412 |
397 def installDependencies(pipInstall): |
413 def installDependencies(pipInstall): |
398 """ |
414 """ |
399 Function to install dependencies of this plug-in. |
415 Function to install dependencies of this plug-in. |
400 |
416 |
401 @param pipInstall function to be called with a list of package names. |
417 @param pipInstall function to be called with a list of package names. |
402 @type function |
418 @type function |
403 """ |
419 """ |
404 try: |
420 try: |
405 import cx_Freeze # __IGNORE_WARNING__ |
421 import cx_Freeze # __IGNORE_WARNING__ |
406 except ImportError: |
422 except ImportError: |
407 pipInstall(["cx-Freeze"]) |
423 pipInstall(["cx-Freeze"]) |
408 |
424 |
|
425 |
409 # |
426 # |
410 # eflag: noqa = M801 |
427 # eflag: noqa = M801 |