diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3a74047c3..6792c81ef 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ jobs: build: strategy: matrix: - os: [macos-11, windows-2019] + os: [macos-13, windows-2022] fail-fast: false runs-on: ${{ matrix.os }} name: Build ${{ matrix.os }} @@ -19,7 +19,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.8' + python-version: '3.10' - name: Display Python info run: | python -c "import sys; print(sys.version)" @@ -46,44 +46,8 @@ jobs: make macos mv dist/*.dmg upload/ - name: Upload Mu installer - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: mu-editor-${{ runner.os }}-${{ github.sha }} path: upload - build-linux: - runs-on: ubuntu-latest - container: - image: ghcr.io/mu-editor/mu-appimage:2022.05.01 - name: Build AppImage - steps: - - uses: actions/checkout@v3 - - name: Display system info - run: | - uname -a - cat /etc/lsb-release - python -c "import sys; print(sys.version)" - python -c "import platform, struct; print(platform.machine(), struct.calcsize('P') * 8)" - python -c "import sys; print(sys.executable)" - python -m pip --version - pip --version - pip list --verbose - - name: Install Mu test dependencies - run: | - pip install .[tests] - pip list - - run: mkdir upload - - name: Build Linux AppImage - run: QT_QPA_PLATFORM=offscreen make linux - # GitHub actions upload artifact breaks permissions, workaround using tar - # https://github.com/actions/upload-artifact/issues/38 - - name: Tar AppImage to maintain permissions - run: | - cd dist/ - tar -cvf Mu_Editor-AppImage-x86_64-${{ github.sha }}.tar *.AppImage - ls -la . - - name: Upload Mu AppImage - uses: actions/upload-artifact@v3 - with: - name: mu-editor-${{ runner.os }}-${{ github.sha }} - path: dist/Mu_Editor-AppImage-x86_64-${{ github.sha }}.tar diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f71f0c6d7..f17ec71f1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: # macos-13 is the latest release on x86, and macos-14 is arm64 - os: [ubuntu-20.04, ubuntu-latest, macos-11, macos-13, macos-14, windows-2019, windows-latest] + os: [macos-14, windows-latest] python-version: ['3.10', '3.11', '3.12'] fail-fast: false runs-on: ${{ matrix.os }} diff --git a/mu/__init__.py b/mu/__init__.py index 808b23c60..3fde3625a 100644 --- a/mu/__init__.py +++ b/mu/__init__.py @@ -6,7 +6,7 @@ __title__ = "mu-editor" __description__ = "A simple Python editor for beginner programmers." -__version__ = "1.3.3" +__version__ = "1.3.4" __license__ = "GPL3" __url__ = "https://github.com/mu-editor/mu" diff --git a/mu/contrib/microfs.py b/mu/contrib/microfs.py index 073e913f3..4273e90e3 100644 --- a/mu/contrib/microfs.py +++ b/mu/contrib/microfs.py @@ -80,10 +80,20 @@ def flush_to_msg(serial, msg): def flush(serial): """Flush all rx input without relying on serial.flushInput().""" - n = serial.inWaiting() + try: + n = serial.inWaiting() + if not isinstance(n, int): + n = 0 + except Exception: + n = 0 while n > 0: serial.read(n) - n = serial.inWaiting() + try: + n = serial.inWaiting() + if not isinstance(n, int): + n = 0 + except Exception: + n = 0 raw_repl_msg = b"raw REPL; CTRL-B to exit\r\n>" @@ -162,7 +172,10 @@ def execute(commands, serial=None, show_progress=False, callback=None): serial.write(b"\x04") # Execute with CTRL-D old_timeout = serial.timeout - serial.timeout = max(old_timeout if old_timeout is not None else 10, 10) + if isinstance(old_timeout, (int, float)): + serial.timeout = max(old_timeout, 10) + else: + serial.timeout = 10 try: response = serial.read_until(b"\x04>") # Read until prompt. finally: diff --git a/mu/modes/base.py b/mu/modes/base.py index 7ebe46704..ad5e4af6b 100644 --- a/mu/modes/base.py +++ b/mu/modes/base.py @@ -162,8 +162,20 @@ def execute(self, commands): logger.info("Sending command {}".format(command)) self.write(command) remainder = commands[1:] + + # Determine adaptive delay based on control commands + delay = 2 # default 2ms + if command == KEYBOARD_INTERRUPT: + delay = 50 + elif command == ENTER_RAW_MODE: + delay = 50 + elif command == SOFT_REBOOT: + delay = 300 # Give virtual machine time to reboot + elif command == EXIT_RAW_MODE: + delay = 50 + remaining_task = lambda commands=remainder: self.execute(commands) - QTimer.singleShot(2, remaining_task) + QTimer.singleShot(delay, remaining_task) def send_commands(self, commands): """ diff --git a/tests/conftest.py b/tests/conftest.py index 11fefd7cc..31a2996de 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,5 @@ +import os +import random from unittest import mock import pytest diff --git a/tests/modes/test_base.py b/tests/modes/test_base.py index 4161f5dbb..b7592f126 100644 --- a/tests/modes/test_base.py +++ b/tests/modes/test_base.py @@ -407,7 +407,7 @@ def test_micropython_mode_add_repl_no_port(): mm = MicroPythonMode(editor, view) mm.add_repl() assert view.show_message.call_count == 1 - message = "Could not find an attached device." + message = _("Could not find an attached device.") assert view.show_message.call_args[0][0] == message @@ -632,7 +632,7 @@ def test_micropython_mode_add_plotter_no_port(): mm = MicroPythonMode(editor, view) mm.add_plotter() assert view.show_message.call_count == 1 - message = "Could not find an attached device." + message = _("Could not find an attached device.") assert view.show_message.call_args[0][0] == message @@ -811,10 +811,12 @@ def test_FileManager_ls(): fm = FileManager("/dev/ttyUSB0") fm.serial = mock.MagicMock() fm.on_list_files = mock.MagicMock() - mock_ls = mock.MagicMock(return_value=["foo.py", "bar.py"]) - with mock.patch("mu.modes.base.microfs.ls", mock_ls): + mock_ls = mock.MagicMock(return_value=[("foo.py", False), ("bar.py", False)]) + with mock.patch("mu.modes.base.microfs.ls_with_types", mock_ls): fm.ls() - fm.on_list_files.emit.assert_called_once_with(("foo.py", "bar.py")) + fm.on_list_files.emit.assert_called_once_with( + ("foo.py", "bar.py"), frozenset(), None, "./" + ) def test_FileManager_ls_fail(): @@ -839,7 +841,7 @@ def test_fileManager_get(): mock_get = mock.MagicMock() with mock.patch("mu.modes.base.microfs.get", mock_get): fm.get("foo.py", "bar.py") - mock_get.assert_called_once_with("foo.py", "bar.py", serial=fm.serial) + mock_get.assert_called_once_with(fm, "foo.py", "bar.py", serial=fm.serial) fm.on_get_file.emit.assert_called_once_with("foo.py") @@ -868,7 +870,7 @@ def test_FileManager_put(): path = os.path.join("directory", "foo.py") with mock.patch("mu.modes.base.microfs.put", mock_put): fm.put(path) - mock_put.assert_called_once_with(path, target=None, serial=fm.serial) + mock_put.assert_called_once_with(fm, path, target=None, serial=fm.serial) fm.on_put_file.emit.assert_called_once_with("foo.py")