11
11
import ssl
12
12
import sys
13
13
import urllib .parse
14
+ from typing import NoReturn
14
15
15
16
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
+ )
17
24
18
25
19
26
logging .basicConfig (level = logging .DEBUG )
20
27
here = pathlib .Path (__file__ ).parent
21
28
22
29
23
- def commands ():
30
+ def commands () -> None :
24
31
''' Print the supported commands. '''
25
32
print ('Commands: ' )
26
33
print ('send <MESSAGE> -> send message' )
@@ -29,7 +36,7 @@ def commands():
29
36
print ()
30
37
31
38
32
- def parse_args ():
39
+ def parse_args () -> argparse . Namespace :
33
40
''' Parse command line arguments. '''
34
41
parser = argparse .ArgumentParser (description = 'Example trio-websocket client' )
35
42
parser .add_argument ('--heartbeat' , action = 'store_true' ,
@@ -38,7 +45,7 @@ def parse_args():
38
45
return parser .parse_args ()
39
46
40
47
41
- async def main (args ) :
48
+ async def main (args : argparse . Namespace ) -> bool :
42
49
''' Main entry point, returning False in the case of logged error. '''
43
50
if urllib .parse .urlsplit (args .url ).scheme == 'wss' :
44
51
# Configure SSL context to handle our self-signed certificate. Most
@@ -59,9 +66,10 @@ async def main(args):
59
66
except HandshakeError as e :
60
67
logging .error ('Connection attempt failed: %s' , e )
61
68
return False
69
+ return True
62
70
63
71
64
- async def handle_connection (ws , use_heartbeat ) :
72
+ async def handle_connection (ws : WebSocketConnection , use_heartbeat : bool ) -> None :
65
73
''' Handle the connection. '''
66
74
logging .debug ('Connected!' )
67
75
try :
@@ -71,11 +79,12 @@ async def handle_connection(ws, use_heartbeat):
71
79
nursery .start_soon (get_commands , ws )
72
80
nursery .start_soon (get_messages , ws )
73
81
except ConnectionClosed as cc :
82
+ assert isinstance (cc .reason , CloseReason )
74
83
reason = '<no reason>' if cc .reason .reason is None else f'"{ cc .reason .reason } "'
75
84
print (f'Closed: { cc .reason .code } /{ cc .reason .name } { reason } ' )
76
85
77
86
78
- async def heartbeat (ws , timeout , interval ) :
87
+ async def heartbeat (ws : WebSocketConnection , timeout : float , interval : float ) -> NoReturn :
79
88
'''
80
89
Send periodic pings on WebSocket ``ws``.
81
90
@@ -99,11 +108,10 @@ async def heartbeat(ws, timeout, interval):
99
108
await trio .sleep (interval )
100
109
101
110
102
- async def get_commands (ws ) :
111
+ async def get_commands (ws : WebSocketConnection ) -> None :
103
112
''' In a loop: get a command from the user and execute it. '''
104
113
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> ' )
107
115
if cmd .startswith ('ping' ):
108
116
payload = cmd [5 :].encode ('utf8' ) or None
109
117
await ws .ping (payload )
@@ -123,11 +131,11 @@ async def get_commands(ws):
123
131
await trio .sleep (0.25 )
124
132
125
133
126
- async def get_messages (ws ) :
134
+ async def get_messages (ws : WebSocketConnection ) -> None :
127
135
''' In a loop: get a WebSocket message and print it out. '''
128
136
while True :
129
137
message = await ws .get_message ()
130
- print (f'message: { message } ' )
138
+ print (f'message: { message !r } ' )
131
139
132
140
133
141
if __name__ == '__main__' :
0 commit comments