src/eric7/MicroPython/PyBoardDevices.py

branch
eric7
changeset 9756
9854647c8c5c
parent 9755
1a09700229e7
child 9757
ab6e87f6f1c4
diff -r 1a09700229e7 -r 9854647c8c5c src/eric7/MicroPython/PyBoardDevices.py
--- a/src/eric7/MicroPython/PyBoardDevices.py	Sun Feb 12 18:11:20 2023 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,522 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2019 - 2023 Detlev Offenbach <detlev@die-offenbachs.de>
-#
-
-"""
-Module implementing the device interface class for PyBoard boards.
-"""
-
-import os
-
-from PyQt6.QtCore import QStandardPaths, QUrl, pyqtSlot
-from PyQt6.QtNetwork import QNetworkRequest
-from PyQt6.QtWidgets import QMenu
-
-from eric7 import Globals, Preferences
-from eric7.EricWidgets import EricFileDialog, EricMessageBox
-from eric7.EricWidgets.EricApplication import ericApp
-from eric7.EricWidgets.EricProcessDialog import EricProcessDialog
-from eric7.SystemUtilities import FileSystemUtilities
-
-from .MicroPythonDevices import FirmwareGithubUrls, MicroPythonDevice
-from .MicroPythonWidget import HAS_QTCHART
-
-
-class PyBoardDevice(MicroPythonDevice):
-    """
-    Class implementing the device for PyBoard boards.
-    """
-
-    DeviceVolumeName = "PYBFLASH"
-
-    FlashInstructionsURL = (
-        "https://github.com/micropython/micropython/wiki/Pyboard-Firmware-Update"
-    )
-
-    def __init__(self, microPythonWidget, deviceType, parent=None):
-        """
-        Constructor
-
-        @param microPythonWidget reference to the main MicroPython widget
-        @type MicroPythonWidget
-        @param deviceType device type assigned to this device interface
-        @type str
-        @param parent reference to the parent object
-        @type QObject
-        """
-        super().__init__(microPythonWidget, deviceType, parent)
-
-        self.__workspace = self.__findWorkspace()
-
-        self.__createPyboardMenu()
-
-    def setButtons(self):
-        """
-        Public method to enable the supported action buttons.
-        """
-        super().setButtons()
-        self.microPython.setActionButtons(
-            run=True, repl=True, files=True, chart=HAS_QTCHART
-        )
-
-        if self.__deviceVolumeMounted():
-            self.microPython.setActionButtons(open=True, save=True)
-
-    def forceInterrupt(self):
-        """
-        Public method to determine the need for an interrupt when opening the
-        serial connection.
-
-        @return flag indicating an interrupt is needed
-        @rtype bool
-        """
-        return False
-
-    def deviceName(self):
-        """
-        Public method to get the name of the device.
-
-        @return name of the device
-        @rtype str
-        """
-        return self.tr("PyBoard")
-
-    def canStartRepl(self):
-        """
-        Public method to determine, if a REPL can be started.
-
-        @return tuple containing a flag indicating it is safe to start a REPL
-            and a reason why it cannot.
-        @rtype tuple of (bool, str)
-        """
-        return True, ""
-
-    def canStartPlotter(self):
-        """
-        Public method to determine, if a Plotter can be started.
-
-        @return tuple containing a flag indicating it is safe to start a
-            Plotter and a reason why it cannot.
-        @rtype tuple of (bool, str)
-        """
-        return True, ""
-
-    def canRunScript(self):
-        """
-        Public method to determine, if a script can be executed.
-
-        @return tuple containing a flag indicating it is safe to start a
-            Plotter and a reason why it cannot.
-        @rtype tuple of (bool, str)
-        """
-        return True, ""
-
-    def runScript(self, script):
-        """
-        Public method to run the given Python script.
-
-        @param script script to be executed
-        @type str
-        """
-        pythonScript = script.split("\n")
-        self.sendCommands(pythonScript)
-
-    def canStartFileManager(self):
-        """
-        Public method to determine, if a File Manager can be started.
-
-        @return tuple containing a flag indicating it is safe to start a
-            File Manager and a reason why it cannot.
-        @rtype tuple of (bool, str)
-        """
-        return True, ""
-
-    def supportsLocalFileAccess(self):
-        """
-        Public method to indicate file access via a local directory.
-
-        @return flag indicating file access via local directory
-        @rtype bool
-        """
-        return self.__deviceVolumeMounted()
-
-    def __deviceVolumeMounted(self):
-        """
-        Private method to check, if the device volume is mounted.
-
-        @return flag indicated a mounted device
-        @rtype bool
-        """
-        if self.__workspace and not os.path.exists(self.__workspace):
-            self.__workspace = ""  # reset
-
-        return self.DeviceVolumeName in self.getWorkspace(silent=True)
-
-    def getWorkspace(self, silent=False):
-        """
-        Public method to get the workspace directory.
-
-        @param silent flag indicating silent operations
-        @type bool
-        @return workspace directory used for saving files
-        @rtype str
-        """
-        if self.__workspace:
-            # return cached entry
-            return self.__workspace
-        else:
-            self.__workspace = self.__findWorkspace(silent=silent)
-            return self.__workspace
-
-    def __findWorkspace(self, silent=False):
-        """
-        Private method to find the workspace directory.
-
-        @param silent flag indicating silent operations
-        @type bool
-        @return workspace directory used for saving files
-        @rtype str
-        """
-        # Attempts to find the path on the filesystem that represents the
-        # plugged in PyBoard board.
-        deviceDirectories = FileSystemUtilities.findVolume(
-            self.DeviceVolumeName, findAll=True
-        )
-
-        if deviceDirectories:
-            if len(deviceDirectories) == 1:
-                return deviceDirectories[0]
-            else:
-                return self.selectDeviceDirectory(deviceDirectories)
-        else:
-            # return the default workspace and give the user a warning (unless
-            # silent mode is selected)
-            if not silent:
-                EricMessageBox.warning(
-                    self.microPython,
-                    self.tr("Workspace Directory"),
-                    self.tr(
-                        "Python files for PyBoard can be edited in"
-                        " place, if the device volume is locally"
-                        " available. Such a volume was not found. In"
-                        " place editing will not be available."
-                    ),
-                )
-
-            return super().getWorkspace()
-
-    def getDocumentationUrl(self):
-        """
-        Public method to get the device documentation URL.
-
-        @return documentation URL of the device
-        @rtype str
-        """
-        return Preferences.getMicroPython("MicroPythonDocuUrl")
-
-    def getFirmwareUrl(self):
-        """
-        Public method to get the device firmware download URL.
-
-        @return firmware download URL of the device
-        @rtype str
-        """
-        return Preferences.getMicroPython("MicroPythonFirmwareUrl")
-
-    def __createPyboardMenu(self):
-        """
-        Private method to create the pyboard submenu.
-        """
-        self.__pyboardMenu = QMenu(self.tr("PyBoard Functions"))
-
-        self.__showMpyAct = self.__pyboardMenu.addAction(
-            self.tr("Show MicroPython Versions"), self.__showFirmwareVersions
-        )
-        self.__pyboardMenu.addSeparator()
-        self.__bootloaderAct = self.__pyboardMenu.addAction(
-            self.tr("Activate Bootloader"), self.__activateBootloader
-        )
-        self.__dfuAct = self.__pyboardMenu.addAction(
-            self.tr("List DFU-capable Devices"), self.__listDfuCapableDevices
-        )
-        self.__pyboardMenu.addSeparator()
-        self.__flashMpyAct = self.__pyboardMenu.addAction(
-            self.tr("Flash MicroPython Firmware"), self.__flashMicroPython
-        )
-        self.__pyboardMenu.addAction(
-            self.tr("MicroPython Flash Instructions"), self.__showFlashInstructions
-        )
-
-    def addDeviceMenuEntries(self, menu):
-        """
-        Public method to add device specific entries to the given menu.
-
-        @param menu reference to the context menu
-        @type QMenu
-        """
-        connected = self.microPython.isConnected()
-        linkConnected = self.microPython.isLinkConnected()
-
-        self.__bootloaderAct.setEnabled(connected)
-        self.__dfuAct.setEnabled(not linkConnected)
-        self.__showMpyAct.setEnabled(connected)
-        self.__flashMpyAct.setEnabled(not linkConnected)
-
-        menu.addMenu(self.__pyboardMenu)
-
-    def hasFlashMenuEntry(self):
-        """
-        Public method to check, if the device has its own flash menu entry.
-
-        @return flag indicating a specific flash menu entry
-        @rtype bool
-        """
-        return True
-
-    @pyqtSlot()
-    def __showFlashInstructions(self):
-        """
-        Private slot to open the URL containing instructions for installing
-        MicroPython on the pyboard.
-        """
-        ericApp().getObject("UserInterface").launchHelpViewer(
-            PyBoardDevice.FlashInstructionsURL
-        )
-
-    def __dfuUtilAvailable(self):
-        """
-        Private method to check the availability of dfu-util.
-
-        @return flag indicating the availability of dfu-util
-        @rtype bool
-        """
-        available = False
-        program = Preferences.getMicroPython("DfuUtilPath")
-        if not program:
-            program = "dfu-util"
-            if FileSystemUtilities.isinpath(program):
-                available = True
-        else:
-            if FileSystemUtilities.isExecutable(program):
-                available = True
-
-        if not available:
-            EricMessageBox.critical(
-                self.microPython,
-                self.tr("dfu-util not available"),
-                self.tr(
-                    """The dfu-util firmware flashing tool"""
-                    """ <b>dfu-util</b> cannot be found or is not"""
-                    """ executable. Ensure it is in the search path"""
-                    """ or configure it on the MicroPython"""
-                    """ configuration page."""
-                ),
-            )
-
-        return available
-
-    def __showDfuEnableInstructions(self, flash=True):
-        """
-        Private method to show some instructions to enable the DFU mode.
-
-        @param flash flag indicating to show a warning message for flashing
-        @type bool
-        @return flag indicating OK to continue or abort
-        @rtype bool
-        """
-        msg = self.tr(
-            "<h3>Enable DFU Mode</h3>"
-            "<p>1. Disconnect everything from your board</p>"
-            "<p>2. Disconnect your board</p>"
-            "<p>3. Connect the DFU/BOOT0 pin with a 3.3V pin</p>"
-            "<p>4. Re-connect your board</p>"
-            "<hr />"
-        )
-
-        if flash:
-            msg += self.tr(
-                "<p><b>Warning:</b> Make sure that all other DFU capable"
-                " devices except your PyBoard are disconnected."
-                "<hr />"
-            )
-
-        msg += self.tr("<p>Press <b>OK</b> to continue...</p>")
-        res = EricMessageBox.information(
-            self.microPython,
-            self.tr("Enable DFU mode"),
-            msg,
-            EricMessageBox.Abort | EricMessageBox.Ok,
-        )
-
-        return res == EricMessageBox.Ok
-
-    def __showDfuDisableInstructions(self):
-        """
-        Private method to show some instructions to disable the DFU mode.
-        """
-        msg = self.tr(
-            "<h3>Disable DFU Mode</h3>"
-            "<p>1. Disconnect your board</p>"
-            "<p>2. Remove the DFU jumper</p>"
-            "<p>3. Re-connect your board</p>"
-            "<hr />"
-            "<p>Press <b>OK</b> to continue...</p>"
-        )
-        EricMessageBox.information(self.microPython, self.tr("Disable DFU mode"), msg)
-
-    @pyqtSlot()
-    def __listDfuCapableDevices(self):
-        """
-        Private slot to list all DFU-capable devices.
-        """
-        if self.__dfuUtilAvailable():
-            ok2continue = self.__showDfuEnableInstructions(flash=False)
-            if ok2continue:
-                program = Preferences.getMicroPython("DfuUtilPath")
-                if not program:
-                    program = "dfu-util"
-
-                args = [
-                    "--list",
-                ]
-                dlg = EricProcessDialog(
-                    self.tr("'dfu-util' Output"), self.tr("List DFU capable Devices")
-                )
-                res = dlg.startProcess(program, args)
-                if res:
-                    dlg.exec()
-
-    @pyqtSlot()
-    def __flashMicroPython(self):
-        """
-        Private slot to flash a MicroPython firmware.
-        """
-        if self.__dfuUtilAvailable():
-            ok2continue = self.__showDfuEnableInstructions()
-            if ok2continue:
-                program = Preferences.getMicroPython("DfuUtilPath")
-                if not program:
-                    program = "dfu-util"
-
-                downloadsPath = QStandardPaths.standardLocations(
-                    QStandardPaths.StandardLocation.DownloadLocation
-                )[0]
-                firmware = EricFileDialog.getOpenFileName(
-                    self.microPython,
-                    self.tr("Flash MicroPython Firmware"),
-                    downloadsPath,
-                    self.tr("MicroPython Firmware Files (*.dfu);;All Files (*)"),
-                )
-                if firmware and os.path.exists(firmware):
-                    args = [
-                        "--alt",
-                        "0",
-                        "--download",
-                        firmware,
-                    ]
-                    dlg = EricProcessDialog(
-                        self.tr("'dfu-util' Output"),
-                        self.tr("Flash MicroPython Firmware"),
-                    )
-                    res = dlg.startProcess(program, args)
-                    if res:
-                        dlg.exec()
-                        self.__showDfuDisableInstructions()
-
-    @pyqtSlot()
-    def __showFirmwareVersions(self):
-        """
-        Private slot to show the firmware version of the connected device and the
-        available firmware version.
-        """
-        if self.microPython.isConnected():
-            if self._deviceData["mpy_name"] != "micropython":
-                EricMessageBox.critical(
-                    None,
-                    self.tr("Show MicroPython Versions"),
-                    self.tr(
-                        """The firmware of the connected device cannot be"""
-                        """ determined or the board does not run MicroPython."""
-                        """ Aborting..."""
-                    ),
-                )
-            else:
-                ui = ericApp().getObject("UserInterface")
-                request = QNetworkRequest(QUrl(FirmwareGithubUrls["micropython"]))
-                reply = ui.networkAccessManager().head(request)
-                reply.finished.connect(lambda: self.__firmwareVersionResponse(reply))
-
-    def __firmwareVersionResponse(self, reply):
-        """
-        Private method handling the response of the latest version request.
-
-        @param reply reference to the reply object
-        @type QNetworkReply
-        """
-        latestUrl = reply.url().toString()
-        tag = latestUrl.rsplit("/", 1)[-1]
-        while tag and not tag[0].isdecimal():
-            # get rid of leading non-decimal characters
-            tag = tag[1:]
-        latestVersion = Globals.versionToTuple(tag)
-
-        if self._deviceData["mpy_version"] == "unknown":
-            currentVersionStr = self.tr("unknown")
-            currentVersion = (0, 0, 0)
-        else:
-            currentVersionStr = self._deviceData["mpy_version"]
-            currentVersion = Globals.versionToTuple(currentVersionStr)
-
-        msg = self.tr(
-            "<h4>MicroPython Version Information</h4>"
-            "<table>"
-            "<tr><td>Installed:</td><td>{0}</td></tr>"
-            "<tr><td>Available:</td><td>{1}</td></tr>"
-            "</table>"
-        ).format(currentVersionStr, tag)
-        if currentVersion < latestVersion:
-            msg += self.tr("<p><b>Update available!</b></p>")
-
-        EricMessageBox.information(
-            None,
-            self.tr("MicroPython Version"),
-            msg,
-        )
-
-    @pyqtSlot()
-    def __activateBootloader(self):
-        """
-        Private slot to activate the bootloader and disconnect.
-        """
-        if self.microPython.isConnected():
-            self.microPython.commandsInterface().execute(
-                [
-                    "import pyb",
-                    "pyb.bootloader()",
-                ]
-            )
-            # simulate pressing the disconnect button
-            self.microPython.on_connectButton_clicked()
-
-
-def createDevice(microPythonWidget, deviceType, vid, pid, boardName, serialNumber):
-    """
-    Function to instantiate a MicroPython device object.
-
-    @param microPythonWidget reference to the main MicroPython widget
-    @type MicroPythonWidget
-    @param deviceType device type assigned to this device interface
-    @type str
-    @param vid vendor ID
-    @type int
-    @param pid product ID
-    @type int
-    @param boardName name of the board
-    @type str
-    @param serialNumber serial number of the board
-    @type str
-    @return reference to the instantiated device object
-    @rtype PyBoardDevice
-    """
-    return PyBoardDevice(microPythonWidget, deviceType)

eric ide

mercurial