Skip to content

Commit f5b2014

Browse files
authored
Add/complete type annotations
2 parents e7706f4 + 35a6235 commit f5b2014

File tree

12 files changed

+673
-352
lines changed

12 files changed

+673
-352
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ lint:
1414
$(PYTHON) -m pylint trio_websocket/ tests/ autobahn/ examples/
1515

1616
typecheck:
17-
$(PYTHON) -m mypy --explicit-package-bases trio_websocket tests autobahn examples
17+
$(PYTHON) -m mypy
1818

1919
publish:
2020
rm -fr build dist .egg trio_websocket.egg-info

autobahn/client.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,21 @@
1717
logger = logging.getLogger('client')
1818

1919

20-
async def get_case_count(url):
20+
async def get_case_count(url: str) -> int:
2121
url = url + '/getCaseCount'
2222
async with open_websocket_url(url) as conn:
2323
case_count = await conn.get_message()
2424
logger.info('Case count=%s', case_count)
2525
return int(case_count)
2626

2727

28-
async def get_case_info(url, case):
28+
async def get_case_info(url: str, case: str) -> object:
2929
url = f'{url}/getCaseInfo?case={case}'
3030
async with open_websocket_url(url) as conn:
3131
return json.loads(await conn.get_message())
3232

3333

34-
async def run_case(url, case):
34+
async def run_case(url: str, case: str) -> None:
3535
url = f'{url}/runCase?case={case}&agent={AGENT}'
3636
try:
3737
async with open_websocket_url(url, max_message_size=MAX_MESSAGE_SIZE) as conn:
@@ -42,15 +42,15 @@ async def run_case(url, case):
4242
pass
4343

4444

45-
async def update_reports(url):
45+
async def update_reports(url: str) -> None:
4646
url = f'{url}/updateReports?agent={AGENT}'
4747
async with open_websocket_url(url) as conn:
4848
# This command runs as soon as we connect to it, so we don't need to
4949
# send any messages.
5050
pass
5151

5252

53-
async def run_tests(args):
53+
async def run_tests(args: argparse.Namespace) -> None:
5454
logger = logging.getLogger('trio-websocket')
5555
if args.debug_cases:
5656
# Don't fetch case count when debugging a subset of test cases. It adds
@@ -62,7 +62,10 @@ async def run_tests(args):
6262
test_cases = list(range(1, case_count + 1))
6363
exception_cases = []
6464
for case in test_cases:
65-
case_id = (await get_case_info(args.url, case))['id']
65+
result = await get_case_info(args.url, case)
66+
assert isinstance(result, dict)
67+
case_id = result['id']
68+
assert isinstance(case_id, int)
6669
if case_count:
6770
logger.info("Running test case %s (%d of %d)", case_id, case, case_count)
6871
else:
@@ -82,7 +85,7 @@ async def run_tests(args):
8285
sys.exit(1)
8386

8487

85-
def parse_args():
88+
def parse_args() -> argparse.Namespace:
8689
''' Parse command line arguments. '''
8790
parser = argparse.ArgumentParser(description='Autobahn client for'
8891
' trio-websocket')

autobahn/server.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@
2323
connection_count = 0
2424

2525

26-
async def main():
26+
async def main() -> None:
2727
''' Main entry point. '''
2828
logger.info('Starting websocket server on ws://%s:%d', BIND_IP, BIND_PORT)
2929
await serve_websocket(handler, BIND_IP, BIND_PORT, ssl_context=None,
3030
max_message_size=MAX_MESSAGE_SIZE)
3131

3232

33-
async def handler(request: WebSocketRequest):
33+
async def handler(request: WebSocketRequest) -> None:
3434
''' Reverse incoming websocket messages and send them back. '''
3535
global connection_count # pylint: disable=global-statement
3636
connection_count += 1
@@ -46,7 +46,7 @@ async def handler(request: WebSocketRequest):
4646
logger.exception(' runtime exception handling connection #%d', connection_count)
4747

4848

49-
def parse_args():
49+
def parse_args() -> argparse.Namespace:
5050
''' Parse command line arguments. '''
5151
parser = argparse.ArgumentParser(description='Autobahn server for'
5252
' trio-websocket')

examples/client.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,23 @@
1111
import ssl
1212
import sys
1313
import urllib.parse
14+
from typing import NoReturn
1415

1516
import trio
16-
from trio_websocket import open_websocket_url, ConnectionClosed, HandshakeError
17+
from trio_websocket import (
18+
open_websocket_url,
19+
ConnectionClosed,
20+
HandshakeError,
21+
WebSocketConnection,
22+
CloseReason,
23+
)
1724

1825

1926
logging.basicConfig(level=logging.DEBUG)
2027
here = pathlib.Path(__file__).parent
2128

2229

23-
def commands():
30+
def commands() -> None:
2431
''' Print the supported commands. '''
2532
print('Commands: ')
2633
print('send <MESSAGE> -> send message')
@@ -29,7 +36,7 @@ def commands():
2936
print()
3037

3138

32-
def parse_args():
39+
def parse_args() -> argparse.Namespace:
3340
''' Parse command line arguments. '''
3441
parser = argparse.ArgumentParser(description='Example trio-websocket client')
3542
parser.add_argument('--heartbeat', action='store_true',
@@ -38,7 +45,7 @@ def parse_args():
3845
return parser.parse_args()
3946

4047

41-
async def main(args):
48+
async def main(args: argparse.Namespace) -> bool:
4249
''' Main entry point, returning False in the case of logged error. '''
4350
if urllib.parse.urlsplit(args.url).scheme == 'wss':
4451
# Configure SSL context to handle our self-signed certificate. Most
@@ -59,9 +66,10 @@ async def main(args):
5966
except HandshakeError as e:
6067
logging.error('Connection attempt failed: %s', e)
6168
return False
69+
return True
6270

6371

64-
async def handle_connection(ws, use_heartbeat):
72+
async def handle_connection(ws: WebSocketConnection, use_heartbeat: bool) -> None:
6573
''' Handle the connection. '''
6674
logging.debug('Connected!')
6775
try:
@@ -71,11 +79,12 @@ async def handle_connection(ws, use_heartbeat):
7179
nursery.start_soon(get_commands, ws)
7280
nursery.start_soon(get_messages, ws)
7381
except ConnectionClosed as cc:
82+
assert isinstance(cc.reason, CloseReason)
7483
reason = '<no reason>' if cc.reason.reason is None else f'"{cc.reason.reason}"'
7584
print(f'Closed: {cc.reason.code}/{cc.reason.name} {reason}')
7685

7786

78-
async def heartbeat(ws, timeout, interval):
87+
async def heartbeat(ws: WebSocketConnection, timeout: float, interval: float) -> NoReturn:
7988
'''
8089
Send periodic pings on WebSocket ``ws``.
8190
@@ -99,11 +108,10 @@ async def heartbeat(ws, timeout, interval):
99108
await trio.sleep(interval)
100109

101110

102-
async def get_commands(ws):
111+
async def get_commands(ws: WebSocketConnection) -> None:
103112
''' In a loop: get a command from the user and execute it. '''
104113
while True:
105-
cmd = await trio.to_thread.run_sync(input, 'cmd> ',
106-
cancellable=True)
114+
cmd = await trio.to_thread.run_sync(input, 'cmd> ')
107115
if cmd.startswith('ping'):
108116
payload = cmd[5:].encode('utf8') or None
109117
await ws.ping(payload)
@@ -123,11 +131,11 @@ async def get_commands(ws):
123131
await trio.sleep(0.25)
124132

125133

126-
async def get_messages(ws):
134+
async def get_messages(ws: WebSocketConnection) -> None:
127135
''' In a loop: get a WebSocket message and print it out. '''
128136
while True:
129137
message = await ws.get_message()
130-
print(f'message: {message}')
138+
print(f'message: {message!r}')
131139

132140

133141
if __name__ == '__main__':

examples/generate-cert.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import trustme
55

6-
def main():
6+
def main() -> None:
77
here = pathlib.Path(__file__).parent
88
ca_path = here / 'fake.ca.pem'
99
server_path = here / 'fake.server.pem'

examples/server.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@
1414
import ssl
1515

1616
import trio
17-
from trio_websocket import serve_websocket, ConnectionClosed
17+
from trio_websocket import serve_websocket, ConnectionClosed, WebSocketRequest
1818

1919

2020
logging.basicConfig(level=logging.DEBUG)
2121
logger = logging.getLogger()
2222
here = pathlib.Path(__file__).parent
2323

2424

25-
def parse_args():
25+
def parse_args() -> argparse.Namespace:
2626
''' Parse command line arguments. '''
2727
parser = argparse.ArgumentParser(description='Example trio-websocket client')
2828
parser.add_argument('--ssl', action='store_true', help='Use SSL')
@@ -32,7 +32,7 @@ def parse_args():
3232
return parser.parse_args()
3333

3434

35-
async def main(args):
35+
async def main(args: argparse.Namespace) -> None:
3636
''' Main entry point. '''
3737
logging.info('Starting websocket server…')
3838
if args.ssl:
@@ -48,7 +48,7 @@ async def main(args):
4848
await serve_websocket(handler, host, args.port, ssl_context)
4949

5050

51-
async def handler(request):
51+
async def handler(request: WebSocketRequest) -> None:
5252
''' Reverse incoming websocket messages and send them back. '''
5353
logging.info('Handler starting on path "%s"', request.path)
5454
ws = await request.accept()

pyproject.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[tool.mypy]
2+
explicit_package_bases = true
3+
files = ["trio_websocket", "tests", "autobahn", "examples"]
4+
show_column_numbers = true
5+
show_error_codes = true
6+
show_traceback = true
7+
disallow_any_decorated = true
8+
disallow_any_unimported = true
9+
ignore_missing_imports = true
10+
local_partial_types = true
11+
no_implicit_optional = true
12+
strict = true
13+
warn_unreachable = true

setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@
3535
'Programming Language :: Python :: 3.12',
3636
'Programming Language :: Python :: Implementation :: CPython',
3737
'Programming Language :: Python :: Implementation :: PyPy',
38+
'Typing :: Typed',
3839
],
3940
python_requires=">=3.8",
4041
keywords='websocket client server trio',
4142
packages=find_packages(exclude=['docs', 'examples', 'tests']),
43+
package_data={"trio-websocket": ["py.typed"]},
4244
install_requires=[
4345
'exceptiongroup; python_version<"3.11"',
4446
'trio>=0.11',

0 commit comments

Comments
 (0)