14
14
15
15
import re
16
16
from http import HTTPStatus
17
- from typing import Tuple
17
+ from typing import Awaitable , Callable , Dict , NoReturn , Optional , Tuple
18
18
19
19
from twisted .internet .defer import Deferred
20
20
from twisted .web .resource import Resource
36
36
from tests import unittest
37
37
from tests .http .server ._base import test_disconnect
38
38
from tests .server import (
39
+ FakeChannel ,
39
40
FakeSite ,
40
41
ThreadedMemoryReactorClock ,
41
42
make_request ,
44
45
45
46
46
47
class JsonResourceTests (unittest .TestCase ):
47
- def setUp (self ):
48
+ def setUp (self ) -> None :
48
49
self .reactor = ThreadedMemoryReactorClock ()
49
50
self .hs_clock = Clock (self .reactor )
50
51
self .homeserver = setup_test_homeserver (
@@ -54,15 +55,17 @@ def setUp(self):
54
55
reactor = self .reactor ,
55
56
)
56
57
57
- def test_handler_for_request (self ):
58
+ def test_handler_for_request (self ) -> None :
58
59
"""
59
60
JsonResource.handler_for_request gives correctly decoded URL args to
60
61
the callback, while Twisted will give the raw bytes of URL query
61
62
arguments.
62
63
"""
63
64
got_kwargs = {}
64
65
65
- def _callback (request , ** kwargs ):
66
+ def _callback (
67
+ request : SynapseRequest , ** kwargs : object
68
+ ) -> Tuple [int , Dict [str , object ]]:
66
69
got_kwargs .update (kwargs )
67
70
return 200 , kwargs
68
71
@@ -83,13 +86,13 @@ def _callback(request, **kwargs):
83
86
84
87
self .assertEqual (got_kwargs , {"room_id" : "\N{SNOWMAN} " })
85
88
86
- def test_callback_direct_exception (self ):
89
+ def test_callback_direct_exception (self ) -> None :
87
90
"""
88
91
If the web callback raises an uncaught exception, it will be translated
89
92
into a 500.
90
93
"""
91
94
92
- def _callback (request , ** kwargs ) :
95
+ def _callback (request : SynapseRequest , ** kwargs : object ) -> NoReturn :
93
96
raise Exception ("boo" )
94
97
95
98
res = JsonResource (self .homeserver )
@@ -103,17 +106,17 @@ def _callback(request, **kwargs):
103
106
104
107
self .assertEqual (channel .result ["code" ], b"500" )
105
108
106
- def test_callback_indirect_exception (self ):
109
+ def test_callback_indirect_exception (self ) -> None :
107
110
"""
108
111
If the web callback raises an uncaught exception in a Deferred, it will
109
112
be translated into a 500.
110
113
"""
111
114
112
- def _throw (* args ) :
115
+ def _throw (* args : object ) -> NoReturn :
113
116
raise Exception ("boo" )
114
117
115
- def _callback (request , ** kwargs ) :
116
- d = Deferred ()
118
+ def _callback (request : SynapseRequest , ** kwargs : object ) -> "Deferred[None]" :
119
+ d : "Deferred[None]" = Deferred ()
117
120
d .addCallback (_throw )
118
121
self .reactor .callLater (0.5 , d .callback , True )
119
122
return make_deferred_yieldable (d )
@@ -129,13 +132,13 @@ def _callback(request, **kwargs):
129
132
130
133
self .assertEqual (channel .result ["code" ], b"500" )
131
134
132
- def test_callback_synapseerror (self ):
135
+ def test_callback_synapseerror (self ) -> None :
133
136
"""
134
137
If the web callback raises a SynapseError, it returns the appropriate
135
138
status code and message set in it.
136
139
"""
137
140
138
- def _callback (request , ** kwargs ) :
141
+ def _callback (request : SynapseRequest , ** kwargs : object ) -> NoReturn :
139
142
raise SynapseError (403 , "Forbidden!!one!" , Codes .FORBIDDEN )
140
143
141
144
res = JsonResource (self .homeserver )
@@ -151,12 +154,12 @@ def _callback(request, **kwargs):
151
154
self .assertEqual (channel .json_body ["error" ], "Forbidden!!one!" )
152
155
self .assertEqual (channel .json_body ["errcode" ], "M_FORBIDDEN" )
153
156
154
- def test_no_handler (self ):
157
+ def test_no_handler (self ) -> None :
155
158
"""
156
159
If there is no handler to process the request, Synapse will return 400.
157
160
"""
158
161
159
- def _callback (request , ** kwargs ) :
162
+ def _callback (request : SynapseRequest , ** kwargs : object ) -> None :
160
163
"""
161
164
Not ever actually called!
162
165
"""
@@ -175,14 +178,16 @@ def _callback(request, **kwargs):
175
178
self .assertEqual (channel .json_body ["error" ], "Unrecognized request" )
176
179
self .assertEqual (channel .json_body ["errcode" ], "M_UNRECOGNIZED" )
177
180
178
- def test_head_request (self ):
181
+ def test_head_request (self ) -> None :
179
182
"""
180
183
JsonResource.handler_for_request gives correctly decoded URL args to
181
184
the callback, while Twisted will give the raw bytes of URL query
182
185
arguments.
183
186
"""
184
187
185
- def _callback (request , ** kwargs ):
188
+ def _callback (
189
+ request : SynapseRequest , ** kwargs : object
190
+ ) -> Tuple [int , Dict [str , object ]]:
186
191
return 200 , {"result" : True }
187
192
188
193
res = JsonResource (self .homeserver )
@@ -203,20 +208,21 @@ def _callback(request, **kwargs):
203
208
204
209
205
210
class OptionsResourceTests (unittest .TestCase ):
206
- def setUp (self ):
211
+ def setUp (self ) -> None :
207
212
self .reactor = ThreadedMemoryReactorClock ()
208
213
209
214
class DummyResource (Resource ):
210
215
isLeaf = True
211
216
212
- def render (self , request ):
213
- return request .path
217
+ def render (self , request : SynapseRequest ) -> bytes :
218
+ # Type-ignore: mypy thinks request.path is Optional[Any], not bytes.
219
+ return request .path # type: ignore[return-value]
214
220
215
221
# Setup a resource with some children.
216
222
self .resource = OptionsResource ()
217
223
self .resource .putChild (b"res" , DummyResource ())
218
224
219
- def _make_request (self , method , path ) :
225
+ def _make_request (self , method : bytes , path : bytes ) -> FakeChannel :
220
226
"""Create a request from the method/path and return a channel with the response."""
221
227
# Create a site and query for the resource.
222
228
site = SynapseSite (
@@ -233,7 +239,7 @@ def _make_request(self, method, path):
233
239
channel = make_request (self .reactor , site , method , path , shorthand = False )
234
240
return channel
235
241
236
- def test_unknown_options_request (self ):
242
+ def test_unknown_options_request (self ) -> None :
237
243
"""An OPTIONS requests to an unknown URL still returns 204 No Content."""
238
244
channel = self ._make_request (b"OPTIONS" , b"/foo/" )
239
245
self .assertEqual (channel .result ["code" ], b"204" )
@@ -253,7 +259,7 @@ def test_unknown_options_request(self):
253
259
"has CORS Headers header" ,
254
260
)
255
261
256
- def test_known_options_request (self ):
262
+ def test_known_options_request (self ) -> None :
257
263
"""An OPTIONS requests to an known URL still returns 204 No Content."""
258
264
channel = self ._make_request (b"OPTIONS" , b"/res/" )
259
265
self .assertEqual (channel .result ["code" ], b"204" )
@@ -273,12 +279,12 @@ def test_known_options_request(self):
273
279
"has CORS Headers header" ,
274
280
)
275
281
276
- def test_unknown_request (self ):
282
+ def test_unknown_request (self ) -> None :
277
283
"""A non-OPTIONS request to an unknown URL should 404."""
278
284
channel = self ._make_request (b"GET" , b"/foo/" )
279
285
self .assertEqual (channel .result ["code" ], b"404" )
280
286
281
- def test_known_request (self ):
287
+ def test_known_request (self ) -> None :
282
288
"""A non-OPTIONS request to an known URL should query the proper resource."""
283
289
channel = self ._make_request (b"GET" , b"/res/" )
284
290
self .assertEqual (channel .result ["code" ], b"200" )
@@ -287,16 +293,17 @@ def test_known_request(self):
287
293
288
294
class WrapHtmlRequestHandlerTests (unittest .TestCase ):
289
295
class TestResource (DirectServeHtmlResource ):
290
- callback = None
296
+ callback : Optional [ Callable [..., Awaitable [ None ]]]
291
297
292
- async def _async_render_GET (self , request ):
298
+ async def _async_render_GET (self , request : SynapseRequest ) -> None :
299
+ assert self .callback is not None
293
300
await self .callback (request )
294
301
295
- def setUp (self ):
302
+ def setUp (self ) -> None :
296
303
self .reactor = ThreadedMemoryReactorClock ()
297
304
298
- def test_good_response (self ):
299
- async def callback (request ) :
305
+ def test_good_response (self ) -> None :
306
+ async def callback (request : SynapseRequest ) -> None :
300
307
request .write (b"response" )
301
308
request .finish ()
302
309
@@ -311,13 +318,13 @@ async def callback(request):
311
318
body = channel .result ["body" ]
312
319
self .assertEqual (body , b"response" )
313
320
314
- def test_redirect_exception (self ):
321
+ def test_redirect_exception (self ) -> None :
315
322
"""
316
323
If the callback raises a RedirectException, it is turned into a 30x
317
324
with the right location.
318
325
"""
319
326
320
- async def callback (request , ** kwargs ) :
327
+ async def callback (request : SynapseRequest , ** kwargs : object ) -> None :
321
328
raise RedirectException (b"/look/an/eagle" , 301 )
322
329
323
330
res = WrapHtmlRequestHandlerTests .TestResource ()
@@ -332,13 +339,13 @@ async def callback(request, **kwargs):
332
339
location_headers = [v for k , v in headers if k == b"Location" ]
333
340
self .assertEqual (location_headers , [b"/look/an/eagle" ])
334
341
335
- def test_redirect_exception_with_cookie (self ):
342
+ def test_redirect_exception_with_cookie (self ) -> None :
336
343
"""
337
344
If the callback raises a RedirectException which sets a cookie, that is
338
345
returned too
339
346
"""
340
347
341
- async def callback (request , ** kwargs ) :
348
+ async def callback (request : SynapseRequest , ** kwargs : object ) -> NoReturn :
342
349
e = RedirectException (b"/no/over/there" , 304 )
343
350
e .cookies .append (b"session=yespls" )
344
351
raise e
@@ -357,10 +364,10 @@ async def callback(request, **kwargs):
357
364
cookies_headers = [v for k , v in headers if k == b"Set-Cookie" ]
358
365
self .assertEqual (cookies_headers , [b"session=yespls" ])
359
366
360
- def test_head_request (self ):
367
+ def test_head_request (self ) -> None :
361
368
"""A head request should work by being turned into a GET request."""
362
369
363
- async def callback (request ) :
370
+ async def callback (request : SynapseRequest ) -> None :
364
371
request .write (b"response" )
365
372
request .finish ()
366
373
@@ -410,7 +417,7 @@ async def _async_render_POST(self, request: SynapseRequest) -> Tuple[int, bytes]
410
417
class DirectServeJsonResourceCancellationTests (unittest .TestCase ):
411
418
"""Tests for `DirectServeJsonResource` cancellation."""
412
419
413
- def setUp (self ):
420
+ def setUp (self ) -> None :
414
421
self .reactor = ThreadedMemoryReactorClock ()
415
422
self .clock = Clock (self .reactor )
416
423
self .resource = CancellableDirectServeJsonResource (self .clock )
@@ -444,7 +451,7 @@ def test_uncancellable_disconnect(self) -> None:
444
451
class DirectServeHtmlResourceCancellationTests (unittest .TestCase ):
445
452
"""Tests for `DirectServeHtmlResource` cancellation."""
446
453
447
- def setUp (self ):
454
+ def setUp (self ) -> None :
448
455
self .reactor = ThreadedMemoryReactorClock ()
449
456
self .clock = Clock (self .reactor )
450
457
self .resource = CancellableDirectServeHtmlResource (self .clock )
0 commit comments