--- a/src/eric7/MicroPython/PyBoardDevices.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/MicroPython/PyBoardDevices.py Wed Jul 13 14:55:47 2022 +0200 @@ -26,17 +26,17 @@ """ Class implementing the device for PyBoard boards. """ + DeviceVolumeName = "PYBFLASH" - + FlashInstructionsURL = ( - "https://github.com/micropython/micropython/wiki/" - "Pyboard-Firmware-Update" + "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 @@ -45,114 +45,115 @@ @type QObject """ super().__init__(microPythonWidget, deviceType, parent) - + 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) - + 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 - + 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 @@ -164,11 +165,11 @@ 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 @@ -176,9 +177,8 @@ """ # Attempts to find the path on the filesystem that represents the # plugged in PyBoard board. - deviceDirectories = Utilities.findVolume(self.DeviceVolumeName, - findAll=True) - + deviceDirectories = Utilities.findVolume(self.DeviceVolumeName, findAll=True) + if deviceDirectories: if len(deviceDirectories) == 1: return deviceDirectories[0] @@ -191,28 +191,29 @@ 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." - ) + 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 """ @@ -221,34 +222,36 @@ 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() - - act = menu.addAction(self.tr("Activate Bootloader"), - self.__activateBootloader) + + act = menu.addAction(self.tr("Activate Bootloader"), self.__activateBootloader) act.setEnabled(connected) - act = menu.addAction(self.tr("List DFU-capable Devices"), - self.__listDfuCapableDevices) + act = menu.addAction( + self.tr("List DFU-capable Devices"), self.__listDfuCapableDevices + ) act.setEnabled(not connected) - act = menu.addAction(self.tr("Flash MicroPython Firmware"), - self.__flashMicroPython) + act = menu.addAction( + self.tr("Flash MicroPython Firmware"), self.__flashMicroPython + ) act.setEnabled(not connected) menu.addSeparator() - menu.addAction(self.tr("MicroPython Flash Instructions"), - self.__showFlashInstructions) - + menu.addAction( + self.tr("MicroPython Flash Instructions"), self.__showFlashInstructions + ) + 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): """ @@ -256,12 +259,13 @@ MicroPython on the pyboard. """ ericApp().getObject("UserInterface").launchHelpViewer( - PyBoardDevice.FlashInstructionsURL) - + PyBoardDevice.FlashInstructionsURL + ) + def __dfuUtilAvailable(self): """ Private method to check the availability of dfu-util. - + @return flag indicating the availability of dfu-util @rtype bool """ @@ -274,24 +278,26 @@ else: if Utilities.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.""") + 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 @@ -305,25 +311,24 @@ "<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>" - ) + + 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) - + EricMessageBox.Abort | EricMessageBox.Ok, + ) + return res == EricMessageBox.Ok - + def __showDfuDisableInstructions(self): """ Private method to show some instructions to disable the DFU mode. @@ -336,12 +341,8 @@ "<hr />" "<p>Press <b>OK</b> to continue...</p>" ) - EricMessageBox.information( - self.microPython, - self.tr("Disable DFU mode"), - msg - ) - + EricMessageBox.information(self.microPython, self.tr("Disable DFU mode"), msg) + @pyqtSlot() def __listDfuCapableDevices(self): """ @@ -353,18 +354,17 @@ 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") + self.tr("'dfu-util' Output"), self.tr("List DFU capable Devices") ) res = dlg.startProcess(program, args) if res: dlg.exec() - + @pyqtSlot() def __flashMicroPython(self): """ @@ -376,39 +376,43 @@ program = Preferences.getMicroPython("DfuUtilPath") if not program: program = "dfu-util" - + downloadsPath = QStandardPaths.standardLocations( - QStandardPaths.StandardLocation.DownloadLocation)[0] + QStandardPaths.StandardLocation.DownloadLocation + )[0] firmware = EricFileDialog.getOpenFileName( self.microPython, self.tr("Flash MicroPython Firmware"), downloadsPath, - self.tr( - "MicroPython Firmware Files (*.dfu);;All Files (*)") + self.tr("MicroPython Firmware Files (*.dfu);;All Files (*)"), ) if firmware and os.path.exists(firmware): args = [ - "--alt", "0", - "--download", firmware, + "--alt", + "0", + "--download", + firmware, ] dlg = EricProcessDialog( self.tr("'dfu-util' Output"), - self.tr("Flash MicroPython Firmware") + self.tr("Flash MicroPython Firmware"), ) res = dlg.startProcess(program, args) if res: dlg.exec() self.__showDfuDisableInstructions() - + @pyqtSlot() def __activateBootloader(self): """ Private slot to activate the bootloader and disconnect. """ if self.microPython.isConnected(): - self.microPython.commandsInterface().execute([ - "import pyb", - "pyb.bootloader()", - ]) + self.microPython.commandsInterface().execute( + [ + "import pyb", + "pyb.bootloader()", + ] + ) # simulate pressing the disconnect button self.microPython.on_connectButton_clicked()