Changelog¶
All notable changes to this project are documented here.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.1.0¶
Initial release.
Core¶
- Async-native serial transport built on AnyIO (>= 4.13).
- Immutable
SerialConfigwithwith_changes,FlowControl,RS485Config, andStrEnumtypes (ByteSize,Parity,StopBits). - Multi-inherited exception hierarchy compatible with stdlib and AnyIO bases.
- Tri-state
Capabilitymodel andSerialCapabilitiessnapshot per backend. BackendProtocol split intoSyncSerialBackend(POSIX) andAsyncSerialBackend(Windows).SerialPort,SerialConnectable, andopen_serial_portwith full AnyIO typed-attribute support.- Runtime reconfiguration via
port.configure(new_config)with serialized concurrent calls; failed applies leaveport.configunchanged. - Raw-bytes API:
receive,receive_available,receive_into,send,drain,drain_exact,input_waiting,output_waiting. MockBackendandFaultPlanunderanyserial.testingfor hardware-free unit testing, plusserial_port_pairhelper.- Blocking
anyserial.sync.SerialPortwrapper backed by a process-wideBlockingPortalProvider; per-calltimeout=keyword;configure_portal(backend=..., backend_options=...)for AnyIO backend selection.
Linux backend¶
LinuxBackendwith nonblocking fd I/O viaanyio.wait_readable/anyio.wait_writable, raw-mode termios, modem-line ioctls, BREAK, exclusive access viaflock, queue-depth, and buffer flush.- Standard and extended baud (
TCSETS2/BOTHER). ASYNC_LOW_LATENCYlow-latency mode with restore-on-close.- Kernel RS-485 (
TIOCSRS485) with read-modify-write that preserves driver-reserved bits and restores pre-touch state on close orconfigure(rs485=None). - Native sysfs-based port discovery with USB-ancestor resolution;
populates VID / PID / serial / manufacturer / product / location /
interface and emits a pyserial-compatible
hwidstring.
macOS (Darwin) backend¶
DarwinBackendwith custom baud viaIOSSIOSPEED, BREAK via the shared<sys/ttycom.h>numeric fallback, andUnsupportedPolicy- routed rejection oflow_latencyandrs485.- Native IOKit discovery walks
IOSerialBSDClient, prefers/dev/cu.*callout paths, and climbs the IORegistry parent chain for USB metadata. The ctypes facade over IOKit + CoreFoundation loads lazily so the module imports cleanly on Linux CI.
BSD backend¶
- One
BsdBackendfor FreeBSD / NetBSD / OpenBSD / DragonFly. Custom baud via integerc_ispeed/c_ospeedpassthrough;low_latency/rs485rejected viaUnsupportedPolicy. /dev-scan discovery with per-variant glob sets. USB metadata is intentionally not populated — uselist_serial_ports(backend="pyserial")when VID / PID is needed.
Windows backend¶
WindowsBackendimplementsAsyncSerialBackendand dispatches hot-pathreceive/sendthrough each runtime's native IOCP machinery:- Trio →
trio.lowlevel.register_with_iocp+readinto_overlapped/write_overlapped. - asyncio on
ProactorEventLoop→loop._proactor._register+_overlapped.Overlapped.ReadFileInto/WriteFile(zero-copy via CPython 3.12+ReadFileInto). - No worker-thread fallback.
SelectorEventLoopraisesUnsupportedPlatformErrorat open time pointing atWindowsProactorEventLoopPolicy. - SetupAPI port discovery via
GUID_DEVINTERFACE_COMPORTpopulates VID / PID / serial / manufacturer / product / location on USB-attached adapters;hwidis pyserial-compatible. Falls back toHKLM\HARDWARE\DEVICEMAP\SERIALCOMMviawinregwhen SetupAPI enumeration fails. WaitCommEventmodem-line change notification (EV_CTS | EV_DSR | EV_RING | EV_RLSD | EV_ERR | EV_BREAK).- DCB round-trip (
GetCommState→ overlay →SetCommState) preserves vendor state stored in reserved DCB fields by FTDI / Prolific / CH340 drivers. - "Wait-for-any"
COMMTIMEOUTSpolicy (MAXDWORD / MAXDWORD / 1 ms) with internal retry loop on zero-byte completions, so idlereceive()doesn't surface spurious EOF. - Win32 error translation (
ERROR_FILE_NOT_FOUND→PortNotFoundError,ERROR_ACCESS_DENIED/ERROR_SHARING_VIOLATION→PortBusyError,ERROR_INVALID_HANDLE/ERROR_OPERATION_ABORTED→SerialClosedError,ERROR_INVALID_PARAMETERon config →UnsupportedConfigurationError,ERROR_DEVICE_REMOVED/ERROR_NOT_READY/ERROR_GEN_FAILURE→SerialDisconnectedError). Exceptions carry a.winerrorattribute. - Capability snapshot reports
SUPPORTEDfor every feature exceptlow_latency(no Windows equivalent ofASYNC_LOW_LATENCY) andrs485(FTDI VCP RS-485 is driver config, not a runtime API).
Discovery¶
list_serial_ports(),find_serial_port(...), and thePortInfodata model — async, always-live, no caching.- Optional
pyudev(Linux) andpyserial(cross-platform) backends selectable via thebackend=keyword. Each raisesImportErrorwith the exact install command when the extra isn't installed. port.port_infotyped attribute onSerialPort:open_serial_portresolves the device path through native discovery and exposes the result onport.port_infoand via the typed-attribute interface.
Tooling and CI¶
pyproject.tomlwithhatchling+hatch-vcsbuild, AnyIO >= 4.13 runtime dep, Python 3.13 / 3.14 support.- uv-managed dependency groups (lint, type, test, docs, bench).
- Ruff, mypy, pyright, pytest, coverage, pre-commit configuration.
- GitHub Actions CI for lint, typecheck, and tests on Linux, macOS,
and Windows across Python 3.13 / 3.14 × asyncio / asyncio + uvloop /
trio (Windows: asyncio Proactor / trio). FreeBSD smoke job via
cross-platform-actions. - Hardware test marker default-deselected (
pytest -m "not hardware"); opt-in viapytest -m hardwarewithANYSERIAL_TEST_PORT. - Benchmark suite under
benchmarks/: receive / send latency, throughput, many-port fan-out, allocation profile, sync-vs-async, Windows IOCP scenarios over an opt-in configured serial pair, and apyserial-asynciohead-to-head. Nightly bench workflow records baselines per backend.
Documentation¶
- Full documentation site covering quickstart, configuration, capabilities, discovery, runtime reconfiguration, RS-485, AnyIO backend selection, uvloop, cancellation, performance, sync wrapper, hardware testing, troubleshooting, migration from pySerial, and per-platform pages (Linux tuning, macOS, BSD, Windows).
- MIT license.