src/eric7/VirtualEnv/VirtualenvAddEditDialog.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 9016
6f079c524e99
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2018 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to enter the data of a virtual environment.
8 """
9
10 import os
11
12 from PyQt6.QtCore import pyqtSlot, Qt
13 from PyQt6.QtWidgets import QDialog, QDialogButtonBox
14
15 from EricWidgets.EricPathPicker import EricPathPickerModes
16
17 from .Ui_VirtualenvAddEditDialog import Ui_VirtualenvAddEditDialog
18
19 import Globals
20 import Utilities
21
22
23 class VirtualenvAddEditDialog(QDialog, Ui_VirtualenvAddEditDialog):
24 """
25 Class implementing a dialog to enter the data of a virtual environment.
26 """
27 def __init__(self, manager, venvName="", venvDirectory="",
28 venvInterpreter="", isGlobal=False, isConda=False,
29 isRemote=False, execPath="", baseDir="", parent=None):
30 """
31 Constructor
32
33 @param manager reference to the virtual environment manager
34 @type VirtualenvManager
35 @param venvName logical name of a virtual environment for editing
36 @type str
37 @param venvDirectory directory of the virtual environment
38 @type str
39 @param venvInterpreter Python interpreter of the virtual environment
40 @type str
41 @param isGlobal flag indicating a global environment
42 @type bool
43 @param isConda flag indicating an Anaconda virtual environment
44 @type bool
45 @param isRemote flag indicating a remotely accessed environment
46 @type bool
47 @param execPath search path string to be prepended to the PATH
48 environment variable
49 @type str
50 @param baseDir base directory for the virtual environments
51 @type str
52 @param parent reference to the parent widget
53 @type QWidget
54 """
55 super().__init__(parent)
56 self.setupUi(self)
57
58 self.__venvName = venvName
59 self.__manager = manager
60 self.__editMode = bool(venvName)
61
62 if self.__editMode:
63 self.setWindowTitle(self.tr("Edit Virtual Environment"))
64 else:
65 self.setWindowTitle(self.tr("Add Virtual Environment"))
66
67 self.__envBaseDir = baseDir
68 if not self.__envBaseDir:
69 self.__envBaseDir = Utilities.getHomeDir()
70
71 self.targetDirectoryPicker.setMode(EricPathPickerModes.DIRECTORY_MODE)
72 self.targetDirectoryPicker.setWindowTitle(
73 self.tr("Virtualenv Target Directory"))
74 self.targetDirectoryPicker.setDefaultDirectory(self.__envBaseDir)
75
76 self.pythonExecPicker.setMode(EricPathPickerModes.OPEN_FILE_MODE)
77 self.pythonExecPicker.setWindowTitle(
78 self.tr("Python Interpreter"))
79 self.pythonExecPicker.setDefaultDirectory(
80 Globals.getPythonExecutable())
81
82 self.execPathEdit.setToolTip(self.tr(
83 "Enter the executable search path to be prepended to the PATH"
84 " environment variable. Use '{0}' as the separator.").format(
85 os.pathsep)
86 )
87
88 self.nameEdit.setText(venvName)
89 if venvDirectory:
90 self.targetDirectoryPicker.setText(venvDirectory,
91 toNative=not isRemote)
92 else:
93 self.targetDirectoryPicker.setText(self.__envBaseDir,
94 toNative=not isRemote)
95 if not venvInterpreter and venvDirectory and not isRemote:
96 py = self.__detectPythonInterpreter(venvDirectory)
97 self.pythonExecPicker.setText(py)
98 else:
99 self.pythonExecPicker.setText(venvInterpreter,
100 toNative=not isRemote)
101
102 self.globalCheckBox.setChecked(isGlobal)
103 self.anacondaCheckBox.setChecked(isConda)
104 self.remoteCheckBox.setChecked(isRemote)
105 self.execPathEdit.setText(execPath)
106
107 self.__updateOk()
108
109 self.nameEdit.setFocus(Qt.FocusReason.OtherFocusReason)
110
111 def __updateOk(self):
112 """
113 Private slot to update the state of the OK button.
114 """
115 enable = (
116 (bool(self.nameEdit.text()) and
117 (self.nameEdit.text() == self.__venvName or
118 self.__manager.isUnique(self.nameEdit.text())))
119 if self.__editMode else
120 (bool(self.nameEdit.text()) and
121 self.__manager.isUnique(self.nameEdit.text()))
122 )
123
124 if not self.globalCheckBox.isChecked():
125 enable &= (
126 self.remoteCheckBox.isChecked() or (
127 bool(self.targetDirectoryPicker.text()) and
128 self.targetDirectoryPicker.text() != self.__envBaseDir and
129 os.path.exists(self.targetDirectoryPicker.text())
130 )
131 )
132
133 enable = (
134 enable and
135 bool(self.pythonExecPicker.text()) and (
136 self.remoteCheckBox.isChecked() or
137 os.access(self.pythonExecPicker.text(), os.X_OK)
138 )
139 )
140
141 self.buttonBox.button(
142 QDialogButtonBox.StandardButton.Ok).setEnabled(enable)
143
144 def __detectPythonInterpreter(self, venvDirectory):
145 """
146 Private method to search for a suitable Python interpreter inside an
147 environment.
148
149 @param venvDirectory directory for the virtual environment
150 @type str
151 @return detected Python interpreter or empty string
152 @rtype str
153 """
154 if venvDirectory:
155 # try to determine a Python interpreter name
156 if Utilities.isWindowsPlatform():
157 candidates = (
158 os.path.join(venvDirectory, "Scripts", "python.exe"),
159 os.path.join(venvDirectory, "python.exe"),
160 )
161 else:
162 candidates = (
163 os.path.join(venvDirectory, "bin", "python3"),
164 )
165 for py in candidates:
166 if os.path.exists(py):
167 return py
168
169 return ""
170
171 @pyqtSlot(str)
172 def on_nameEdit_textChanged(self, txt):
173 """
174 Private slot to handle changes of the logical name.
175
176 @param txt current logical name
177 @type str
178 """
179 self.__updateOk()
180
181 @pyqtSlot(str)
182 def on_targetDirectoryPicker_textChanged(self, txt):
183 """
184 Private slot to handle changes of the virtual environment directory.
185
186 @param txt virtual environment directory
187 @type str
188 """
189 self.__updateOk()
190
191 if txt:
192 self.pythonExecPicker.setDefaultDirectory(txt)
193 else:
194 self.pythonExecPicker.setDefaultDirectory(
195 Globals.getPythonExecutable())
196 py = self.__detectPythonInterpreter(txt)
197 if py:
198 self.pythonExecPicker.setText(py)
199
200 @pyqtSlot(str)
201 def on_pythonExecPicker_textChanged(self, txt):
202 """
203 Private slot to handle changes of the virtual environment interpreter.
204
205 @param txt virtual environment interpreter
206 @type str
207 """
208 self.__updateOk()
209
210 @pyqtSlot(bool)
211 def on_globalCheckBox_toggled(self, checked):
212 """
213 Private slot handling a change of the global check box state.
214
215 @param checked state of the check box
216 @type bool
217 """
218 self.__updateOk()
219
220 @pyqtSlot(bool)
221 def on_remoteCheckBox_toggled(self, checked):
222 """
223 Private slot handling a change of the remote check box state.
224
225 @param checked state of the check box
226 @type bool
227 """
228 self.__updateOk()
229
230 @pyqtSlot(bool)
231 def on_anacondaCheckBox_clicked(self, checked):
232 """
233 Private slot handling a user click on this check box.
234
235 @param checked state of the check box
236 @type bool
237 """
238 if checked and not bool(self.execPathEdit.text()):
239 # prepopulate the execPathEdit widget
240 if Utilities.isWindowsPlatform():
241 self.execPathEdit.setText(os.pathsep.join([
242 self.targetDirectoryPicker.text(),
243 os.path.join(self.targetDirectoryPicker.text(),
244 "Scripts"),
245 os.path.join(self.targetDirectoryPicker.text(),
246 "Library", "bin"),
247 ]))
248 else:
249 self.execPathEdit.setText(
250 os.path.join(self.targetDirectoryPicker.text(),
251 "bin"),
252 )
253
254 def getData(self):
255 """
256 Public method to retrieve the entered data.
257
258 @return tuple containing the logical name, the directory, the
259 interpreter of the virtual environment, a flag indicating a
260 global environment, a flag indicating an Anaconda environment,
261 a flag indicating a remotely accessed environment and a string
262 to be prepended to the PATH environment variable
263 @rtype tuple of (str, str, str, bool, bool, bool, str)
264 """
265 nativePaths = not self.remoteCheckBox.isChecked()
266 return (
267 self.nameEdit.text(),
268 self.targetDirectoryPicker.text(toNative=nativePaths),
269 self.pythonExecPicker.text(toNative=nativePaths),
270 self.globalCheckBox.isChecked(),
271 self.anacondaCheckBox.isChecked(),
272 self.remoteCheckBox.isChecked(),
273 self.execPathEdit.text(),
274 )

eric ide

mercurial