Skip to content

Commit 2dd594e

Browse files
feat: add BaseInterface(Protocol) to base in samps module
feat: add BaseInterface(Protocol) to base in samps module
1 parent efb84c0 commit 2dd594e

File tree

2 files changed

+231
-0
lines changed

2 files changed

+231
-0
lines changed

src/samps/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
# **************************************************************************************
1818

1919
from .asynchronous import SerialAsyncCommonInterface
20+
from .base import BaseInterface
2021
from .baudrate import BAUDRATE_LOOKUP_FLAGS, BAUDRATES, BaudrateType
2122
from .crc import get_cyclic_redundancy_checksum
2223
from .errors import (
@@ -52,6 +53,7 @@
5253
"BAUDRATE_LOOKUP_FLAGS",
5354
"BAUDRATES",
5455
"BaudrateType",
56+
"BaseInterface",
5557
"Serial",
5658
"SerialAsyncCommonInterface",
5759
"SerialCommonInterface",

src/samps/base.py

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
# **************************************************************************************
2+
3+
# @package samps
4+
# @license MIT License Copyright (c) 2025 Michael J. Roberts
5+
6+
# **************************************************************************************
7+
8+
from types import TracebackType
9+
from typing import Optional, Protocol, Type, runtime_checkable
10+
11+
# **************************************************************************************
12+
13+
14+
@runtime_checkable
15+
class BaseInterface(Protocol):
16+
"""
17+
Protocol defining the interface for all base transport classes.
18+
19+
All implementations must provide all methods with identical signatures.
20+
21+
Unsupported operations should log a warning and return gracefully.
22+
"""
23+
24+
def open(self) -> None:
25+
"""
26+
Open the connection to the device.
27+
28+
Raises:
29+
Exception: If opening the connection fails.
30+
"""
31+
...
32+
33+
def close(self) -> None:
34+
"""
35+
Close the connection to the device if it is open.
36+
"""
37+
...
38+
39+
def read(self, size: int = 1) -> bytes:
40+
"""
41+
Read up to `size` bytes from the device.
42+
43+
Args:
44+
size: Number of bytes to read (default: 1).
45+
46+
Returns:
47+
A bytes object containing the data read.
48+
49+
Raises:
50+
RuntimeError: If the connection is not open.
51+
Exception: On timeout or read errors.
52+
"""
53+
...
54+
55+
def write(self, data: bytes) -> int:
56+
"""
57+
Write all of `data` to the device.
58+
59+
Args:
60+
data: Bytes to write.
61+
62+
Returns:
63+
The total number of bytes successfully written.
64+
65+
Raises:
66+
RuntimeError: If the connection is not open.
67+
Exception: On write failure.
68+
"""
69+
...
70+
71+
def readline(
72+
self,
73+
eol: bytes = b"\n",
74+
maximum_bytes: int = -1,
75+
) -> bytes:
76+
"""
77+
Read up to and including the next `eol` byte sequence.
78+
79+
Args:
80+
eol: End-of-line marker to read until (default: b'\\n').
81+
maximum_bytes: Maximum bytes to read (-1 for no limit).
82+
83+
Returns:
84+
A bytes object containing the line read, including the EOL marker.
85+
86+
Raises:
87+
RuntimeError: If the connection is not open.
88+
Exception: On timeout or read errors.
89+
"""
90+
...
91+
92+
def ask(
93+
self,
94+
data: bytes,
95+
eol: bytes = b"\n",
96+
maximum_bytes: int = -1,
97+
) -> bytes:
98+
"""
99+
Write `data` to the device and read a response line ending with `eol`.
100+
101+
Args:
102+
data: Bytes to write as the query.
103+
eol: End-of-line marker for the response (default: b'\n').
104+
maximum_bytes: Maximum bytes to read in response (-1 for no limit).
105+
106+
Returns:
107+
The response bytes read from the device.
108+
109+
Raises:
110+
RuntimeError: If the connection is not open.
111+
Exception: On write or read failure.
112+
"""
113+
...
114+
115+
def flush(self) -> None:
116+
"""
117+
Block until all written output has been transmitted to the device.
118+
119+
Raises:
120+
RuntimeError: If the connection is not open.
121+
"""
122+
...
123+
124+
def abort_in(self) -> None:
125+
"""
126+
Discard any data waiting in the input buffer.
127+
128+
Raises:
129+
RuntimeError: If the connection is not open.
130+
"""
131+
...
132+
133+
def abort_out(self) -> None:
134+
"""
135+
Discard any data waiting in the output buffer.
136+
137+
Raises:
138+
RuntimeError: If the connection is not open.
139+
"""
140+
...
141+
142+
def clear(self) -> None:
143+
"""
144+
Clear the device by aborting all pending transfers and resetting I/O buffers.
145+
146+
Raises:
147+
RuntimeError: If the connection is not open.
148+
"""
149+
...
150+
151+
def is_open(self) -> bool:
152+
"""
153+
Check whether the connection is currently open.
154+
155+
Returns:
156+
True if open, False otherwise.
157+
"""
158+
...
159+
160+
def is_closed(self) -> bool:
161+
"""
162+
Check whether the connection is currently closed.
163+
164+
Returns:
165+
True if closed, False otherwise.
166+
"""
167+
...
168+
169+
def __enter__(self) -> "BaseInterface":
170+
"""
171+
Synchronous context manager entry: opens the connection.
172+
173+
Returns:
174+
The BaseInterface instance.
175+
"""
176+
...
177+
178+
def __exit__(
179+
self,
180+
exc_type: Optional[Type[BaseException]],
181+
exc_val: Optional[BaseException],
182+
exc_tb: Optional[TracebackType],
183+
) -> None:
184+
"""
185+
Synchronous context manager exit: closes the connection.
186+
187+
Args:
188+
exc_type: The exception type, if an exception was raised.
189+
exc_val: The exception instance, if an exception was raised.
190+
exc_tb: The traceback, if an exception was raised.
191+
"""
192+
...
193+
194+
async def __aenter__(self) -> "BaseInterface":
195+
"""
196+
Asynchronous context manager entry: opens the connection.
197+
198+
Returns:
199+
The BaseInterface instance.
200+
"""
201+
...
202+
203+
async def __aexit__(
204+
self,
205+
exc_type: Optional[Type[BaseException]],
206+
exc_val: Optional[BaseException],
207+
exc_tb: Optional[TracebackType],
208+
) -> None:
209+
"""
210+
Asynchronous context manager exit: closes the connection.
211+
212+
Args:
213+
exc_type: The exception type, if an exception was raised.
214+
exc_val: The exception instance, if an exception was raised.
215+
exc_tb: The traceback, if an exception was raised.
216+
"""
217+
...
218+
219+
def __repr__(self) -> str:
220+
"""
221+
Return a string representation of the interface.
222+
223+
Returns:
224+
A human-readable string describing the interface.
225+
"""
226+
...
227+
228+
229+
# **************************************************************************************

0 commit comments

Comments
 (0)