PluginPyInstaller.py

changeset 1
f7788bc8c08d
parent 0
c6363afe8387
child 2
5109c484bc49
--- a/PluginPyInstaller.py	Tue Jan 16 12:04:56 2018 +0100
+++ b/PluginPyInstaller.py	Tue Jan 16 14:53:10 2018 +0100
@@ -0,0 +1,258 @@
+# -*- 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

eric ide

mercurial