diff -r 82f08c4fd930 -r 135240382a3e eric7/VirtualEnv/VirtualenvUpgradeConfigurationDialog.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/eric7/VirtualEnv/VirtualenvUpgradeConfigurationDialog.py Fri Jun 10 18:13:47 2022 +0200 @@ -0,0 +1,157 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2022 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to enter the virtual environment upgrade +parameters. +""" + +import re + +from PyQt6.QtCore import pyqtSlot, QProcess, QTimer +from PyQt6.QtWidgets import QDialog, QDialogButtonBox + +from EricWidgets.EricPathPicker import EricPathPickerModes + +from .Ui_VirtualenvUpgradeConfigurationDialog import ( + Ui_VirtualenvUpgradeConfigurationDialog +) + +import Globals +import Preferences +import Utilities + + +class VirtualenvUpgradeConfigurationDialog( + QDialog, Ui_VirtualenvUpgradeConfigurationDialog +): + """ + Class implementing a dialog to enter the virtual environment upgrade + parameters. + """ + def __init__(self, envName, envPath, parent=None): + """ + Constructor + + @param envName name of the environment to be upgraded + @type str + @param envPath directory of the environment to be upgraded + @type str + @param parent reference to the parent widget (defaults to None) + @type QWidget (optional) + """ + super().__init__(parent) + self.setupUi(self) + + self.pythonExecPicker.setMode(EricPathPickerModes.OPEN_FILE_MODE) + self.pythonExecPicker.setWindowTitle( + self.tr("Python Interpreter")) + self.pythonExecPicker.setDefaultDirectory( + Globals.getPythonExecutable()) + + self.envNameLabel.setText(envName) + self.envDirectoryLabel.setText(envPath) + + self.__versionRe = re.compile(r""".*?(\d+\.\d+\.\d+).*""") + + self.upgradePythonCheckBox.toggled.connect(self.__updateOkButton) + self.upgradeDepsCheckBox.toggled.connect(self.__updateOkButton) + self.pythonExecPicker.textChanged.connect( + self.__updateUpgradeDepsCheckBox) + + self.__updateUpgradeDepsCheckBox() + + msh = self.minimumSizeHint() + self.resize(max(self.width(), msh.width()), msh.height()) + + def __getPyvenvVersion(self): + """ + Private method to determine the version of the venv module. + + @return tuple containing the venv modules version + @rtype tuple of (int, int, int) + """ + calls = [] + if self.pythonExecPicker.text(): + calls.append((self.pythonExecPicker.text(), + ["-m", "venv"])) + calls.extend([ + (Globals.getPythonExecutable(), ["-m", "venv"]), + ("python3", ["-m", "venv"]), + ("python", ["-m", "venv"]), + ]) + + proc = QProcess() + for prog, args in calls: + proc.start(prog, args) + + if not proc.waitForStarted(5000): + # try next entry + continue + + if not proc.waitForFinished(5000): + # process hangs, kill it and try next entry + QTimer.singleShot(2000, proc.kill) + proc.waitForFinished(3000) + continue + + if proc.exitCode() not in [0, 2]: + # returned with error code, try next + continue + + proc.start(prog, ["--version"]) + proc.waitForFinished(5000) + output = str(proc.readAllStandardOutput(), + Preferences.getSystem("IOEncoding"), + 'replace').strip() + match = re.match(self.__versionRe, output) + if match: + return Globals.versionToTuple(match.group(1)) + + return (0, 0, 0) # dummy version tuple + + @pyqtSlot() + def __updateUpgradeDepsCheckBox(self): + """ + Private slot to set the enabled state of the button depending + on the version of the given Python interpreter. + """ + pyvenvVersion = self.__getPyvenvVersion() + if pyvenvVersion >= (3, 9, 0): + self.upgradeDepsCheckBox.setEnabled(True) + else: + self.upgradeDepsCheckBox.setEnabled(False) + self.upgradeDepsCheckBox.setChecked(False) + + @pyqtSlot() + def __updateOkButton(self): + """ + Private slot to set the enabled state of the OK button. + """ + self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setEnabled( + self.upgradePythonCheckBox.isChecked() or + self.upgradeDepsCheckBox.isChecked() + ) + + def getData(self): + """ + Public method to retrieve the dialog data. + + @return tuple containing the selected python executable, the list of + arguments and a flag indicating to write a log file + @rtype tuple of (str, list of str, bool) + """ + args = ["-m", "venv"] + if self.upgradePythonCheckBox.isChecked(): + args.append("--upgrade") + if self.upgradeDepsCheckBox.isChecked(): + args.append("--upgrade-deps") + args.append(self.envDirectoryLabel.text()) + + return ( + Utilities.toNativeSeparators(self.pythonExecPicker.text()), + args, + self.logCheckBox.isChecked(), + )