Skip to content

Commit e04b97a

Browse files
committed
Add type annotations
1 parent 60919b1 commit e04b97a

File tree

3 files changed

+71
-37
lines changed

3 files changed

+71
-37
lines changed

tests/test_tinylink.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,29 @@ class DummyHandle(object):
77
Dummy handler, so the TinyLink class can exchange data with itself.
88
"""
99

10-
def __init__(self):
10+
stream: bytes
11+
index: int
12+
length: int
13+
14+
def __init__(self) -> None:
1115
self.stream = bytearray()
1216
self.index = 0
1317
self.length = 0
1418

15-
def write(self, data):
19+
def read(self, size: int) -> bytes:
20+
data = self.stream[self.index:min(self.length, self.index + size)]
21+
self.index += len(data)
22+
23+
# Return data.
24+
return bytes(data)
25+
26+
def write(self, data: bytes) -> int:
1627
self.stream.extend(data)
1728
self.length += len(data)
1829

19-
# Return number of bytes written
30+
# Return number of bytes written.
2031
return len(data)
2132

22-
def read(self, count):
23-
data = self.stream[self.index:min(self.length, self.index + count)]
24-
self.index += len(data)
25-
26-
# Return data
27-
return bytes(data)
28-
2933

3034
class TinyLinkTest(unittest.TestCase):
3135
"""

tinylink/cli.py

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import time
44
import select
55
import struct
6+
from typing import Optional
67
import tinylink
78
import argparse
89

@@ -14,20 +15,12 @@
1415
serial = None
1516

1617

17-
def run():
18-
"""
19-
Entry point for console script.
20-
"""
21-
22-
sys.exit(main())
23-
24-
25-
def parse_arguments():
18+
def parse_arguments(argv: list[str]) -> argparse.Namespace:
2619
"""
2720
Create and parse command line arguments.
2821
"""
2922

30-
parser = argparse.ArgumentParser()
23+
parser = argparse.ArgumentParser(prog=argv[0])
3124

3225
# Add options.
3326
parser.add_argument("port", type=str, help="serial port")
@@ -40,10 +33,10 @@ def parse_arguments():
4033
help="maximum length of frame")
4134

4235
# Parse command line.
43-
return parser.parse_args(), parser
36+
return parser.parse_args(argv[1:])
4437

4538

46-
def dump(prefix, data):
39+
def dump(prefix: str, data: bytes) -> str:
4740
"""
4841
Dump data as two hex columns.
4942
"""
@@ -72,7 +65,7 @@ def dump(prefix, data):
7265
return "\n".join(result)
7366

7467

75-
def process_link(link):
68+
def process_link(link: tinylink.TinyLink) -> None:
7669
"""
7770
Process incoming link data.
7871
"""
@@ -88,7 +81,7 @@ def process_link(link):
8881
sys.stdout.write(dump("<<<", frame.data) + "\n\n")
8982

9083

91-
def process_stdin(link):
84+
def process_stdin(link: tinylink.TinyLink) -> Optional[bool]:
9285
"""
9386
Process stdin commands.
9487
"""
@@ -137,9 +130,9 @@ def process_stdin(link):
137130
link.endianness + pack, int(item, 0))
138131
except ValueError:
139132
# Assume it is a byte string.
140-
item = item.encode("ascii")
133+
item_bytes = item.encode("ascii")
141134
value = struct.pack(
142-
link.endianness + str(len(item)) + "s", item)
135+
link.endianness + str(len(item_bytes)) + "s", item_bytes)
143136

144137
# Concat to frame.
145138
frame.data = (frame.data or bytes()) + value
@@ -162,7 +155,15 @@ def process_stdin(link):
162155
return
163156

164157

165-
def main():
158+
def run() -> None:
159+
"""
160+
Entry point for console script.
161+
"""
162+
163+
sys.exit(main(sys.argv))
164+
165+
166+
def main(argv: list[str]) -> int:
166167
"""
167168
Main entry point.
168169
"""
@@ -174,7 +175,7 @@ def main():
174175
return 1
175176

176177
# Parse arguments.
177-
arguments, parser = parse_arguments()
178+
arguments = parse_arguments(argv)
178179

179180
if arguments.endianness == "little":
180181
endianness = tinylink.LITTLE_ENDIAN

tinylink/link.py

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,38 @@
1+
from typing import Protocol
2+
13
from . import consts
24
from . import utils
35

46
import struct
57

68

7-
class Frame(object):
9+
class Handle(Protocol):
10+
"""
11+
Protocol for a handler.
12+
"""
13+
14+
def read(self, size: int) -> bytes:
15+
""""
16+
Read up to `size` bytes.
17+
"""
18+
19+
def write(self, data: bytes) -> int:
20+
"""
21+
Write data and return the number of bytes written.
22+
"""
23+
24+
25+
class Frame:
826
"""
927
Represents a frame.
1028
"""
1129

12-
def __init__(self, data=None, flags=consts.FLAG_NONE, damaged=False):
30+
data: bytes
31+
flags: int
32+
damaged: int
33+
34+
def __init__(self, data: bytes = None, flags: int = consts.FLAG_NONE,
35+
damaged: bool = False) -> None:
1336
if data is not None:
1437
if type(data) is not bytes:
1538
raise ValueError("Provided data must be encoded as bytes.")
@@ -20,12 +43,12 @@ def __init__(self, data=None, flags=consts.FLAG_NONE, damaged=False):
2043
self.flags = flags
2144
self.damaged = damaged
2245

23-
def __repr__(self):
46+
def __repr__(self) -> str:
2447
return "%s(%s, flags=%d, damaged=%s)" % (
2548
self.__class__.__name__, repr(self.data), self.flags, self.damaged)
2649

2750

28-
class TinyLink(object):
51+
class TinyLink:
2952
"""
3053
TinyLink state machine for streaming communication with low-speed embedded
3154
applications that only use RX/TX. Every message is encapsulated in a frame.
@@ -39,8 +62,14 @@ class TinyLink(object):
3962
It does not provide error correction and the bytes are not aligned.
4063
"""
4164

42-
def __init__(self, handle, endianness=consts.LITTLE_ENDIAN,
43-
max_length=2**(consts.LEN_LENGTH * 8), ignore_damaged=False):
65+
handle: Handle
66+
endianness: str
67+
max_length: int
68+
ignore_damaged: bool
69+
70+
def __init__(self, handle: Handle, endianness: str = consts.LITTLE_ENDIAN,
71+
max_length: int = 2**(consts.LEN_LENGTH * 8),
72+
ignore_damaged: bool = False) -> None:
4473
"""
4574
Construct a new TinyLink state machine. A state machine takes a handle,
4675
which provides a `read` and `write` method.
@@ -75,7 +104,7 @@ def __init__(self, handle, endianness=consts.LITTLE_ENDIAN,
75104
# Python 2 does not allow unpack from bytearray, but Python 3.
76105
self.buffer = self.stream
77106

78-
def write_frame(self, frame):
107+
def write_frame(self, frame: Frame) -> int:
79108
"""
80109
Write a frame via the handle.
81110
"""
@@ -105,14 +134,14 @@ def write_frame(self, frame):
105134
# Write to file.
106135
return self.handle.write(result)
107136

108-
def write(self, data, flags=consts.FLAG_NONE):
137+
def write(self, data: bytes, flags: int = consts.FLAG_NONE) -> int:
109138
"""
110139
Shorthand for `write_frame(Frame(data, flags=flags))`.
111140
"""
112141

113142
return self.write_frame(Frame(data, flags=flags))
114143

115-
def read(self, limit=1):
144+
def read(self, limit: int = 1) -> list[Frame]:
116145
"""
117146
Read up to `limit` bytes from the handle and process it. Returns a list
118147
of received frames, if any.

0 commit comments

Comments
 (0)