Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 5cace20

Browse files
authored
Add missing type hints to synapse.app. (#11287)
1 parent 66c4b77 commit 5cace20

17 files changed

+223
-190
lines changed

changelog.d/11287.misc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add missing type hints to `synapse.app`.

mypy.ini

+3-16
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,6 @@ files =
2323
# https://docs.python.org/3/library/re.html#re.X
2424
exclude = (?x)
2525
^(
26-
|synapse/app/__init__.py
27-
|synapse/app/_base.py
28-
|synapse/app/admin_cmd.py
29-
|synapse/app/appservice.py
30-
|synapse/app/client_reader.py
31-
|synapse/app/event_creator.py
32-
|synapse/app/federation_reader.py
33-
|synapse/app/federation_sender.py
34-
|synapse/app/frontend_proxy.py
35-
|synapse/app/generic_worker.py
36-
|synapse/app/homeserver.py
37-
|synapse/app/media_repository.py
38-
|synapse/app/phone_stats_home.py
39-
|synapse/app/pusher.py
40-
|synapse/app/synchrotron.py
41-
|synapse/app/user_dir.py
4226
|synapse/storage/databases/__init__.py
4327
|synapse/storage/databases/main/__init__.py
4428
|synapse/storage/databases/main/account_data.py
@@ -179,6 +163,9 @@ exclude = (?x)
179163
[mypy-synapse.api.*]
180164
disallow_untyped_defs = True
181165

166+
[mypy-synapse.app.*]
167+
disallow_untyped_defs = True
168+
182169
[mypy-synapse.crypto.*]
183170
disallow_untyped_defs = True
184171

synapse/app/__init__.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414
import logging
1515
import sys
16+
from typing import Container
1617

1718
from synapse import python_dependencies # noqa: E402
1819

@@ -27,7 +28,9 @@
2728
sys.exit(1)
2829

2930

30-
def check_bind_error(e, address, bind_addresses):
31+
def check_bind_error(
32+
e: Exception, address: str, bind_addresses: Container[str]
33+
) -> None:
3134
"""
3235
This method checks an exception occurred while binding on 0.0.0.0.
3336
If :: is specified in the bind addresses a warning is shown.
@@ -38,9 +41,9 @@ def check_bind_error(e, address, bind_addresses):
3841
When binding on 0.0.0.0 after :: this can safely be ignored.
3942
4043
Args:
41-
e (Exception): Exception that was caught.
42-
address (str): Address on which binding was attempted.
43-
bind_addresses (list): Addresses on which the service listens.
44+
e: Exception that was caught.
45+
address: Address on which binding was attempted.
46+
bind_addresses: Addresses on which the service listens.
4447
"""
4548
if address == "0.0.0.0" and "::" in bind_addresses:
4649
logger.warning(

synapse/app/_base.py

+89-51
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,27 @@
2222
import sys
2323
import traceback
2424
import warnings
25-
from typing import TYPE_CHECKING, Awaitable, Callable, Iterable
25+
from typing import (
26+
TYPE_CHECKING,
27+
Any,
28+
Awaitable,
29+
Callable,
30+
Collection,
31+
Dict,
32+
Iterable,
33+
List,
34+
NoReturn,
35+
Tuple,
36+
cast,
37+
)
2638

2739
from cryptography.utils import CryptographyDeprecationWarning
28-
from typing_extensions import NoReturn
2940

3041
import twisted
31-
from twisted.internet import defer, error, reactor
42+
from twisted.internet import defer, error, reactor as _reactor
43+
from twisted.internet.interfaces import IOpenSSLContextFactory, IReactorSSL, IReactorTCP
44+
from twisted.internet.protocol import ServerFactory
45+
from twisted.internet.tcp import Port
3246
from twisted.logger import LoggingFile, LogLevel
3347
from twisted.protocols.tls import TLSMemoryBIOFactory
3448
from twisted.python.threadpool import ThreadPool
@@ -48,6 +62,7 @@
4862
from synapse.metrics import register_threadpool
4963
from synapse.metrics.background_process_metrics import wrap_as_background_process
5064
from synapse.metrics.jemalloc import setup_jemalloc_stats
65+
from synapse.types import ISynapseReactor
5166
from synapse.util.caches.lrucache import setup_expire_lru_cache_entries
5267
from synapse.util.daemonize import daemonize_process
5368
from synapse.util.gai_resolver import GAIResolver
@@ -57,33 +72,44 @@
5772
if TYPE_CHECKING:
5873
from synapse.server import HomeServer
5974

75+
# Twisted injects the global reactor to make it easier to import, this confuses
76+
# mypy which thinks it is a module. Tell it that it a more proper type.
77+
reactor = cast(ISynapseReactor, _reactor)
78+
79+
6080
logger = logging.getLogger(__name__)
6181

6282
# list of tuples of function, args list, kwargs dict
63-
_sighup_callbacks = []
83+
_sighup_callbacks: List[
84+
Tuple[Callable[..., None], Tuple[Any, ...], Dict[str, Any]]
85+
] = []
6486

6587

66-
def register_sighup(func, *args, **kwargs):
88+
def register_sighup(func: Callable[..., None], *args: Any, **kwargs: Any) -> None:
6789
"""
6890
Register a function to be called when a SIGHUP occurs.
6991
7092
Args:
71-
func (function): Function to be called when sent a SIGHUP signal.
93+
func: Function to be called when sent a SIGHUP signal.
7294
*args, **kwargs: args and kwargs to be passed to the target function.
7395
"""
7496
_sighup_callbacks.append((func, args, kwargs))
7597

7698

77-
def start_worker_reactor(appname, config, run_command=reactor.run):
99+
def start_worker_reactor(
100+
appname: str,
101+
config: HomeServerConfig,
102+
run_command: Callable[[], None] = reactor.run,
103+
) -> None:
78104
"""Run the reactor in the main process
79105
80106
Daemonizes if necessary, and then configures some resources, before starting
81107
the reactor. Pulls configuration from the 'worker' settings in 'config'.
82108
83109
Args:
84-
appname (str): application name which will be sent to syslog
85-
config (synapse.config.Config): config object
86-
run_command (Callable[]): callable that actually runs the reactor
110+
appname: application name which will be sent to syslog
111+
config: config object
112+
run_command: callable that actually runs the reactor
87113
"""
88114

89115
logger = logging.getLogger(config.worker.worker_app)
@@ -101,32 +127,32 @@ def start_worker_reactor(appname, config, run_command=reactor.run):
101127

102128

103129
def start_reactor(
104-
appname,
105-
soft_file_limit,
106-
gc_thresholds,
107-
pid_file,
108-
daemonize,
109-
print_pidfile,
110-
logger,
111-
run_command=reactor.run,
112-
):
130+
appname: str,
131+
soft_file_limit: int,
132+
gc_thresholds: Tuple[int, int, int],
133+
pid_file: str,
134+
daemonize: bool,
135+
print_pidfile: bool,
136+
logger: logging.Logger,
137+
run_command: Callable[[], None] = reactor.run,
138+
) -> None:
113139
"""Run the reactor in the main process
114140
115141
Daemonizes if necessary, and then configures some resources, before starting
116142
the reactor
117143
118144
Args:
119-
appname (str): application name which will be sent to syslog
120-
soft_file_limit (int):
145+
appname: application name which will be sent to syslog
146+
soft_file_limit:
121147
gc_thresholds:
122-
pid_file (str): name of pid file to write to if daemonize is True
123-
daemonize (bool): true to run the reactor in a background process
124-
print_pidfile (bool): whether to print the pid file, if daemonize is True
125-
logger (logging.Logger): logger instance to pass to Daemonize
126-
run_command (Callable[]): callable that actually runs the reactor
148+
pid_file: name of pid file to write to if daemonize is True
149+
daemonize: true to run the reactor in a background process
150+
print_pidfile: whether to print the pid file, if daemonize is True
151+
logger: logger instance to pass to Daemonize
152+
run_command: callable that actually runs the reactor
127153
"""
128154

129-
def run():
155+
def run() -> None:
130156
logger.info("Running")
131157
setup_jemalloc_stats()
132158
change_resource_limit(soft_file_limit)
@@ -185,7 +211,7 @@ def redirect_stdio_to_logs() -> None:
185211
print("Redirected stdout/stderr to logs")
186212

187213

188-
def register_start(cb: Callable[..., Awaitable], *args, **kwargs) -> None:
214+
def register_start(cb: Callable[..., Awaitable], *args: Any, **kwargs: Any) -> None:
189215
"""Register a callback with the reactor, to be called once it is running
190216
191217
This can be used to initialise parts of the system which require an asynchronous
@@ -195,7 +221,7 @@ def register_start(cb: Callable[..., Awaitable], *args, **kwargs) -> None:
195221
will exit.
196222
"""
197223

198-
async def wrapper():
224+
async def wrapper() -> None:
199225
try:
200226
await cb(*args, **kwargs)
201227
except Exception:
@@ -224,7 +250,7 @@ async def wrapper():
224250
reactor.callWhenRunning(lambda: defer.ensureDeferred(wrapper()))
225251

226252

227-
def listen_metrics(bind_addresses, port):
253+
def listen_metrics(bind_addresses: Iterable[str], port: int) -> None:
228254
"""
229255
Start Prometheus metrics server.
230256
"""
@@ -236,11 +262,11 @@ def listen_metrics(bind_addresses, port):
236262

237263

238264
def listen_manhole(
239-
bind_addresses: Iterable[str],
265+
bind_addresses: Collection[str],
240266
port: int,
241267
manhole_settings: ManholeConfig,
242268
manhole_globals: dict,
243-
):
269+
) -> None:
244270
# twisted.conch.manhole 21.1.0 uses "int_from_bytes", which produces a confusing
245271
# warning. It's fixed by https://github.com/twisted/twisted/pull/1522), so
246272
# suppress the warning for now.
@@ -259,12 +285,18 @@ def listen_manhole(
259285
)
260286

261287

262-
def listen_tcp(bind_addresses, port, factory, reactor=reactor, backlog=50):
288+
def listen_tcp(
289+
bind_addresses: Collection[str],
290+
port: int,
291+
factory: ServerFactory,
292+
reactor: IReactorTCP = reactor,
293+
backlog: int = 50,
294+
) -> List[Port]:
263295
"""
264296
Create a TCP socket for a port and several addresses
265297
266298
Returns:
267-
list[twisted.internet.tcp.Port]: listening for TCP connections
299+
list of twisted.internet.tcp.Port listening for TCP connections
268300
"""
269301
r = []
270302
for address in bind_addresses:
@@ -273,12 +305,19 @@ def listen_tcp(bind_addresses, port, factory, reactor=reactor, backlog=50):
273305
except error.CannotListenError as e:
274306
check_bind_error(e, address, bind_addresses)
275307

276-
return r
308+
# IReactorTCP returns an object implementing IListeningPort from listenTCP,
309+
# but we know it will be a Port instance.
310+
return r # type: ignore[return-value]
277311

278312

279313
def listen_ssl(
280-
bind_addresses, port, factory, context_factory, reactor=reactor, backlog=50
281-
):
314+
bind_addresses: Collection[str],
315+
port: int,
316+
factory: ServerFactory,
317+
context_factory: IOpenSSLContextFactory,
318+
reactor: IReactorSSL = reactor,
319+
backlog: int = 50,
320+
) -> List[Port]:
282321
"""
283322
Create an TLS-over-TCP socket for a port and several addresses
284323
@@ -294,10 +333,13 @@ def listen_ssl(
294333
except error.CannotListenError as e:
295334
check_bind_error(e, address, bind_addresses)
296335

297-
return r
336+
# IReactorSSL incorrectly declares that an int is returned from listenSSL,
337+
# it actually returns an object implementing IListeningPort, but we know it
338+
# will be a Port instance.
339+
return r # type: ignore[return-value]
298340

299341

300-
def refresh_certificate(hs: "HomeServer"):
342+
def refresh_certificate(hs: "HomeServer") -> None:
301343
"""
302344
Refresh the TLS certificates that Synapse is using by re-reading them from
303345
disk and updating the TLS context factories to use them.
@@ -329,7 +371,7 @@ def refresh_certificate(hs: "HomeServer"):
329371
logger.info("Context factories updated.")
330372

331373

332-
async def start(hs: "HomeServer"):
374+
async def start(hs: "HomeServer") -> None:
333375
"""
334376
Start a Synapse server or worker.
335377
@@ -360,7 +402,7 @@ async def start(hs: "HomeServer"):
360402
if hasattr(signal, "SIGHUP"):
361403

362404
@wrap_as_background_process("sighup")
363-
def handle_sighup(*args, **kwargs):
405+
def handle_sighup(*args: Any, **kwargs: Any) -> None:
364406
# Tell systemd our state, if we're using it. This will silently fail if
365407
# we're not using systemd.
366408
sdnotify(b"RELOADING=1")
@@ -373,7 +415,7 @@ def handle_sighup(*args, **kwargs):
373415
# We defer running the sighup handlers until next reactor tick. This
374416
# is so that we're in a sane state, e.g. flushing the logs may fail
375417
# if the sighup happens in the middle of writing a log entry.
376-
def run_sighup(*args, **kwargs):
418+
def run_sighup(*args: Any, **kwargs: Any) -> None:
377419
# `callFromThread` should be "signal safe" as well as thread
378420
# safe.
379421
reactor.callFromThread(handle_sighup, *args, **kwargs)
@@ -436,12 +478,8 @@ def run_sighup(*args, **kwargs):
436478
atexit.register(gc.freeze)
437479

438480

439-
def setup_sentry(hs: "HomeServer"):
440-
"""Enable sentry integration, if enabled in configuration
441-
442-
Args:
443-
hs
444-
"""
481+
def setup_sentry(hs: "HomeServer") -> None:
482+
"""Enable sentry integration, if enabled in configuration"""
445483

446484
if not hs.config.metrics.sentry_enabled:
447485
return
@@ -466,7 +504,7 @@ def setup_sentry(hs: "HomeServer"):
466504
scope.set_tag("worker_name", name)
467505

468506

469-
def setup_sdnotify(hs: "HomeServer"):
507+
def setup_sdnotify(hs: "HomeServer") -> None:
470508
"""Adds process state hooks to tell systemd what we are up to."""
471509

472510
# Tell systemd our state, if we're using it. This will silently fail if
@@ -481,7 +519,7 @@ def setup_sdnotify(hs: "HomeServer"):
481519
sdnotify_sockaddr = os.getenv("NOTIFY_SOCKET")
482520

483521

484-
def sdnotify(state):
522+
def sdnotify(state: bytes) -> None:
485523
"""
486524
Send a notification to systemd, if the NOTIFY_SOCKET env var is set.
487525
@@ -490,7 +528,7 @@ def sdnotify(state):
490528
package which many OSes don't include as a matter of principle.
491529
492530
Args:
493-
state (bytes): notification to send
531+
state: notification to send
494532
"""
495533
if not isinstance(state, bytes):
496534
raise TypeError("sdnotify should be called with a bytes")

0 commit comments

Comments
 (0)