src/eric7/MicroPython/Devices/GenericMicroPythonDevices.py

branch
eric7
changeset 9756
9854647c8c5c
parent 9751
606ac0e26533
child 9763
52f982c08301
diff -r 1a09700229e7 -r 9854647c8c5c src/eric7/MicroPython/Devices/GenericMicroPythonDevices.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/MicroPython/Devices/GenericMicroPythonDevices.py	Mon Feb 13 17:49:52 2023 +0100
@@ -0,0 +1,227 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2021 - 2023 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the device interface class for generic MicroPython devices
+(i.e. those devices not specifically supported yet).
+"""
+
+import os
+
+from eric7 import Preferences
+from eric7.EricWidgets import EricMessageBox
+from eric7.SystemUtilities import FileSystemUtilities
+
+from .DeviceBase import BaseDevice
+from .MicroPythonWidget import HAS_QTCHART
+
+
+class GenericMicroPythonDevice(BaseDevice):
+    """
+    Class implementing the device interface for generic MicroPython boards.
+    """
+
+    def __init__(self, microPythonWidget, deviceType, vid, pid, 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 vid vendor ID
+        @type int
+        @param pid product ID
+        @type int
+        @param parent reference to the parent object
+        @type QObject
+        """
+        super().__init__(microPythonWidget, deviceType, parent)
+
+        self.__directAccess = False
+        self.__deviceVolumeName = ""
+        self.__workspace = ""
+        self.__deviceName = ""
+
+        for deviceData in Preferences.getMicroPython("ManualDevices"):
+            if deviceData["vid"] == vid and deviceData["pid"] == pid:
+                self.__deviceVolumeName = deviceData["data_volume"]
+                self.__directAccess = bool(deviceData["data_volume"])
+                self.__deviceName = deviceData["description"]
+
+                if self.__directAccess:
+                    self.__workspace = self.__findWorkspace()
+
+    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.__directAccess and self.__deviceVolumeMounted():
+            self.microPython.setActionButtons(open=True, save=True)
+
+    def deviceName(self):
+        """
+        Public method to get the name of the device.
+
+        @return name of the device
+        @rtype str
+        """
+        return self.__deviceName
+
+    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.__directAccess and 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.__directAccess:
+            if self.__workspace:
+                # return cached entry
+                return self.__workspace
+            else:
+                self.__workspace = self.__findWorkspace(silent=silent)
+                return self.__workspace
+        else:
+            return super().getWorkspace()
+
+    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 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 this generic board can be"
+                        " edited in place, if the device volume is locally"
+                        " available. A volume named '{0}' was not found."
+                        " In place editing will not be available."
+                    ).format(self.__deviceVolumeName),
+                )
+
+            return super().getWorkspace()
+
+
+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 GenericMicroPythonDevice
+    """
+    return GenericMicroPythonDevice(microPythonWidget, deviceType, vid, pid)

eric ide

mercurial