MicroPythonWidget: added menu entries to cross compile a selectable Python file or the current editor to a .mpy file. micropython

Fri, 16 Aug 2019 17:17:32 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 16 Aug 2019 17:17:32 +0200
branch
micropython
changeset 7140
22f5fd76c10f
parent 7139
9bb36ec2d1b5
child 7143
9eb66bad154d
child 7144
de779a22396a

MicroPythonWidget: added menu entries to cross compile a selectable Python file or the current editor to a .mpy file.

eric6/MicroPython/MicroPythonWidget.py file | annotate | diff | comparison | revisions
eric6/Preferences/ConfigurationPages/MicroPythonPage.py file | annotate | diff | comparison | revisions
eric6/Preferences/ConfigurationPages/MicroPythonPage.ui file | annotate | diff | comparison | revisions
eric6/Preferences/__init__.py file | annotate | diff | comparison | revisions
--- a/eric6/MicroPython/MicroPythonWidget.py	Thu Aug 15 17:19:28 2019 +0200
+++ b/eric6/MicroPython/MicroPythonWidget.py	Fri Aug 16 17:17:32 2019 +0200
@@ -11,6 +11,7 @@
 
 import re
 import time
+import os
 
 from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QPoint, QEvent
 from PyQt5.QtGui import QColor, QKeySequence, QTextCursor, QBrush
@@ -22,6 +23,7 @@
 from E5Gui.E5ZoomWidget import E5ZoomWidget
 from E5Gui import E5MessageBox, E5FileDialog
 from E5Gui.E5Application import e5App
+from E5Gui.E5ProcessDialog import E5ProcessDialog
 
 from .Ui_MicroPythonWidget import Ui_MicroPythonWidget
 
@@ -41,6 +43,7 @@
 import Globals
 import UI.PixmapCache
 import Preferences
+import Utilities
 
 # ANSI Colors (see https://en.wikipedia.org/wiki/ANSI_escape_code)
 AnsiColorSchemes = {
@@ -1087,7 +1090,6 @@
         else:
             hasTime = False
         
-        # TODO: add menu entry to cross-compile a .py file (using mpy-cross)
         act = self.__superMenu.addAction(
             self.tr("Show Version"), self.__showDeviceVersion)
         act.setEnabled(self.__connected)
@@ -1105,6 +1107,14 @@
             self.__superMenu.addAction(
                 self.tr("Show Local Time"), self.__showLocalTime)
             self.__superMenu.addSeparator()
+        if not Globals.isWindowsPlatform():
+            self.__superMenu.addAction(
+                self.tr("Compile Python File"), self.__compileFile2Mpy)
+            act = self.__superMenu.addAction(
+                self.tr("Compile Current Editor"), self.__compileEditor2Mpy)
+            aw = e5App().getObject("ViewManager").activeWindow()
+            act.setEnabled(bool(aw))
+            self.__superMenu.addSeparator()
         if self.__device:
             self.__device.addDeviceMenuEntries(self.__superMenu)
     
@@ -1261,3 +1271,89 @@
             self.tr("<p>There was an error communicating with the connected"
                     " device.</p><p>Method: {0}</p><p>Message: {1}</p>")
             .format(method, error))
+    
+    def __crossCompile(self, pythonFile="", title=""):
+        """
+        Private method to cross compile a Python file to a .mpy file.
+        
+        @param pythonFile name of the Python file to be compiled
+        @type str
+        @param title title for the various dialogs
+        @type str
+        """
+        program = Preferences.getMicroPython("MpyCrossCompiler")
+        if not program:
+            program = "mpy-cross"
+            if not Utilities.isinpath(program):
+                E5MessageBox.critical(
+                    self,
+                    title,
+                    self.tr("""The MicroPython cross compiler"""
+                            """ <b>mpy-cross</b> cannot be found. Ensure it"""
+                            """ is in the search path or configure it on"""
+                            """ the MicroPython configuration page."""))
+                return
+        
+        if not pythonFile:
+            defaultDirectory = ""
+            aw = e5App().getObject("ViewManager").activeWindow()
+            if aw:
+                fn = aw.getFileName()
+                if fn:
+                    defaultDirectory = os.path.dirname(fn)
+            if not defaultDirectory:
+                defaultDirectory = Preferences.getMultiProject("Workspace")
+            pythonFile = E5FileDialog.getOpenFileName(
+                self,
+                title,
+                defaultDirectory,
+                self.tr("Python Files (*.py);;All Files (*)"))
+            if not pythonFile:
+                # user cancelled
+                return
+        
+        if not os.path.exists(pythonFile):
+            E5MessageBox.critical(
+                self,
+                title,
+                self.tr("""The Python file <b>{0}</b> does not exist."""
+                        """ Aborting...""").format(pythonFile))
+            return
+        
+        compileArgs = [
+            pythonFile,
+        ]
+        dlg = E5ProcessDialog(self.tr("'mpy-cross' Output"), title)
+        res = dlg.startProcess(program, compileArgs)
+        if res:
+            dlg.exec_()
+    
+    @pyqtSlot()
+    def __compileFile2Mpy(self):
+        """
+        Private slot to cross compile a Python file (*.py) to a .mpy file.
+        """
+        self.__crossCompile(title=self.tr("Compile Python File"))
+    
+    @pyqtSlot()
+    def __compileEditor2Mpy(self):
+        """
+        Private slot to cross compile the current editor to a .mpy file.
+        """
+        aw = e5App().getObject("ViewManager").activeWindow()
+        if not aw.checkDirty():
+            # editor still has unsaved changes, abort...
+            return
+        if not aw.isPyFile():
+            # no Python file
+            E5MessageBox.critical(
+                self,
+                self.tr("Compile Current Editor"),
+                self.tr("""The current editor does not contain a Python"""
+                        """ file. Aborting..."""))
+            return
+        
+        self.__crossCompile(
+            pythonFile=aw.getFileName(),
+            title=self.tr("Compile Current Editor")
+        )
--- a/eric6/Preferences/ConfigurationPages/MicroPythonPage.py	Thu Aug 15 17:19:28 2019 +0200
+++ b/eric6/Preferences/ConfigurationPages/MicroPythonPage.py	Fri Aug 16 17:17:32 2019 +0200
@@ -9,6 +9,8 @@
 
 from __future__ import unicode_literals
 
+from E5Gui.E5PathPicker import E5PathPickerModes
+
 from .ConfigurationPageBase import ConfigurationPageBase
 from .Ui_MicroPythonPage import Ui_MicroPythonPage
 
@@ -34,6 +36,9 @@
         
         self.colorSchemeComboBox.addItems(sorted(AnsiColorSchemes.keys()))
         
+        self.mpyCrossPicker.setMode(E5PathPickerModes.OpenFileMode)
+        self.mpyCrossPicker.setFilters(self.tr("All Files (*)"))
+        
         # set initial values
         self.timeoutSpinBox.setValue(
             Preferences.getMicroPython("SerialTimeout") / 1000)
@@ -45,6 +50,8 @@
                 Preferences.getMicroPython("ColorScheme")))
         self.replWrapCheckBox.setChecked(
             Preferences.getMicroPython("ReplLineWrap"))
+        self.mpyCrossPicker.setText(
+            Preferences.getMicroPython("MpyCrossCompiler"))
     
     def save(self):
         """
@@ -59,6 +66,8 @@
             "ColorScheme", self.colorSchemeComboBox.currentText())
         Preferences.setMicroPython(
             "ReplLineWrap", self.replWrapCheckBox.isChecked())
+        Preferences.setMicroPython(
+            "MpyCrossCompiler", self.mpyCrossPicker.text())
     
 
 def create(dlg):
@@ -68,5 +77,4 @@
     @param dlg reference to the configuration dialog
     @return reference to the instantiated page (ConfigurationPageBase)
     """
-    page = MicroPythonPage()
-    return page
+    return MicroPythonPage()
--- a/eric6/Preferences/ConfigurationPages/MicroPythonPage.ui	Thu Aug 15 17:19:28 2019 +0200
+++ b/eric6/Preferences/ConfigurationPages/MicroPythonPage.ui	Fri Aug 16 17:17:32 2019 +0200
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>477</width>
-    <height>346</height>
+    <width>476</width>
+    <height>356</height>
    </rect>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
@@ -135,6 +135,38 @@
     </widget>
    </item>
    <item>
+    <widget class="QGroupBox" name="groupBox_3">
+     <property name="title">
+      <string>MPY Cross Compiler</string>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QLabel" name="label_3">
+        <property name="text">
+         <string>Program:</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="E5PathPicker" name="mpyCrossPicker" native="true">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="focusPolicy">
+         <enum>Qt::WheelFocus</enum>
+        </property>
+        <property name="toolTip">
+         <string>Enter the path of the cross compiler executable</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
     <spacer name="verticalSpacer">
      <property name="orientation">
       <enum>Qt::Vertical</enum>
@@ -149,6 +181,14 @@
    </item>
   </layout>
  </widget>
+ <customwidgets>
+  <customwidget>
+   <class>E5PathPicker</class>
+   <extends>QWidget</extends>
+   <header>E5Gui/E5PathPicker.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
  <tabstops>
   <tabstop>timeoutSpinBox</tabstop>
   <tabstop>syncTimeCheckBox</tabstop>
--- a/eric6/Preferences/__init__.py	Thu Aug 15 17:19:28 2019 +0200
+++ b/eric6/Preferences/__init__.py	Fri Aug 16 17:17:32 2019 +0200
@@ -1597,6 +1597,7 @@
         "SyncTimeAfterConnect": True,
         "ShowHiddenLocal": True,
         "ShowHiddenDevice": True,
+        "MpyCrossCompiler": "",    # path of the mpy cross compiler
     }
     if Globals.isWindowsPlatform():
         microPythonDefaults["ColorScheme"] = "Windows 10"

eric ide

mercurial