10 import contextlib |
10 import contextlib |
11 import os |
11 import os |
12 import platform |
12 import platform |
13 import shutil |
13 import shutil |
14 |
14 |
15 from PyQt5.QtCore import ( |
15 from PyQt6.QtCore import ( |
16 pyqtSlot, QObject, QCoreApplication, QTranslator, QProcess |
16 pyqtSlot, QObject, QCoreApplication, QTranslator, QProcess |
17 ) |
17 ) |
18 from PyQt5.QtWidgets import QDialog |
18 from PyQt6.QtWidgets import QDialog |
19 |
19 |
20 from E5Gui import E5MessageBox |
20 from EricWidgets import EricMessageBox |
21 from E5Gui.E5Action import E5Action |
21 from EricGui.EricAction import EricAction |
22 from E5Gui.E5Application import e5App |
22 from EricWidgets.EricApplication import ericApp |
23 |
23 |
24 import Utilities |
24 import Utilities |
25 |
25 |
26 # Start-Of-Header |
26 # Start-Of-Header |
27 name = "PyInstaller Plugin" |
27 name = "PyInstaller Plugin" |
28 author = "Detlev Offenbach <detlev@die-offenbachs.de>" |
28 author = "Detlev Offenbach <detlev@die-offenbachs.de>" |
29 autoactivate = True |
29 autoactivate = True |
30 deactivateable = True |
30 deactivateable = True |
31 version = "2.2.0" |
31 version = "1.0.0" |
32 className = "PyInstallerPlugin" |
32 className = "PyInstallerPlugin" |
33 packageName = "PyInstaller" |
33 packageName = "PyInstallerInterface" |
34 shortDescription = "Show dialogs to configure and execute PyInstaller." |
34 shortDescription = "Show dialogs to configure and execute PyInstaller." |
35 longDescription = ( |
35 longDescription = ( |
36 """This plug-in implements dialogs to configure and execute PyInstaller""" |
36 """This plug-in implements dialogs to configure and execute PyInstaller""" |
37 """ for an eric project. PyInstaller must be available or must be""" |
37 """ for an eric project. PyInstaller must be available or must be""" |
38 """ installed via 'pip install PyInstaller'.""" |
38 """ installed via 'pip install PyInstaller'.""" |
279 return None, False |
279 return None, False |
280 |
280 |
281 # clear previous error |
281 # clear previous error |
282 error = "" |
282 error = "" |
283 |
283 |
284 project = e5App().getObject("Project") |
284 project = ericApp().getObject("Project") |
285 menu = project.getMenu("Packagers") |
285 menu = project.getMenu("Packagers") |
286 if menu: |
286 if menu: |
287 self.__projectSeparator = menu.addSeparator() |
287 self.__projectSeparator = menu.addSeparator() |
288 |
288 |
289 # Execute PyInstaller |
289 # Execute PyInstaller |
290 act = E5Action( |
290 act = EricAction( |
291 self.tr('Execute PyInstaller'), |
291 self.tr('Execute PyInstaller'), |
292 self.tr('Execute Py&Installer'), 0, 0, |
292 self.tr('Execute Py&Installer'), 0, 0, |
293 self, 'packagers_pyinstaller_run') |
293 self, 'packagers_pyinstaller_run') |
294 act.setStatusTip( |
294 act.setStatusTip( |
295 self.tr('Generate a distribution package using PyInstaller')) |
295 self.tr('Generate a distribution package using PyInstaller')) |
303 act.triggered.connect(self.__pyinstaller) |
303 act.triggered.connect(self.__pyinstaller) |
304 menu.addAction(act) |
304 menu.addAction(act) |
305 self.__projectActs.append(act) |
305 self.__projectActs.append(act) |
306 |
306 |
307 # Execute pyi-makespec |
307 # Execute pyi-makespec |
308 act = E5Action( |
308 act = EricAction( |
309 self.tr('Make PyInstaller Spec File'), |
309 self.tr('Make PyInstaller Spec File'), |
310 self.tr('Make PyInstaller &Spec File'), 0, 0, |
310 self.tr('Make PyInstaller &Spec File'), 0, 0, |
311 self, 'packagers_pyinstaller_spec') |
311 self, 'packagers_pyinstaller_spec') |
312 act.setStatusTip( |
312 act.setStatusTip( |
313 self.tr('Generate a spec file to be used by PyInstaller')) |
313 self.tr('Generate a spec file to be used by PyInstaller')) |
321 act.triggered.connect(self.__pyiMakeSpec) |
321 act.triggered.connect(self.__pyiMakeSpec) |
322 menu.addAction(act) |
322 menu.addAction(act) |
323 self.__projectActs.append(act) |
323 self.__projectActs.append(act) |
324 |
324 |
325 # clean the pyinstaller created directories |
325 # clean the pyinstaller created directories |
326 act = E5Action( |
326 act = EricAction( |
327 self.tr('Clean PyInstaller'), |
327 self.tr('Clean PyInstaller'), |
328 self.tr('&Clean PyInstaller'), 0, 0, |
328 self.tr('&Clean PyInstaller'), 0, 0, |
329 self, 'packagers_pyinstaller_clean') |
329 self, 'packagers_pyinstaller_clean') |
330 act.setStatusTip( |
330 act.setStatusTip( |
331 self.tr('Remove the PyInstaller created directories')) |
331 self.tr('Remove the PyInstaller created directories')) |
337 )) |
337 )) |
338 act.triggered.connect(self.__pyinstallerCleanup) |
338 act.triggered.connect(self.__pyinstallerCleanup) |
339 menu.addAction(act) |
339 menu.addAction(act) |
340 self.__projectActs.append(act) |
340 self.__projectActs.append(act) |
341 |
341 |
342 project.addE5Actions(self.__projectActs) |
342 project.addEricActions(self.__projectActs) |
343 project.showMenu.connect(self.__projectShowMenu) |
343 project.showMenu.connect(self.__projectShowMenu) |
344 |
344 |
345 return None, True |
345 return None, True |
346 |
346 |
347 def deactivate(self): |
347 def deactivate(self): |
348 """ |
348 """ |
349 Public method to deactivate this plug-in. |
349 Public method to deactivate this plug-in. |
350 """ |
350 """ |
351 menu = e5App().getObject("Project").getMenu("Packagers") |
351 menu = ericApp().getObject("Project").getMenu("Packagers") |
352 if menu: |
352 if menu: |
353 for act in self.__projectActs: |
353 for act in self.__projectActs: |
354 menu.removeAction(act) |
354 menu.removeAction(act) |
355 if self.__projectSeparator: |
355 if self.__projectSeparator: |
356 menu.removeAction(self.__projectSeparator) |
356 menu.removeAction(self.__projectSeparator) |
357 |
357 |
358 e5App().getObject("Project").removeE5Actions( |
358 ericApp().getObject("Project").removeEricActions( |
359 self.__projectActs) |
359 self.__projectActs) |
360 |
360 |
361 self.__initialize() |
361 self.__initialize() |
362 |
362 |
363 def __projectShowMenu(self, menuName, menu): |
363 def __projectShowMenu(self, menuName, menu): |
383 """ |
384 """ |
384 if self.__ui is not None: |
385 if self.__ui is not None: |
385 loc = self.__ui.getLocale() |
386 loc = self.__ui.getLocale() |
386 if loc and loc != "C": |
387 if loc and loc != "C": |
387 locale_dir = os.path.join(os.path.dirname(__file__), |
388 locale_dir = os.path.join(os.path.dirname(__file__), |
388 "PyInstaller", "i18n") |
389 "PyInstallerInterface", "i18n") |
389 translation = "pyinstaller_{0}".format(loc) |
390 translation = "pyinstaller_{0}".format(loc) |
390 translator = QTranslator(None) |
391 translator = QTranslator(None) |
391 loaded = translator.load(translation, locale_dir) |
392 loaded = translator.load(translation, locale_dir) |
392 if loaded: |
393 if loaded: |
393 self.__translator = translator |
394 self.__translator = translator |
394 e5App().installTranslator(self.__translator) |
395 ericApp().installTranslator(self.__translator) |
395 else: |
396 else: |
396 print("Warning: translation file '{0}' could not be" |
397 print("Warning: translation file '{0}' could not be" |
397 " loaded.".format(translation)) |
398 " loaded.".format(translation)) |
398 print("Using default.") |
399 print("Using default.") |
399 |
400 |
401 def __pyinstaller(self): |
402 def __pyinstaller(self): |
402 """ |
403 """ |
403 Private slot to execute the pyinstaller command for the current |
404 Private slot to execute the pyinstaller command for the current |
404 project. |
405 project. |
405 """ |
406 """ |
406 project = e5App().getObject("Project") |
407 project = ericApp().getObject("Project") |
407 majorVersionStr = project.getProjectLanguage() |
408 majorVersionStr = project.getProjectLanguage() |
408 if majorVersionStr == "Python3": |
409 if majorVersionStr == "Python3": |
409 executables = [f for f in exePy3 if |
410 executables = [f for f in exePy3 if |
410 f.endswith(("pyinstaller", "pyinstaller.exe"))] |
411 f.endswith(("pyinstaller", "pyinstaller.exe"))] |
411 if not executables: |
412 if not executables: |
412 E5MessageBox.critical( |
413 EricMessageBox.critical( |
413 self.__ui, |
414 self.__ui, |
414 self.tr("pyinstaller"), |
415 self.tr("pyinstaller"), |
415 self.tr("""The pyinstaller executable could not be""" |
416 self.tr("""The pyinstaller executable could not be""" |
416 """ found.""")) |
417 """ found.""")) |
417 return |
418 return |
418 |
419 |
419 # check if all files saved and errorfree before continue |
420 # check if all files saved and errorfree before continue |
420 if not project.checkAllScriptsDirty(reportSyntaxErrors=True): |
421 if not project.checkAllScriptsDirty(reportSyntaxErrors=True): |
421 return |
422 return |
422 |
423 |
423 from PyInstaller.PyInstallerConfigDialog import ( |
424 from PyInstallerInterface.PyInstallerConfigDialog import ( |
424 PyInstallerConfigDialog |
425 PyInstallerConfigDialog |
425 ) |
426 ) |
426 params = project.getData('PACKAGERSPARMS', "PYINSTALLER") |
427 params = project.getData('PACKAGERSPARMS', "PYINSTALLER") |
427 dlg = PyInstallerConfigDialog(project, executables, params, |
428 dlg = PyInstallerConfigDialog(project, executables, params, |
428 mode="installer") |
429 mode="installer") |
429 if dlg.exec() == QDialog.Accepted: |
430 if dlg.exec() == QDialog.DialogCode.Accepted: |
430 args, params, script = dlg.generateParameters() |
431 args, params, script = dlg.generateParameters() |
431 project.setData('PACKAGERSPARMS', "PYINSTALLER", params) |
432 project.setData('PACKAGERSPARMS', "PYINSTALLER", params) |
432 |
433 |
433 # now do the call |
434 # now do the call |
434 from PyInstaller.PyInstallerExecDialog import ( |
435 from PyInstallerInterface.PyInstallerExecDialog import ( |
435 PyInstallerExecDialog |
436 PyInstallerExecDialog |
436 ) |
437 ) |
437 dia = PyInstallerExecDialog("pyinstaller") |
438 dia = PyInstallerExecDialog("pyinstaller") |
438 dia.show() |
439 dia.show() |
439 res = dia.start(args, params, project, script) |
440 res = dia.start(args, params, project, script) |
444 def __pyiMakeSpec(self): |
445 def __pyiMakeSpec(self): |
445 """ |
446 """ |
446 Private slot to execute the pyi-makespec command for the current |
447 Private slot to execute the pyi-makespec command for the current |
447 project to generate a spec file to be used by pyinstaller. |
448 project to generate a spec file to be used by pyinstaller. |
448 """ |
449 """ |
449 project = e5App().getObject("Project") |
450 project = ericApp().getObject("Project") |
450 majorVersionStr = project.getProjectLanguage() |
451 majorVersionStr = project.getProjectLanguage() |
451 if majorVersionStr == "Python3": |
452 if majorVersionStr == "Python3": |
452 executables = [f for f in exePy3 if |
453 executables = [f for f in exePy3 if |
453 f.endswith(("pyi-makespec", "pyi-makespec.exe"))] |
454 f.endswith(("pyi-makespec", "pyi-makespec.exe"))] |
454 if not executables: |
455 if not executables: |
455 E5MessageBox.critical( |
456 EricMessageBox.critical( |
456 self.__ui, |
457 self.__ui, |
457 self.tr("pyi-makespec"), |
458 self.tr("pyi-makespec"), |
458 self.tr("""The pyi-makespec executable could not be""" |
459 self.tr("""The pyi-makespec executable could not be""" |
459 """ found.""")) |
460 """ found.""")) |
460 return |
461 return |
461 |
462 |
462 # check if all files saved and errorfree before continue |
463 # check if all files saved and errorfree before continue |
463 if not project.checkAllScriptsDirty(reportSyntaxErrors=True): |
464 if not project.checkAllScriptsDirty(reportSyntaxErrors=True): |
464 return |
465 return |
465 |
466 |
466 from PyInstaller.PyInstallerConfigDialog import ( |
467 from PyInstallerInterface.PyInstallerConfigDialog import ( |
467 PyInstallerConfigDialog |
468 PyInstallerConfigDialog |
468 ) |
469 ) |
469 params = project.getData('PACKAGERSPARMS', "PYINSTALLER") |
470 params = project.getData('PACKAGERSPARMS', "PYINSTALLER") |
470 dlg = PyInstallerConfigDialog(project, executables, params, |
471 dlg = PyInstallerConfigDialog(project, executables, params, |
471 mode="spec") |
472 mode="spec") |
472 if dlg.exec() == QDialog.Accepted: |
473 if dlg.exec() == QDialog.DialogCode.Accepted: |
473 args, params, script = dlg.generateParameters() |
474 args, params, script = dlg.generateParameters() |
474 project.setData('PACKAGERSPARMS', "PYINSTALLER", params) |
475 project.setData('PACKAGERSPARMS', "PYINSTALLER", params) |
475 |
476 |
476 # now do the call |
477 # now do the call |
477 from PyInstaller.PyInstallerExecDialog import ( |
478 from PyInstallerInterface.PyInstallerExecDialog import ( |
478 PyInstallerExecDialog |
479 PyInstallerExecDialog |
479 ) |
480 ) |
480 dia = PyInstallerExecDialog("pyinstaller") |
481 dia = PyInstallerExecDialog("pyinstaller") |
481 dia.show() |
482 dia.show() |
482 res = dia.start(args, params, project, script) |
483 res = dia.start(args, params, project, script) |
486 @pyqtSlot() |
487 @pyqtSlot() |
487 def __pyinstallerCleanup(self): |
488 def __pyinstallerCleanup(self): |
488 """ |
489 """ |
489 Private slot to remove the directories created by pyinstaller. |
490 Private slot to remove the directories created by pyinstaller. |
490 """ |
491 """ |
491 project = e5App().getObject("Project") |
492 project = ericApp().getObject("Project") |
492 |
493 |
493 from PyInstaller.PyInstallerCleanupDialog import ( |
494 from PyInstallerInterface.PyInstallerCleanupDialog import ( |
494 PyInstallerCleanupDialog |
495 PyInstallerCleanupDialog |
495 ) |
496 ) |
496 dlg = PyInstallerCleanupDialog() |
497 dlg = PyInstallerCleanupDialog() |
497 if dlg.exec() == QDialog.Accepted: |
498 if dlg.exec() == QDialog.DialogCode.Accepted: |
498 removeDirs = dlg.getDirectories() |
499 removeDirs = dlg.getDirectories() |
499 for directory in removeDirs: |
500 for directory in removeDirs: |
500 rd = os.path.join(project.getProjectPath(), directory) |
501 rd = os.path.join(project.getProjectPath(), directory) |
501 shutil.rmtree(rd, ignore_errors=True) |
502 shutil.rmtree(rd, ignore_errors=True) |
502 |
503 |
|
504 |
|
505 def installDependencies(pipInstall): |
|
506 """ |
|
507 Function to install dependencies of this plug-in. |
|
508 |
|
509 @param pipInstall function to be called with a list of package names. |
|
510 @type function |
|
511 """ |
|
512 try: |
|
513 import PyInstaller # __IGNORE_WARNING__ |
|
514 except ImportError: |
|
515 pipInstall(["pyinstaller"]) |
|
516 |
503 # |
517 # |
504 # eflag: noqa = M801 |
518 # eflag: noqa = M801 |