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

Add type hints to sync REST servlet. #10666

Merged
merged 2 commits into from
Aug 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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/10666.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add missing type hints to REST servlets.
21 changes: 11 additions & 10 deletions synapse/handlers/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

from synapse.api.constants import AccountDataTypes, EventTypes, Membership
from synapse.api.filtering import FilterCollection
from synapse.api.presence import UserPresenceState
from synapse.api.room_versions import KNOWN_ROOM_VERSIONS
from synapse.events import EventBase
from synapse.logging.context import current_context
Expand Down Expand Up @@ -231,7 +232,7 @@ class SyncResult:
"""

next_batch: StreamToken
presence: List[JsonDict]
presence: List[UserPresenceState]
account_data: List[JsonDict]
joined: List[JoinedSyncResult]
invited: List[InvitedSyncResult]
Expand Down Expand Up @@ -2177,14 +2178,14 @@ class SyncResultBuilder:
joined_room_ids: List of rooms the user is joined to

# The following mirror the fields in a sync response
presence (list)
account_data (list)
joined (list[JoinedSyncResult])
invited (list[InvitedSyncResult])
knocked (list[KnockedSyncResult])
archived (list[ArchivedSyncResult])
groups (GroupsSyncResult|None)
to_device (list)
presence
account_data
joined
invited
knocked
archived
groups
to_device
"""

sync_config: SyncConfig
Expand All @@ -2193,7 +2194,7 @@ class SyncResultBuilder:
now_token: StreamToken
joined_room_ids: FrozenSet[str]

presence: List[JsonDict] = attr.Factory(list)
presence: List[UserPresenceState] = attr.Factory(list)
account_data: List[JsonDict] = attr.Factory(list)
joined: List[JoinedSyncResult] = attr.Factory(list)
invited: List[InvitedSyncResult] = attr.Factory(list)
Expand Down
132 changes: 81 additions & 51 deletions synapse/rest/client/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,26 @@
import itertools
import logging
from collections import defaultdict
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Tuple
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union

from synapse.api.constants import Membership, PresenceState
from synapse.api.errors import Codes, StoreError, SynapseError
from synapse.api.filtering import DEFAULT_FILTER_COLLECTION, FilterCollection
from synapse.api.presence import UserPresenceState
from synapse.events.utils import (
format_event_for_client_v2_without_room_id,
format_event_raw,
)
from synapse.handlers.presence import format_user_presence_state
from synapse.handlers.sync import KnockedSyncResult, SyncConfig
from synapse.handlers.sync import (
ArchivedSyncResult,
InvitedSyncResult,
JoinedSyncResult,
KnockedSyncResult,
SyncConfig,
SyncResult,
)
from synapse.http.server import HttpServer
from synapse.http.servlet import RestServlet, parse_boolean, parse_integer, parse_string
from synapse.http.site import SynapseRequest
from synapse.types import JsonDict, StreamToken
Expand Down Expand Up @@ -192,14 +201,22 @@ async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
return 200, {}

time_now = self.clock.time_msec()
# We know that the the requester has an access token since appservices
# cannot use sync.
response_content = await self.encode_response(
time_now, sync_result, requester.access_token_id, filter_collection
)

logger.debug("Event formatting complete")
return 200, response_content

async def encode_response(self, time_now, sync_result, access_token_id, filter):
async def encode_response(
self,
time_now: int,
sync_result: SyncResult,
access_token_id: Optional[int],
filter: FilterCollection,
) -> JsonDict:
logger.debug("Formatting events in sync response")
if filter.event_format == "client":
event_formatter = format_event_for_client_v2_without_room_id
Expand Down Expand Up @@ -234,7 +251,7 @@ async def encode_response(self, time_now, sync_result, access_token_id, filter):

logger.debug("building sync response dict")

response: dict = defaultdict(dict)
response: JsonDict = defaultdict(dict)
response["next_batch"] = await sync_result.next_batch.to_string(self.store)

if sync_result.account_data:
Expand Down Expand Up @@ -274,6 +291,8 @@ async def encode_response(self, time_now, sync_result, access_token_id, filter):
if archived:
response["rooms"][Membership.LEAVE] = archived

# By the time we get here groups is no longer optional.
assert sync_result.groups is not None
if sync_result.groups.join:
response["groups"][Membership.JOIN] = sync_result.groups.join
if sync_result.groups.invite:
Expand All @@ -284,7 +303,7 @@ async def encode_response(self, time_now, sync_result, access_token_id, filter):
return response

@staticmethod
def encode_presence(events, time_now):
def encode_presence(events: List[UserPresenceState], time_now: int) -> JsonDict:
return {
"events": [
{
Expand All @@ -299,25 +318,27 @@ def encode_presence(events, time_now):
}

async def encode_joined(
self, rooms, time_now, token_id, event_fields, event_formatter
):
self,
rooms: List[JoinedSyncResult],
time_now: int,
token_id: Optional[int],
event_fields: List[str],
event_formatter: Callable[[JsonDict], JsonDict],
) -> JsonDict:
"""
Encode the joined rooms in a sync result

Args:
rooms(list[synapse.handlers.sync.JoinedSyncResult]): list of sync
results for rooms this user is joined to
time_now(int): current time - used as a baseline for age
calculations
token_id(int): ID of the user's auth token - used for namespacing
rooms: list of sync results for rooms this user is joined to
time_now: current time - used as a baseline for age calculations
token_id: ID of the user's auth token - used for namespacing
of transaction IDs
event_fields(list<str>): List of event fields to include. If empty,
event_fields: List of event fields to include. If empty,
all fields will be returned.
event_formatter (func[dict]): function to convert from federation format
event_formatter: function to convert from federation format
to client format
Returns:
dict[str, dict[str, object]]: the joined rooms list, in our
response format
The joined rooms list, in our response format
"""
joined = {}
for room in rooms:
Expand All @@ -332,23 +353,26 @@ async def encode_joined(

return joined

async def encode_invited(self, rooms, time_now, token_id, event_formatter):
async def encode_invited(
self,
rooms: List[InvitedSyncResult],
time_now: int,
token_id: Optional[int],
event_formatter: Callable[[JsonDict], JsonDict],
) -> JsonDict:
"""
Encode the invited rooms in a sync result

Args:
rooms(list[synapse.handlers.sync.InvitedSyncResult]): list of
sync results for rooms this user is invited to
time_now(int): current time - used as a baseline for age
calculations
token_id(int): ID of the user's auth token - used for namespacing
rooms: list of sync results for rooms this user is invited to
time_now: current time - used as a baseline for age calculations
token_id: ID of the user's auth token - used for namespacing
of transaction IDs
event_formatter (func[dict]): function to convert from federation format
event_formatter: function to convert from federation format
to client format

Returns:
dict[str, dict[str, object]]: the invited rooms list, in our
response format
The invited rooms list, in our response format
"""
invited = {}
for room in rooms:
Expand All @@ -371,7 +395,7 @@ async def encode_knocked(
self,
rooms: List[KnockedSyncResult],
time_now: int,
token_id: int,
token_id: Optional[int],
event_formatter: Callable[[Dict], Dict],
) -> Dict[str, Dict[str, Any]]:
"""
Expand Down Expand Up @@ -422,25 +446,26 @@ async def encode_knocked(
return knocked

async def encode_archived(
self, rooms, time_now, token_id, event_fields, event_formatter
):
self,
rooms: List[ArchivedSyncResult],
time_now: int,
token_id: Optional[int],
event_fields: List[str],
event_formatter: Callable[[JsonDict], JsonDict],
) -> JsonDict:
"""
Encode the archived rooms in a sync result

Args:
rooms (list[synapse.handlers.sync.ArchivedSyncResult]): list of
sync results for rooms this user is joined to
time_now(int): current time - used as a baseline for age
calculations
token_id(int): ID of the user's auth token - used for namespacing
rooms: list of sync results for rooms this user is joined to
time_now: current time - used as a baseline for age calculations
token_id: ID of the user's auth token - used for namespacing
of transaction IDs
event_fields(list<str>): List of event fields to include. If empty,
event_fields: List of event fields to include. If empty,
all fields will be returned.
event_formatter (func[dict]): function to convert from federation format
to client format
event_formatter: function to convert from federation format to client format
Returns:
dict[str, dict[str, object]]: The invited rooms list, in our
response format
The archived rooms list, in our response format
"""
joined = {}
for room in rooms:
Expand All @@ -456,23 +481,27 @@ async def encode_archived(
return joined

async def encode_room(
self, room, time_now, token_id, joined, only_fields, event_formatter
):
self,
room: Union[JoinedSyncResult, ArchivedSyncResult],
time_now: int,
token_id: Optional[int],
joined: bool,
only_fields: Optional[List[str]],
event_formatter: Callable[[JsonDict], JsonDict],
) -> JsonDict:
"""
Args:
room (JoinedSyncResult|ArchivedSyncResult): sync result for a
single room
time_now (int): current time - used as a baseline for age
calculations
token_id (int): ID of the user's auth token - used for namespacing
room: sync result for a single room
time_now: current time - used as a baseline for age calculations
token_id: ID of the user's auth token - used for namespacing
of transaction IDs
joined (bool): True if the user is joined to this room - will mean
joined: True if the user is joined to this room - will mean
we handle ephemeral events
only_fields(list<str>): Optional. The list of event fields to include.
event_formatter (func[dict]): function to convert from federation format
only_fields: Optional. The list of event fields to include.
event_formatter: function to convert from federation format
to client format
Returns:
dict[str, object]: the room, encoded in our response format
The room, encoded in our response format
"""

def serialize(events):
Expand Down Expand Up @@ -508,7 +537,7 @@ def serialize(events):

account_data = room.account_data

result = {
result: JsonDict = {
"timeline": {
"events": serialized_timeline,
"prev_batch": await room.timeline.prev_batch.to_string(self.store),
Expand All @@ -519,6 +548,7 @@ def serialize(events):
}

if joined:
assert isinstance(room, JoinedSyncResult)
ephemeral_events = room.ephemeral
result["ephemeral"] = {"events": ephemeral_events}
result["unread_notifications"] = room.unread_notifications
Expand All @@ -528,5 +558,5 @@ def serialize(events):
return result


def register_servlets(hs, http_server):
def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
SyncRestServlet(hs).register(http_server)