Tue, 16 Jan 2018 14:53:10 +0100
Implemented support for the programs dialog.
# -*- coding: utf-8 -*- # Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing the PyInstaller interface plug-in. """ from __future__ import unicode_literals import os import platform from PyQt5.QtCore import QObject, QCoreApplication import Utilities # Start-Of-Header name = "PyInstaller Plugin" author = "Detlev Offenbach <detlev@die-offenbachs.de>" autoactivate = True deactivateable = True version = "0.1.0" className = "PyInstallerPlugin" packageName = "PyInstaller" shortDescription = "Show dialogs to configure and execute PyInstaller." longDescription = ( """This plug-in implements dialogs to configure and execute PyInstaller""" """ for an eric project. PyInstaller must be available or must be""" """ installed via 'pip install PyInstaller'.""" ) needsRestart = False pyqtApi = 2 python2Compatible = True # End-Of-Header error = "" exePy2 = [] exePy3 = [] def exeDisplayDataList(): """ Module function to support the display of some executable info. @return list of dictionaries containing the data to query the presence of the executable @rtype list of dict """ dataList = [] data = { "programEntry": True, "header": QCoreApplication.translate( "PyInstallerPlugin", "Packagers - PyInstaller"), "exe": "dummyExe", "versionCommand": "--version", "versionStartsWith": "dummyExe", "versionPosition": -1, "version": "", "versionCleanup": None, "versionRe": "^\d", } if _checkProgram(): for exePath in (exePy2 + exePy3): data["exe"] = exePath data["versionStartsWith"] = "" dataList.append(data.copy()) else: dataList.append(data) return dataList def _findExecutable(majorVersion): """ Restricted function to determine the names of the executables. @param majorVersion major python version @type int @return names of the executables @rtype list of str """ # Determine Python Version if majorVersion == 3: minorVersions = range(10) elif majorVersion == 2: minorVersions = [7] # PyInstaller supports just Python 2.7 else: return [] executables = set() if Utilities.isWindowsPlatform(): # # Windows # try: import winreg except ImportError: import _winreg as winreg # __IGNORE_WARNING__ def getExePath(branch, access, versionStr): exes = [] try: software = winreg.OpenKey(branch, 'Software', 0, access) python = winreg.OpenKey(software, 'Python', 0, access) pcore = winreg.OpenKey(python, 'PythonCore', 0, access) version = winreg.OpenKey(pcore, versionStr, 0, access) installpath = winreg.QueryValue(version, 'InstallPath') # Look for pyinstaller.exe exe = os.path.join(installpath, 'Scripts', 'pyinstaller.exe') if os.access(exe, os.X_OK): exes.append(exe) # Look for pyi-makespec.exe exe = os.path.join(installpath, 'Scripts', 'pyi-makespec.exe') if os.access(exe, os.X_OK): exes.append(exe) except (WindowsError, OSError): # __IGNORE_WARNING__ pass return exes for minorVersion in minorVersions: versionStr = '{0}.{1}'.format(majorVersion, minorVersion) exePath = getExePath( winreg.HKEY_CURRENT_USER, winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr) if exePath is not None: executables.add(exePath) exePath = getExePath( winreg.HKEY_LOCAL_MACHINE, winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr) if exePath is not None: executables.add(exePath) # Even on Intel 64-bit machines it's 'AMD64' if platform.machine() == 'AMD64': exePath = getExePath( winreg.HKEY_CURRENT_USER, winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr) if exePath is not None: executables.add(exePath) exePath = getExePath( winreg.HKEY_LOCAL_MACHINE, winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr) if exePath is not None: executables.add(exePath) else: # # Linux, Unix ... pyinstallerScripts = ['pyinstaller', 'pyi-makespec'] ## scriptSuffixes = [""] ## for minorVersion in minorVersions: ## scriptSuffixes.append( ## "-python{0}.{1}".format(majorVersion, minorVersion)) # There could be multiple pyinstaller executables in the path # e.g. for different python variants path = Utilities.getEnvironmentEntry('PATH') # environment variable not defined if path is None: return [] # step 1: determine possible candidates exes = [] dirs = path.split(os.pathsep) for directory in dirs: for pyinstallerScript in pyinstallerScripts: exe = os.path.join(directory, pyinstallerScript) if os.access(exe, os.X_OK): exes.append(exe) # step 2: determine the Python variant if Utilities.isMacPlatform(): checkStrings = ["Python.framework/Versions/3".lower(), "python3"] else: checkStrings = ["python3"] _exePy2 = set() _exePy3 = set() for exe in exes: try: f = open(exe, "r") line0 = f.readline() for checkStr in checkStrings: if checkStr in line0.lower(): _exePy3.add(exe) break else: _exePy2.add(exe) finally: f.close() executables = _exePy3 if majorVersion == 3 else _exePy2 # sort items, the probably newest topmost executables = list(executables) executables.sort(reverse=True) return executables def _checkProgram(): """ Restricted function to check the availability of pyinstaller. @return flag indicating availability (boolean) """ global error, exePy2, exePy3 exePy2 = _findExecutable(2) exePy3 = _findExecutable(3) if (exePy2 + exePy3) == []: if Utilities.isWindowsPlatform(): error = QCoreApplication.translate( "PyInstallerPlugin", "The pyinstaller.exe executable could not be found." ) else: error = QCoreApplication.translate( "PyInstallerPlugin", "The pyinstaller executable could not be found." ) return False else: return True class PyInstallerPlugin(QObject): """ Class documentation goes here. """ def __init__(self, ui): """ Constructor @param ui reference to the user interface object (UI.UserInterface) """ super(PyInstallerPlugin, self).__init__(ui) self.__ui = ui def activate(self): """ Public method to activate this plugin. @return tuple of None and activation status (boolean) """ global error error = "" # clear previous error return None, True def deactivate(self): """ Public method to deactivate this plugin. """ pass