PluginCxFreeze.py

changeset 47
986f27beaad4
parent 44
8b51b5efd1ae
child 50
ed85ec1358f0
equal deleted inserted replaced
45:d08fd21d74d3 47:986f27beaad4
5 5
6 """ 6 """
7 Module implementing the CxFreeze plugin. 7 Module implementing the CxFreeze plugin.
8 """ 8 """
9 9
10 from __future__ import unicode_literals # __IGNORE_WARNING__
11
10 import os 12 import os
11 import sys 13 import platform
12 14
13 from PyQt4.QtCore import QObject, QTranslator, QCoreApplication 15 from PyQt4.QtCore import QObject, QTranslator, QCoreApplication
14 from PyQt4.QtGui import QDialog 16 from PyQt4.QtGui import QDialog
15 17
16 from E5Gui import E5MessageBox 18 from E5Gui import E5MessageBox
22 # Start-of-Header 24 # Start-of-Header
23 name = "CxFreeze Plugin" 25 name = "CxFreeze Plugin"
24 author = "Detlev Offenbach <detlev@die-offenbachs.de>" 26 author = "Detlev Offenbach <detlev@die-offenbachs.de>"
25 autoactivate = True 27 autoactivate = True
26 deactivateable = True 28 deactivateable = True
27 version = "5.1.2" 29 version = "5.2.0"
28 className = "CxFreezePlugin" 30 className = "CxFreezePlugin"
29 packageName = "CxFreeze" 31 packageName = "CxFreeze"
30 shortDescription = "Show the CxFreeze dialogs." 32 shortDescription = "Show the CxFreeze dialogs."
31 longDescription = """This plugin implements the CxFreeze dialogs.""" \ 33 longDescription = """This plugin implements the CxFreeze dialogs.""" \
32 """ CxFreeze is used to generate a distribution package.""" 34 """ CxFreeze is used to generate a distribution package."""
33 needsRestart = False 35 needsRestart = False
34 pyqtApi = 2 36 pyqtApi = 2
35 # End-of-Header 37 # End-of-Header
36 38
37 error = "" 39 error = ""
38 40 exePy2 = []
39 def exeDisplayData(): 41 exePy3 = []
42
43 def exeDisplayDataList():
40 """ 44 """
41 Public method to support the display of some executable info. 45 Public method to support the display of some executable info.
42 46
43 @return dictionary containing the data to query the presence of 47 @return dictionary containing the data to query the presence of
44 the executable 48 the executable
45 """ 49 """
50 dataList = []
46 data = { 51 data = {
47 "programEntry" : True, 52 "programEntry" : True,
48 "header" : QCoreApplication.translate("CxFreezePlugin", 53 "header" : QCoreApplication.translate("CxFreezePlugin",
49 "Packagers - cx_freeze"), 54 "Packagers - cx_freeze"),
50 "exe" : 'dummyfreeze', 55 "exe" : 'dummyfreeze',
51 "versionCommand" : '--version', 56 "versionCommand" : '--version',
52 "versionStartsWith" : 'dummyfreeze', 57 "versionStartsWith" : 'dummyfreeze',
53 "versionPosition" : -1, 58 "versionPosition" : -1,
54 "version" : "", 59 "version" : "",
55 "versionCleanup" : None, 60 "versionCleanup" : None,
56 } 61 }
57 62
58 exe = _findExecutable() 63 if _checkProgram():
59 if exe: 64 for exePath in (exePy2+exePy3):
60 data["exe"] = exe 65 data["exe"] = exePath
61 data["versionStartsWith"] = "cxfreeze" 66 data["versionStartsWith"] = "cxfreeze"
62 67 dataList.append(data.copy())
63 return data 68 else:
64 69 dataList.append(data)
65 def _findExecutable(): 70 return dataList
66 """ 71
67 Restricted function to determine the name of the executable. 72 def _findExecutable(majorVersion):
68 73 """
69 @return name of the executable (string) 74 Restricted function to determine the names of the executable.
70 """ 75
76 @param majorVersion major python version of the executables (int)
77 @return names of the executable (list)
78 """
79 # Determine Python Version
80 if majorVersion == 3:
81 minorVersions = range(5)
82 elif majorVersion == 2:
83 minorVersions = range(5, 9)
84 else:
85 return []
86
87 executables = set()
71 if Utilities.isWindowsPlatform(): 88 if Utilities.isWindowsPlatform():
72 # 89 #
73 # Windows 90 # Windows
74 # 91 #
75 exe = 'cxfreeze.bat'
76 if Utilities.isinpath(exe):
77 return exe
78 try: 92 try:
79 #only since python 3.2 93 import winreg
80 import sysconfig
81 scripts = sysconfig.get_path('scripts','nt')
82 return os.path.join(scripts, exe)
83 except ImportError: 94 except ImportError:
95 import _winreg as winreg # __IGNORE_WARNING__
96
97 def getExePath(branch, access, versionStr):
84 try: 98 try:
85 import winreg 99 software = winreg.OpenKey(branch, 'Software', 0, access)
86 except ImportError: 100 python = winreg.OpenKey(software, 'Python', 0, access)
87 # give up ... 101 pcore = winreg.OpenKey(python, 'PythonCore', 0, access)
102 version = winreg.OpenKey(pcore, versionStr, 0, access)
103 installpath = winreg.QueryValue(version, 'InstallPath')
104 exe = os.path.join(installpath, 'Scripts', 'cxfreeze.bat')
105 if os.access(exe, os.X_OK):
106 return exe
107 except WindowsError: # __IGNORE_WARNING__
88 return None 108 return None
109 return None
110
111 for minorVersion in minorVersions:
112 versionStr = '{0}.{1}'.format(majorVersion, minorVersion)
113 exePath = getExePath(winreg.HKEY_CURRENT_USER,
114 winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr)
115
116 if exePath is not None:
117 executables.add(exePath)
118 exePath = getExePath(winreg.HKEY_LOCAL_MACHINE,
119 winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr)
89 120
90 def getExePath(branch): 121 # Even on Intel 64-bit machines it's 'AMD64'
91 version = str(sys.version_info.major) + '.' + \ 122 if platform.machine() == 'AMD64':
92 str(sys.version_info.minor) 123 if exePath is not None:
93 try: 124 executables.add(exePath)
94 software = winreg.OpenKey(branch, 'Software') 125 exePath = getExePath(winreg.HKEY_CURRENT_USER,
95 python = winreg.OpenKey(software, 'Python') 126 winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr)
96 pcore = winreg.OpenKey(python, 'PythonCore') 127
97 version = winreg.OpenKey(pcore, version) 128 if exePath is not None:
98 installpath = winreg.QueryValue(version, 'InstallPath') 129 executables.add(exePath)
99 return os.path.join(installpath, 'Scripts', exe) 130 exePath = getExePath(winreg.HKEY_LOCAL_MACHINE,
100 except WindowsError: # __IGNORE_WARNING__ 131 winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr)
101 return None 132
102 133 if exePath is not None:
103 exePath = getExePath(winreg.HKEY_CURRENT_USER) 134 executables.add(exePath)
104 if not exePath:
105 exePath = getExePath(winreg.HKEY_LOCAL_MACHINE)
106 return exePath
107 else: 135 else:
108 # 136 #
109 # Linux, Unix ... 137 # Linux, Unix ...
110 cxfreezeScript = 'cxfreeze' 138 cxfreezeScript = 'cxfreeze'
111 scriptSuffixes = ["", 139 scriptSuffixes = ["",
112 "-python{0}".format(sys.version[:1]), 140 "-python{0}".format(majorVersion)]
113 "-python{0}".format(sys.version[:3])] 141 for minorVersion in minorVersions:
142 scriptSuffixes.append(
143 "-python{0}.{1}".format(majorVersion, minorVersion))
114 # There could be multiple cxfreeze executables in the path 144 # There could be multiple cxfreeze executables in the path
115 # e.g. for different python variants 145 # e.g. for different python variants
116 path = Utilities.getEnvironmentEntry('PATH') 146 path = Utilities.getEnvironmentEntry('PATH')
117 # environment variable not defined 147 # environment variable not defined
118 if path is None: 148 if path is None:
119 return None 149 return []
120 150
121 # step 1: determine possible candidates 151 # step 1: determine possible candidates
122 exes = [] 152 exes = []
123 dirs = path.split(os.pathsep) 153 dirs = path.split(os.pathsep)
124 for dir in dirs: 154 for dir in dirs:
125 for suffix in scriptSuffixes: 155 for suffix in scriptSuffixes:
126 exe = os.path.join(dir, cxfreezeScript + suffix) 156 exe = os.path.join(dir, cxfreezeScript + suffix)
127 if os.access(exe, os.X_OK): 157 if os.access(exe, os.X_OK):
128 exes.append(exe) 158 exes.append(exe)
129 159
130 # step 2: determine the Python 3 variant 160 # step 2: determine the Python variant
131 found = False
132 if Utilities.isMacPlatform(): 161 if Utilities.isMacPlatform():
133 checkStrings = ["Python.framework/Versions/3".lower(), 162 checkStrings = ["Python.framework/Versions/3".lower(),
134 "python3"] 163 "python3"]
135 else: 164 else:
136 checkStrings = ["python3"] 165 checkStrings = ["python3"]
166
167 _exePy2 = set()
168 _exePy3 = set()
137 for exe in exes: 169 for exe in exes:
138 try: 170 try:
139 f = open(exe, "r") 171 f = open(exe, "r")
140 line0 = f.readline() 172 line0 = f.readline()
141 for checkStr in checkStrings: 173 for checkStr in checkStrings:
142 if checkStr in line0.lower(): 174 if checkStr in line0.lower():
143 found = True 175 _exePy3.add(exe)
144 break 176 break
177 else:
178 _exePy2.add(exe)
145 finally: 179 finally:
146 f.close() 180 f.close()
147 if found: 181
148 return exe 182 executables = _exePy3 if majorVersion == 3 else _exePy2
149 183
150 return None 184 # sort items, the probably newest topmost
185 executables = list(executables)
186 executables.sort(reverse=True)
187 return executables
151 188
152 def _checkProgram(): 189 def _checkProgram():
153 """ 190 """
154 Restricted function to check the availability of cxfreeze. 191 Restricted function to check the availability of cxfreeze.
155 192
156 @return flag indicating availability (boolean) 193 @return flag indicating availability (boolean)
157 """ 194 """
158 global error 195 global error, exePy2, exePy3
159 196
160 if _findExecutable() is None: 197 exePy2 = _findExecutable(2)
198 exePy3 = _findExecutable(3)
199 if (exePy2+exePy3) == []:
161 error = QCoreApplication.translate("CxFreezePlugin", 200 error = QCoreApplication.translate("CxFreezePlugin",
162 "The cxfreeze executable could not be found.") 201 "The cxfreeze executable could not be found.")
163 return False 202 return False
164 else: 203 else:
165 return True 204 return True
166 _checkProgram() 205
167 206
168 class CxFreezePlugin(QObject): 207 class CxFreezePlugin(QObject):
169 """ 208 """
170 Class implementing the CxFreeze plugin. 209 Class implementing the CxFreeze plugin.
171 """ 210 """
199 238
200 # cxfreeze is only activated if it is available 239 # cxfreeze is only activated if it is available
201 if not _checkProgram(): 240 if not _checkProgram():
202 return None, False 241 return None, False
203 242
204 menu = e5App().getObject("Project").getMenu("Packagers") 243 project = e5App().getObject("Project")
244 menu = project.getMenu("Packagers")
205 if menu: 245 if menu:
206 self.__projectAct = E5Action(self.trUtf8('Use cx_freeze'), 246 self.__projectAct = E5Action(self.trUtf8('Use cx_freeze'),
207 self.trUtf8('Use cx_&freeze'), 0, 0, 247 self.trUtf8('Use cx_&freeze'), 0, 0,
208 self, 'packagers_cxfreeze') 248 self, 'packagers_cxfreeze')
209 self.__projectAct.setStatusTip( 249 self.__projectAct.setStatusTip(
214 """ The command is executed in the project path. All""" 254 """ The command is executed in the project path. All"""
215 """ files and directories must be given absolute or""" 255 """ files and directories must be given absolute or"""
216 """ relative to the project directory.</p>""" 256 """ relative to the project directory.</p>"""
217 )) 257 ))
218 self.__projectAct.triggered[()].connect(self.__cxfreeze) 258 self.__projectAct.triggered[()].connect(self.__cxfreeze)
219 e5App().getObject("Project").addE5Actions([self.__projectAct]) 259 project.addE5Actions([self.__projectAct])
220 menu.addAction(self.__projectAct) 260 menu.addAction(self.__projectAct)
261 project.showMenu.connect(self.__projectShowMenu)
221 262
222 error = "" 263 error = ""
223 return None, True 264 return None, True
224 265
225 def deactivate(self): 266 def deactivate(self):
230 if menu: 271 if menu:
231 if self.__projectAct: 272 if self.__projectAct:
232 menu.removeAction(self.__projectAct) 273 menu.removeAction(self.__projectAct)
233 e5App().getObject("Project").removeE5Actions([self.__projectAct]) 274 e5App().getObject("Project").removeE5Actions([self.__projectAct])
234 self.__initialize() 275 self.__initialize()
276
277 def __projectShowMenu(self, menuName, menu):
278 """
279 Private slot called, when the the project menu or a submenu is
280 about to be shown.
281
282 @param menuName name of the menu to be shown (string)
283 @param menu reference to the menu (QMenu)
284 """
285 if menuName == "Packagers":
286 if self.__projectAct is not None:
287 self.__projectAct.setEnabled(
288 e5App().getObject("Project").getProjectLanguage() in \
289 ["Python", "Python2", "Python3"])
235 290
236 def __loadTranslator(self): 291 def __loadTranslator(self):
237 """ 292 """
238 Private method to load the translation file. 293 Private method to load the translation file.
239 """ 294 """
265 self.trUtf8( 320 self.trUtf8(
266 """There is no main script defined for the current project."""), 321 """There is no main script defined for the current project."""),
267 E5MessageBox.StandardButtons(E5MessageBox.Abort)) 322 E5MessageBox.StandardButtons(E5MessageBox.Abort))
268 return 323 return
269 324
270 parms = project.getData('PACKAGERSPARMS', "CXFREEZE") 325 majorVersionStr = project.getProjectLanguage()
271 exe = _findExecutable() 326 exe = {"Python": exePy2, "Python2": exePy2, "Python3": exePy3}.get(majorVersionStr)
272 if exe is None: 327 if exe == []:
273 E5MessageBox.critical(None, 328 E5MessageBox.critical(None,
274 self.trUtf8("cxfreeze"), 329 self.trUtf8("cxfreeze"),
275 self.trUtf8("""The cxfreeze executable could not be found.""")) 330 self.trUtf8("""The cxfreeze executable could not be found."""))
276 return 331 return
277 332
278 from CxFreeze.CxfreezeConfigDialog import CxfreezeConfigDialog 333 from CxFreeze.CxfreezeConfigDialog import CxfreezeConfigDialog
334 parms = project.getData('PACKAGERSPARMS', "CXFREEZE")
279 dlg = CxfreezeConfigDialog(project, exe, parms) 335 dlg = CxfreezeConfigDialog(project, exe, parms)
280 if dlg.exec_() == QDialog.Accepted: 336 if dlg.exec_() == QDialog.Accepted:
281 args, parms = dlg.generateParameters() 337 args, parms = dlg.generateParameters()
282 project.setData('PACKAGERSPARMS', "CXFREEZE", parms) 338 project.setData('PACKAGERSPARMS', "CXFREEZE", parms)
283 339
284 # now do the call 340 # now do the call
285 from CxFreeze.CxfreezeExecDialog import CxfreezeExecDialog 341 from CxFreeze.CxfreezeExecDialog import CxfreezeExecDialog
286 dia = CxfreezeExecDialog("cxfreeze") 342 dia = CxfreezeExecDialog("cxfreeze")
287 dia.show() 343 dia.show()
288 res = dia.start(args, 344 res = dia.start(args,
289 os.path.join(project.ppath, project.pdata["MAINSCRIPT"][0])) 345 os.path.join(project.ppath, project.pdata["MAINSCRIPT"][0]))
290 if res: 346 if res:
291 dia.exec_() 347 dia.exec_()
292

eric ide

mercurial