Type-check RestServlet.PATTERNS (#20258)

Spawning from
https://github.com/element-hq/synapse/pull/20143#discussion_r4080708454

`RestServlet.register` read `PATTERNS` via `getattr`, so it was typed as
`Any` and mypy never checked subclasses' patterns against what
`HttpServer.register_paths` expects.

This declares the attribute so that classes extending `RestServlet`
provide the right type for the `PATTERNS` attribute.
This commit is contained in:
Quentin Gliech
2026-09-25 13:32:11 +02:00
committed by GitHub
parent 7630492e90
commit d93380a8df
2 changed files with 10 additions and 4 deletions
+2
View File
@@ -0,0 +1,2 @@
Add type annotations for `RestServlet.PATTERNS` to prevent misuse.
+8 -4
View File
@@ -27,8 +27,10 @@ import urllib.parse as urlparse
from http import HTTPStatus
from typing import (
TYPE_CHECKING,
Iterable,
Literal,
Mapping,
Pattern,
Sequence,
TypeVar,
overload,
@@ -944,9 +946,9 @@ class RestServlet:
An implementing class can either provide its own custom 'register' method,
or use the automatic pattern handling provided by the base class.
To use this latter, the implementing class instead provides a `PATTERN`
class attribute containing a pre-compiled regular expression. The automatic
register method will then use this method to register any of the following
To use this latter, the implementing class instead provides a `PATTERNS`
class attribute containing pre-compiled regular expressions. The automatic
register method will then use them to register any of the following
instance methods associated with the corresponding HTTP method:
on_GET
@@ -958,9 +960,11 @@ class RestServlet:
into the appropriate HTTP response.
"""
PATTERNS: Iterable[Pattern[str]] | None = None
def register(self, http_server: HttpServer) -> None:
"""Register this servlet with the given HTTP server."""
patterns = getattr(self, "PATTERNS", None)
patterns = self.PATTERNS
if patterns:
for method in ("GET", "PUT", "POST", "DELETE"):
if hasattr(self, "on_%s" % (method,)):