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

Add types to synapse.util. #10601

Merged
merged 41 commits into from
Sep 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ff8f94d
fairly mechanical changes
reivilibre Aug 13, 2021
6deee28
stranger changes (REVIEW)
reivilibre Aug 13, 2021
3c2b4dd
Newsfile & mypy.ini
reivilibre Aug 13, 2021
1d0b435
Put the switch back in to the 'more magic' position
reivilibre Aug 16, 2021
22df193
Fix up some more types
reivilibre Aug 16, 2021
e36db3f
Update annotations in util
reivilibre Aug 18, 2021
db57064
Fix fallout (related annotations and assertions around codebase)
reivilibre Aug 18, 2021
cd15b4b
Merge remote-tracking branch 'origin/develop' into rei/types1
reivilibre Aug 18, 2021
348f9ff
antilint
reivilibre Aug 18, 2021
d081c83
add type parameters for Deferreds
reivilibre Aug 18, 2021
76c3b6b
Fix circular import of HomeServer
reivilibre Aug 23, 2021
30ffee4
Quote deferreds in method signatures
reivilibre Aug 23, 2021
10bd84f
Annotate more types
reivilibre Sep 1, 2021
0c26b7f
Use attrs class and fix ignored fields [WANTS REVIEW]
reivilibre Sep 1, 2021
715bfdc
Ignore import issues [WANTS REVIEW]
reivilibre Sep 1, 2021
1e4632f
Annotate more types
reivilibre Sep 1, 2021
05cc10c
Annotate more types
reivilibre Sep 2, 2021
1c6704c
Annotate types and ignore Twisted issues [WANTS REVIEW]
reivilibre Sep 2, 2021
c384373
Add IReactorThreads as parent of ISynapseReactor
reivilibre Sep 2, 2021
884a8b6
Annotate more types
reivilibre Sep 2, 2021
a22f4c0
Add type annotation fixes to fix CI
reivilibre Sep 2, 2021
029bf34
Merge remote-tracking branch 'origin/develop' into rei/types1
reivilibre Sep 2, 2021
9444ca1
Resolve type issue that arose from merge
reivilibre Sep 2, 2021
a0aef0b
Back out of generics due to python-attrs/attrs#313
reivilibre Sep 2, 2021
289df40
Quote return types with Deferreds
reivilibre Sep 3, 2021
8e719ed
Fix use of None as default
reivilibre Sep 6, 2021
34e327d
Use a cast to work around Mocks not working with isinstance
reivilibre Sep 6, 2021
cd9a68d
Fix up parameters which were previously silently ignored
reivilibre Sep 6, 2021
b4cded1
Apply suggestions
reivilibre Sep 8, 2021
6f7fac0
Use `cast` to IReactorTime [WANTS REVIEW]
reivilibre Sep 8, 2021
d4afbca
Add types and casts to `__exit__` [REVIEW]
reivilibre Sep 8, 2021
f5cee54
Fix adherence to Jinja2's interface [REVIEW]
reivilibre Sep 8, 2021
12cfb9a
Annotate `WheelTimer`, notably `bucket_size`
reivilibre Sep 8, 2021
e69a3d6
Update Newsfile
reivilibre Sep 8, 2021
9f301ae
Note that code was lifted from CPython
reivilibre Sep 8, 2021
e6618d7
Add more type annotations
reivilibre Sep 8, 2021
b1b4f1b
Enable stricter checking on applicable modules
reivilibre Sep 8, 2021
ea4f7e0
Merge remote-tracking branch 'origin/develop' into rei/types1
reivilibre Sep 8, 2021
8871674
Correct types used in `__exit__`
reivilibre Sep 8, 2021
20d63a0
Fix up manhole types after merge [REVIEW, SEE DESC]
reivilibre Sep 8, 2021
19a602e
Avoid using evil typecasts
reivilibre Sep 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/10601.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add type annotations to the synapse.util package.
75 changes: 64 additions & 11 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,7 @@ files =
synapse/storage/util,
synapse/streams,
synapse/types.py,
synapse/util/async_helpers.py,
synapse/util/caches,
synapse/util/daemonize.py,
synapse/util/hash.py,
synapse/util/iterutils.py,
synapse/util/linked_list.py,
synapse/util/metrics.py,
synapse/util/macaroons.py,
synapse/util/module_loader.py,
synapse/util/msisdn.py,
synapse/util/stringutils.py,
synapse/util,
synapse/visibility.py,
tests/replication,
tests/test_event_auth.py,
Expand All @@ -102,6 +92,69 @@ files =
[mypy-synapse.rest.client.*]
disallow_untyped_defs = True

[mypy-synapse.util.batching_queue]
disallow_untyped_defs = True

[mypy-synapse.util.caches.dictionary_cache]
disallow_untyped_defs = True

[mypy-synapse.util.file_consumer]
disallow_untyped_defs = True

[mypy-synapse.util.frozenutils]
disallow_untyped_defs = True

[mypy-synapse.util.hash]
disallow_untyped_defs = True

[mypy-synapse.util.httpresourcetree]
disallow_untyped_defs = True

[mypy-synapse.util.iterutils]
disallow_untyped_defs = True

[mypy-synapse.util.linked_list]
disallow_untyped_defs = True

[mypy-synapse.util.logcontext]
disallow_untyped_defs = True

[mypy-synapse.util.logformatter]
disallow_untyped_defs = True

[mypy-synapse.util.macaroons]
disallow_untyped_defs = True

[mypy-synapse.util.manhole]
disallow_untyped_defs = True

[mypy-synapse.util.module_loader]
disallow_untyped_defs = True

[mypy-synapse.util.msisdn]
disallow_untyped_defs = True

[mypy-synapse.util.ratelimitutils]
disallow_untyped_defs = True

[mypy-synapse.util.retryutils]
disallow_untyped_defs = True

[mypy-synapse.util.rlimit]
disallow_untyped_defs = True

[mypy-synapse.util.stringutils]
disallow_untyped_defs = True

[mypy-synapse.util.templates]
disallow_untyped_defs = True

[mypy-synapse.util.threepids]
disallow_untyped_defs = True

[mypy-synapse.util.wheel_timer]
disallow_untyped_defs = True

[mypy-pymacaroons.*]
ignore_missing_imports = True

Expand Down
2 changes: 1 addition & 1 deletion stubs/txredisapi.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@ class RedisFactory(protocol.ReconnectingClientFactory):
def buildProtocol(self, addr) -> RedisProtocol: ...

class SubscriberFactory(RedisFactory):
def __init__(self): ...
def __init__(self) -> None: ...
8 changes: 4 additions & 4 deletions synapse/api/ratelimiting.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def __init__(
# * How many times an action has occurred since a point in time
# * The point in time
# * The rate_hz of this particular entry. This can vary per request
self.actions: OrderedDict[Hashable, Tuple[float, int, float]] = OrderedDict()
self.actions: OrderedDict[Hashable, Tuple[float, float, float]] = OrderedDict()

async def can_do_action(
self,
Expand All @@ -56,7 +56,7 @@ async def can_do_action(
burst_count: Optional[int] = None,
update: bool = True,
n_actions: int = 1,
_time_now_s: Optional[int] = None,
_time_now_s: Optional[float] = None,
) -> Tuple[bool, float]:
"""Can the entity (e.g. user or IP address) perform the action?

Expand Down Expand Up @@ -160,7 +160,7 @@ async def can_do_action(

return allowed, time_allowed

def _prune_message_counts(self, time_now_s: int):
def _prune_message_counts(self, time_now_s: float):
"""Remove message count entries that have not exceeded their defined
rate_hz limit

Expand Down Expand Up @@ -188,7 +188,7 @@ async def ratelimit(
burst_count: Optional[int] = None,
update: bool = True,
n_actions: int = 1,
_time_now_s: Optional[int] = None,
_time_now_s: Optional[float] = None,
):
"""Checks if an action can be performed. If not, raises a LimitExceededError

Expand Down
33 changes: 17 additions & 16 deletions synapse/config/ratelimiting.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

from typing import Dict, Optional

import attr

from ._base import Config


Expand All @@ -29,18 +31,13 @@ def __init__(
self.burst_count = int(config.get("burst_count", defaults["burst_count"]))


@attr.s(auto_attribs=True)
class FederationRateLimitConfig:
_items_and_default = {
"window_size": 1000,
"sleep_limit": 10,
"sleep_delay": 500,
"reject_limit": 50,
"concurrent": 3,
}

def __init__(self, **kwargs):
for i in self._items_and_default.keys():
setattr(self, i, kwargs.get(i) or self._items_and_default[i])
window_size: int = 1000
sleep_limit: int = 10
sleep_delay: int = 500
reject_limit: int = 50
concurrent: int = 3


class RatelimitConfig(Config):
Expand Down Expand Up @@ -69,11 +66,15 @@ def read_config(self, config, **kwargs):
else:
self.rc_federation = FederationRateLimitConfig(
**{
"window_size": config.get("federation_rc_window_size"),
"sleep_limit": config.get("federation_rc_sleep_limit"),
"sleep_delay": config.get("federation_rc_sleep_delay"),
"reject_limit": config.get("federation_rc_reject_limit"),
"concurrent": config.get("federation_rc_concurrent"),
k: v
for k, v in {
"window_size": config.get("federation_rc_window_size"),
"sleep_limit": config.get("federation_rc_sleep_limit"),
"sleep_delay": config.get("federation_rc_sleep_delay"),
"reject_limit": config.get("federation_rc_reject_limit"),
"concurrent": config.get("federation_rc_concurrent"),
}.items()
if v is not None
}
)

Expand Down
8 changes: 6 additions & 2 deletions synapse/federation/sender/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from typing_extensions import Literal

from twisted.internet import defer
from twisted.internet.interfaces import IDelayedCall

import synapse.metrics
from synapse.api.presence import UserPresenceState
Expand Down Expand Up @@ -284,7 +285,9 @@ def __init__(self, hs: "HomeServer"):
)

# wake up destinations that have outstanding PDUs to be caught up
self._catchup_after_startup_timer = self.clock.call_later(
self._catchup_after_startup_timer: Optional[
IDelayedCall
] = self.clock.call_later(
CATCH_UP_STARTUP_DELAY_SEC,
run_as_background_process,
"wake_destinations_needing_catchup",
Expand Down Expand Up @@ -406,7 +409,7 @@ async def handle_event(event: EventBase) -> None:

now = self.clock.time_msec()
ts = await self.store.get_received_ts(event.event_id)

assert ts is not None
synapse.metrics.event_processing_lag_by_event.labels(
"federation_sender"
).observe((now - ts) / 1000)
Expand Down Expand Up @@ -435,6 +438,7 @@ async def handle_room_events(events: Iterable[EventBase]) -> None:
if events:
now = self.clock.time_msec()
ts = await self.store.get_received_ts(events[-1].event_id)
assert ts is not None

synapse.metrics.event_processing_lag.labels(
"federation_sender"
Expand Down
1 change: 1 addition & 0 deletions synapse/handlers/account_validity.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ async def renew_account_for_user(
"""
now = self.clock.time_msec()
if expiration_ts is None:
assert self._account_validity_period is not None
expiration_ts = now + self._account_validity_period

await self.store.set_account_validity_for_user(
Expand Down
3 changes: 3 additions & 0 deletions synapse/handlers/appservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ async def start_scheduler():

now = self.clock.time_msec()
ts = await self.store.get_received_ts(event.event_id)
assert ts is not None

synapse.metrics.event_processing_lag_by_event.labels(
"appservice_sender"
).observe((now - ts) / 1000)
Expand Down Expand Up @@ -166,6 +168,7 @@ async def handle_room_events(events):
if events:
now = self.clock.time_msec()
ts = await self.store.get_received_ts(events[-1].event_id)
assert ts is not None

synapse.metrics.event_processing_lag.labels(
"appservice_sender"
Expand Down
5 changes: 3 additions & 2 deletions synapse/handlers/presence.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from contextlib import contextmanager
from typing import (
TYPE_CHECKING,
Any,
Callable,
Collection,
Dict,
Expand Down Expand Up @@ -615,7 +616,7 @@ def __init__(self, hs: "HomeServer"):
super().__init__(hs)
self.hs = hs
self.server_name = hs.hostname
self.wheel_timer = WheelTimer()
self.wheel_timer: WheelTimer[str] = WheelTimer()
self.notifier = hs.get_notifier()
self._presence_enabled = hs.config.use_presence

Expand Down Expand Up @@ -924,7 +925,7 @@ async def bump_presence_active_time(self, user: UserID) -> None:

prev_state = await self.current_state_for_user(user_id)

new_fields = {"last_active_ts": self.clock.time_msec()}
new_fields: Dict[str, Any] = {"last_active_ts": self.clock.time_msec()}
if prev_state.state == PresenceState.UNAVAILABLE:
new_fields["state"] = PresenceState.ONLINE

Expand Down
2 changes: 1 addition & 1 deletion synapse/handlers/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def __init__(self, hs: "HomeServer"):
self._room_typing: Dict[str, Set[str]] = {}

self._member_last_federation_poke: Dict[RoomMember, int] = {}
self.wheel_timer = WheelTimer(bucket_size=5000)
self.wheel_timer: WheelTimer[RoomMember] = WheelTimer(bucket_size=5000)
self._latest_room_serial = 0

self.clock.looping_call(self._handle_timeouts, 5000)
Expand Down
11 changes: 7 additions & 4 deletions synapse/rest/client/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,11 +330,11 @@ def __init__(self, hs: "HomeServer"):
# Artificially delay requests if rate > sleep_limit/window_size
sleep_limit=1,
# Amount of artificial delay to apply
sleep_msec=1000,
sleep_delay=1000,
# Error with 429 if more than reject_limit requests are queued
reject_limit=1,
# Allow 1 request at a time
concurrent_requests=1,
concurrent=1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a functional change too? I think its fine though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, forgot to point it out

),
)

Expand Down Expand Up @@ -763,7 +763,10 @@ async def _create_registration_details(
Returns:
dictionary for response from /register
"""
result = {"user_id": user_id, "home_server": self.hs.hostname}
result: JsonDict = {
"user_id": user_id,
"home_server": self.hs.hostname,
}
if not params.get("inhibit_login", False):
device_id = params.get("device_id")
initial_display_name = params.get("initial_device_display_name")
Expand Down Expand Up @@ -814,7 +817,7 @@ async def _do_guest_registration(
user_id, device_id, initial_display_name, is_guest=True
)

result = {
result: JsonDict = {
"user_id": user_id,
"device_id": device_id,
"access_token": access_token,
Expand Down
2 changes: 1 addition & 1 deletion synapse/rest/synapse/client/new_user_consent.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def template_search_dirs():
yield hs.config.sso.sso_template_dir
yield hs.config.sso.default_template_dir

self._jinja_env = build_jinja_env(template_search_dirs(), hs.config)
self._jinja_env = build_jinja_env(list(template_search_dirs()), hs.config)

async def _async_render_GET(self, request: Request) -> None:
try:
Expand Down
2 changes: 1 addition & 1 deletion synapse/rest/synapse/client/pick_username.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def template_search_dirs():
yield hs.config.sso.sso_template_dir
yield hs.config.sso.default_template_dir

self._jinja_env = build_jinja_env(template_search_dirs(), hs.config)
self._jinja_env = build_jinja_env(list(template_search_dirs()), hs.config)

async def _async_render_GET(self, request: Request) -> None:
try:
Expand Down
1 change: 1 addition & 0 deletions synapse/storage/databases/main/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,7 @@ def set_expiration_date_for_user_txn(self, txn, user_id, use_delta=False):
delta equal to 10% of the validity period.
"""
now_ms = self._clock.time_msec()
assert self._account_validity_period is not None
expiration_ts = now_ms + self._account_validity_period

if use_delta:
Expand Down
8 changes: 7 additions & 1 deletion synapse/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
IReactorCore,
IReactorPluggableNameResolver,
IReactorTCP,
IReactorThreads,
IReactorTime,
)

Expand All @@ -63,7 +64,12 @@
# Note that this seems to require inheriting *directly* from Interface in order
# for mypy-zope to realize it is an interface.
class ISynapseReactor(
IReactorTCP, IReactorPluggableNameResolver, IReactorTime, IReactorCore, Interface
IReactorTCP,
IReactorPluggableNameResolver,
IReactorTime,
IReactorCore,
IReactorThreads,
Interface,
):
"""The interfaces necessary for Synapse to function."""

Expand Down
Loading