1414
1515import re
1616from http import HTTPStatus
17- from typing import Tuple
17+ from typing import Awaitable , Callable , Dict , NoReturn , Optional , Tuple
1818
1919from twisted .internet .defer import Deferred
2020from twisted .web .resource import Resource
3636from tests import unittest
3737from tests .http .server ._base import test_disconnect
3838from tests .server import (
39+ FakeChannel ,
3940 FakeSite ,
4041 ThreadedMemoryReactorClock ,
4142 make_request ,
4445
4546
4647class JsonResourceTests (unittest .TestCase ):
47- def setUp (self ):
48+ def setUp (self ) -> None :
4849 self .reactor = ThreadedMemoryReactorClock ()
4950 self .hs_clock = Clock (self .reactor )
5051 self .homeserver = setup_test_homeserver (
@@ -54,15 +55,17 @@ def setUp(self):
5455 reactor = self .reactor ,
5556 )
5657
57- def test_handler_for_request (self ):
58+ def test_handler_for_request (self ) -> None :
5859 """
5960 JsonResource.handler_for_request gives correctly decoded URL args to
6061 the callback, while Twisted will give the raw bytes of URL query
6162 arguments.
6263 """
6364 got_kwargs = {}
6465
65- def _callback (request , ** kwargs ):
66+ def _callback (
67+ request : SynapseRequest , ** kwargs : object
68+ ) -> Tuple [int , Dict [str , object ]]:
6669 got_kwargs .update (kwargs )
6770 return 200 , kwargs
6871
@@ -83,13 +86,13 @@ def _callback(request, **kwargs):
8386
8487 self .assertEqual (got_kwargs , {"room_id" : "\N{SNOWMAN} " })
8588
86- def test_callback_direct_exception (self ):
89+ def test_callback_direct_exception (self ) -> None :
8790 """
8891 If the web callback raises an uncaught exception, it will be translated
8992 into a 500.
9093 """
9194
92- def _callback (request , ** kwargs ) :
95+ def _callback (request : SynapseRequest , ** kwargs : object ) -> NoReturn :
9396 raise Exception ("boo" )
9497
9598 res = JsonResource (self .homeserver )
@@ -103,17 +106,17 @@ def _callback(request, **kwargs):
103106
104107 self .assertEqual (channel .result ["code" ], b"500" )
105108
106- def test_callback_indirect_exception (self ):
109+ def test_callback_indirect_exception (self ) -> None :
107110 """
108111 If the web callback raises an uncaught exception in a Deferred, it will
109112 be translated into a 500.
110113 """
111114
112- def _throw (* args ) :
115+ def _throw (* args : object ) -> NoReturn :
113116 raise Exception ("boo" )
114117
115- def _callback (request , ** kwargs ) :
116- d = Deferred ()
118+ def _callback (request : SynapseRequest , ** kwargs : object ) -> "Deferred[None]" :
119+ d : "Deferred[None]" = Deferred ()
117120 d .addCallback (_throw )
118121 self .reactor .callLater (0.5 , d .callback , True )
119122 return make_deferred_yieldable (d )
@@ -129,13 +132,13 @@ def _callback(request, **kwargs):
129132
130133 self .assertEqual (channel .result ["code" ], b"500" )
131134
132- def test_callback_synapseerror (self ):
135+ def test_callback_synapseerror (self ) -> None :
133136 """
134137 If the web callback raises a SynapseError, it returns the appropriate
135138 status code and message set in it.
136139 """
137140
138- def _callback (request , ** kwargs ) :
141+ def _callback (request : SynapseRequest , ** kwargs : object ) -> NoReturn :
139142 raise SynapseError (403 , "Forbidden!!one!" , Codes .FORBIDDEN )
140143
141144 res = JsonResource (self .homeserver )
@@ -151,12 +154,12 @@ def _callback(request, **kwargs):
151154 self .assertEqual (channel .json_body ["error" ], "Forbidden!!one!" )
152155 self .assertEqual (channel .json_body ["errcode" ], "M_FORBIDDEN" )
153156
154- def test_no_handler (self ):
157+ def test_no_handler (self ) -> None :
155158 """
156159 If there is no handler to process the request, Synapse will return 400.
157160 """
158161
159- def _callback (request , ** kwargs ) :
162+ def _callback (request : SynapseRequest , ** kwargs : object ) -> None :
160163 """
161164 Not ever actually called!
162165 """
@@ -175,14 +178,16 @@ def _callback(request, **kwargs):
175178 self .assertEqual (channel .json_body ["error" ], "Unrecognized request" )
176179 self .assertEqual (channel .json_body ["errcode" ], "M_UNRECOGNIZED" )
177180
178- def test_head_request (self ):
181+ def test_head_request (self ) -> None :
179182 """
180183 JsonResource.handler_for_request gives correctly decoded URL args to
181184 the callback, while Twisted will give the raw bytes of URL query
182185 arguments.
183186 """
184187
185- def _callback (request , ** kwargs ):
188+ def _callback (
189+ request : SynapseRequest , ** kwargs : object
190+ ) -> Tuple [int , Dict [str , object ]]:
186191 return 200 , {"result" : True }
187192
188193 res = JsonResource (self .homeserver )
@@ -203,20 +208,21 @@ def _callback(request, **kwargs):
203208
204209
205210class OptionsResourceTests (unittest .TestCase ):
206- def setUp (self ):
211+ def setUp (self ) -> None :
207212 self .reactor = ThreadedMemoryReactorClock ()
208213
209214 class DummyResource (Resource ):
210215 isLeaf = True
211216
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]
214220
215221 # Setup a resource with some children.
216222 self .resource = OptionsResource ()
217223 self .resource .putChild (b"res" , DummyResource ())
218224
219- def _make_request (self , method , path ) :
225+ def _make_request (self , method : bytes , path : bytes ) -> FakeChannel :
220226 """Create a request from the method/path and return a channel with the response."""
221227 # Create a site and query for the resource.
222228 site = SynapseSite (
@@ -233,7 +239,7 @@ def _make_request(self, method, path):
233239 channel = make_request (self .reactor , site , method , path , shorthand = False )
234240 return channel
235241
236- def test_unknown_options_request (self ):
242+ def test_unknown_options_request (self ) -> None :
237243 """An OPTIONS requests to an unknown URL still returns 204 No Content."""
238244 channel = self ._make_request (b"OPTIONS" , b"/foo/" )
239245 self .assertEqual (channel .result ["code" ], b"204" )
@@ -253,7 +259,7 @@ def test_unknown_options_request(self):
253259 "has CORS Headers header" ,
254260 )
255261
256- def test_known_options_request (self ):
262+ def test_known_options_request (self ) -> None :
257263 """An OPTIONS requests to an known URL still returns 204 No Content."""
258264 channel = self ._make_request (b"OPTIONS" , b"/res/" )
259265 self .assertEqual (channel .result ["code" ], b"204" )
@@ -273,12 +279,12 @@ def test_known_options_request(self):
273279 "has CORS Headers header" ,
274280 )
275281
276- def test_unknown_request (self ):
282+ def test_unknown_request (self ) -> None :
277283 """A non-OPTIONS request to an unknown URL should 404."""
278284 channel = self ._make_request (b"GET" , b"/foo/" )
279285 self .assertEqual (channel .result ["code" ], b"404" )
280286
281- def test_known_request (self ):
287+ def test_known_request (self ) -> None :
282288 """A non-OPTIONS request to an known URL should query the proper resource."""
283289 channel = self ._make_request (b"GET" , b"/res/" )
284290 self .assertEqual (channel .result ["code" ], b"200" )
@@ -287,16 +293,17 @@ def test_known_request(self):
287293
288294class WrapHtmlRequestHandlerTests (unittest .TestCase ):
289295 class TestResource (DirectServeHtmlResource ):
290- callback = None
296+ callback : Optional [ Callable [..., Awaitable [ None ]]]
291297
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
293300 await self .callback (request )
294301
295- def setUp (self ):
302+ def setUp (self ) -> None :
296303 self .reactor = ThreadedMemoryReactorClock ()
297304
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 :
300307 request .write (b"response" )
301308 request .finish ()
302309
@@ -311,13 +318,13 @@ async def callback(request):
311318 body = channel .result ["body" ]
312319 self .assertEqual (body , b"response" )
313320
314- def test_redirect_exception (self ):
321+ def test_redirect_exception (self ) -> None :
315322 """
316323 If the callback raises a RedirectException, it is turned into a 30x
317324 with the right location.
318325 """
319326
320- async def callback (request , ** kwargs ) :
327+ async def callback (request : SynapseRequest , ** kwargs : object ) -> None :
321328 raise RedirectException (b"/look/an/eagle" , 301 )
322329
323330 res = WrapHtmlRequestHandlerTests .TestResource ()
@@ -332,13 +339,13 @@ async def callback(request, **kwargs):
332339 location_headers = [v for k , v in headers if k == b"Location" ]
333340 self .assertEqual (location_headers , [b"/look/an/eagle" ])
334341
335- def test_redirect_exception_with_cookie (self ):
342+ def test_redirect_exception_with_cookie (self ) -> None :
336343 """
337344 If the callback raises a RedirectException which sets a cookie, that is
338345 returned too
339346 """
340347
341- async def callback (request , ** kwargs ) :
348+ async def callback (request : SynapseRequest , ** kwargs : object ) -> NoReturn :
342349 e = RedirectException (b"/no/over/there" , 304 )
343350 e .cookies .append (b"session=yespls" )
344351 raise e
@@ -357,10 +364,10 @@ async def callback(request, **kwargs):
357364 cookies_headers = [v for k , v in headers if k == b"Set-Cookie" ]
358365 self .assertEqual (cookies_headers , [b"session=yespls" ])
359366
360- def test_head_request (self ):
367+ def test_head_request (self ) -> None :
361368 """A head request should work by being turned into a GET request."""
362369
363- async def callback (request ) :
370+ async def callback (request : SynapseRequest ) -> None :
364371 request .write (b"response" )
365372 request .finish ()
366373
@@ -410,7 +417,7 @@ async def _async_render_POST(self, request: SynapseRequest) -> Tuple[int, bytes]
410417class DirectServeJsonResourceCancellationTests (unittest .TestCase ):
411418 """Tests for `DirectServeJsonResource` cancellation."""
412419
413- def setUp (self ):
420+ def setUp (self ) -> None :
414421 self .reactor = ThreadedMemoryReactorClock ()
415422 self .clock = Clock (self .reactor )
416423 self .resource = CancellableDirectServeJsonResource (self .clock )
@@ -444,7 +451,7 @@ def test_uncancellable_disconnect(self) -> None:
444451class DirectServeHtmlResourceCancellationTests (unittest .TestCase ):
445452 """Tests for `DirectServeHtmlResource` cancellation."""
446453
447- def setUp (self ):
454+ def setUp (self ) -> None :
448455 self .reactor = ThreadedMemoryReactorClock ()
449456 self .clock = Clock (self .reactor )
450457 self .resource = CancellableDirectServeHtmlResource (self .clock )
0 commit comments