59 |
58 |
60 self.pythonExecPicker.setMode(EricPathPickerModes.OPEN_FILE_MODE) |
59 self.pythonExecPicker.setMode(EricPathPickerModes.OPEN_FILE_MODE) |
61 self.pythonExecPicker.setWindowTitle(self.tr("Python Interpreter")) |
60 self.pythonExecPicker.setWindowTitle(self.tr("Python Interpreter")) |
62 self.pythonExecPicker.setDefaultDirectory(PythonUtilities.getPythonExecutable()) |
61 self.pythonExecPicker.setDefaultDirectory(PythonUtilities.getPythonExecutable()) |
63 |
62 |
64 self.condaTargetDirectoryPicker.setMode(EricPathPickerModes.DIRECTORY_MODE) |
63 self.versionComboBox.addItems(["", "3.13", "3.12", "3.11", "3.10", "3.9"]) |
65 self.condaTargetDirectoryPicker.setWindowTitle( |
|
66 self.tr("Conda Environment Location") |
|
67 ) |
|
68 self.condaTargetDirectoryPicker.setDefaultDirectory(os.path.expanduser("~")) |
|
69 |
|
70 self.condaCloneDirectoryPicker.setMode(EricPathPickerModes.DIRECTORY_MODE) |
|
71 self.condaCloneDirectoryPicker.setWindowTitle( |
|
72 self.tr("Conda Environment Location") |
|
73 ) |
|
74 self.condaCloneDirectoryPicker.setDefaultDirectory(os.path.expanduser("~")) |
|
75 |
|
76 self.condaRequirementsFilePicker.setMode(EricPathPickerModes.OPEN_FILE_MODE) |
|
77 self.condaRequirementsFilePicker.setWindowTitle( |
|
78 self.tr("Conda Requirements File") |
|
79 ) |
|
80 self.condaRequirementsFilePicker.setDefaultDirectory(os.path.expanduser("~")) |
|
81 self.condaRequirementsFilePicker.setFilters( |
|
82 self.tr("Text Files (*.txt);;All Files (*)") |
|
83 ) |
|
84 |
64 |
85 self.__versionRe = re.compile(r""".*?(\d+\.\d+\.\d+).*""") |
65 self.__versionRe = re.compile(r""".*?(\d+\.\d+\.\d+).*""") |
86 |
66 |
87 self.__virtualenvFound = False |
67 self.__virtualenvFound = False |
88 self.__pyvenvFound = False |
68 self.__pyvenvFound = False |
89 self.__condaFound = False |
|
90 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(False) |
69 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(False) |
91 |
70 |
92 self.__mandatoryStyleSheet = ( |
71 self.__mandatoryStyleSheet = ( |
93 "QLineEdit {border: 2px solid; border-color: #dd8888}" |
72 "QLineEdit {border: 2px solid; border-color: #dd8888}" |
94 if ericApp().usesDarkPalette() |
73 if ericApp().usesDarkPalette() |
95 else "QLineEdit {border: 2px solid; border-color: #800000}" |
74 else "QLineEdit {border: 2px solid; border-color: #800000}" |
96 ) |
75 ) |
97 self.targetDirectoryPicker.setStyleSheet(self.__mandatoryStyleSheet) |
76 self.targetDirectoryPicker.setStyleSheet(self.__mandatoryStyleSheet) |
98 self.nameEdit.setStyleSheet(self.__mandatoryStyleSheet) |
77 self.nameEdit.setStyleSheet(self.__mandatoryStyleSheet) |
99 self.condaTargetDirectoryPicker.setStyleSheet(self.__mandatoryStyleSheet) |
|
100 self.condaNameEdit.setStyleSheet(self.__mandatoryStyleSheet) |
|
101 |
78 |
102 self.__setVirtualenvVersion() |
79 self.__setVirtualenvVersion() |
103 self.__setPyvenvVersion() |
80 self.__setPyvenvVersion() |
104 self.__setCondaVersion() |
|
105 if self.__pyvenvFound: |
81 if self.__pyvenvFound: |
106 self.pyvenvButton.setChecked(True) |
82 self.pyvenvButton.setChecked(True) |
107 elif self.__virtualenvFound: |
83 elif self.__virtualenvFound: |
108 self.virtualenvButton.setChecked(True) |
84 self.virtualenvButton.setChecked(True) |
109 elif self.__condaFound: |
85 |
110 self.condaButton.setChecked(True) |
86 self.nameEdit.textChanged.connect(self.__updateOK) |
111 |
87 self.targetDirectoryPicker.textChanged.connect(self.__updateOK) |
112 self.condaInsecureCheckBox.setEnabled( |
88 self.virtualenvButton.toggled.connect(self.__updateUi) |
113 CondaInterface.condaVersion() >= (4, 3, 18) |
89 self.pyvenvButton.toggled.connect(self.__updateUi) |
114 ) |
|
115 |
90 |
116 msh = self.minimumSizeHint() |
91 msh = self.minimumSizeHint() |
117 self.resize(max(self.width(), msh.width()), msh.height()) |
92 self.resize(max(self.width(), msh.width()), msh.height()) |
118 |
93 |
|
94 @pyqtSlot() |
119 def __updateOK(self): |
95 def __updateOK(self): |
120 """ |
96 """ |
121 Private method to update the enabled status of the OK button. |
97 Private slot to update the enabled status of the OK button. |
122 """ |
98 """ |
123 if self.virtualenvButton.isChecked() or self.pyvenvButton.isChecked(): |
99 if self.virtualenvButton.isChecked() or self.pyvenvButton.isChecked(): |
124 enable = ( |
100 enable = ( |
125 (self.__virtualenvFound or self.__pyvenvFound) |
101 (self.__virtualenvFound or self.__pyvenvFound) |
126 and bool(self.targetDirectoryPicker.text()) |
102 and bool(self.targetDirectoryPicker.text()) |
127 and bool(self.nameEdit.text()) |
103 and bool(self.nameEdit.text()) |
128 ) |
104 ) |
129 enable &= self.targetDirectoryPicker.text() != self.__envBaseDir |
105 enable &= self.targetDirectoryPicker.text() != self.__envBaseDir |
130 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(enable) |
106 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(enable) |
131 elif self.condaButton.isChecked(): |
|
132 enable = bool(self.condaNameEdit.text()) or bool( |
|
133 self.condaTargetDirectoryPicker.text() |
|
134 ) |
|
135 if self.condaSpecialsGroup.isChecked(): |
|
136 if self.condaCloneButton.isChecked(): |
|
137 enable &= bool(self.condaCloneNameEdit.text()) or bool( |
|
138 self.condaCloneDirectoryPicker.text() |
|
139 ) |
|
140 elif self.condaRequirementsButton.isChecked(): |
|
141 enable &= bool(self.condaRequirementsFilePicker.text()) |
|
142 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(enable) |
|
143 else: |
107 else: |
144 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(False) |
108 self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled(False) |
145 |
109 |
|
110 @pyqtSlot() |
146 def __updateUi(self): |
111 def __updateUi(self): |
147 """ |
112 """ |
148 Private method to update the UI depending on the selected |
113 Private slot to update the UI depending on the selected |
149 virtual environment creator (virtualenv or pyvenv). |
114 virtual environment creator (virtualenv or pyvenv). |
150 """ |
115 """ |
151 # venv page |
|
152 enable = self.virtualenvButton.isChecked() |
116 enable = self.virtualenvButton.isChecked() |
153 self.extraSearchPathLabel.setEnabled(enable) |
117 self.extraSearchPathLabel.setEnabled(enable) |
154 self.extraSearchPathPicker.setEnabled(enable) |
118 self.extraSearchPathPicker.setEnabled(enable) |
155 self.promptPrefixLabel.setEnabled(enable) |
119 self.promptPrefixLabel.setEnabled(enable) |
156 self.promptPrefixEdit.setEnabled(enable) |
120 self.promptPrefixEdit.setEnabled(enable) |
157 self.verbosityLabel.setEnabled(enable) |
121 self.verbosityLabel.setEnabled(enable) |
158 self.verbositySpinBox.setEnabled(enable) |
122 self.verbositySpinBox.setEnabled(enable) |
159 self.versionLabel.setEnabled(enable) |
123 self.versionLabel.setEnabled(enable) |
160 self.versionComboBox.setEnabled(enable) |
124 self.versionComboBox.setEnabled(enable) |
161 self.unzipCheckBox.setEnabled(enable) |
125 self.noWheelCheckBox.setEnabled(enable) |
162 self.noSetuptoolsCheckBox.setEnabled(enable) |
126 self.noSetuptoolsCheckBox.setEnabled(enable) |
163 self.symlinkCheckBox.setEnabled(not enable) |
127 self.symlinkCheckBox.setEnabled(not enable) |
164 self.upgradeCheckBox.setEnabled(not enable) |
128 self.upgradeCheckBox.setEnabled(not enable) |
165 |
129 |
166 # conda page |
|
167 enable = not self.condaSpecialsGroup.isChecked() |
|
168 self.condaPackagesEdit.setEnabled(enable) |
|
169 self.condaPythonEdit.setEnabled(enable) |
|
170 self.condaInsecureCheckBox.setEnabled( |
|
171 enable and CondaInterface.condaVersion() >= (4, 3, 18) |
|
172 ) |
|
173 self.condaDryrunCheckBox.setEnabled(enable) |
|
174 |
|
175 # select page |
|
176 if self.condaButton.isChecked(): |
|
177 self.venvStack.setCurrentWidget(self.condaPage) |
|
178 else: |
|
179 self.venvStack.setCurrentWidget(self.venvPage) |
|
180 |
|
181 @pyqtSlot(str) |
|
182 def on_nameEdit_textChanged(self, _txt): |
|
183 """ |
|
184 Private slot handling a change of the virtual environment name. |
|
185 |
|
186 @param _txt name of the virtual environment (unused) |
|
187 @type str |
|
188 """ |
|
189 self.__updateOK() |
|
190 |
|
191 @pyqtSlot(str) |
|
192 def on_targetDirectoryPicker_textChanged(self, _txt): |
|
193 """ |
|
194 Private slot handling a change of the target directory. |
|
195 |
|
196 @param _txt target directory (unused) |
|
197 @type str |
|
198 """ |
|
199 self.__updateOK() |
|
200 |
|
201 @pyqtSlot(str) |
130 @pyqtSlot(str) |
202 def on_pythonExecPicker_textChanged(self, _txt): |
131 def on_pythonExecPicker_textChanged(self, _txt): |
203 """ |
132 """ |
204 Private slot to react to a change of the Python executable. |
133 Private slot to react to a change of the Python executable. |
205 |
134 |
206 @param _txt contents of the picker's line edit (unused) |
135 @param _txt contents of the picker's line edit (unused) |
207 @type str |
136 @type str |
208 """ |
137 """ |
209 self.__setVirtualenvVersion() |
138 self.__setVirtualenvVersion() |
210 self.__setPyvenvVersion() |
139 self.__setPyvenvVersion() |
211 self.__updateOK() |
|
212 |
|
213 @pyqtSlot(bool) |
|
214 def on_virtualenvButton_toggled(self, _checked): |
|
215 """ |
|
216 Private slot to react to the selection of 'virtualenv'. |
|
217 |
|
218 @param _checked state of the checkbox (unused) |
|
219 @type bool |
|
220 """ |
|
221 self.__updateUi() |
|
222 |
|
223 @pyqtSlot(bool) |
|
224 def on_pyvenvButton_toggled(self, _checked): |
|
225 """ |
|
226 Private slot to react to the selection of 'pyvenv'. |
|
227 |
|
228 @param _checked state of the checkbox (unused) |
|
229 @type bool |
|
230 """ |
|
231 self.__updateUi() |
|
232 |
|
233 @pyqtSlot(bool) |
|
234 def on_condaButton_toggled(self, _checked): |
|
235 """ |
|
236 Private slot to react to the selection of 'conda'. |
|
237 |
|
238 @param _checked state of the checkbox (unused) |
|
239 @type bool |
|
240 """ |
|
241 self.__updateUi() |
|
242 |
|
243 @pyqtSlot(str) |
|
244 def on_condaNameEdit_textChanged(self, _txt): |
|
245 """ |
|
246 Private slot handling a change of the conda environment name. |
|
247 |
|
248 @param _txt environment name (unused) |
|
249 @type str |
|
250 """ |
|
251 self.__updateOK() |
|
252 |
|
253 @pyqtSlot(str) |
|
254 def on_condaTargetDirectoryPicker_textChanged(self, _txt): |
|
255 """ |
|
256 Private slot handling a change of the conda target directory. |
|
257 |
|
258 @param _txt target directory (unused) |
|
259 @type str |
|
260 """ |
|
261 self.__updateOK() |
|
262 |
|
263 @pyqtSlot() |
|
264 def on_condaSpecialsGroup_clicked(self): |
|
265 """ |
|
266 Private slot handling the selection of the specials group. |
|
267 """ |
|
268 self.__updateOK() |
|
269 self.__updateUi() |
|
270 |
|
271 @pyqtSlot(str) |
|
272 def on_condaCloneNameEdit_textChanged(self, _txt): |
|
273 """ |
|
274 Private slot handling a change of the conda source environment name. |
|
275 |
|
276 @param _txt name of the environment to be cloned (unused) |
|
277 @type str |
|
278 """ |
|
279 self.__updateOK() |
|
280 |
|
281 @pyqtSlot(str) |
|
282 def on_condaCloneDirectoryPicker_textChanged(self, _txt): |
|
283 """ |
|
284 Private slot handling a change of the cloned from directory. |
|
285 |
|
286 @param _txt target directory (unused) |
|
287 @type str |
|
288 """ |
|
289 self.__updateOK() |
|
290 |
|
291 @pyqtSlot() |
|
292 def on_condaCloneButton_clicked(self): |
|
293 """ |
|
294 Private slot handling the selection of the clone button. |
|
295 """ |
|
296 self.__updateOK() |
|
297 |
|
298 @pyqtSlot() |
|
299 def on_condaRequirementsButton_clicked(self): |
|
300 """ |
|
301 Private slot handling the selection of the requirements button. |
|
302 """ |
|
303 self.__updateOK() |
|
304 |
|
305 @pyqtSlot(str) |
|
306 def on_condaRequirementsFilePicker_textChanged(self, _txt): |
|
307 """ |
|
308 Private slot handling a change of the requirements file entry. |
|
309 |
|
310 @param _txt current text of the requirements file entry (unused) |
|
311 @type str |
|
312 """ |
|
313 self.__updateOK() |
140 self.__updateOK() |
314 |
141 |
315 def __setVirtualenvVersion(self): |
142 def __setVirtualenvVersion(self): |
316 """ |
143 """ |
317 Private method to determine the virtualenv version and set the |
144 Private method to determine the virtualenv version and set the |
461 |
275 |
462 @return process arguments |
276 @return process arguments |
463 @rtype list of str |
277 @rtype list of str |
464 """ |
278 """ |
465 args = [] |
279 args = [] |
466 if self.condaButton.isChecked(): |
280 if self.virtualenvButton.isChecked(): |
467 if bool(self.condaNameEdit.text()): |
281 if self.extraSearchPathPicker.text(): |
468 args.extend(["--name", self.condaNameEdit.text()]) |
282 args.append( |
469 if bool(self.condaTargetDirectoryPicker.text()): |
283 "--extra-search-dir={0}".format(self.extraSearchPathPicker.text()) |
470 args.extend(["--prefix", self.condaTargetDirectoryPicker.text()]) |
284 ) |
471 if self.condaSpecialsGroup.isChecked(): |
285 if self.promptPrefixEdit.text(): |
472 if self.condaCloneButton.isChecked(): |
286 args.append( |
473 if bool(self.condaCloneNameEdit.text()): |
287 "--prompt={0}".format( |
474 args.extend(["--clone", self.condaCloneNameEdit.text()]) |
288 self.promptPrefixEdit.text().replace(" ", "_") |
475 elif bool(self.condaCloneDirectoryPicker.text()): |
|
476 args.extend(["--clone", self.condaCloneDirectoryPicker.text()]) |
|
477 elif self.condaRequirementsButton.isChecked(): |
|
478 args.extend(["--file", self.condaRequirementsFilePicker.text()]) |
|
479 if self.condaInsecureCheckBox.isChecked(): |
|
480 args.append("--insecure") |
|
481 if self.condaDryrunCheckBox.isChecked(): |
|
482 args.append("--dry-run") |
|
483 if not self.condaSpecialsGroup.isChecked(): |
|
484 if bool(self.condaPythonEdit.text()): |
|
485 args.append("python={0}".format(self.condaPythonEdit.text())) |
|
486 if bool(self.condaPackagesEdit.text()): |
|
487 args.extend(self.condaPackagesEdit.text().split()) |
|
488 else: |
|
489 if self.virtualenvButton.isChecked(): |
|
490 if self.extraSearchPathPicker.text(): |
|
491 args.append( |
|
492 "--extra-search-dir={0}".format( |
|
493 self.extraSearchPathPicker.text() |
|
494 ) |
|
495 ) |
289 ) |
496 if self.promptPrefixEdit.text(): |
290 ) |
497 args.append( |
291 if self.pythonExecPicker.text(): |
498 "--prompt={0}".format( |
292 args.append("--python={0}".format(self.pythonExecPicker.text())) |
499 self.promptPrefixEdit.text().replace(" ", "_") |
293 elif self.versionComboBox.currentText(): |
500 ) |
294 args.append( |
501 ) |
295 "--python=python{0}".format(self.versionComboBox.currentText()) |
502 if self.pythonExecPicker.text(): |
296 ) |
503 args.append("--python={0}".format(self.pythonExecPicker.text())) |
297 if self.verbositySpinBox.value() == 1: |
504 elif self.versionComboBox.currentText(): |
298 args.append("--verbose") |
505 args.append( |
299 elif self.verbositySpinBox.value() == -1: |
506 "--python=python{0}".format(self.versionComboBox.currentText()) |
300 args.append("--quiet") |
507 ) |
301 if self.clearCheckBox.isChecked(): |
508 if self.verbositySpinBox.value() == 1: |
302 args.append("--clear") |
509 args.append("--verbose") |
303 if self.systemCheckBox.isChecked(): |
510 elif self.verbositySpinBox.value() == -1: |
304 args.append("--system-site-packages") |
511 args.append("--quiet") |
305 if self.noWheelCheckBox.isChecked(): |
512 if self.clearCheckBox.isChecked(): |
306 args.append("--no-wheel") |
513 args.append("--clear") |
307 if self.noSetuptoolsCheckBox.isChecked(): |
514 if self.systemCheckBox.isChecked(): |
308 args.append("--no-setuptools") |
515 args.append("--system-site-packages") |
309 if self.noPipCcheckBox.isChecked(): |
516 if self.unzipCheckBox.isChecked(): |
310 args.append("--no-pip") |
517 args.append("--unzip-setuptools") |
311 if self.copyCheckBox.isChecked(): |
518 if self.noSetuptoolsCheckBox.isChecked(): |
312 args.append("--always-copy") |
519 args.append("--no-setuptools") |
313 elif self.pyvenvButton.isChecked(): |
520 if self.noPipCcheckBox.isChecked(): |
314 if self.clearCheckBox.isChecked(): |
521 args.append("--no-pip") |
315 args.append("--clear") |
522 if self.copyCheckBox.isChecked(): |
316 if self.systemCheckBox.isChecked(): |
523 args.append("--always-copy") |
317 args.append("--system-site-packages") |
524 elif self.pyvenvButton.isChecked(): |
318 if self.noPipCcheckBox.isChecked(): |
525 if self.clearCheckBox.isChecked(): |
319 args.append("--without-pip") |
526 args.append("--clear") |
320 if self.copyCheckBox.isChecked(): |
527 if self.systemCheckBox.isChecked(): |
321 args.append("--copies") |
528 args.append("--system-site-packages") |
322 if self.symlinkCheckBox.isChecked(): |
529 if self.noPipCcheckBox.isChecked(): |
323 args.append("--symlinks") |
530 args.append("--without-pip") |
324 if self.upgradeCheckBox.isChecked(): |
531 if self.copyCheckBox.isChecked(): |
325 args.append("--upgrade") |
532 args.append("--copies") |
326 targetDirectory = self.__generateTargetDir() |
533 if self.symlinkCheckBox.isChecked(): |
327 args.append(targetDirectory) |
534 args.append("--symlinks") |
|
535 if self.upgradeCheckBox.isChecked(): |
|
536 args.append("--upgrade") |
|
537 targetDirectory = self.__generateTargetDir() |
|
538 args.append(targetDirectory) |
|
539 |
328 |
540 return args |
329 return args |
541 |
330 |
542 def getData(self): |
331 def getData(self): |
543 """ |
332 """ |
544 Public method to retrieve the dialog data. |
333 Public method to retrieve the dialog data. |
545 |
334 |
546 @return dictionary containing the data for the two environment |
335 @return dictionary containing the data for the new environment. The keys |
547 variants. The keys for both variants are 'arguments' containing the |
336 are 'arguments' containing the command line arguments, 'logicalName' |
548 command line arguments, 'logicalName' containing the environment |
337 containing the environment name to be used with the virtual environment |
549 name to be used with the virtual env manager and 'envType' |
338 manager and 'envType' containing the environment type (virtualenv or |
550 containing the environment type (virtualenv, pyvenv or conda). The |
339 pyvenv). Additional keys are 'openTarget' containg a flag to open the |
551 virtualenv/pyvenv specific keys are 'openTarget' containg a flag to |
340 target directory after creation, 'createLog' containing a flag to write |
552 open the target directory after creation, 'createLog' containing a |
341 a log file, 'createScript' containing a flag to write a script, |
553 flag to write a log file, 'createScript' containing a flag to write |
342 'targetDirectory' containing the target directory and 'pythonExe' |
554 a script, 'targetDirectory' containing the target directory and |
343 containing the Python interpreter to be used. |
555 'pythonExe' containing the Python interpreter to be used. The |
|
556 conda specific key is 'command' giving the conda command to be |
|
557 executed (always 'create'). |
|
558 @rtype dict |
344 @rtype dict |
559 """ |
345 """ |
560 args = self.__generateArguments() |
346 return { |
561 resultDict = { |
347 "arguments": self.__generateArguments(), |
562 "arguments": args, |
|
563 "logicalName": self.nameEdit.text(), |
348 "logicalName": self.nameEdit.text(), |
|
349 "envType": "pyvenv" if self.pyvenvButton.isChecked() else "virtualenv", |
|
350 "openTarget": self.openCheckBox.isChecked(), |
|
351 "createLog": self.logCheckBox.isChecked(), |
|
352 "createScript": self.scriptCheckBox.isChecked(), |
|
353 "targetDirectory": self.__generateTargetDir(), |
|
354 "pythonExe": self.pythonExecPicker.text(), |
564 } |
355 } |
565 if self.condaButton.isChecked(): |
|
566 resultDict.update( |
|
567 { |
|
568 "envType": "conda", |
|
569 "command": "create", |
|
570 } |
|
571 ) |
|
572 else: |
|
573 resultDict.update( |
|
574 { |
|
575 "envType": ( |
|
576 "pyvenv" if self.pyvenvButton.isChecked() else "virtualenv" |
|
577 ), |
|
578 "openTarget": self.openCheckBox.isChecked(), |
|
579 "createLog": self.logCheckBox.isChecked(), |
|
580 "createScript": self.scriptCheckBox.isChecked(), |
|
581 "targetDirectory": self.__generateTargetDir(), |
|
582 "pythonExe": self.pythonExecPicker.text(), |
|
583 } |
|
584 ) |
|
585 |
|
586 return resultDict |
|