Repository: twisted/twisted

Issue:
type annotate more tests again
**Is your feature request related to a problem? Please describe.**
type annotate more tests again


Discussion:

Resolving patch:
diff --git a/src/twisted/web/pages.py b/src/twisted/web/pages.py
--- a/src/twisted/web/pages.py
+++ b/src/twisted/web/pages.py
@@ -76,7 +76,7 @@ def getChild(self, path: bytes, request: IRequest) -> Resource:
         return self
 
 
-def errorPage(code: int, brief: str, detail: str) -> IResource:
+def errorPage(code: int, brief: str, detail: str) -> _ErrorPage:
     """
     Build a resource that responds to all requests with a particular HTTP
     status code and an HTML body containing some descriptive text. This is
diff --git a/src/twisted/web/resource.py b/src/twisted/web/resource.py
--- a/src/twisted/web/resource.py
+++ b/src/twisted/web/resource.py
@@ -7,7 +7,7 @@
 
 See L{twisted.web.pages} for some utility implementations.
 """
-
+from __future__ import annotations
 
 __all__ = [
     "IResource",
@@ -20,6 +20,7 @@
 ]
 
 import warnings
+from typing import Sequence
 
 from zope.interface import Attribute, Interface, implementer
 
@@ -116,6 +117,7 @@ class Resource:
     """
 
     entityType = IResource
+    allowedMethods: Sequence[bytes]
 
     server = None
 


Test patch:
diff --git a/src/twisted/web/test/test_pages.py b/src/twisted/web/test/test_pages.py
--- a/src/twisted/web/test/test_pages.py
+++ b/src/twisted/web/test/test_pages.py
@@ -52,7 +52,7 @@ def assertResponse(self, request: DummyRequest, code: int, body: bytes) -> None:
             body.decode("latin-1"),
         )
 
-    def test_escapesHTML(self):
+    def test_escapesHTML(self) -> None:
         """
         The I{brief} and I{detail} parameters are HTML-escaped on render.
         """
@@ -67,18 +67,18 @@ def test_escapesHTML(self):
             ),
         )
 
-    def test_getChild(self):
+    def test_getChild(self) -> None:
         """
         The C{getChild} method of the resource returned by L{errorPage} returns
         the L{_ErrorPage} it is called on.
         """
         page = errorPage(404, "foo", "bar")
         self.assertIs(
-            page.getChild(b"name", DummyRequest([b""])),
+            page.getChild(b"name", cast(IRequest, DummyRequest([b""]))),
             page,
         )
 
-    def test_notFoundDefaults(self):
+    def test_notFoundDefaults(self) -> None:
         """
         The default arguments to L{twisted.web.pages.notFound} produce
         a reasonable error page.
@@ -95,7 +95,7 @@ def test_notFoundDefaults(self):
             ),
         )
 
-    def test_forbiddenDefaults(self):
+    def test_forbiddenDefaults(self) -> None:
         """
         The default arguments to L{twisted.web.pages.forbidden} produce
         a reasonable error page.
diff --git a/src/twisted/web/test/test_resource.py b/src/twisted/web/test/test_resource.py
--- a/src/twisted/web/test/test_resource.py
+++ b/src/twisted/web/test/test_resource.py
@@ -8,6 +8,7 @@
 from twisted.trial.unittest import TestCase
 from twisted.web.error import UnsupportedMethod
 from twisted.web.http_headers import Headers
+from twisted.web.iweb import IRequest
 from twisted.web.resource import (
     FORBIDDEN,
     NOT_FOUND,
@@ -30,7 +31,7 @@ class ErrorPageTests(TestCase):
     noResource = NoResource
     forbiddenResource = ForbiddenResource
 
-    def test_deprecatedErrorPage(self):
+    def test_deprecatedErrorPage(self) -> None:
         """
         The public C{twisted.web.resource.ErrorPage} alias for the
         corresponding C{_Unsafe} class produces a deprecation warning when
@@ -44,7 +45,7 @@ def test_deprecatedErrorPage(self):
         self.assertEqual(warning["category"], DeprecationWarning)
         self.assertIn("twisted.web.pages.errorPage", warning["message"])
 
-    def test_deprecatedNoResource(self):
+    def test_deprecatedNoResource(self) -> None:
         """
         The public C{twisted.web.resource.NoResource} alias for the
         corresponding C{_Unsafe} class produces a deprecation warning when
@@ -58,7 +59,7 @@ def test_deprecatedNoResource(self):
         self.assertEqual(warning["category"], DeprecationWarning)
         self.assertIn("twisted.web.pages.notFound", warning["message"])
 
-    def test_deprecatedForbiddenResource(self):
+    def test_deprecatedForbiddenResource(self) -> None:
         """
         The public C{twisted.web.resource.ForbiddenResource} alias for the
         corresponding C{_Unsafe} class produce a deprecation warning when
@@ -72,7 +73,7 @@ def test_deprecatedForbiddenResource(self):
         self.assertEqual(warning["category"], DeprecationWarning)
         self.assertIn("twisted.web.pages.forbidden", warning["message"])
 
-    def test_getChild(self):
+    def test_getChild(self) -> None:
         """
         The C{getChild} method of L{ErrorPage} returns the L{ErrorPage} it is
         called on.
@@ -80,7 +81,9 @@ def test_getChild(self):
         page = self.errorPage(321, "foo", "bar")
         self.assertIdentical(page.getChild(b"name", object()), page)
 
-    def _pageRenderingTest(self, page, code, brief, detail):
+    def _pageRenderingTest(
+        self, page: Resource, code: int, brief: str, detail: str
+    ) -> None:
         request = DummyRequest([b""])
         template = (
             "\n"
@@ -100,7 +103,7 @@ def _pageRenderingTest(self, page, code, brief, detail):
             Headers({b"content-type": [b"text/html; charset=utf-8"]}),
         )
 
-    def test_errorPageRendering(self):
+    def test_errorPageRendering(self) -> None:
         """
         L{ErrorPage.render} returns a C{bytes} describing the error defined by
         the response code and message passed to L{ErrorPage.__init__}.  It also
@@ -113,7 +116,7 @@ def test_errorPageRendering(self):
         page = self.errorPage(code, brief, detail)
         self._pageRenderingTest(page, code, brief, detail)
 
-    def test_noResourceRendering(self):
+    def test_noResourceRendering(self) -> None:
         """
         L{NoResource} sets the HTTP I{NOT FOUND} code.
         """
@@ -121,7 +124,7 @@ def test_noResourceRendering(self):
         page = self.noResource(detail)
         self._pageRenderingTest(page, NOT_FOUND, "No Such Resource", detail)
 
-    def test_forbiddenResourceRendering(self):
+    def test_forbiddenResourceRendering(self) -> None:
         """
         L{ForbiddenResource} sets the HTTP I{FORBIDDEN} code.
         """
@@ -135,7 +138,7 @@ class DynamicChild(Resource):
     A L{Resource} to be created on the fly by L{DynamicChildren}.
     """
 
-    def __init__(self, path, request):
+    def __init__(self, path: bytes, request: IRequest) -> None:
         Resource.__init__(self)
         self.path = path
         self.request = request
@@ -146,7 +149,7 @@ class DynamicChildren(Resource):
     A L{Resource} with dynamic children.
     """
 
-    def getChild(self, path, request):
+    def getChild(self, path: bytes, request: IRequest) -> DynamicChild:
         return DynamicChild(path, request)
 
 
@@ -155,7 +158,7 @@ class BytesReturnedRenderable(Resource):
     A L{Resource} with minimal capabilities to render a response.
     """
 
-    def __init__(self, response):
+    def __init__(self, response: bytes) -> None:
         """
         @param response: A C{bytes} object giving the value to return from
             C{render_GET}.
@@ -163,7 +166,7 @@ def __init__(self, response):
         Resource.__init__(self)
         self._response = response
 
-    def render_GET(self, request):
+    def render_GET(self, request: object) -> bytes:
         """
         Render a response to a I{GET} request by returning a short byte string
         to be written by the server.
@@ -177,10 +180,10 @@ class ImplicitAllowedMethods(Resource):
     renderers to handle them.
     """
 
-    def render_GET(self, request):
+    def render_GET(self, request: object) -> None:
         pass
 
-    def render_PUT(self, request):
+    def render_PUT(self, request: object) -> None:
         pass
 
 
@@ -189,7 +192,7 @@ class ResourceTests(TestCase):
     Tests for L{Resource}.
     """
 
-    def test_staticChildren(self):
+    def test_staticChildren(self) -> None:
         """
         L{Resource.putChild} adds a I{static} child to the resource.  That child
         is returned from any call to L{Resource.getChildWithDefault} for the
@@ -204,7 +207,7 @@ def test_staticChildren(self):
             child, resource.getChildWithDefault(b"foo", DummyRequest([]))
         )
 
-    def test_dynamicChildren(self):
+    def test_dynamicChildren(self) -> None:
         """
         L{Resource.getChildWithDefault} delegates to L{Resource.getChild} when
         the requested path is not associated with any static child.
@@ -217,7 +220,7 @@ def test_dynamicChildren(self):
         self.assertEqual(child.path, path)
         self.assertIdentical(child.request, request)
 
-    def test_staticChildPathType(self):
+    def test_staticChildPathType(self) -> None:
         """
         Test that passing the wrong type to putChild results in a warning,
         and a failure in Python 3
@@ -228,7 +231,7 @@ def test_staticChildPathType(self):
         self.assertRaises(TypeError, resource.putChild, "foo", child)
         self.assertRaises(TypeError, resource.putChild, None, sibling)
 
-    def test_defaultHEAD(self):
+    def test_defaultHEAD(self) -> None:
         """
         When not otherwise overridden, L{Resource.render} treats a I{HEAD}
         request as if it were a I{GET} request.
@@ -239,7 +242,7 @@ def test_defaultHEAD(self):
         resource = BytesReturnedRenderable(expected)
         self.assertEqual(expected, resource.render(request))
 
-    def test_explicitAllowedMethods(self):
+    def test_explicitAllowedMethods(self) -> None:
         """
         The L{UnsupportedMethod} raised by L{Resource.render} for an unsupported
         request method has a C{allowedMethods} attribute set to the value of the
@@ -253,7 +256,7 @@ def test_explicitAllowedMethods(self):
         exc = self.assertRaises(UnsupportedMethod, resource.render, request)
         self.assertEqual(set(expected), set(exc.allowedMethods))
 
-    def test_implicitAllowedMethods(self):
+    def test_implicitAllowedMethods(self) -> None:
         """
         The L{UnsupportedMethod} raised by L{Resource.render} for an unsupported
         request method has a C{allowedMethods} attribute set to a list of the
@@ -274,7 +277,7 @@ class GetChildForRequestTests(TestCase):
     Tests for L{getChildForRequest}.
     """
 
-    def test_exhaustedPostPath(self):
+    def test_exhaustedPostPath(self) -> None:
         """
         L{getChildForRequest} returns whatever resource has been reached by the
         time the request's C{postpath} is empty.
@@ -284,7 +287,7 @@ def test_exhaustedPostPath(self):
         result = getChildForRequest(resource, request)
         self.assertIdentical(resource, result)
 
-    def test_leafResource(self):
+    def test_leafResource(self) -> None:
         """
         L{getChildForRequest} returns the first resource it encounters with a
         C{isLeaf} attribute set to C{True}.
@@ -295,7 +298,7 @@ def test_leafResource(self):
         result = getChildForRequest(resource, request)
         self.assertIdentical(resource, result)
 
-    def test_postPathToPrePath(self):
+    def test_postPathToPrePath(self) -> None:
         """
         As path segments from the request are traversed, they are taken from
         C{postpath} and put into C{prepath}.
diff --git a/src/twisted/web/test/test_tap.py b/src/twisted/web/test/test_tap.py
--- a/src/twisted/web/test/test_tap.py
+++ b/src/twisted/web/test/test_tap.py
@@ -4,14 +4,15 @@
 """
 Tests for L{twisted.web.tap}.
 """
-
+from __future__ import annotations
 
 import os
 import stat
+from typing import cast
 from unittest import skipIf
 
 from twisted.internet import endpoints, reactor
-from twisted.internet.interfaces import IReactorUNIX
+from twisted.internet.interfaces import IReactorCore, IReactorUNIX
 from twisted.python.filepath import FilePath
 from twisted.python.reflect import requireModule
 from twisted.python.threadpool import ThreadPool
@@ -41,7 +42,7 @@ class ServiceTests(TestCase):
     Tests for the service creation APIs in L{twisted.web.tap}.
     """
 
-    def _pathOption(self):
+    def _pathOption(self) -> tuple[FilePath[str], File]:
         """
         Helper for the I{--path} tests which creates a directory and creates
         an L{Options} object which uses that directory as its static
@@ -58,7 +59,7 @@ def _pathOption(self):
         root = options["root"]
         return path, root
 
-    def test_path(self):
+    def test_path(self) -> None:
         """
         The I{--path} option causes L{Options} to create a root resource
         which serves responses from the specified path.
@@ -71,7 +72,7 @@ def test_path(self):
         not IReactorUNIX.providedBy(reactor),
         "The reactor does not support UNIX domain sockets",
     )
-    def test_pathServer(self):
+    def test_pathServer(self) -> None:
         """
         The I{--path} option to L{makeService} causes it to return a service
         which will listen on the server address given by the I{--port} option.
@@ -89,7 +90,7 @@ def test_pathServer(self):
         self.assertTrue(os.path.exists(port))
         self.assertTrue(stat.S_ISSOCK(os.stat(port).st_mode))
 
-    def test_cgiProcessor(self):
+    def test_cgiProcessor(self) -> None:
         """
         The I{--path} option creates a root resource which serves a
         L{CGIScript} instance for any child with the C{".cgi"} extension.
@@ -98,7 +99,7 @@ def test_cgiProcessor(self):
         path.child("foo.cgi").setContent(b"")
         self.assertIsInstance(root.getChild("foo.cgi", None), CGIScript)
 
-    def test_epyProcessor(self):
+    def test_epyProcessor(self) -> None:
         """
         The I{--path} option creates a root resource which serves a
         L{PythonScript} instance for any child with the C{".epy"} extension.
@@ -107,7 +108,7 @@ def test_epyProcessor(self):
         path.child("foo.epy").setContent(b"")
         self.assertIsInstance(root.getChild("foo.epy", None), PythonScript)
 
-    def test_rpyProcessor(self):
+    def test_rpyProcessor(self) -> None:
         """
         The I{--path} option creates a root resource which serves the
         C{resource} global defined by the Python source in any child with
@@ -123,7 +124,7 @@ def test_rpyProcessor(self):
         self.assertEqual(child.data, "content")
         self.assertEqual(child.type, "major/minor")
 
-    def test_makePersonalServerFactory(self):
+    def test_makePersonalServerFactory(self) -> None:
         """
         L{makePersonalServerFactory} returns a PB server factory which has
         as its root object a L{ResourcePublisher}.
@@ -140,7 +141,7 @@ def test_makePersonalServerFactory(self):
         not IReactorUNIX.providedBy(reactor),
         "The reactor does not support UNIX domain sockets",
     )
-    def test_personalServer(self):
+    def test_personalServer(self) -> None:
         """
         The I{--personal} option to L{makeService} causes it to return a
         service which will listen on the server address given by the I{--port}
@@ -159,7 +160,7 @@ def test_personalServer(self):
         not IReactorUNIX.providedBy(reactor),
         "The reactor does not support UNIX domain sockets",
     )
-    def test_defaultPersonalPath(self):
+    def test_defaultPersonalPath(self) -> None:
         """
         If the I{--port} option not specified but the I{--personal} option is,
         L{Options} defaults the port to C{UserDirectory.userSocketName} in the
@@ -170,7 +171,7 @@ def test_defaultPersonalPath(self):
         path = os.path.expanduser(os.path.join("~", UserDirectory.userSocketName))
         self.assertEqual(options["ports"][0], f"unix:{path}")
 
-    def test_defaultPort(self):
+    def test_defaultPort(self) -> None:
         """
         If the I{--port} option is not specified, L{Options} defaults the port
         to C{8080}.
@@ -181,7 +182,7 @@ def test_defaultPort(self):
             endpoints._parseServer(options["ports"][0], None)[:2], ("TCP", (8080, None))
         )
 
-    def test_twoPorts(self):
+    def test_twoPorts(self) -> None:
         """
         If the I{--http} option is given twice, there are two listeners
         """
@@ -190,7 +191,7 @@ def test_twoPorts(self):
         self.assertIn("8001", options["ports"][0])
         self.assertIn("8002", options["ports"][1])
 
-    def test_wsgi(self):
+    def test_wsgi(self) -> None:
         """
         The I{--wsgi} option takes the fully-qualifed Python name of a WSGI
         application object and creates a L{WSGIResource} at the root which
@@ -206,13 +207,13 @@ def test_wsgi(self):
 
         # The threadpool should start and stop with the reactor.
         self.assertFalse(root._threadpool.started)
-        reactor.fireSystemEvent("startup")
+        cast(IReactorCore, reactor).fireSystemEvent("startup")
         self.assertTrue(root._threadpool.started)
         self.assertFalse(root._threadpool.joined)
-        reactor.fireSystemEvent("shutdown")
+        cast(IReactorCore, reactor).fireSystemEvent("shutdown")
         self.assertTrue(root._threadpool.joined)
 
-    def test_invalidApplication(self):
+    def test_invalidApplication(self) -> None:
         """
         If I{--wsgi} is given an invalid name, L{Options.parseOptions}
         raises L{UsageError}.
@@ -223,7 +224,7 @@ def test_invalidApplication(self):
             self.assertEqual(str(exc), f"No such WSGI application: {name!r}")
 
     @skipIf(requireModule("OpenSSL.SSL") is not None, "SSL module is available.")
-    def test_HTTPSFailureOnMissingSSL(self):
+    def test_HTTPSFailureOnMissingSSL(self) -> None:
         """
         An L{UsageError} is raised when C{https} is requested but there is no
         support for SSL.
@@ -235,7 +236,7 @@ def test_HTTPSFailureOnMissingSSL(self):
         self.assertEqual("SSL support not installed", exception.args[0])
 
     @skipIf(requireModule("OpenSSL.SSL") is None, "SSL module is not available.")
-    def test_HTTPSAcceptedOnAvailableSSL(self):
+    def test_HTTPSAcceptedOnAvailableSSL(self) -> None:
         """
         When SSL support is present, it accepts the --https option.
         """
@@ -246,7 +247,7 @@ def test_HTTPSAcceptedOnAvailableSSL(self):
         self.assertIn("ssl", options["ports"][0])
         self.assertIn("443", options["ports"][0])
 
-    def test_add_header_parsing(self):
+    def test_add_header_parsing(self) -> None:
         """
         When --add-header is specific, the value is parsed.
         """
@@ -254,7 +255,7 @@ def test_add_header_parsing(self):
         options.parseOptions(["--add-header", "K1: V1", "--add-header", "K2: V2"])
         self.assertEqual(options["extraHeaders"], [("K1", "V1"), ("K2", "V2")])
 
-    def test_add_header_resource(self):
+    def test_add_header_resource(self) -> None:
         """
         When --add-header is specified, the resource is a composition that adds
         headers.
@@ -267,7 +268,7 @@ def test_add_header_resource(self):
         self.assertEqual(resource._headers, [("K1", "V1"), ("K2", "V2")])
         self.assertIsInstance(resource._originalResource, demo.Test)
 
-    def test_noTracebacksDeprecation(self):
+    def test_noTracebacksDeprecation(self) -> None:
         """
         Passing --notracebacks is deprecated.
         """
@@ -282,7 +283,7 @@ def test_noTracebacksDeprecation(self):
         )
         self.assertEqual(len(warnings), 1)
 
-    def test_displayTracebacks(self):
+    def test_displayTracebacks(self) -> None:
         """
         Passing --display-tracebacks will enable traceback rendering on the
         generated Site.
@@ -292,7 +293,7 @@ def test_displayTracebacks(self):
         service = makeService(options)
         self.assertTrue(service.services[0].factory.displayTracebacks)
 
-    def test_displayTracebacksNotGiven(self):
+    def test_displayTracebacksNotGiven(self) -> None:
         """
         Not passing --display-tracebacks will leave traceback rendering on the
         generated Site off.
@@ -304,7 +305,7 @@ def test_displayTracebacksNotGiven(self):
 
 
 class AddHeadersResourceTests(TestCase):
-    def test_getChildWithDefault(self):
+    def test_getChildWithDefault(self) -> None:
         """
         When getChildWithDefault is invoked, it adds the headers to the
         response.