PluginPyInstaller.py

branch
eric7
changeset 38
fc9ef9dcd51a
parent 35
d9b3cadaf707
child 43
01ce3d6f7a07
equal deleted inserted replaced
37:9ecfea29a47c 38:fc9ef9dcd51a
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'."""
87 @return names of the executables 87 @return names of the executables
88 @rtype list of str 88 @rtype list of str
89 """ 89 """
90 # Determine Python Version 90 # Determine Python Version
91 if majorVersion == 3: 91 if majorVersion == 3:
92 minorVersions = range(10) 92 minorVersions = range(16)
93 elif majorVersion == 2:
94 minorVersions = [7] # PyInstaller supports just Python 2.7
95 else: 93 else:
96 return [] 94 return []
97 95
98 executables = set() 96 executables = set()
99 if Utilities.isWindowsPlatform(): 97 if Utilities.isWindowsPlatform():
212 210
213 def _checkProgram(): 211 def _checkProgram():
214 """ 212 """
215 Restricted function to check the availability of pyinstaller. 213 Restricted function to check the availability of pyinstaller.
216 214
217 @return flag indicating availability (boolean) 215 @return flag indicating availability
216 @rtype bool
218 """ 217 """
219 global error, exePy3 218 global error, exePy3
220 219
221 exePy3 = _findExecutable(3) 220 exePy3 = _findExecutable(3)
222 if not exePy3: 221 if not exePy3:
264 263
265 def activate(self): 264 def activate(self):
266 """ 265 """
267 Public method to activate this plug-in. 266 Public method to activate this plug-in.
268 267
269 @return tuple of None and activation status (boolean) 268 @return tuple of None and activation status
269 @rtype tuple of (None, bool)
270 """ 270 """
271 global error 271 global error
272 272
273 # There is already an error, don't activate 273 # There is already an error, don't activate
274 if error: 274 if error:
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):
370 @param menu reference to the menu 370 @param menu reference to the menu
371 @type QMenu 371 @type QMenu
372 """ 372 """
373 if menuName == "Packagers": 373 if menuName == "Packagers":
374 enable = ( 374 enable = (
375 e5App().getObject("Project").getProjectLanguage() == "Python3" 375 ericApp().getObject("Project").getProjectLanguage() ==
376 "Python3"
376 ) 377 )
377 for act in self.__projectActs: 378 for act in self.__projectActs:
378 act.setEnabled(enable) 379 act.setEnabled(enable)
379 380
380 def __loadTranslator(self): 381 def __loadTranslator(self):
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

eric ide

mercurial