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