PipInterface/Pip.py

branch
pypi
changeset 6798
3985c1a67fa2
parent 6795
6e2ed2aac325
child 6819
6c49d4ed077d
equal deleted inserted replaced
6795:6e2ed2aac325 6798:3985c1a67fa2
15 15
16 import os 16 import os
17 import sys 17 import sys
18 import json 18 import json
19 19
20 from PyQt5.QtCore import pyqtSlot, QObject, QProcess 20 from PyQt5.QtCore import pyqtSlot, QObject, QProcess, QUrl, QCoreApplication
21 from PyQt5.QtWidgets import QMenu, QInputDialog, QDialog 21 from PyQt5.QtWidgets import QDialog
22 from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, \
23 QNetworkReply
22 24
23 from E5Gui import E5MessageBox 25 from E5Gui import E5MessageBox
24 from E5Gui.E5Action import E5Action
25 from E5Gui.E5Application import e5App 26 from E5Gui.E5Application import e5App
27
28 from E5Network.E5NetworkProxyFactory import proxyAuthenticationRequired
29 try:
30 from E5Network.E5SslErrorHandler import E5SslErrorHandler
31 SSL_AVAILABLE = True
32 except ImportError:
33 SSL_AVAILABLE = False
26 34
27 from .PipDialog import PipDialog 35 from .PipDialog import PipDialog
28 36
29 import Preferences 37 import Preferences
30 import Globals 38 import Globals
31 ##
32 ##import UI.PixmapCache
33 39
34 40
35 class Pip(QObject): 41 class Pip(QObject):
36 """ 42 """
37 Class implementing the pip GUI logic. 43 Class implementing the pip GUI logic.
46 52
47 @param parent parent 53 @param parent parent
48 @type QObject 54 @type QObject
49 """ 55 """
50 super(Pip, self).__init__(parent) 56 super(Pip, self).__init__(parent)
51 ## 57
52 ## self.__virtualenvManager = e5App().getObject("VirtualEnvManager") 58 # attributes for the network objects
53 ## self.__project = e5App().getObject("Project") 59 self.__networkManager = QNetworkAccessManager(self)
54 ## 60 self.__networkManager.proxyAuthenticationRequired.connect(
55 ## self.__menus = {} # dictionary with references to menus 61 proxyAuthenticationRequired)
56 ## 62 if SSL_AVAILABLE:
57 ## self.__plugin.currentEnvironmentChanged.connect( 63 self.__sslErrorHandler = E5SslErrorHandler(self)
58 ## self.__handleTearOffMenu) 64 self.__networkManager.sslErrors.connect(
59 65 self.__sslErrorHandler.sslErrorsReply)
60 ## def initActions(self): 66 self.__replies = []
61 ## """
62 ## Public method to define the actions.
63 ## """
64 ## self.actions = []
65 ##
66 ## self.selectEnvironmentAct = E5Action(
67 ## self.tr('Virtual Environment for pip'),
68 ## self.tr('&Virtual Environment for pip'),
69 ## 0, 0,
70 ## self, 'pip_select_environment')
71 ## self.selectEnvironmentAct.setStatusTip(self.tr(
72 ## 'Selects the virtual environment to be used for pip'))
73 ## self.selectEnvironmentAct.setWhatsThis(self.tr(
74 ## """<b>Virtual Environment for pip</b>"""
75 ## """<p>This selects the virtual environment to be used for pip."""
76 ## """</p>"""
77 ## ))
78 ## self.selectEnvironmentAct.triggered.connect(self.__selectPipVirtualenv)
79 ## self.actions.append(self.selectEnvironmentAct)
80 ##
81 ## ##############################################
82 ## ## Actions for listing packages
83 ## ##############################################
84 ##
85 ## self.listPackagesAct = E5Action(
86 ## self.tr('List Installed Packages'),
87 ## self.tr('&List Installed Packages...'),
88 ## 0, 0,
89 ## self, 'pip_list_packages')
90 ## self.listPackagesAct.setStatusTip(self.tr(
91 ## 'List all installed packages with versions'))
92 ## self.listPackagesAct.setWhatsThis(self.tr(
93 ## """<b>List Installed Packages</b>"""
94 ## """<p>This lists all the installed packages together"""
95 ## """ with their versions.</p>"""
96 ## ))
97 ## self.listPackagesAct.triggered.connect(self.__listPackages)
98 ## self.actions.append(self.listPackagesAct)
99 ##
100 ## self.listUptodatePackagesAct = E5Action(
101 ## self.tr('List Up-to-date Packages'),
102 ## self.tr('List Up-to-&date Packages...'),
103 ## 0, 0,
104 ## self, 'pip_list_uptodate_packages')
105 ## self.listUptodatePackagesAct.setStatusTip(self.tr(
106 ## 'List all installed, up-to-date packages with versions'))
107 ## self.listUptodatePackagesAct.setWhatsThis(self.tr(
108 ## """<b>List Up-to-date Packages</b>"""
109 ## """<p>This lists all the installed, up-to-date packages together"""
110 ## """ with their versions.</p>"""
111 ## ))
112 ## self.listUptodatePackagesAct.triggered.connect(
113 ## self.__listUptodatePackages)
114 ## self.actions.append(self.listUptodatePackagesAct)
115 ##
116 ## self.listOutdatedPackagesAct = E5Action(
117 ## self.tr('List Outdated Packages'),
118 ## self.tr('List &Outdated Packages...'),
119 ## 0, 0,
120 ## self, 'pip_list_outdated_packages')
121 ## self.listOutdatedPackagesAct.setStatusTip(self.tr(
122 ## 'List all installed, outdated packages with versions'))
123 ## self.listOutdatedPackagesAct.setWhatsThis(self.tr(
124 ## """<b>List Up-to-date Packages</b>"""
125 ## """<p>This lists all the installed, outdated packages together"""
126 ## """ with their current and latest versions.</p>"""
127 ## ))
128 ## self.listOutdatedPackagesAct.triggered.connect(
129 ## self.__listOutdatedPackages)
130 ## self.actions.append(self.listOutdatedPackagesAct)
131 ##
132 ## ##############################################
133 ## ## Actions for installing packages
134 ## ##############################################
135 ##
136 ## self.installPackagesAct = E5Action(
137 ## self.tr('Install Packages'),
138 ## self.tr('&Install Packages'),
139 ## 0, 0,
140 ## self, 'pip_install_packages')
141 ## self.installPackagesAct.setStatusTip(self.tr(
142 ## 'Install packages according to user input'))
143 ## self.installPackagesAct.setWhatsThis(self.tr(
144 ## """<b>Install Packages</b>"""
145 ## """<p>This installs packages according to user input.</p>"""
146 ## ))
147 ## self.installPackagesAct.triggered.connect(self.__installPackages)
148 ## self.actions.append(self.installPackagesAct)
149 ##
150 ## self.installLocalPackageAct = E5Action(
151 ## self.tr('Install Local Package'),
152 ## self.tr('Install Local Package'),
153 ## 0, 0,
154 ## self, 'pip_install_local_package')
155 ## self.installLocalPackageAct.setStatusTip(self.tr(
156 ## 'Install a package from local storage'))
157 ## self.installLocalPackageAct.setWhatsThis(self.tr(
158 ## """<b>Install Local Package</b>"""
159 ## """<p>This installs a package available on local storage.</p>"""
160 ## ))
161 ## self.installLocalPackageAct.triggered.connect(
162 ## self.__installLocalPackage)
163 ## self.actions.append(self.installLocalPackageAct)
164 ##
165 ## self.installRequirementsAct = E5Action(
166 ## self.tr('Install Requirements'),
167 ## self.tr('Install Requirements'),
168 ## 0, 0,
169 ## self, 'pip_install_requirements')
170 ## self.installRequirementsAct.setStatusTip(self.tr(
171 ## 'Install packages according to a requirements file'))
172 ## self.installRequirementsAct.setWhatsThis(self.tr(
173 ## """<b>Install Requirements</b>"""
174 ## """<p>This installs packages according to a requirements"""
175 ## """ file.</p>"""
176 ## ))
177 ## self.installRequirementsAct.triggered.connect(
178 ## self.__installRequirements)
179 ## self.actions.append(self.installRequirementsAct)
180 ##
181 ## self.installPipAct = E5Action(
182 ## self.tr('Install Pip'),
183 ## self.tr('Install Pip'),
184 ## 0, 0,
185 ## self, 'pip_install_pip')
186 ## self.installPipAct.setStatusTip(self.tr(
187 ## 'Install the pip package itself'))
188 ## self.installPipAct.setWhatsThis(self.tr(
189 ## """<b>Install Pip</b>"""
190 ## """<p>This installs the pip package itself.</p>"""
191 ## ))
192 ## self.installPipAct.triggered.connect(self.__installPip)
193 ## self.actions.append(self.installPipAct)
194 ##
195 ## self.repairPipAct = E5Action(
196 ## self.tr('Repair Pip'),
197 ## self.tr('Repair Pip'),
198 ## 0, 0,
199 ## self, 'pip_repair_pip')
200 ## self.repairPipAct.setStatusTip(self.tr(
201 ## 'Repair the pip package'))
202 ## self.repairPipAct.setWhatsThis(self.tr(
203 ## """<b>Repair Pip</b>"""
204 ## """<p>This repairs the pip package by re-installing it.</p>"""
205 ## ))
206 ## self.repairPipAct.triggered.connect(self.__repairPip)
207 ## self.actions.append(self.repairPipAct)
208 ##
209 ## self.upgradePipAct = E5Action(
210 ## self.tr('Upgrade Pip'),
211 ## self.tr('Upgrade &Pip'),
212 ## 0, 0,
213 ## self, 'pip_upgrade_pip')
214 ## self.upgradePipAct.setStatusTip(self.tr(
215 ## 'Upgrade the pip package itself'))
216 ## self.upgradePipAct.setWhatsThis(self.tr(
217 ## """<b>Upgrade Pip</b>"""
218 ## """<p>This upgrades the pip package itself.</p>"""
219 ## ))
220 ## self.upgradePipAct.triggered.connect(self.upgradePip)
221 ## self.actions.append(self.upgradePipAct)
222 ##
223 ## self.upgradePackagesAct = E5Action(
224 ## self.tr('Upgrade Packages'),
225 ## self.tr('&Upgrade Packages'),
226 ## 0, 0,
227 ## self, 'pip_upgrade_packages')
228 ## self.upgradePackagesAct.setStatusTip(self.tr(
229 ## 'Upgrade packages according to user input'))
230 ## self.upgradePackagesAct.setWhatsThis(self.tr(
231 ## """<b>Upgrade Packages</b>"""
232 ## """<p>This upgrades packages according to user input.</p>"""
233 ## ))
234 ## self.upgradePackagesAct.triggered.connect(self.__upgradePackages)
235 ## self.actions.append(self.upgradePackagesAct)
236 ##
237 ## ##############################################
238 ## ## Actions for uninstalling packages
239 ## ##############################################
240 ##
241 ## self.uninstallPackagesAct = E5Action(
242 ## self.tr('Uninstall Packages'),
243 ## self.tr('Uninstall Packages'),
244 ## 0, 0,
245 ## self, 'pip_uninstall_packages')
246 ## self.uninstallPackagesAct.setStatusTip(self.tr(
247 ## 'Uninstall packages according to user input'))
248 ## self.uninstallPackagesAct.setWhatsThis(self.tr(
249 ## """<b>Uninstall Packages</b>"""
250 ## """<p>This uninstalls packages according to user input.</p>"""
251 ## ))
252 ## self.uninstallPackagesAct.triggered.connect(self.__uninstallPackages)
253 ## self.actions.append(self.uninstallPackagesAct)
254 ##
255 ## self.uninstallRequirementsAct = E5Action(
256 ## self.tr('Uninstall Requirements'),
257 ## self.tr('Uninstall Requirements'),
258 ## 0, 0,
259 ## self, 'pip_uninstall_requirements')
260 ## self.uninstallRequirementsAct.setStatusTip(self.tr(
261 ## 'Uninstall packages according to a requirements file'))
262 ## self.uninstallRequirementsAct.setWhatsThis(self.tr(
263 ## """<b>Uninstall Requirements</b>"""
264 ## """<p>This uninstalls packages according to a requirements"""
265 ## """ file.</p>"""
266 ## ))
267 ## self.uninstallRequirementsAct.triggered.connect(
268 ## self.__uninstallRequirements)
269 ## self.actions.append(self.uninstallRequirementsAct)
270 ##
271 ## ##############################################
272 ## ## Actions for generating requirements files
273 ## ##############################################
274 ##
275 ## self.generateRequirementsAct = E5Action(
276 ## self.tr('Generate Requirements'),
277 ## self.tr('&Generate Requirements...'),
278 ## 0, 0,
279 ## self, 'pip_generate_requirements')
280 ## self.generateRequirementsAct.setStatusTip(self.tr(
281 ## 'Generate the contents of a requirements file'))
282 ## self.generateRequirementsAct.setWhatsThis(self.tr(
283 ## """<b>Generate Requirements</b>"""
284 ## """<p>This generates the contents of a requirements file.</p>"""
285 ## ))
286 ## self.generateRequirementsAct.triggered.connect(
287 ## self.__generateRequirements)
288 ## self.actions.append(self.generateRequirementsAct)
289 ##
290 ## ##############################################
291 ## ## Actions for generating requirements files
292 ## ##############################################
293 ##
294 ## self.searchPyPIAct = E5Action(
295 ## self.tr('Search PyPI'),
296 ## self.tr('&Search PyPI...'),
297 ## 0, 0,
298 ## self, 'pip_search_pypi')
299 ## self.searchPyPIAct.setStatusTip(self.tr(
300 ## 'Open a dialog to search the Python Package Index'))
301 ## self.searchPyPIAct.setWhatsThis(self.tr(
302 ## """<b>Search PyPI</b>"""
303 ## """<p>This opens a dialog to search the Python Package"""
304 ## """ Index.</p>"""
305 ## ))
306 ## self.searchPyPIAct.triggered.connect(self.__searchPyPI)
307 ## self.actions.append(self.searchPyPIAct)
308 ##
309 ## ##############################################
310 ## ## Actions for editing configuration files
311 ## ##############################################
312 ##
313 ## self.editUserConfigAct = E5Action(
314 ## self.tr('Edit User Configuration'),
315 ## self.tr('Edit User Configuration...'),
316 ## 0, 0,
317 ## self, 'pip_edit_user_config')
318 ## self.editUserConfigAct.setStatusTip(self.tr(
319 ## 'Open the per user configuration file in an editor'))
320 ## self.editUserConfigAct.setWhatsThis(self.tr(
321 ## """<b>Edit User Configuration</b>"""
322 ## """<p>This opens the per user configuration file in an editor."""
323 ## """</p>"""
324 ## ))
325 ## self.editUserConfigAct.triggered.connect(self.__editUserConfiguration)
326 ## self.actions.append(self.editUserConfigAct)
327 ##
328 ## self.editVirtualenvConfigAct = E5Action(
329 ## self.tr('Edit Current Virtualenv Configuration'),
330 ## self.tr('Edit Current Virtualenv Configuration...'),
331 ## 0, 0,
332 ## self, 'pip_edit_virtualenv_config')
333 ## self.editVirtualenvConfigAct.setStatusTip(self.tr(
334 ## 'Open the current virtualenv configuration file in an editor'))
335 ## self.editVirtualenvConfigAct.setWhatsThis(self.tr(
336 ## """<b>Edit Current Virtualenv Configuration</b>"""
337 ## """<p>This opens the current virtualenv configuration file in"""
338 ## """ an editor. </p>"""
339 ## ))
340 ## self.editVirtualenvConfigAct.triggered.connect(
341 ## self.__editVirtualenvConfiguration)
342 ## self.actions.append(self.editVirtualenvConfigAct)
343 ##
344 ## self.pipConfigAct = E5Action(
345 ## self.tr('Configure'),
346 ## self.tr('Configure...'),
347 ## 0, 0, self, 'pip_configure')
348 ## self.pipConfigAct.setStatusTip(self.tr(
349 ## 'Show the configuration dialog with the Python Package Management'
350 ## ' page selected'
351 ## ))
352 ## self.pipConfigAct.setWhatsThis(self.tr(
353 ## """<b>Configure</b>"""
354 ## """<p>Show the configuration dialog with the Python Package"""
355 ## """ Management page selected.</p>"""
356 ## ))
357 ## self.pipConfigAct.triggered.connect(self.__pipConfigure)
358 ## self.actions.append(self.pipConfigAct)
359 ##
360 ## def initMenu(self):
361 ## """
362 ## Public slot to initialize the menu.
363 ##
364 ## @return the menu generated
365 ## @rtype QMenu
366 ## """
367 ## self.__menus = {} # clear menus references
368 ##
369 ## menu = QMenu()
370 ## menu.setTearOffEnabled(True)
371 ## menu.setIcon(UI.PixmapCache.getIcon("pypi.png"))
372 ##
373 ## menu.addAction(self.selectEnvironmentAct)
374 ## menu.addSeparator()
375 ## menu.addAction(self.listPackagesAct)
376 ## menu.addAction(self.listUptodatePackagesAct)
377 ## menu.addAction(self.listOutdatedPackagesAct)
378 ## menu.addSeparator()
379 ## menu.addAction(self.installPipAct)
380 ## menu.addSeparator()
381 ## menu.addAction(self.installPackagesAct)
382 ## menu.addAction(self.installLocalPackageAct)
383 ## menu.addAction(self.installRequirementsAct)
384 ## menu.addSeparator()
385 ## menu.addAction(self.upgradePipAct)
386 ## menu.addAction(self.upgradePackagesAct)
387 ## menu.addSeparator()
388 ## menu.addAction(self.uninstallPackagesAct)
389 ## menu.addAction(self.uninstallRequirementsAct)
390 ## menu.addSeparator()
391 ## menu.addAction(self.generateRequirementsAct)
392 ## menu.addSeparator()
393 ## menu.addAction(self.searchPyPIAct)
394 ## menu.addSeparator()
395 ## menu.addAction(self.repairPipAct)
396 ## menu.addSeparator()
397 ## menu.addAction(self.editUserConfigAct)
398 ## menu.addAction(self.editVirtualenvConfigAct)
399 ## menu.addSeparator()
400 ## menu.addAction(self.pipConfigAct)
401 ##
402 ## self.__menus["main"] = menu
403 ##
404 ## menu.aboutToShow.connect(self.__aboutToShowMenu)
405 ##
406 ## return menu
407 ##
408 ## def __aboutToShowMenu(self):
409 ## """
410 ## Private slot to set the action enabled status.
411 ## """
412 ## enable = bool(Preferences.getPip("CurrentEnvironment"))
413 ## for act in self.actions:
414 ## if act not in [self.selectEnvironmentAct,
415 ## self.installPipAct,
416 ## self.editUserConfigAct,
417 ## self.editVirtualenvConfigAct,
418 ## self.pipConfigAct]:
419 ## act.setEnabled(enable)
420 ##
421 ## def getMenu(self, name):
422 ## """
423 ## Public method to get a reference to the requested menu.
424 ##
425 ## @param name name of the menu
426 ## @type str
427 ## @return reference to the menu or None, if no
428 ## menu with the given name exists
429 ## @rtype QMenu or None
430 ## """
431 ## if name in self.__menus:
432 ## return self.__menus[name]
433 ## else:
434 ## return None
435 ##
436 ## def getMenuNames(self):
437 ## """
438 ## Public method to get the names of all menus.
439 ##
440 ## @return menu names
441 ## @rtype list of str
442 ## """
443 ## return list(self.__menus.keys())
444 ##
445 ## def __handleTearOffMenu(self, venvName):
446 ## """
447 ## Private slot to handle a change of the selected virtual environment.
448 ##
449 ## @param venvName logical name of the virtual environment
450 ## @type str
451 ## """
452 ## if self.__menus["main"].isTearOffMenuVisible():
453 ## # determine, if torn off menu needs to be refreshed
454 ## enabled = self.listPackagesAct.isEnabled()
455 ## if ((bool(venvName) and not enabled) or
456 ## (not bool(venvName) and enabled)):
457 ## self.__menus["main"].hideTearOffMenu()
458 67
459 ########################################################################## 68 ##########################################################################
460 ## Methods below implement some utility functions 69 ## Methods below implement some utility functions
461 ########################################################################## 70 ##########################################################################
462 71
499 return False, self.tr("python did not finish within" 108 return False, self.tr("python did not finish within"
500 " 30 seconds.") 109 " 30 seconds.")
501 110
502 return False, self.tr("python could not be started.") 111 return False, self.tr("python could not be started.")
503 112
504 def __getUserConfig(self): 113 def getUserConfig(self):
505 """ 114 """
506 Private method to get the name of the user configuration file. 115 Public method to get the name of the user configuration file.
507 116
508 @return path of the user configuration file 117 @return path of the user configuration file
509 @rtype str 118 @rtype str
510 """ 119 """
511 # Unix: ~/.config/pip/pip.conf 120 # Unix: ~/.config/pip/pip.conf
526 else: 135 else:
527 config = os.path.expanduser("~/.config/pip/pip.conf") 136 config = os.path.expanduser("~/.config/pip/pip.conf")
528 137
529 return config 138 return config
530 139
531 def __getVirtualenvConfig(self): 140 def getVirtualenvConfig(self, venvName):
532 """ 141 """
533 Private method to get the name of the virtualenv configuration file. 142 Public method to get the name of the virtualenv configuration file.
534 143
144 @param venvName name of the environment to get config file path for
145 @type str
535 @return path of the virtualenv configuration file 146 @return path of the virtualenv configuration file
536 @rtype str 147 @rtype str
537 """ 148 """
538 # Unix, OS X: $VIRTUAL_ENV/pip.conf 149 # Unix, OS X: $VIRTUAL_ENV/pip.conf
539 # Windows: %VIRTUAL_ENV%\pip.ini 150 # Windows: %VIRTUAL_ENV%\pip.ini
540 151
541 # TODO: modify to use venvName
542 if Globals.isWindowsPlatform(): 152 if Globals.isWindowsPlatform():
543 pip = "pip.ini" 153 pip = "pip.ini"
544 else: 154 else:
545 pip = "pip.conf" 155 pip = "pip.conf"
546 try: 156
547 venvDirectory = os.environ["VIRTUAL_ENV"] 157 venvManager = e5App().getObject("VirtualEnvManager")
548 except KeyError: 158 if venvManager.isGlobalEnvironment(venvName):
549 venvName = Preferences.getPip("CurrentEnvironment") 159 venvDirectory = self.__getUserConfig()
550 if not venvName: 160 else:
551 self.__selectPipVirtualenv() 161 venvDirectory = venvManager.getVirtualenvDirectory(venvName)
552 venvName = Preferences.getPip("CurrentEnvironment")
553 venvManager = e5App().getObject("VirtualEnvManager")
554 if venvManager.isGlobalEnvironment(venvName):
555 venvDirectory = self.__getUserConfig()
556 else:
557 venvDirectory = venvManager.getVirtualenvDirectory(venvName)
558 162
559 if venvDirectory: 163 if venvDirectory:
560 config = os.path.join(venvDirectory, pip) 164 config = os.path.join(venvDirectory, pip)
561 else: 165 else:
562 config = "" 166 config = ""
563 167
564 return config 168 return config
565 169
566 ## def getDefaultEnvironmentString(self):
567 ## """
568 ## Public method to get the string for the default environment.
569 ##
570 ## @return string for the default environment
571 ## @rtype str
572 ## """
573 ## return self.tr("<standard>")
574 ##
575 def getProjectEnvironmentString(self): 170 def getProjectEnvironmentString(self):
576 """ 171 """
577 Public method to get the string for the project environment. 172 Public method to get the string for the project environment.
578 173
579 @return string for the project environment 174 @return string for the project environment
591 @param venvName logical name for the virtual environment 186 @param venvName logical name for the virtual environment
592 @type str 187 @type str
593 @return interpreter path 188 @return interpreter path
594 @rtype str 189 @rtype str
595 """ 190 """
596 ## if venvName == self.getDefaultEnvironmentString():
597 ## venvName = Preferences.getPip("CurrentEnvironment")
598 if venvName == self.getProjectEnvironmentString(): 191 if venvName == self.getProjectEnvironmentString():
599 venvName = \ 192 venvName = \
600 e5App().getObject("Project").getDebugProperty("VIRTUALENV") 193 e5App().getObject("Project").getDebugProperty("VIRTUALENV")
601 if not venvName: 194 if not venvName:
602 # fall back to interpreter used to run eric6 195 # fall back to interpreter used to run eric6
603 return sys.executable 196 return sys.executable
604 ## # fall back to standard if not defined
605 ## venvName = Preferences.getPip("CurrentEnvironment")
606 197
607 interpreter = \ 198 interpreter = \
608 e5App().getObject("VirtualEnvManager").getVirtualenvInterpreter( 199 e5App().getObject("VirtualEnvManager").getVirtualenvInterpreter(
609 venvName) 200 venvName)
610 if not interpreter: 201 if not interpreter:
624 @rtype list of str 215 @rtype list of str
625 """ 216 """
626 return sorted( 217 return sorted(
627 e5App().getObject("VirtualEnvManager").getVirtualenvNames()) 218 e5App().getObject("VirtualEnvManager").getVirtualenvNames())
628 219
629 ##########################################################################
630 ## Methods below implement the individual menu entries
631 ##########################################################################
632
633 ## def __selectPipVirtualenv(self):
634 ## """
635 ## Private method to select the virtual environment to be used.
636 ## """
637 ## environments = self.getVirtualenvNames()
638 ## if environments:
639 ## currentEnvironment = Preferences.getPip("CurrentEnvironment")
640 ## try:
641 ## index = environments.index(currentEnvironment)
642 ## except ValueError:
643 ## index = 0
644 ## environment, ok = QInputDialog.getItem(
645 ## None,
646 ## self.tr("Virtual Environment for pip"),
647 ## self.tr("Select the virtual environment to be used:"),
648 ## environments, index, False)
649 ##
650 ## if ok and environment:
651 ## Preferences.getPip("CurrentEnvironment", environment)
652 ## else:
653 ## E5MessageBox.warning(
654 ## None,
655 ## self.tr("Virtual Environment for pip"),
656 ## self.tr("""No virtual environments have been configured yet."""
657 ## """ Please use the Virtualenv Manager to do that."""))
658 ##
659 ## def __listPackages(self):
660 ## """
661 ## Private slot to list all installed packages.
662 ## """
663 ## from .PipListDialog import PipListDialog
664 ## self.__listDialog = PipListDialog(
665 ## self, "list", Preferences.getPip("PipSearchIndex"),
666 ## self.tr("Installed Packages"))
667 ## self.__listDialog.show()
668 ## self.__listDialog.start()
669 ##
670 ## def __listUptodatePackages(self):
671 ## """
672 ## Private slot to list all installed, up-to-date packages.
673 ## """
674 ## from .PipListDialog import PipListDialog
675 ## self.__listUptodateDialog = PipListDialog(
676 ## self, "uptodate", Preferences.getPip("PipSearchIndex"),
677 ## self.tr("Up-to-date Packages"))
678 ## self.__listUptodateDialog.show()
679 ## self.__listUptodateDialog.start()
680 ##
681 ## def __listOutdatedPackages(self):
682 ## """
683 ## Private slot to list all installed, up-to-date packages.
684 ## """
685 ## from .PipListDialog import PipListDialog
686 ## self.__listOutdatedDialog = PipListDialog(
687 ## self, "outdated", Preferences.getPip("PipSearchIndex"),
688 ## self.tr("Outdated Packages"))
689 ## self.__listOutdatedDialog.show()
690 ## self.__listOutdatedDialog.start()
691 ##
692 ## def __editUserConfiguration(self):
693 ## """
694 ## Private slot to edit the user configuration.
695 ## """
696 ## self.__editConfiguration()
697 ##
698 ## def __editVirtualenvConfiguration(self):
699 ## """
700 ## Private slot to edit the current virtualenv configuration.
701 ## """
702 ## self.__editConfiguration(virtualenv=True)
703 ##
704 ## def __editConfiguration(self, virtualenv=False):
705 ## """
706 ## Private method to edit a configuration.
707 ##
708 ## @param virtualenv flag indicating to edit the current virtualenv
709 ## configuration file
710 ## @type bool
711 ## """
712 ## from QScintilla.MiniEditor import MiniEditor
713 ## if virtualenv:
714 ## cfgFile = self.__getVirtualenvConfig()
715 ## if not cfgFile:
716 ## return
717 ## else:
718 ## cfgFile = self.__getUserConfig()
719 ## cfgDir = os.path.dirname(cfgFile)
720 ## if not cfgDir:
721 ## E5MessageBox.critical(
722 ## None,
723 ## self.tr("Edit Configuration"),
724 ## self.tr("""No valid configuration path determined."""
725 ## """ Is a virtual environment selected? Aborting"""))
726 ## return
727 ##
728 ## try:
729 ## if not os.path.isdir(cfgDir):
730 ## os.makedirs(cfgDir)
731 ## except OSError:
732 ## E5MessageBox.critical(
733 ## None,
734 ## self.tr("Edit Configuration"),
735 ## self.tr("""No valid configuration path determined."""
736 ## """ Is a virtual environment selected? Aborting"""))
737 ## return
738 ##
739 ## if not os.path.exists(cfgFile):
740 ## try:
741 ## f = open(cfgFile, "w")
742 ## f.write("[global]\n")
743 ## f.close()
744 ## except (IOError, OSError):
745 ## # ignore these
746 ## pass
747 ##
748 ## # check, if the destination is writeable
749 ## if not os.access(cfgFile, os.W_OK):
750 ## E5MessageBox.critical(
751 ## None,
752 ## self.tr("Edit Configuration"),
753 ## self.tr("""No valid configuartion path determined."""
754 ## """ Is a virtual environment selected? Aborting"""))
755 ## return
756 ##
757 ## self.__editor = MiniEditor(cfgFile, "Properties")
758 ## self.__editor.show()
759 ##
760 def installPip(self, venvName, userSite=False): 220 def installPip(self, venvName, userSite=False):
761 """ 221 """
762 Public method to install pip. 222 Public method to install pip.
763 223
764 @param venvName name of the environment to install pip into 224 @param venvName name of the environment to install pip into
789 249
790 res = dia.startProcesses(commands) 250 res = dia.startProcesses(commands)
791 if res: 251 if res:
792 dia.exec_() 252 dia.exec_()
793 253
794 ## @pyqtSlot()
795 ## def upgradePip(self, venvName="", userSite=False):
796 ## """
797 ## Public method to upgrade pip itself.
798 ##
799 ## @param venvName name of the virtual environment to be used
800 ## @type str
801 ## @param userSite flag indicating an install to the user install
802 ## directory
803 ## @type bool
804 ## @return flag indicating a successful execution
805 ## @rtype bool
806 ## """
807 ## # Upgrading pip needs to be treated specially because
808 ## # it must be done using the python executable
809 ##
810 ## if not venvName:
811 ## from .PipSelectionDialog import PipSelectionDialog
812 ## dlg = PipSelectionDialog(self)
813 ## if dlg.exec_() != QDialog.Accepted:
814 ## return
815 ##
816 ## venvName, userSite = dlg.getData()
817 ##
818 ## interpreter = self.getVirtualenvInterpreter(venvName)
819 ## if not interpreter:
820 ## return
821 ##
822 ## if Preferences.getPip("PipSearchIndex"):
823 ## indexUrl = Preferences.getPip("PipSearchIndex") + "/simple"
824 ## args = ["-m", "pip", "install", "--index-url", indexUrl,
825 ## "--upgrade"]
826 ## else:
827 ## args = ["-m", "pip", "install", "--upgrade"]
828 ## if userSite:
829 ## args.append("--user")
830 ## args.append("pip")
831 ##
832 ## dia = PipDialog(self.tr('Upgrade PIP'))
833 ## res = dia.startProcess(interpreter, args)
834 ## if res:
835 ## dia.exec_()
836 ## return res
837 ##
838 @pyqtSlot() 254 @pyqtSlot()
839 def repairPip(self, venvName): 255 def repairPip(self, venvName):
840 """ 256 """
841 Public method to repair the pip installation. 257 Public method to repair the pip installation.
842 258
843 @param venvName name of the environment to install pip into 259 @param venvName name of the environment to install pip into
844 @type str 260 @type str
845 @return flag indicating a successful execution
846 @rtype bool
847 """ 261 """
848 interpreter = self.getVirtualenvInterpreter(venvName) 262 interpreter = self.getVirtualenvInterpreter(venvName)
849 if not interpreter: 263 if not interpreter:
850 return 264 return
851 265
871 @type list of str 285 @type list of str
872 @return flag indicating to abort the upgrade attempt 286 @return flag indicating to abort the upgrade attempt
873 @rtype bool 287 @rtype bool
874 """ 288 """
875 pyqtPackages = [p for p in packages 289 pyqtPackages = [p for p in packages
876 if p.lower() in ["pyqt5", "qscintilla", "sip"]] 290 if p.lower() in ["pyqt5", "pyqt5-sip", "pyqtwebengine",
291 "qscintilla", "sip"]]
877 292
878 if bool(pyqtPackages): 293 if bool(pyqtPackages):
879 abort = not E5MessageBox.yesNo( 294 abort = not E5MessageBox.yesNo(
880 None, 295 None,
881 self.tr("Upgrade Packages"), 296 self.tr("Upgrade Packages"),
882 self.tr( 297 self.tr(
883 """You are trying to upgrade PyQt packages. This will""" 298 """You are trying to upgrade PyQt packages. This might"""
884 """ not work for the current instance of Python ({0}).""" 299 """ not work for the current instance of Python ({0})."""
885 """ Do you want to continue?""").format(sys.executable), 300 """ Do you want to continue?""").format(sys.executable),
886 icon=E5MessageBox.Critical) 301 icon=E5MessageBox.Critical)
887 else: 302 else:
888 abort = False 303 abort = False
889 304
890 return abort 305 return abort
891 306
892 def upgradePackages(self, packages, venvName="", userSite=False): 307 def upgradePackages(self, packages, venvName, userSite=False):
893 """ 308 """
894 Public method to upgrade the given list of packages. 309 Public method to upgrade the given list of packages.
895 310
896 @param packages list of packages to upgrade 311 @param packages list of packages to upgrade
897 @type list of str 312 @type list of str
905 """ 320 """
906 if self.__checkUpgradePyQt(packages): 321 if self.__checkUpgradePyQt(packages):
907 return False 322 return False
908 323
909 if not venvName: 324 if not venvName:
910 venvName = Preferences.getPip("CurrentEnvironment") 325 return False
326
911 interpreter = self.getVirtualenvInterpreter(venvName) 327 interpreter = self.getVirtualenvInterpreter(venvName)
912 if not interpreter: 328 if not interpreter:
913 return 329 return False
914 330
915 if Preferences.getPip("PipSearchIndex"): 331 if Preferences.getPip("PipSearchIndex"):
916 indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" 332 indexUrl = Preferences.getPip("PipSearchIndex") + "/simple"
917 args = ["-m", "pip", "install", "--index-url", indexUrl, 333 args = ["-m", "pip", "install", "--index-url", indexUrl,
918 "--upgrade"] 334 "--upgrade"]
925 res = dia.startProcess(interpreter, args) 341 res = dia.startProcess(interpreter, args)
926 if res: 342 if res:
927 dia.exec_() 343 dia.exec_()
928 return res 344 return res
929 345
930 def __upgradePackages(self): 346 def installPackages(self, packages, venvName, userSite=False):
931 """
932 Private slot to upgrade packages to be given by the user.
933 """
934 from .PipPackagesInputDialog import PipPackagesInputDialog
935 dlg = PipPackagesInputDialog(self, self.tr("Upgrade Packages"))
936 if dlg.exec_() == QDialog.Accepted:
937 venvName, packages, user = dlg.getData()
938 if packages:
939 self.upgradePackages(packages, venvName=venvName,
940 userSite=user)
941
942 def installPackages(self, packages, venvName="", userSite=False):
943 """ 347 """
944 Public method to install the given list of packages. 348 Public method to install the given list of packages.
945 349
946 @param packages list of packages to install 350 @param packages list of packages to install
947 @type list of str 351 @type list of str
949 @type str 353 @type str
950 @param userSite flag indicating an install to the user install 354 @param userSite flag indicating an install to the user install
951 directory 355 directory
952 @type bool 356 @type bool
953 """ 357 """
954 if not venvName: 358 if venvName:
955 venvName = Preferences.getPip("CurrentEnvironment") 359 interpreter = self.getVirtualenvInterpreter(venvName)
956 interpreter = self.getVirtualenvInterpreter(venvName) 360 if not interpreter:
957 if not interpreter: 361 return
958 return 362
959 363 if Preferences.getPip("PipSearchIndex"):
960 if Preferences.getPip("PipSearchIndex"): 364 indexUrl = Preferences.getPip("PipSearchIndex") + "/simple"
961 indexUrl = Preferences.getPip("PipSearchIndex") + "/simple" 365 args = ["-m", "pip", "install", "--index-url", indexUrl]
962 args = ["-m", "pip", "install", "--index-url", indexUrl] 366 else:
963 else: 367 args = ["-m", "pip", "install"]
964 args = ["-m", "pip", "install"] 368 if userSite:
965 if userSite: 369 args.append("--user")
966 args.append("--user") 370 args += packages
967 args += packages 371 dia = PipDialog(self.tr('Install Packages'))
968 dia = PipDialog(self.tr('Install Packages')) 372 res = dia.startProcess(interpreter, args)
969 res = dia.startProcess(interpreter, args) 373 if res:
970 if res: 374 dia.exec_()
971 dia.exec_() 375
972 ## 376 def installRequirements(self, venvName):
973 ## def __installPackages(self): 377 """
974 ## """ 378 Public method to install packages as given in a requirements file.
975 ## Private slot to install packages to be given by the user. 379
976 ## """ 380 @param venvName name of the virtual environment to be used
977 ## from .PipPackagesInputDialog import PipPackagesInputDialog 381 @type str
978 ## dlg = PipPackagesInputDialog(
979 ## self, self.tr("Install Packages"))
980 ## if dlg.exec_() == QDialog.Accepted:
981 ## venvName, packages, user = dlg.getData()
982 ## if packages:
983 ## self.installPackages(packages, venvName=venvName,
984 ## userSite=user)
985 ##
986 ## def __installLocalPackage(self):
987 ## """
988 ## Private slot to install a package available on local storage.
989 ## """
990 ## from .PipFileSelectionDialog import PipFileSelectionDialog
991 ## dlg = PipFileSelectionDialog(self, "package")
992 ## if dlg.exec_() == QDialog.Accepted:
993 ## venvName, package, user = dlg.getData()
994 ## if package and os.path.exists(package):
995 ## self.installPackages([package], venvName=venvName,
996 ## userSite=user)
997
998 def __installRequirements(self):
999 """
1000 Private slot to install packages as given in a requirements file.
1001 """ 382 """
1002 from .PipFileSelectionDialog import PipFileSelectionDialog 383 from .PipFileSelectionDialog import PipFileSelectionDialog
1003 dlg = PipFileSelectionDialog(self, "requirements") 384 dlg = PipFileSelectionDialog(self, "requirements")
1004 if dlg.exec_() == QDialog.Accepted: 385 if dlg.exec_() == QDialog.Accepted:
1005 venvName, requirements, user = dlg.getData() 386 requirements, user = dlg.getData()
1006 if requirements and os.path.exists(requirements): 387 if requirements and os.path.exists(requirements):
1007 interpreter = self.getVirtualenvInterpreter(venvName) 388 interpreter = self.getVirtualenvInterpreter(venvName)
1008 if not interpreter: 389 if not interpreter:
1009 return 390 return
391
1010 if Preferences.getPip("PipSearchIndex"): 392 if Preferences.getPip("PipSearchIndex"):
1011 indexUrl = Preferences.getPip("PipSearchIndex") + \ 393 indexUrl = Preferences.getPip("PipSearchIndex") + \
1012 "/simple" 394 "/simple"
1013 args = ["-m", "pip", "install", "--index-url", indexUrl] 395 args = ["-m", "pip", "install", "--index-url", indexUrl]
1014 else: 396 else:
1019 dia = PipDialog(self.tr('Install Packages from Requirements')) 401 dia = PipDialog(self.tr('Install Packages from Requirements'))
1020 res = dia.startProcess(interpreter, args) 402 res = dia.startProcess(interpreter, args)
1021 if res: 403 if res:
1022 dia.exec_() 404 dia.exec_()
1023 405
1024 def uninstallPackages(self, packages, venvName=""): 406 def uninstallPackages(self, packages, venvName):
1025 """ 407 """
1026 Public method to uninstall the given list of packages. 408 Public method to uninstall the given list of packages.
1027 409
1028 @param packages list of packages to uninstall 410 @param packages list of packages to uninstall
1029 @type list of str 411 @type list of str
1031 @type str 413 @type str
1032 @return flag indicating a successful execution 414 @return flag indicating a successful execution
1033 @rtype bool 415 @rtype bool
1034 """ 416 """
1035 res = False 417 res = False
1036 if packages: 418 if packages and venvName:
1037 from UI.DeleteFilesConfirmationDialog import \ 419 from UI.DeleteFilesConfirmationDialog import \
1038 DeleteFilesConfirmationDialog 420 DeleteFilesConfirmationDialog
1039 dlg = DeleteFilesConfirmationDialog( 421 dlg = DeleteFilesConfirmationDialog(
1040 self.parent(), 422 self.parent(),
1041 self.tr("Uninstall Packages"), 423 self.tr("Uninstall Packages"),
1042 self.tr( 424 self.tr(
1043 "Do you really want to uninstall these packages?"), 425 "Do you really want to uninstall these packages?"),
1044 packages) 426 packages)
1045 if dlg.exec_() == QDialog.Accepted: 427 if dlg.exec_() == QDialog.Accepted:
1046 if not venvName:
1047 venvName = Preferences.getPip("CurrentEnvironment")
1048 interpreter = self.getVirtualenvInterpreter(venvName) 428 interpreter = self.getVirtualenvInterpreter(venvName)
1049 if not interpreter: 429 if not interpreter:
1050 return 430 return
1051 args = ["-m", "pip", "uninstall", "--yes"] + packages 431 args = ["-m", "pip", "uninstall", "--yes"] + packages
1052 dia = PipDialog(self.tr('Uninstall Packages')) 432 dia = PipDialog(self.tr('Uninstall Packages'))
1053 res = dia.startProcess(interpreter, args) 433 res = dia.startProcess(interpreter, args)
1054 if res: 434 if res:
1055 dia.exec_() 435 dia.exec_()
1056 return res 436 return res
1057 437
1058 ## def __uninstallPackages(self): 438 def uninstallRequirements(self, venvName):
1059 ## """ 439 """
1060 ## Private slot to uninstall packages to be given by the user. 440 Public method to uninstall packages as given in a requirements file.
1061 ## """ 441
1062 ## from .PipPackagesInputDialog import PipPackagesInputDialog 442 @param venvName name of the virtual environment to be used
1063 ## dlg = PipPackagesInputDialog( 443 @type str
1064 ## self, self.tr("Uninstall Packages"), install=False) 444 """
1065 ## if dlg.exec_() == QDialog.Accepted: 445 if venvName:
1066 ## venvName, packages, _user = dlg.getData() 446 from .PipFileSelectionDialog import PipFileSelectionDialog
1067 ## if packages: 447 dlg = PipFileSelectionDialog(self, "requirements",
1068 ## self.uninstallPackages(packages, venvName=venvName) 448 install=False)
1069 ## 449 if dlg.exec_() == QDialog.Accepted:
1070 def __uninstallRequirements(self): 450 requirements, _user = dlg.getData()
1071 """ 451 if requirements and os.path.exists(requirements):
1072 Private slot to uninstall packages as given in a requirements file. 452 try:
1073 """ 453 f = open(requirements, "r")
1074 from .PipFileSelectionDialog import PipFileSelectionDialog 454 reqs = f.read().splitlines()
1075 dlg = PipFileSelectionDialog(self, "requirements", 455 f.close()
1076 install=False) 456 except (OSError, IOError):
1077 if dlg.exec_() == QDialog.Accepted:
1078 venvName, requirements, _user = dlg.getData()
1079 if requirements and os.path.exists(requirements):
1080 try:
1081 f = open(requirements, "r")
1082 reqs = f.read().splitlines()
1083 f.close()
1084 except (OSError, IOError):
1085 return
1086
1087 from UI.DeleteFilesConfirmationDialog import \
1088 DeleteFilesConfirmationDialog
1089 dlg = DeleteFilesConfirmationDialog(
1090 self.parent(),
1091 self.tr("Uninstall Packages"),
1092 self.tr(
1093 "Do you really want to uninstall these packages?"),
1094 reqs)
1095 if dlg.exec_() == QDialog.Accepted:
1096 if not venvName:
1097 venvName = Preferences.getPip("CurrentEnvironment")
1098 interpreter = self.getVirtualenvInterpreter(venvName)
1099 if not interpreter:
1100 return 457 return
1101 args = ["-m", "pip", "uninstall", "--requirement", 458
1102 requirements] 459 from UI.DeleteFilesConfirmationDialog import \
1103 dia = PipDialog( 460 DeleteFilesConfirmationDialog
1104 self.tr('Uninstall Packages from Requirements')) 461 dlg = DeleteFilesConfirmationDialog(
1105 res = dia.startProcess(interpreter, args) 462 self.parent(),
1106 if res: 463 self.tr("Uninstall Packages"),
1107 dia.exec_() 464 self.tr(
1108 465 "Do you really want to uninstall these packages?"),
1109 ## def __generateRequirements(self): 466 reqs)
1110 ## """ 467 if dlg.exec_() == QDialog.Accepted:
1111 ## Private slot to generate the contents for a requirements file. 468 interpreter = self.getVirtualenvInterpreter(venvName)
1112 ## """ 469 if not interpreter:
1113 ## from .PipFreezeDialog import PipFreezeDialog 470 return
1114 ## self.__freezeDialog = PipFreezeDialog(self) 471
1115 ## self.__freezeDialog.show() 472 args = ["-m", "pip", "uninstall", "--requirement",
1116 ## self.__freezeDialog.start() 473 requirements]
1117 ## 474 dia = PipDialog(
1118 ## def __searchPyPI(self): 475 self.tr('Uninstall Packages from Requirements'))
1119 ## """ 476 res = dia.startProcess(interpreter, args)
1120 ## Private slot to search the Python Package Index. 477 if res:
1121 ## """ 478 dia.exec_()
1122 ## from .PipSearchDialog import PipSearchDialog 479
1123 ##
1124 ## if Preferences.getPip("PipSearchIndex"):
1125 ## indexUrl = Preferences.getPip("PipSearchIndex") + "/pypi"
1126 ## else:
1127 ## indexUrl = DefaultIndexUrlXml
1128 ##
1129 ## self.__searchDialog = PipSearchDialog(self, indexUrl)
1130 ## self.__searchDialog.show()
1131 ##
1132 def getIndexUrl(self): 480 def getIndexUrl(self):
1133 """ 481 """
1134 Public method to get the index URL for PyPI. 482 Public method to get the index URL for PyPI.
1135 483
1136 @return index URL for PyPI 484 @return index URL for PyPI
1269 package["version"], 617 package["version"],
1270 package["latest_version"], 618 package["latest_version"],
1271 )) 619 ))
1272 620
1273 return packages 621 return packages
1274 ## 622
1275 ## def __pipConfigure(self): 623 def getPackageDetails(self, name, version):
1276 ## """ 624 """
1277 ## Private slot to open the configuration page. 625 Public method to get package details using the PyPI JSON interface.
1278 ## """ 626
1279 ## e5App().getObject("UserInterface").showPreferences("pipPage") 627 @param name package name
628 @type str
629 @param version package version
630 @type str
631 @return dictionary containing PyPI package data
632 @rtype dict
633 """
634 result = {}
635
636 if name and version:
637 url = "https://pypi.org/pypi/{0}/{1}/json".format(name, version)
638 request = QNetworkRequest(QUrl(url))
639 reply = self.__networkManager.get(request)
640 while not reply.isFinished():
641 QCoreApplication.processEvents()
642
643 reply.deleteLater()
644 if reply.error() == QNetworkReply.NoError:
645 data = str(reply.readAll(),
646 Preferences.getSystem("IOEncoding"),
647 'replace')
648 try:
649 result = json.loads(data)
650 except Exception:
651 # ignore JSON exceptions
652 pass
653
654 return result

eric ide

mercurial