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 |
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 |