src/eric7/VirtualEnv/VirtualenvUpgradeConfigurationDialog.py

Fri, 04 Nov 2022 13:52:26 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 04 Nov 2022 13:52:26 +0100
branch
eric7
changeset 9473
3f23dbf37dbe
parent 9413
80c06d472826
child 9624
b47dfa7a137d
permissions
-rw-r--r--

Resorted the import statements using isort.

# -*- 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 QProcess, QTimer, pyqtSlot
from PyQt6.QtWidgets import QDialog, QDialogButtonBox

from eric7 import Globals, Preferences, Utilities
from eric7.EricWidgets.EricPathPicker import EricPathPickerModes

from .Ui_VirtualenvUpgradeConfigurationDialog import (
    Ui_VirtualenvUpgradeConfigurationDialog,
)


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(),
        )

eric ide

mercurial