src/eric7/VirtualEnv/VirtualenvManager.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
24 24
25 25
26 class VirtualenvManager(QObject): 26 class VirtualenvManager(QObject):
27 """ 27 """
28 Class implementing an object to manage Python virtual environments. 28 Class implementing an object to manage Python virtual environments.
29 29
30 @signal virtualEnvironmentAdded() emitted to indicate the addition of 30 @signal virtualEnvironmentAdded() emitted to indicate the addition of
31 a virtual environment 31 a virtual environment
32 @signal virtualEnvironmentRemoved() emitted to indicate the removal and 32 @signal virtualEnvironmentRemoved() emitted to indicate the removal and
33 deletion of a virtual environment 33 deletion of a virtual environment
34 @signal virtualEnvironmentChanged(name) emitted to indicate a change of 34 @signal virtualEnvironmentChanged(name) emitted to indicate a change of
35 a virtual environment 35 a virtual environment
36 @signal virtualEnvironmentsListChanged() emitted to indicate a change of 36 @signal virtualEnvironmentsListChanged() emitted to indicate a change of
37 the list of virtual environments (may be used to refresh the list) 37 the list of virtual environments (may be used to refresh the list)
38 """ 38 """
39
39 DefaultKey = "<default>" 40 DefaultKey = "<default>"
40 41
41 virtualEnvironmentAdded = pyqtSignal() 42 virtualEnvironmentAdded = pyqtSignal()
42 virtualEnvironmentRemoved = pyqtSignal() 43 virtualEnvironmentRemoved = pyqtSignal()
43 virtualEnvironmentChanged = pyqtSignal(str) 44 virtualEnvironmentChanged = pyqtSignal(str)
44 45
45 virtualEnvironmentsListChanged = pyqtSignal() 46 virtualEnvironmentsListChanged = pyqtSignal()
46 47
47 def __init__(self, parent=None): 48 def __init__(self, parent=None):
48 """ 49 """
49 Constructor 50 Constructor
50 51
51 @param parent reference to the parent object 52 @param parent reference to the parent object
52 @type QWidget 53 @type QWidget
53 """ 54 """
54 super().__init__(parent) 55 super().__init__(parent)
55 56
56 self.__ui = parent 57 self.__ui = parent
57 58
58 self.__loadSettings() 59 self.__loadSettings()
59 60
60 def __loadSettings(self): 61 def __loadSettings(self):
61 """ 62 """
62 Private slot to load the virtual environments. 63 Private slot to load the virtual environments.
63 """ 64 """
64 self.__virtualEnvironmentsBaseDir = Preferences.getSettings().value( 65 self.__virtualEnvironmentsBaseDir = Preferences.getSettings().value(
65 "PyVenv/VirtualEnvironmentsBaseDir", "") 66 "PyVenv/VirtualEnvironmentsBaseDir", ""
66 67 )
68
67 venvString = Preferences.getSettings().value( 69 venvString = Preferences.getSettings().value(
68 "PyVenv/VirtualEnvironments", "{}") # __IGNORE_WARNING_M613__ 70 "PyVenv/VirtualEnvironments", "{}" # __IGNORE_WARNING_M613__
71 )
69 environments = json.loads(venvString) 72 environments = json.loads(venvString)
70 73
71 self.__virtualEnvironments = {} 74 self.__virtualEnvironments = {}
72 # each environment entry is a dictionary: 75 # each environment entry is a dictionary:
73 # path: the directory of the virtual environment 76 # path: the directory of the virtual environment
74 # (empty for a global environment) 77 # (empty for a global environment)
75 # interpreter: the path of the Python interpreter 78 # interpreter: the path of the Python interpreter
81 # setting 84 # setting
82 # 85 #
83 envsToDelete = [] 86 envsToDelete = []
84 for venvName in environments: 87 for venvName in environments:
85 environment = environments[venvName] 88 environment = environments[venvName]
86 if ( 89 if ("is_remote" in environment and environment["is_remote"]) or os.access(
87 ("is_remote" in environment and environment["is_remote"]) or 90 environment["interpreter"], os.X_OK
88 os.access(environment["interpreter"], os.X_OK)
89 ): 91 ):
90 if "is_global" not in environment: 92 if "is_global" not in environment:
91 environment["is_global"] = environment["path"] == "" 93 environment["is_global"] = environment["path"] == ""
92 if "is_conda" not in environment: 94 if "is_conda" not in environment:
93 environment["is_conda"] = False 95 environment["is_conda"] = False
94 if "is_remote" not in environment: 96 if "is_remote" not in environment:
95 environment["is_remote"] = False 97 environment["is_remote"] = False
96 if "exec_path" not in environment: 98 if "exec_path" not in environment:
97 environment["exec_path"] = "" 99 environment["exec_path"] = ""
98 self.__virtualEnvironments[venvName] = environment 100 self.__virtualEnvironments[venvName] = environment
99 101
100 # now remove unsupported environments 102 # now remove unsupported environments
101 for venvName in envsToDelete: 103 for venvName in envsToDelete:
102 del environments[venvName] 104 del environments[venvName]
103 105
104 # check, if the interpreter used to run eric is in the environments 106 # check, if the interpreter used to run eric is in the environments
105 defaultPy = Globals.getPythonExecutable() 107 defaultPy = Globals.getPythonExecutable()
106 found = False 108 found = False
107 for venvName in self.__virtualEnvironments: 109 for venvName in self.__virtualEnvironments:
108 if (defaultPy == 110 if defaultPy == self.__virtualEnvironments[venvName]["interpreter"]:
109 self.__virtualEnvironments[venvName]["interpreter"]):
110 found = True 111 found = True
111 break 112 break
112 if not found: 113 if not found:
113 # add an environment entry for the default interpreter 114 # add an environment entry for the default interpreter
114 self.__virtualEnvironments[VirtualenvManager.DefaultKey] = { 115 self.__virtualEnvironments[VirtualenvManager.DefaultKey] = {
118 "is_global": True, 119 "is_global": True,
119 "is_conda": False, 120 "is_conda": False,
120 "is_remote": False, 121 "is_remote": False,
121 "exec_path": "", 122 "exec_path": "",
122 } 123 }
123 124
124 self.__saveSettings() 125 self.__saveSettings()
125 126
126 def __saveSettings(self): 127 def __saveSettings(self):
127 """ 128 """
128 Private slot to save the virtual environments. 129 Private slot to save the virtual environments.
129 """ 130 """
130 Preferences.getSettings().setValue( 131 Preferences.getSettings().setValue(
131 "PyVenv/VirtualEnvironmentsBaseDir", 132 "PyVenv/VirtualEnvironmentsBaseDir", self.__virtualEnvironmentsBaseDir
132 self.__virtualEnvironmentsBaseDir) 133 )
133 134
134 Preferences.getSettings().setValue( 135 Preferences.getSettings().setValue(
135 "PyVenv/VirtualEnvironments", 136 "PyVenv/VirtualEnvironments", json.dumps(self.__virtualEnvironments)
136 json.dumps(self.__virtualEnvironments)
137 ) 137 )
138 Preferences.syncPreferences() 138 Preferences.syncPreferences()
139 139
140 @pyqtSlot() 140 @pyqtSlot()
141 def reloadSettings(self): 141 def reloadSettings(self):
142 """ 142 """
143 Public slot to reload the virtual environments. 143 Public slot to reload the virtual environments.
144 """ 144 """
145 Preferences.syncPreferences() 145 Preferences.syncPreferences()
146 self.__loadSettings() 146 self.__loadSettings()
147 147
148 def getDefaultEnvironment(self): 148 def getDefaultEnvironment(self):
149 """ 149 """
150 Public method to get the default virtual environment. 150 Public method to get the default virtual environment.
151 151
152 Default is an environment with the key '<default>' or the first one 152 Default is an environment with the key '<default>' or the first one
153 having an interpreter matching sys.executable (i.e. the one used to 153 having an interpreter matching sys.executable (i.e. the one used to
154 execute eric with) 154 execute eric with)
155 155
156 @return tuple containing the environment name and a dictionary 156 @return tuple containing the environment name and a dictionary
157 containing a copy of the default virtual environment 157 containing a copy of the default virtual environment
158 @rtype tuple of (str, dict) 158 @rtype tuple of (str, dict)
159 """ 159 """
160 if VirtualenvManager.DefaultKey in self.__virtualEnvironments: 160 if VirtualenvManager.DefaultKey in self.__virtualEnvironments:
161 return ( 161 return (
162 VirtualenvManager.DefaultKey, 162 VirtualenvManager.DefaultKey,
163 copy.copy( 163 copy.copy(self.__virtualEnvironments[VirtualenvManager.DefaultKey]),
164 self.__virtualEnvironments[VirtualenvManager.DefaultKey])
165 ) 164 )
166 165
167 else: 166 else:
168 return self.environmentForInterpreter(sys.executable) 167 return self.environmentForInterpreter(sys.executable)
169 168
170 def environmentForInterpreter(self, interpreter): 169 def environmentForInterpreter(self, interpreter):
171 """ 170 """
172 Public method to get the environment a given interpreter belongs to. 171 Public method to get the environment a given interpreter belongs to.
173 172
174 @param interpreter path of the interpreter 173 @param interpreter path of the interpreter
175 @type str 174 @type str
176 @return tuple containing the environment name and a dictionary 175 @return tuple containing the environment name and a dictionary
177 containing a copy of the default virtual environment 176 containing a copy of the default virtual environment
178 @rtype tuple of (str, dict) 177 @rtype tuple of (str, dict)
179 """ 178 """
180 py = interpreter.replace("w.exe", ".exe") 179 py = interpreter.replace("w.exe", ".exe")
181 for venvName in self.__virtualEnvironments: 180 for venvName in self.__virtualEnvironments:
182 if (py == self.__virtualEnvironments[venvName]["interpreter"]): 181 if py == self.__virtualEnvironments[venvName]["interpreter"]:
183 return ( 182 return (venvName, copy.copy(self.__virtualEnvironments[venvName]))
184 venvName, 183
185 copy.copy(self.__virtualEnvironments[venvName])
186 )
187
188 return ("", {}) 184 return ("", {})
189 185
190 @pyqtSlot() 186 @pyqtSlot()
191 def createVirtualEnv(self, baseDir=""): 187 def createVirtualEnv(self, baseDir=""):
192 """ 188 """
193 Public slot to create a new virtual environment. 189 Public slot to create a new virtual environment.
194 190
195 @param baseDir base directory for the virtual environments 191 @param baseDir base directory for the virtual environments
196 @type str 192 @type str
197 """ 193 """
198 from .VirtualenvConfigurationDialog import ( 194 from .VirtualenvConfigurationDialog import VirtualenvConfigurationDialog
199 VirtualenvConfigurationDialog 195
200 )
201
202 if not baseDir: 196 if not baseDir:
203 baseDir = self.__virtualEnvironmentsBaseDir 197 baseDir = self.__virtualEnvironmentsBaseDir
204 198
205 dlg = VirtualenvConfigurationDialog(baseDir=baseDir) 199 dlg = VirtualenvConfigurationDialog(baseDir=baseDir)
206 if dlg.exec() == QDialog.DialogCode.Accepted: 200 if dlg.exec() == QDialog.DialogCode.Accepted:
207 resultDict = dlg.getData() 201 resultDict = dlg.getData()
208 202
209 if resultDict["envType"] == "conda": 203 if resultDict["envType"] == "conda":
210 # create the conda environment 204 # create the conda environment
211 conda = ericApp().getObject("Conda") 205 conda = ericApp().getObject("Conda")
212 ok, prefix, interpreter = conda.createCondaEnvironment( 206 ok, prefix, interpreter = conda.createCondaEnvironment(
213 resultDict["arguments"]) 207 resultDict["arguments"]
208 )
214 if ok and "--dry-run" not in resultDict["arguments"]: 209 if ok and "--dry-run" not in resultDict["arguments"]:
215 self.addVirtualEnv(resultDict["logicalName"], 210 self.addVirtualEnv(
216 prefix, 211 resultDict["logicalName"],
217 venvInterpreter=interpreter, 212 prefix,
218 isConda=True) 213 venvInterpreter=interpreter,
214 isConda=True,
215 )
219 else: 216 else:
220 # now do the call 217 # now do the call
221 from .VirtualenvExecDialog import VirtualenvExecDialog 218 from .VirtualenvExecDialog import VirtualenvExecDialog
219
222 dia = VirtualenvExecDialog(resultDict, self) 220 dia = VirtualenvExecDialog(resultDict, self)
223 dia.show() 221 dia.show()
224 dia.start(resultDict["arguments"]) 222 dia.start(resultDict["arguments"])
225 dia.exec() 223 dia.exec()
226 224
227 @pyqtSlot() 225 @pyqtSlot()
228 def upgradeVirtualEnv(self, venvName): 226 def upgradeVirtualEnv(self, venvName):
229 """ 227 """
230 Public slot to upgrade a virtual environment. 228 Public slot to upgrade a virtual environment.
231 229
232 @param venvName name of the virtual environment 230 @param venvName name of the virtual environment
233 @type str 231 @type str
234 """ 232 """
235 from .VirtualenvUpgradeConfigurationDialog import ( 233 from .VirtualenvUpgradeConfigurationDialog import (
236 VirtualenvUpgradeConfigurationDialog 234 VirtualenvUpgradeConfigurationDialog,
237 ) 235 )
238 236
239 venvDirectory = self.getVirtualenvDirectory(venvName) 237 venvDirectory = self.getVirtualenvDirectory(venvName)
240 if not os.path.exists(os.path.join(venvDirectory, "pyvenv.cfg")): 238 if not os.path.exists(os.path.join(venvDirectory, "pyvenv.cfg")):
241 # The environment was not created by the 'venv' module. 239 # The environment was not created by the 'venv' module.
242 return 240 return
243 241
244 dlg = VirtualenvUpgradeConfigurationDialog(venvName, venvDirectory) 242 dlg = VirtualenvUpgradeConfigurationDialog(venvName, venvDirectory)
245 if dlg.exec() == QDialog.DialogCode.Accepted: 243 if dlg.exec() == QDialog.DialogCode.Accepted:
246 pythonExe, args, createLog = dlg.getData() 244 pythonExe, args, createLog = dlg.getData()
247 245
248 from .VirtualenvUpgradeExecDialog import ( 246 from .VirtualenvUpgradeExecDialog import VirtualenvUpgradeExecDialog
249 VirtualenvUpgradeExecDialog 247
250 ) 248 dia = VirtualenvUpgradeExecDialog(venvName, pythonExe, createLog, self)
251 dia = VirtualenvUpgradeExecDialog(
252 venvName, pythonExe, createLog, self)
253 dia.show() 249 dia.show()
254 dia.start(args) 250 dia.start(args)
255 dia.exec() 251 dia.exec()
256 252
257 def addVirtualEnv(self, venvName, venvDirectory, venvInterpreter="", 253 def addVirtualEnv(
258 isGlobal=False, isConda=False, isRemote=False, 254 self,
259 execPath=""): 255 venvName,
256 venvDirectory,
257 venvInterpreter="",
258 isGlobal=False,
259 isConda=False,
260 isRemote=False,
261 execPath="",
262 ):
260 """ 263 """
261 Public method to add a virtual environment. 264 Public method to add a virtual environment.
262 265
263 @param venvName logical name for the virtual environment 266 @param venvName logical name for the virtual environment
264 @type str 267 @type str
265 @param venvDirectory directory of the virtual environment 268 @param venvDirectory directory of the virtual environment
266 @type str 269 @type str
267 @param venvInterpreter interpreter of the virtual environment 270 @param venvInterpreter interpreter of the virtual environment
278 """ 281 """
279 if venvName in self.__virtualEnvironments: 282 if venvName in self.__virtualEnvironments:
280 ok = EricMessageBox.yesNo( 283 ok = EricMessageBox.yesNo(
281 None, 284 None,
282 self.tr("Add Virtual Environment"), 285 self.tr("Add Virtual Environment"),
283 self.tr("""A virtual environment named <b>{0}</b> exists""" 286 self.tr(
284 """ already. Shall it be replaced?""") 287 """A virtual environment named <b>{0}</b> exists"""
285 .format(venvName), 288 """ already. Shall it be replaced?"""
286 icon=EricMessageBox.Warning) 289 ).format(venvName),
290 icon=EricMessageBox.Warning,
291 )
287 if not ok: 292 if not ok:
288 from .VirtualenvNameDialog import VirtualenvNameDialog 293 from .VirtualenvNameDialog import VirtualenvNameDialog
294
289 dlg = VirtualenvNameDialog( 295 dlg = VirtualenvNameDialog(
290 list(self.__virtualEnvironments.keys()), 296 list(self.__virtualEnvironments.keys()), venvName
291 venvName) 297 )
292 if dlg.exec() != QDialog.DialogCode.Accepted: 298 if dlg.exec() != QDialog.DialogCode.Accepted:
293 return 299 return
294 300
295 venvName = dlg.getName() 301 venvName = dlg.getName()
296 302
297 if not venvInterpreter: 303 if not venvInterpreter:
298 from .VirtualenvInterpreterSelectionDialog import ( 304 from .VirtualenvInterpreterSelectionDialog import (
299 VirtualenvInterpreterSelectionDialog 305 VirtualenvInterpreterSelectionDialog,
300 ) 306 )
307
301 dlg = VirtualenvInterpreterSelectionDialog(venvName, venvDirectory) 308 dlg = VirtualenvInterpreterSelectionDialog(venvName, venvDirectory)
302 if dlg.exec() == QDialog.DialogCode.Accepted: 309 if dlg.exec() == QDialog.DialogCode.Accepted:
303 venvInterpreter = dlg.getData() 310 venvInterpreter = dlg.getData()
304 311
305 if venvInterpreter: 312 if venvInterpreter:
306 self.__virtualEnvironments[venvName] = { 313 self.__virtualEnvironments[venvName] = {
307 "path": venvDirectory, 314 "path": venvDirectory,
308 "interpreter": venvInterpreter, 315 "interpreter": venvInterpreter,
309 "variant": 3, # always 3 316 "variant": 3, # always 3
310 "is_global": isGlobal, 317 "is_global": isGlobal,
311 "is_conda": isConda, 318 "is_conda": isConda,
312 "is_remote": isRemote, 319 "is_remote": isRemote,
313 "exec_path": execPath, 320 "exec_path": execPath,
314 } 321 }
315 322
316 self.__saveSettings() 323 self.__saveSettings()
317 324
318 self.virtualEnvironmentAdded.emit() 325 self.virtualEnvironmentAdded.emit()
319 self.virtualEnvironmentsListChanged.emit() 326 self.virtualEnvironmentsListChanged.emit()
320 327
321 def setVirtualEnv(self, venvName, venvDirectory, venvInterpreter, 328 def setVirtualEnv(
322 isGlobal, isConda, isRemote, execPath): 329 self,
330 venvName,
331 venvDirectory,
332 venvInterpreter,
333 isGlobal,
334 isConda,
335 isRemote,
336 execPath,
337 ):
323 """ 338 """
324 Public method to change a virtual environment. 339 Public method to change a virtual environment.
325 340
326 @param venvName logical name of the virtual environment 341 @param venvName logical name of the virtual environment
327 @type str 342 @type str
328 @param venvDirectory directory of the virtual environment 343 @param venvDirectory directory of the virtual environment
329 @type str 344 @type str
330 @param venvInterpreter interpreter of the virtual environment 345 @param venvInterpreter interpreter of the virtual environment
341 """ 356 """
342 if venvName not in self.__virtualEnvironments: 357 if venvName not in self.__virtualEnvironments:
343 EricMessageBox.yesNo( 358 EricMessageBox.yesNo(
344 None, 359 None,
345 self.tr("Change Virtual Environment"), 360 self.tr("Change Virtual Environment"),
346 self.tr("""A virtual environment named <b>{0}</b> does not""" 361 self.tr(
347 """ exist. Aborting!""") 362 """A virtual environment named <b>{0}</b> does not"""
348 .format(venvName), 363 """ exist. Aborting!"""
349 icon=EricMessageBox.Warning) 364 ).format(venvName),
365 icon=EricMessageBox.Warning,
366 )
350 return 367 return
351 368
352 self.__virtualEnvironments[venvName] = { 369 self.__virtualEnvironments[venvName] = {
353 "path": venvDirectory, 370 "path": venvDirectory,
354 "interpreter": venvInterpreter, 371 "interpreter": venvInterpreter,
355 "variant": 3, # always 3 372 "variant": 3, # always 3
356 "is_global": isGlobal, 373 "is_global": isGlobal,
357 "is_conda": isConda, 374 "is_conda": isConda,
358 "is_remote": isRemote, 375 "is_remote": isRemote,
359 "exec_path": execPath, 376 "exec_path": execPath,
360 } 377 }
361 378
362 self.__saveSettings() 379 self.__saveSettings()
363 380
364 self.virtualEnvironmentChanged.emit(venvName) 381 self.virtualEnvironmentChanged.emit(venvName)
365 self.virtualEnvironmentsListChanged.emit() 382 self.virtualEnvironmentsListChanged.emit()
366 383
367 def renameVirtualEnv(self, oldVenvName, venvName, venvDirectory, 384 def renameVirtualEnv(
368 venvInterpreter, isGlobal, isConda, 385 self,
369 isRemote, execPath): 386 oldVenvName,
387 venvName,
388 venvDirectory,
389 venvInterpreter,
390 isGlobal,
391 isConda,
392 isRemote,
393 execPath,
394 ):
370 """ 395 """
371 Public method to substitute a virtual environment entry with a new 396 Public method to substitute a virtual environment entry with a new
372 name. 397 name.
373 398
374 @param oldVenvName old name of the virtual environment 399 @param oldVenvName old name of the virtual environment
375 @type str 400 @type str
376 @param venvName logical name for the virtual environment 401 @param venvName logical name for the virtual environment
377 @type str 402 @type str
378 @param venvDirectory directory of the virtual environment 403 @param venvDirectory directory of the virtual environment
391 """ 416 """
392 if oldVenvName not in self.__virtualEnvironments: 417 if oldVenvName not in self.__virtualEnvironments:
393 EricMessageBox.yesNo( 418 EricMessageBox.yesNo(
394 None, 419 None,
395 self.tr("Rename Virtual Environment"), 420 self.tr("Rename Virtual Environment"),
396 self.tr("""A virtual environment named <b>{0}</b> does not""" 421 self.tr(
397 """ exist. Aborting!""") 422 """A virtual environment named <b>{0}</b> does not"""
398 .format(oldVenvName), 423 """ exist. Aborting!"""
399 icon=EricMessageBox.Warning) 424 ).format(oldVenvName),
425 icon=EricMessageBox.Warning,
426 )
400 return 427 return
401 428
402 del self.__virtualEnvironments[oldVenvName] 429 del self.__virtualEnvironments[oldVenvName]
403 self.addVirtualEnv(venvName, venvDirectory, venvInterpreter, 430 self.addVirtualEnv(
404 isGlobal, isConda, isRemote, execPath) 431 venvName,
405 432 venvDirectory,
433 venvInterpreter,
434 isGlobal,
435 isConda,
436 isRemote,
437 execPath,
438 )
439
406 def deleteVirtualEnvs(self, venvNames): 440 def deleteVirtualEnvs(self, venvNames):
407 """ 441 """
408 Public method to delete virtual environments from the list and disk. 442 Public method to delete virtual environments from the list and disk.
409 443
410 @param venvNames list of logical names for the virtual environments 444 @param venvNames list of logical names for the virtual environments
411 @type list of str 445 @type list of str
412 """ 446 """
413 venvMessages = [] 447 venvMessages = []
414 for venvName in venvNames: 448 for venvName in venvNames:
415 if ( 449 if venvName in self.__virtualEnvironments and bool(
416 venvName in self.__virtualEnvironments and 450 self.__virtualEnvironments[venvName]["path"]
417 bool(self.__virtualEnvironments[venvName]["path"])
418 ): 451 ):
419 venvMessages.append(self.tr("{0} - {1}").format( 452 venvMessages.append(
420 venvName, self.__virtualEnvironments[venvName]["path"])) 453 self.tr("{0} - {1}").format(
454 venvName, self.__virtualEnvironments[venvName]["path"]
455 )
456 )
421 if venvMessages: 457 if venvMessages:
422 from UI.DeleteFilesConfirmationDialog import ( 458 from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog
423 DeleteFilesConfirmationDialog 459
424 )
425 dlg = DeleteFilesConfirmationDialog( 460 dlg = DeleteFilesConfirmationDialog(
426 None, 461 None,
427 self.tr("Delete Virtual Environments"), 462 self.tr("Delete Virtual Environments"),
428 self.tr("""Do you really want to delete these virtual""" 463 self.tr(
429 """ environments?"""), 464 """Do you really want to delete these virtual"""
430 venvMessages 465 """ environments?"""
466 ),
467 venvMessages,
431 ) 468 )
432 if dlg.exec() == QDialog.DialogCode.Accepted: 469 if dlg.exec() == QDialog.DialogCode.Accepted:
433 for venvName in venvNames: 470 for venvName in venvNames:
434 if self.__isEnvironmentDeleteable(venvName): 471 if self.__isEnvironmentDeleteable(venvName):
435 if self.isCondaEnvironment(venvName): 472 if self.isCondaEnvironment(venvName):
438 res = conda.removeCondaEnvironment(prefix=path) 475 res = conda.removeCondaEnvironment(prefix=path)
439 if res: 476 if res:
440 del self.__virtualEnvironments[venvName] 477 del self.__virtualEnvironments[venvName]
441 else: 478 else:
442 shutil.rmtree( 479 shutil.rmtree(
443 self.__virtualEnvironments[venvName]["path"], 480 self.__virtualEnvironments[venvName]["path"], True
444 True) 481 )
445 del self.__virtualEnvironments[venvName] 482 del self.__virtualEnvironments[venvName]
446 483
447 self.__saveSettings() 484 self.__saveSettings()
448 485
449 self.virtualEnvironmentRemoved.emit() 486 self.virtualEnvironmentRemoved.emit()
450 self.virtualEnvironmentsListChanged.emit() 487 self.virtualEnvironmentsListChanged.emit()
451 488
452 def __isEnvironmentDeleteable(self, venvName): 489 def __isEnvironmentDeleteable(self, venvName):
453 """ 490 """
454 Private method to check, if a virtual environment can be deleted from 491 Private method to check, if a virtual environment can be deleted from
455 disk. 492 disk.
456 493
457 @param venvName name of the virtual environment 494 @param venvName name of the virtual environment
458 @type str 495 @type str
459 @return flag indicating it can be deleted 496 @return flag indicating it can be deleted
460 @rtype bool 497 @rtype bool
461 """ 498 """
463 if venvName in self.__virtualEnvironments: 500 if venvName in self.__virtualEnvironments:
464 ok = True 501 ok = True
465 ok &= bool(self.__virtualEnvironments[venvName]["path"]) 502 ok &= bool(self.__virtualEnvironments[venvName]["path"])
466 ok &= not self.__virtualEnvironments[venvName]["is_global"] 503 ok &= not self.__virtualEnvironments[venvName]["is_global"]
467 ok &= not self.__virtualEnvironments[venvName]["is_remote"] 504 ok &= not self.__virtualEnvironments[venvName]["is_remote"]
468 ok &= os.access(self.__virtualEnvironments[venvName]["path"], 505 ok &= os.access(self.__virtualEnvironments[venvName]["path"], os.W_OK)
469 os.W_OK) 506
470
471 return ok 507 return ok
472 508
473 def removeVirtualEnvs(self, venvNames): 509 def removeVirtualEnvs(self, venvNames):
474 """ 510 """
475 Public method to delete virtual environment from the list. 511 Public method to delete virtual environment from the list.
476 512
477 @param venvNames list of logical names for the virtual environments 513 @param venvNames list of logical names for the virtual environments
478 @type list of str 514 @type list of str
479 """ 515 """
480 venvMessages = [] 516 venvMessages = []
481 for venvName in venvNames: 517 for venvName in venvNames:
482 if venvName in self.__virtualEnvironments: 518 if venvName in self.__virtualEnvironments:
483 venvMessages.append(self.tr("{0} - {1}").format( 519 venvMessages.append(
484 venvName, self.__virtualEnvironments[venvName]["path"])) 520 self.tr("{0} - {1}").format(
521 venvName, self.__virtualEnvironments[venvName]["path"]
522 )
523 )
485 if venvMessages: 524 if venvMessages:
486 from UI.DeleteFilesConfirmationDialog import ( 525 from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog
487 DeleteFilesConfirmationDialog 526
488 )
489 dlg = DeleteFilesConfirmationDialog( 527 dlg = DeleteFilesConfirmationDialog(
490 None, 528 None,
491 self.tr("Remove Virtual Environments"), 529 self.tr("Remove Virtual Environments"),
492 self.tr("""Do you really want to remove these virtual""" 530 self.tr(
493 """ environments?"""), 531 """Do you really want to remove these virtual"""
494 venvMessages 532 """ environments?"""
533 ),
534 venvMessages,
495 ) 535 )
496 if dlg.exec() == QDialog.DialogCode.Accepted: 536 if dlg.exec() == QDialog.DialogCode.Accepted:
497 for venvName in venvNames: 537 for venvName in venvNames:
498 if venvName in self.__virtualEnvironments: 538 if venvName in self.__virtualEnvironments:
499 del self.__virtualEnvironments[venvName] 539 del self.__virtualEnvironments[venvName]
500 540
501 self.__saveSettings() 541 self.__saveSettings()
502 542
503 self.virtualEnvironmentRemoved.emit() 543 self.virtualEnvironmentRemoved.emit()
504 self.virtualEnvironmentsListChanged.emit() 544 self.virtualEnvironmentsListChanged.emit()
505 545
506 def getEnvironmentEntries(self): 546 def getEnvironmentEntries(self):
507 """ 547 """
508 Public method to get a dictionary containing the defined virtual 548 Public method to get a dictionary containing the defined virtual
509 environment entries. 549 environment entries.
510 550
511 @return dictionary containing a copy of the defined virtual 551 @return dictionary containing a copy of the defined virtual
512 environments 552 environments
513 @rtype dict 553 @rtype dict
514 """ 554 """
515 return copy.deepcopy(self.__virtualEnvironments) 555 return copy.deepcopy(self.__virtualEnvironments)
516 556
517 @pyqtSlot() 557 @pyqtSlot()
518 def showVirtualenvManagerDialog(self, modal=False): 558 def showVirtualenvManagerDialog(self, modal=False):
519 """ 559 """
520 Public slot to show the virtual environment manager dialog. 560 Public slot to show the virtual environment manager dialog.
521 561
522 @param modal flag indicating that the dialog should be shown in 562 @param modal flag indicating that the dialog should be shown in
523 a blocking mode 563 a blocking mode
524 """ 564 """
525 if modal: 565 if modal:
526 from .VirtualenvManagerWidgets import VirtualenvManagerDialog 566 from .VirtualenvManagerWidgets import VirtualenvManagerDialog
527 virtualenvManagerDialog = VirtualenvManagerDialog( 567
528 self, self.__ui) 568 virtualenvManagerDialog = VirtualenvManagerDialog(self, self.__ui)
529 virtualenvManagerDialog.exec() 569 virtualenvManagerDialog.exec()
530 self.virtualEnvironmentsListChanged.emit() 570 self.virtualEnvironmentsListChanged.emit()
531 else: 571 else:
532 self.__ui.activateVirtualenvManager() 572 self.__ui.activateVirtualenvManager()
533 573
534 def isUnique(self, venvName): 574 def isUnique(self, venvName):
535 """ 575 """
536 Public method to check, if the give logical name is unique. 576 Public method to check, if the give logical name is unique.
537 577
538 @param venvName logical name for the virtual environment 578 @param venvName logical name for the virtual environment
539 @type str 579 @type str
540 @return flag indicating uniqueness 580 @return flag indicating uniqueness
541 @rtype bool 581 @rtype bool
542 """ 582 """
543 return venvName not in self.__virtualEnvironments 583 return venvName not in self.__virtualEnvironments
544 584
545 def getVirtualenvInterpreter(self, venvName): 585 def getVirtualenvInterpreter(self, venvName):
546 """ 586 """
547 Public method to get the interpreter for a virtual environment. 587 Public method to get the interpreter for a virtual environment.
548 588
549 @param venvName logical name for the virtual environment 589 @param venvName logical name for the virtual environment
550 @type str 590 @type str
551 @return interpreter path 591 @return interpreter path
552 @rtype str 592 @rtype str
553 """ 593 """
554 if venvName in self.__virtualEnvironments: 594 if venvName in self.__virtualEnvironments:
555 return ( 595 return self.__virtualEnvironments[venvName]["interpreter"].replace(
556 self.__virtualEnvironments[venvName]["interpreter"] 596 "w.exe", ".exe"
557 .replace("w.exe", ".exe")
558 ) 597 )
559 else: 598 else:
560 return "" 599 return ""
561 600
562 def setVirtualEnvInterpreter(self, venvName, venvInterpreter): 601 def setVirtualEnvInterpreter(self, venvName, venvInterpreter):
563 """ 602 """
564 Public method to change the interpreter for a virtual environment. 603 Public method to change the interpreter for a virtual environment.
565 604
566 @param venvName logical name for the virtual environment 605 @param venvName logical name for the virtual environment
567 @type str 606 @type str
568 @param venvInterpreter interpreter path to be set 607 @param venvInterpreter interpreter path to be set
569 @type str 608 @type str
570 """ 609 """
571 if venvName in self.__virtualEnvironments: 610 if venvName in self.__virtualEnvironments:
572 self.__virtualEnvironments[venvName]["interpreter"] = ( 611 self.__virtualEnvironments[venvName]["interpreter"] = venvInterpreter
573 venvInterpreter
574 )
575 self.__saveSettings() 612 self.__saveSettings()
576 613
577 self.virtualEnvironmentChanged.emit(venvName) 614 self.virtualEnvironmentChanged.emit(venvName)
578 self.virtualEnvironmentsListChanged.emit() 615 self.virtualEnvironmentsListChanged.emit()
579 616
580 def getVirtualenvDirectory(self, venvName): 617 def getVirtualenvDirectory(self, venvName):
581 """ 618 """
582 Public method to get the directory of a virtual environment. 619 Public method to get the directory of a virtual environment.
583 620
584 @param venvName logical name for the virtual environment 621 @param venvName logical name for the virtual environment
585 @type str 622 @type str
586 @return directory path 623 @return directory path
587 @rtype str 624 @rtype str
588 """ 625 """
589 if venvName in self.__virtualEnvironments: 626 if venvName in self.__virtualEnvironments:
590 return self.__virtualEnvironments[venvName]["path"] 627 return self.__virtualEnvironments[venvName]["path"]
591 else: 628 else:
592 return "" 629 return ""
593 630
594 def getVirtualenvNames(self, noRemote=False, noConda=False): 631 def getVirtualenvNames(self, noRemote=False, noConda=False):
595 """ 632 """
596 Public method to get a list of defined virtual environments. 633 Public method to get a list of defined virtual environments.
597 634
598 @param noRemote flag indicating to exclude environments for remote 635 @param noRemote flag indicating to exclude environments for remote
599 debugging 636 debugging
600 @type bool 637 @type bool
601 @param noConda flag indicating to exclude Conda environments 638 @param noConda flag indicating to exclude Conda environments
602 @type bool 639 @type bool
603 @return list of defined virtual environments 640 @return list of defined virtual environments
604 @rtype list of str 641 @rtype list of str
605 """ 642 """
606 environments = list(self.__virtualEnvironments.keys()) 643 environments = list(self.__virtualEnvironments.keys())
607 if noRemote: 644 if noRemote:
608 environments = [name for name in environments 645 environments = [
609 if not self.isRemoteEnvironment(name)] 646 name for name in environments if not self.isRemoteEnvironment(name)
647 ]
610 if noConda: 648 if noConda:
611 environments = [name for name in environments 649 environments = [
612 if not self.isCondaEnvironment(name)] 650 name for name in environments if not self.isCondaEnvironment(name)
613 651 ]
652
614 return environments 653 return environments
615 654
616 def isGlobalEnvironment(self, venvName): 655 def isGlobalEnvironment(self, venvName):
617 """ 656 """
618 Public method to test, if a given environment is a global one. 657 Public method to test, if a given environment is a global one.
619 658
620 @param venvName logical name of the virtual environment 659 @param venvName logical name of the virtual environment
621 @type str 660 @type str
622 @return flag indicating a global environment 661 @return flag indicating a global environment
623 @rtype bool 662 @rtype bool
624 """ 663 """
625 if venvName in self.__virtualEnvironments: 664 if venvName in self.__virtualEnvironments:
626 return self.__virtualEnvironments[venvName]["is_global"] 665 return self.__virtualEnvironments[venvName]["is_global"]
627 else: 666 else:
628 return False 667 return False
629 668
630 def isCondaEnvironment(self, venvName): 669 def isCondaEnvironment(self, venvName):
631 """ 670 """
632 Public method to test, if a given environment is an Anaconda 671 Public method to test, if a given environment is an Anaconda
633 environment. 672 environment.
634 673
635 @param venvName logical name of the virtual environment 674 @param venvName logical name of the virtual environment
636 @type str 675 @type str
637 @return flag indicating an Anaconda environment 676 @return flag indicating an Anaconda environment
638 @rtype bool 677 @rtype bool
639 """ 678 """
640 if venvName in self.__virtualEnvironments: 679 if venvName in self.__virtualEnvironments:
641 return self.__virtualEnvironments[venvName]["is_conda"] 680 return self.__virtualEnvironments[venvName]["is_conda"]
642 else: 681 else:
643 return False 682 return False
644 683
645 def isRemoteEnvironment(self, venvName): 684 def isRemoteEnvironment(self, venvName):
646 """ 685 """
647 Public method to test, if a given environment is a remotely accessed 686 Public method to test, if a given environment is a remotely accessed
648 environment. 687 environment.
649 688
650 @param venvName logical name of the virtual environment 689 @param venvName logical name of the virtual environment
651 @type str 690 @type str
652 @return flag indicating a remotely accessed environment 691 @return flag indicating a remotely accessed environment
653 @rtype bool 692 @rtype bool
654 """ 693 """
655 if venvName in self.__virtualEnvironments: 694 if venvName in self.__virtualEnvironments:
656 return self.__virtualEnvironments[venvName]["is_remote"] 695 return self.__virtualEnvironments[venvName]["is_remote"]
657 else: 696 else:
658 return False 697 return False
659 698
660 def getVirtualenvExecPath(self, venvName): 699 def getVirtualenvExecPath(self, venvName):
661 """ 700 """
662 Public method to get the search path prefix of a virtual environment. 701 Public method to get the search path prefix of a virtual environment.
663 702
664 @param venvName logical name for the virtual environment 703 @param venvName logical name for the virtual environment
665 @type str 704 @type str
666 @return search path prefix 705 @return search path prefix
667 @rtype str 706 @rtype str
668 """ 707 """
669 if venvName in self.__virtualEnvironments: 708 if venvName in self.__virtualEnvironments:
670 return self.__virtualEnvironments[venvName]["exec_path"] 709 return self.__virtualEnvironments[venvName]["exec_path"]
671 else: 710 else:
672 return "" 711 return ""
673 712
674 def setVirtualEnvironmentsBaseDir(self, baseDir): 713 def setVirtualEnvironmentsBaseDir(self, baseDir):
675 """ 714 """
676 Public method to set the base directory for the virtual environments. 715 Public method to set the base directory for the virtual environments.
677 716
678 @param baseDir base directory for the virtual environments 717 @param baseDir base directory for the virtual environments
679 @type str 718 @type str
680 """ 719 """
681 self.__virtualEnvironmentsBaseDir = baseDir 720 self.__virtualEnvironmentsBaseDir = baseDir
682 self.__saveSettings() 721 self.__saveSettings()
683 722
684 def getVirtualEnvironmentsBaseDir(self): 723 def getVirtualEnvironmentsBaseDir(self):
685 """ 724 """
686 Public method to set the base directory for the virtual environments. 725 Public method to set the base directory for the virtual environments.
687 726
688 @return base directory for the virtual environments 727 @return base directory for the virtual environments
689 @rtype str 728 @rtype str
690 """ 729 """
691 return self.__virtualEnvironmentsBaseDir 730 return self.__virtualEnvironmentsBaseDir

eric ide

mercurial