From 92053ecded7892c48cf56ac4caa887b38fe63384 Mon Sep 17 00:00:00 2001 From: Brad Barnett <127794626+bdbarnett@users.noreply.github.com> Date: Mon, 12 Oct 2026 22:10:13 -0500 Subject: [PATCH] Serial commands reach a board behind a USB-UART bridge again with mpremote 1.29 On a CH343 or CP210x port mpftp opens the port itself, to keep DTR and RTS low, and skipped mpremote's __init__, which sets is_pty. mpremote 1.29 reads it while it takes the board's prompt, so every exec, put and connect on such a port failed with "'PacedSerialTransport' object has no attribute 'is_pty'". --- cli/src/mpftp/rawpaste.py | 4 ++++ cli/tests/test_stray_output.py | 1 + 2 files changed, 5 insertions(+) diff --git a/cli/src/mpftp/rawpaste.py b/cli/src/mpftp/rawpaste.py index dad524b..535a1ac 100644 --- a/cli/src/mpftp/rawpaste.py +++ b/cli/src/mpftp/rawpaste.py @@ -118,6 +118,10 @@ def __init__( self.use_raw_paste = True self.device_name = device self.mounted = False + # mpremote 1.29 reads is_pty when it waits for the board; its own + # __init__, skipped here, sets it from the device path. + is_pty = getattr(SerialTransport, "_is_pty_device", None) + self.is_pty = bool(is_pty(device)) if is_pty else False kwargs: dict[str, Any] = { "baudrate": baudrate, "timeout": timeout, diff --git a/cli/tests/test_stray_output.py b/cli/tests/test_stray_output.py index 83bc666..b9aa4d6 100644 --- a/cli/tests/test_stray_output.py +++ b/cli/tests/test_stray_output.py @@ -114,6 +114,7 @@ def test_dtr_and_rts_are_low_before_the_port_opens(self): self.assertTrue(make.call_args.kwargs.get("do_not_open")) self.assertFalse(t.in_raw_repl) self.assertTrue(t.use_raw_paste) + self.assertFalse(t.is_pty) # mpremote 1.29 reads it; a COM port is not a pty def test_sidecar_holds_lines_low_on_a_uart_bridge_only(self): ports = [