Plugins/PluginPipInterface.py

changeset 6342
c79ecba9cde7
parent 6076
b784925fb174
child 6645
ad476851d7e0
equal deleted inserted replaced
6341:a00e63f6d766 6342:c79ecba9cde7
7 Module implementing the pip interface plug-in. 7 Module implementing the pip interface plug-in.
8 """ 8 """
9 9
10 from __future__ import unicode_literals 10 from __future__ import unicode_literals
11 11
12 import os 12
13 import platform 13 from PyQt5.QtCore import pyqtSignal, QObject, QCoreApplication
14
15 from PyQt5.QtCore import pyqtSignal, QObject, QCoreApplication, QProcess
16 14
17 from E5Gui.E5Application import e5App 15 from E5Gui.E5Application import e5App
18 16
19 import Preferences 17 import Preferences
20 import Utilities
21 import UI.Info 18 import UI.Info
22 19
23 # Start-Of-Header 20 # Start-Of-Header
24 name = "pip Interface Plug-in" 21 name = "pip Interface Plug-in"
25 author = "Detlev Offenbach <detlev@die-offenbachs.de>" 22 author = "Detlev Offenbach <detlev@die-offenbachs.de>"
56 "programEntry": True, 53 "programEntry": True,
57 "header": QCoreApplication.translate( 54 "header": QCoreApplication.translate(
58 "PipInterfacePlugin", "Package Management - pip"), 55 "PipInterfacePlugin", "Package Management - pip"),
59 "exe": "dummyExe", 56 "exe": "dummyExe",
60 "versionCommand": "--version", 57 "versionCommand": "--version",
61 "versionStartsWith": "dummyExe", 58 "versionStartsWith": "pip",
62 "versionPosition": 1, 59 "versionPosition": 1,
63 "version": "", 60 "version": "",
64 "versionCleanup": None, 61 "versionCleanup": None,
62 "exeModule": ["-m", "pip"],
65 } 63 }
66 if pipPluginObject is not None: 64 virtualenvManager = e5App().getObject("VirtualEnvManager")
67 executables = pipPluginObject.getPreferences("PipExecutables") 65 for venvName in virtualenvManager.getVirtualenvNames():
68 if not executables: 66 interpreter = virtualenvManager.getVirtualenvInterpreter(venvName)
69 executables = ["pip3", "pip2", "pip"] 67 data["exe"] = interpreter
70 for exePath in executables: 68 dataList.append(data.copy())
71 data["exe"] = exePath
72 data["versionStartsWith"] = "pip"
73 dataList.append(data.copy())
74 return dataList 69 return dataList
75 70
76 71
77 def createPipPage(configDlg): 72 def createPipPage(configDlg):
78 """ 73 """
109 Module function to prepare for an un-installation. 104 Module function to prepare for an un-installation.
110 """ 105 """
111 Preferences.Prefs.settings.remove(PipInterfacePlugin.PreferencesKey) 106 Preferences.Prefs.settings.remove(PipInterfacePlugin.PreferencesKey)
112 107
113 108
114 def _findDefaultExecutables(majorVersion):
115 """
116 Restricted function to determine the name and path of the executables.
117
118 @param majorVersion major python version of the executables (int)
119 @return path names of the executables (list of string)
120 """
121 # Determine Python Version
122 if majorVersion == 3:
123 minorVersions = range(10)
124 elif majorVersion == 2:
125 minorVersions = range(6, 8)
126 else:
127 return []
128
129 executables = set()
130 if Utilities.isWindowsPlatform():
131 #
132 # Windows
133 #
134 try:
135 import winreg
136 except ImportError:
137 import _winreg as winreg # __IGNORE_WARNING__
138
139 def getExePath(branch, access, versionStr):
140 exes = []
141 try:
142 software = winreg.OpenKey(branch, 'Software', 0, access)
143 python = winreg.OpenKey(software, 'Python', 0, access)
144 pcore = winreg.OpenKey(python, 'PythonCore', 0, access)
145 version = winreg.OpenKey(pcore, versionStr, 0, access)
146 installpath = winreg.QueryValue(version, 'InstallPath')
147 exe = os.path.join(installpath, 'Scripts', 'pip.exe')
148 if os.access(exe, os.X_OK):
149 exes.append(exe)
150 except (WindowsError, OSError): # __IGNORE_WARNING__
151 pass
152 return exes
153
154 versionSuffixes = ["", "-32", "-64"]
155 for minorVersion in minorVersions:
156 for versionSuffix in versionSuffixes:
157 versionStr = '{0}.{1}{2}'.format(majorVersion, minorVersion,
158 versionSuffix)
159 exePaths = getExePath(
160 winreg.HKEY_CURRENT_USER,
161 winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr)
162 for exePath in exePaths:
163 executables.add(exePath)
164
165 exePaths = getExePath(
166 winreg.HKEY_LOCAL_MACHINE,
167 winreg.KEY_WOW64_32KEY | winreg.KEY_READ, versionStr)
168 for exePath in exePaths:
169 executables.add(exePath)
170
171 # Even on Intel 64-bit machines it's 'AMD64'
172 if platform.machine() == 'AMD64':
173 exePaths = getExePath(
174 winreg.HKEY_CURRENT_USER,
175 winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr)
176 for exePath in exePaths:
177 executables.add(exePath)
178
179 exePath = getExePath(
180 winreg.HKEY_LOCAL_MACHINE,
181 winreg.KEY_WOW64_64KEY | winreg.KEY_READ, versionStr)
182 for exePath in exePaths:
183 executables.add(exePath)
184 else:
185 #
186 # Linux, Unix ...
187 pipScript = 'pip'
188 scriptSuffixes = ["",
189 "{0}".format(majorVersion),
190 "-{0}".format(majorVersion),
191 ]
192 for minorVersion in minorVersions:
193 scriptSuffixes.append(
194 "{0}.{1}".format(majorVersion, minorVersion))
195 scriptSuffixes.append(
196 "-{0}.{1}".format(majorVersion, minorVersion))
197 # There could be multiple pip executables in the path
198 # e.g. for different python variants
199 path = Utilities.getEnvironmentEntry('PATH')
200 # environment variable not defined
201 if path is None:
202 return []
203
204 # step 1: determine possible candidates
205 exes = []
206 dirs = path.split(os.pathsep)
207 for directory in dirs:
208 for suffix in scriptSuffixes:
209 exe = os.path.join(directory, pipScript + suffix)
210 if os.access(exe, os.X_OK):
211 exes.append(exe)
212
213 # step 2: determine the Python variant
214 _exePy2 = set()
215 _exePy3 = set()
216 versionArgs = ["-c", "import sys; print(sys.version_info[0])"]
217 for exe in exes:
218 try:
219 f = open(exe, "r")
220 line0 = f.readline()
221 program = line0.replace("#!", "").strip()
222 process = QProcess()
223 process.start(program, versionArgs)
224 process.waitForFinished(5000)
225 # get a QByteArray of the output
226 versionBytes = process.readAllStandardOutput()
227 versionStr = str(versionBytes, encoding='utf-8').strip()
228 if versionStr == "3":
229 _exePy3.add(exe)
230 elif versionStr == "2":
231 _exePy2.add(exe)
232 finally:
233 f.close()
234
235 executables = _exePy3 if majorVersion == 3 else _exePy2
236
237 return list(executables)
238
239
240 class PipInterfacePlugin(QObject): 109 class PipInterfacePlugin(QObject):
241 """ 110 """
242 Class implementing the pip interface plug-in. 111 Class implementing the pip interface plug-in.
243 112
244 @signal currentPipChanged(exe) emitted to signal a change of the current 113 @signal currentEnvironmentChanged(str) emitted to signal a change of the
245 pip executable 114 currently selected virtual environment
246 """ 115 """
247 PreferencesKey = "PipPlugin" 116 PreferencesKey = "PipPlugin"
248 117
249 currentPipChanged = pyqtSignal(str) 118 currentEnvironmentChanged = pyqtSignal(str)
250 119
251 def __init__(self, ui): 120 def __init__(self, ui):
252 """ 121 """
253 Constructor 122 Constructor
254 123
257 super(PipInterfacePlugin, self).__init__(ui) 126 super(PipInterfacePlugin, self).__init__(ui)
258 self.__ui = ui 127 self.__ui = ui
259 self.__initialize() 128 self.__initialize()
260 129
261 self.__defaults = { 130 self.__defaults = {
262 "PipExecutables": [], 131 "CurrentEnvironment": "",
263 "CurrentPipExecutable": "",
264 "PipSearchIndex": "", # used by the search command 132 "PipSearchIndex": "", # used by the search command
265 } 133 }
266 134
267 def __initialize(self): 135 def __initialize(self):
268 """ 136 """
275 143
276 def activate(self): 144 def activate(self):
277 """ 145 """
278 Public method to activate this plugin. 146 Public method to activate this plugin.
279 147
280 @return tuple of None and activation status (boolean) 148 @return tuple of None and activation status
149 @rtype tuple of (None, bool)
281 """ 150 """
282 global error 151 global error
283 error = "" # clear previous error 152 error = "" # clear previous error
284 153
285 global pipPluginObject 154 global pipPluginObject
292 161
293 menu = self.__ui.getMenu("extras") 162 menu = self.__ui.getMenu("extras")
294 self.__mainMenu = self.__object.initMenu() 163 self.__mainMenu = self.__object.initMenu()
295 self.__mainAct = menu.addMenu(self.__mainMenu) 164 self.__mainAct = menu.addMenu(self.__mainMenu)
296 165
297 if self.getPreferences("PipExecutables"):
298 # remove all executables, that don't exist anymore
299 executables = []
300 for executable in self.getPreferences("PipExecutables"):
301 if os.access(executable, os.X_OK):
302 executables.append(executable)
303 self.setPreferences("PipExecutables", executables)
304
305 current = self.getPreferences("CurrentPipExecutable")
306 if current not in executables:
307 current = ""
308 self.setPreferences("CurrentPipExecutable", current)
309 else:
310 # load the list with default executables
311 self.setPreferences("PipExecutables",
312 self.getDefaultPipExecutables())
313
314 return None, True 166 return None, True
315 167
316 def deactivate(self): 168 def deactivate(self):
317 """ 169 """
318 Public method to deactivate this plugin. 170 Public method to deactivate this plugin.
325 177
326 self.__initialize() 178 self.__initialize()
327 179
328 def getPreferences(self, key): 180 def getPreferences(self, key):
329 """ 181 """
330 Public method to retrieve the various refactoring settings. 182 Public method to retrieve the various pip related settings.
331 183
332 @param key the key of the value to get 184 @param key the key of the value to get
333 @return the requested refactoring setting 185 @type str
334 """ 186 @return the requested setting
335 if key in ["PipExecutables"]: 187 @rtype any
336 return Preferences.toList(Preferences.Prefs.settings.value( 188 """
337 self.PreferencesKey + "/" + key, self.__defaults[key])) 189 return Preferences.Prefs.settings.value(
338 else: 190 self.PreferencesKey + "/" + key, self.__defaults[key])
339 return Preferences.Prefs.settings.value(
340 self.PreferencesKey + "/" + key, self.__defaults[key])
341 191
342 def setPreferences(self, key, value): 192 def setPreferences(self, key, value):
343 """ 193 """
344 Public method to store the various refactoring settings. 194 Public method to store the various pip related settings.
345 195
346 @param key the key of the setting to be set (string) 196 @param key the key of the setting to be set
197 @type str
347 @param value the value to be set 198 @param value the value to be set
199 @type any
348 """ 200 """
349 Preferences.Prefs.settings.setValue( 201 Preferences.Prefs.settings.setValue(
350 self.PreferencesKey + "/" + key, value) 202 self.PreferencesKey + "/" + key, value)
351 203
352 if key == "CurrentPipExecutable": 204 if key == "CurrentEnvironment":
353 self.currentPipChanged.emit(value) 205 self.currentEnvironmentChanged.emit(value)
354 206
355 def getMenu(self, name): 207 def getMenu(self, name):
356 """ 208 """
357 Public method to get a reference to the requested menu. 209 Public method to get a reference to the requested menu.
358 210
359 @param name name of the menu (string) 211 @param name name of the menu
360 @return reference to the menu (QMenu) or None, if no 212 @type str
213 @return reference to the menu or None, if no
361 menu with the given name exists 214 menu with the given name exists
215 @rtype QMenu or None
362 """ 216 """
363 if self.__object is not None: 217 if self.__object is not None:
364 return self.__object.getMenu(name) 218 return self.__object.getMenu(name)
365 else: 219 else:
366 return None 220 return None
367 221
368 def getMenuNames(self): 222 def getMenuNames(self):
369 """ 223 """
370 Public method to get the names of all menus. 224 Public method to get the names of all menus.
371 225
372 @return menu names (list of string) 226 @return menu names
227 @rtype list of str
373 """ 228 """
374 if self.__object is not None: 229 if self.__object is not None:
375 return list(self.__menus.keys()) 230 return list(self.__menus.keys())
376 else: 231 else:
377 return [] 232 return []
378
379 def getDefaultPipExecutables(self):
380 """
381 Public method to get the default list of pip executables.
382
383 @return list of pip executables (list of string)
384 """
385 return _findDefaultExecutables(2) + _findDefaultExecutables(3)
386 233
387 # 234 #
388 # eflag: noqa = M801 235 # eflag: noqa = M801

eric ide

mercurial