PluginPyInstaller.py

changeset 1
f7788bc8c08d
parent 0
c6363afe8387
child 2
5109c484bc49
equal deleted inserted replaced
0:c6363afe8387 1:f7788bc8c08d
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the PyInstaller interface plug-in.
8 """
9
10 from __future__ import unicode_literals
11
12 import os
13 import platform
14
15 from PyQt5.QtCore import QObject, QCoreApplication
16
17 import Utilities
18
19 # Start-Of-Header
20 name = "PyInstaller Plugin"
21 author = "Detlev Offenbach <detlev@die-offenbachs.de>"
22 autoactivate = True
23 deactivateable = True
24 version = "0.1.0"
25 className = "PyInstallerPlugin"
26 packageName = "PyInstaller"
27 shortDescription = "Show dialogs to configure and execute PyInstaller."
28 longDescription = (
29 """This plug-in implements dialogs to configure and execute PyInstaller"""
30 """ for an eric project. PyInstaller must be available or must be"""
31 """ installed via 'pip install PyInstaller'."""
32 )
33 needsRestart = False
34 pyqtApi = 2
35 python2Compatible = True
36 # End-Of-Header
37
38 error = ""
39
40 exePy2 = []
41 exePy3 = []
42
43
44 def exeDisplayDataList():
45 """
46 Module function to support the display of some executable info.
47
48 @return list of dictionaries containing the data to query the presence of
49 the executable
50 @rtype list of dict
51 """
52 dataList = []
53 data = {
54 "programEntry": True,
55 "header": QCoreApplication.translate(
56 "PyInstallerPlugin", "Packagers - PyInstaller"),
57 "exe": "dummyExe",
58 "versionCommand": "--version",
59 "versionStartsWith": "dummyExe",
60 "versionPosition": -1,
61 "version": "",
62 "versionCleanup": None,
63 "versionRe": "^\d",
64 }
65
66 if _checkProgram():
67 for exePath in (exePy2 + exePy3):
68 data["exe"] = exePath
69 data["versionStartsWith"] = ""
70 dataList.append(data.copy())
71 else:
72 dataList.append(data)
73 return dataList
74
75
76 def _findExecutable(majorVersion):
77 """
78 Restricted function to determine the names of the executables.
79
80 @param majorVersion major python version
81 @type int
82 @return names of the executables
83 @rtype list of str
84 """
85 # Determine Python Version
86 if majorVersion == 3:
87 minorVersions = range(10)
88 elif majorVersion == 2:
89 minorVersions = [7] # PyInstaller supports just Python 2.7
90 else:
91 return []
92
93 executables = set()
94 if Utilities.isWindowsPlatform():
95 #
96 # Windows
97 #
98 try:
99 import winreg
100 except ImportError:
101 import _winreg as winreg # __IGNORE_WARNING__
102
103 def getExePath(branch, access, versionStr):
104 exes = []
105 try:
106 software = winreg.OpenKey(branch, 'Software', 0, access)
107 python = winreg.OpenKey(software, 'Python', 0, access)
108 pcore = winreg.OpenKey(python, 'PythonCore', 0, access)
109 version = winreg.OpenKey(pcore, versionStr, 0, access)
110 installpath = winreg.QueryValue(version, 'InstallPath')
111 # Look for pyinstaller.exe
112 exe = os.path.join(installpath, 'Scripts', 'pyinstaller.exe')
113 if os.access(exe, os.X_OK):
114 exes.append(exe)
115 # Look for pyi-makespec.exe
116 exe = os.path.join(installpath, 'Scripts', 'pyi-makespec.exe')
117 if os.access(exe, os.X_OK):
118 exes.append(exe)
119 except (WindowsError, OSError): # __IGNORE_WARNING__
120 pass
121 return exes
122
123 for minorVersion in minorVersions:
124 versionStr = '{0}.{1}'.format(majorVersion, minorVersion)
125 exePath = getExePath(
126 winreg.HKEY_CURRENT_USER,
127 winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr)
128 if exePath is not None:
129 executables.add(exePath)
130
131 exePath = getExePath(
132 winreg.HKEY_LOCAL_MACHINE,
133 winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr)
134 if exePath is not None:
135 executables.add(exePath)
136
137 # Even on Intel 64-bit machines it's 'AMD64'
138 if platform.machine() == 'AMD64':
139 exePath = getExePath(
140 winreg.HKEY_CURRENT_USER,
141 winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr)
142 if exePath is not None:
143 executables.add(exePath)
144
145 exePath = getExePath(
146 winreg.HKEY_LOCAL_MACHINE,
147 winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr)
148 if exePath is not None:
149 executables.add(exePath)
150 else:
151 #
152 # Linux, Unix ...
153 pyinstallerScripts = ['pyinstaller', 'pyi-makespec']
154 ## scriptSuffixes = [""]
155 ## for minorVersion in minorVersions:
156 ## scriptSuffixes.append(
157 ## "-python{0}.{1}".format(majorVersion, minorVersion))
158 # There could be multiple pyinstaller executables in the path
159 # e.g. for different python variants
160 path = Utilities.getEnvironmentEntry('PATH')
161 # environment variable not defined
162 if path is None:
163 return []
164
165 # step 1: determine possible candidates
166 exes = []
167 dirs = path.split(os.pathsep)
168 for directory in dirs:
169 for pyinstallerScript in pyinstallerScripts:
170 exe = os.path.join(directory, pyinstallerScript)
171 if os.access(exe, os.X_OK):
172 exes.append(exe)
173
174 # step 2: determine the Python variant
175 if Utilities.isMacPlatform():
176 checkStrings = ["Python.framework/Versions/3".lower(),
177 "python3"]
178 else:
179 checkStrings = ["python3"]
180
181 _exePy2 = set()
182 _exePy3 = set()
183 for exe in exes:
184 try:
185 f = open(exe, "r")
186 line0 = f.readline()
187 for checkStr in checkStrings:
188 if checkStr in line0.lower():
189 _exePy3.add(exe)
190 break
191 else:
192 _exePy2.add(exe)
193 finally:
194 f.close()
195
196 executables = _exePy3 if majorVersion == 3 else _exePy2
197
198 # sort items, the probably newest topmost
199 executables = list(executables)
200 executables.sort(reverse=True)
201 return executables
202
203
204 def _checkProgram():
205 """
206 Restricted function to check the availability of pyinstaller.
207
208 @return flag indicating availability (boolean)
209 """
210 global error, exePy2, exePy3
211
212 exePy2 = _findExecutable(2)
213 exePy3 = _findExecutable(3)
214 if (exePy2 + exePy3) == []:
215 if Utilities.isWindowsPlatform():
216 error = QCoreApplication.translate(
217 "PyInstallerPlugin",
218 "The pyinstaller.exe executable could not be found."
219 )
220 else:
221 error = QCoreApplication.translate(
222 "PyInstallerPlugin",
223 "The pyinstaller executable could not be found."
224 )
225 return False
226 else:
227 return True
228
229
230 class PyInstallerPlugin(QObject):
231 """
232 Class documentation goes here.
233 """
234 def __init__(self, ui):
235 """
236 Constructor
237
238 @param ui reference to the user interface object (UI.UserInterface)
239 """
240 super(PyInstallerPlugin, self).__init__(ui)
241 self.__ui = ui
242
243 def activate(self):
244 """
245 Public method to activate this plugin.
246
247 @return tuple of None and activation status (boolean)
248 """
249 global error
250 error = "" # clear previous error
251
252 return None, True
253
254 def deactivate(self):
255 """
256 Public method to deactivate this plugin.
257 """
258 pass

eric ide

mercurial