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

Commit

Permalink
Convert all namedtuples to attrs. (#11665)
Browse files Browse the repository at this point in the history
To improve type hints throughout the code.
  • Loading branch information
clokep authored Dec 30, 2021
1 parent 07a3b5d commit cbd82d0
Show file tree
Hide file tree
Showing 22 changed files with 231 additions and 206 deletions.
1 change: 1 addition & 0 deletions changelog.d/11665.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Convert `namedtuples` to `attrs`.
3 changes: 1 addition & 2 deletions synapse/api/filtering.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,7 @@ def _check(self, event: FilterEvent) -> bool:
True if the event matches the filter.
"""
# We usually get the full "events" as dictionaries coming through,
# except for presence which actually gets passed around as its own
# namedtuple type.
# except for presence which actually gets passed around as its own type.
if isinstance(event, UserPresenceState):
user_id = event.user_id
field_matchers = {
Expand Down
34 changes: 18 additions & 16 deletions synapse/config/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@

import logging
import os
from collections import namedtuple
from typing import Dict, List, Tuple
from urllib.request import getproxies_environment # type: ignore

import attr

from synapse.config.server import DEFAULT_IP_RANGE_BLACKLIST, generate_ip_set
from synapse.python_dependencies import DependencyException, check_requirements
from synapse.types import JsonDict
Expand All @@ -44,18 +45,20 @@
HTTP_PROXY_SET_WARNING = """\
The Synapse config url_preview_ip_range_blacklist will be ignored as an HTTP(s) proxy is configured."""

ThumbnailRequirement = namedtuple(
"ThumbnailRequirement", ["width", "height", "method", "media_type"]
)

MediaStorageProviderConfig = namedtuple(
"MediaStorageProviderConfig",
(
"store_local", # Whether to store newly uploaded local files
"store_remote", # Whether to store newly downloaded remote files
"store_synchronous", # Whether to wait for successful storage for local uploads
),
)
@attr.s(frozen=True, slots=True, auto_attribs=True)
class ThumbnailRequirement:
width: int
height: int
method: str
media_type: str


@attr.s(frozen=True, slots=True, auto_attribs=True)
class MediaStorageProviderConfig:
store_local: bool # Whether to store newly uploaded local files
store_remote: bool # Whether to store newly downloaded remote files
store_synchronous: bool # Whether to wait for successful storage for local uploads


def parse_thumbnail_requirements(
Expand All @@ -66,11 +69,10 @@ def parse_thumbnail_requirements(
method, and thumbnail media type to precalculate
Args:
thumbnail_sizes(list): List of dicts with "width", "height", and
"method" keys
thumbnail_sizes: List of dicts with "width", "height", and "method" keys
Returns:
Dictionary mapping from media type string to list of
ThumbnailRequirement tuples.
Dictionary mapping from media type string to list of ThumbnailRequirement.
"""
requirements: Dict[str, List[ThumbnailRequirement]] = {}
for size in thumbnail_sizes:
Expand Down
5 changes: 0 additions & 5 deletions synapse/federation/federation_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from collections import namedtuple
from typing import TYPE_CHECKING

from synapse.api.constants import MAX_DEPTH, EventContentFields, EventTypes, Membership
Expand Down Expand Up @@ -104,10 +103,6 @@ async def _check_sigs_and_hash(
return pdu


class PduToCheckSig(namedtuple("PduToCheckSig", ["pdu", "sender_domain", "deferreds"])):
pass


async def _check_sigs_on_pdu(
keyring: Keyring, room_version: RoomVersion, pdu: EventBase
) -> None:
Expand Down
47 changes: 23 additions & 24 deletions synapse/federation/send_queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
"""

import logging
from collections import namedtuple
from typing import (
TYPE_CHECKING,
Dict,
Expand All @@ -43,6 +42,7 @@
Type,
)

import attr
from sortedcontainers import SortedDict

from synapse.api.presence import UserPresenceState
Expand Down Expand Up @@ -382,13 +382,11 @@ def add_to_buffer(self, buff: "ParsedFederationStreamData") -> None:
raise NotImplementedError()


class PresenceDestinationsRow(
BaseFederationRow,
namedtuple(
"PresenceDestinationsRow",
("state", "destinations"), # UserPresenceState # list[str]
),
):
@attr.s(slots=True, frozen=True, auto_attribs=True)
class PresenceDestinationsRow(BaseFederationRow):
state: UserPresenceState
destinations: List[str]

TypeId = "pd"

@staticmethod
Expand All @@ -404,17 +402,15 @@ def add_to_buffer(self, buff: "ParsedFederationStreamData") -> None:
buff.presence_destinations.append((self.state, self.destinations))


class KeyedEduRow(
BaseFederationRow,
namedtuple(
"KeyedEduRow",
("key", "edu"), # tuple(str) - the edu key passed to send_edu # Edu
),
):
@attr.s(slots=True, frozen=True, auto_attribs=True)
class KeyedEduRow(BaseFederationRow):
"""Streams EDUs that have an associated key that is ued to clobber. For example,
typing EDUs clobber based on room_id.
"""

key: Tuple[str, ...] # the edu key passed to send_edu
edu: Edu

TypeId = "k"

@staticmethod
Expand All @@ -428,9 +424,12 @@ def add_to_buffer(self, buff: "ParsedFederationStreamData") -> None:
buff.keyed_edus.setdefault(self.edu.destination, {})[self.key] = self.edu


class EduRow(BaseFederationRow, namedtuple("EduRow", ("edu",))): # Edu
@attr.s(slots=True, frozen=True, auto_attribs=True)
class EduRow(BaseFederationRow):
"""Streams EDUs that don't have keys. See KeyedEduRow"""

edu: Edu

TypeId = "e"

@staticmethod
Expand All @@ -453,14 +452,14 @@ def add_to_buffer(self, buff: "ParsedFederationStreamData") -> None:
TypeToRow = {Row.TypeId: Row for Row in _rowtypes}


ParsedFederationStreamData = namedtuple(
"ParsedFederationStreamData",
(
"presence_destinations", # list of tuples of UserPresenceState and destinations
"keyed_edus", # dict of destination -> { key -> Edu }
"edus", # dict of destination -> [Edu]
),
)
@attr.s(slots=True, frozen=True, auto_attribs=True)
class ParsedFederationStreamData:
# list of tuples of UserPresenceState and destinations
presence_destinations: List[Tuple[UserPresenceState, List[str]]]
# dict of destination -> { key -> Edu }
keyed_edus: Dict[str, Dict[Tuple[str, ...], Edu]]
# dict of destination -> [Edu]
edus: Dict[str, List[Edu]]


def process_rows_for_federation(
Expand Down
4 changes: 2 additions & 2 deletions synapse/handlers/appservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,9 +462,9 @@ async def query_room_alias_exists(
Args:
room_alias: The room alias to query.
Returns:
namedtuple: with keys "room_id" and "servers" or None if no
association can be found.
RoomAliasMapping or None if no association can be found.
"""
room_alias_str = room_alias.to_string()
services = self.store.get_app_services()
Expand Down
10 changes: 6 additions & 4 deletions synapse/handlers/directory.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,13 +278,15 @@ async def get_association(self, room_alias: RoomAlias) -> JsonDict:

users = await self.store.get_users_in_room(room_id)
extra_servers = {get_domain_from_id(u) for u in users}
servers = set(extra_servers) | set(servers)
servers_set = set(extra_servers) | set(servers)

# If this server is in the list of servers, return it first.
if self.server_name in servers:
servers = [self.server_name] + [s for s in servers if s != self.server_name]
if self.server_name in servers_set:
servers = [self.server_name] + [
s for s in servers_set if s != self.server_name
]
else:
servers = list(servers)
servers = list(servers_set)

return {"room_id": room_id, "servers": servers}

Expand Down
22 changes: 9 additions & 13 deletions synapse/handlers/room_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
# limitations under the License.

import logging
from collections import namedtuple
from typing import TYPE_CHECKING, Any, Optional, Tuple

import attr
import msgpack
from unpaddedbase64 import decode_base64, encode_base64

Expand Down Expand Up @@ -474,16 +474,12 @@ async def _get_remote_list_cached(
)


class RoomListNextBatch(
namedtuple(
"RoomListNextBatch",
(
"last_joined_members", # The count to get rooms after/before
"last_room_id", # The room_id to get rooms after/before
"direction_is_forward", # Bool if this is a next_batch, false if prev_batch
),
)
):
@attr.s(slots=True, frozen=True, auto_attribs=True)
class RoomListNextBatch:
last_joined_members: int # The count to get rooms after/before
last_room_id: str # The room_id to get rooms after/before
direction_is_forward: bool # True if this is a next_batch, false if prev_batch

KEY_DICT = {
"last_joined_members": "m",
"last_room_id": "r",
Expand All @@ -502,12 +498,12 @@ def from_token(cls, token: str) -> "RoomListNextBatch":
def to_token(self) -> str:
return encode_base64(
msgpack.dumps(
{self.KEY_DICT[key]: val for key, val in self._asdict().items()}
{self.KEY_DICT[key]: val for key, val in attr.asdict(self).items()}
)
)

def copy_and_replace(self, **kwds: Any) -> "RoomListNextBatch":
return self._replace(**kwds)
return attr.evolve(self, **kwds)


def _matches_room_entry(room_entry: JsonDict, search_filter: dict) -> bool:
Expand Down
14 changes: 9 additions & 5 deletions synapse/handlers/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
# limitations under the License.
import logging
import random
from collections import namedtuple
from typing import TYPE_CHECKING, Dict, Iterable, List, Optional, Set, Tuple

import attr

from synapse.api.errors import AuthError, ShadowBanError, SynapseError
from synapse.appservice import ApplicationService
from synapse.metrics.background_process_metrics import (
Expand All @@ -37,7 +38,10 @@

# A tiny object useful for storing a user's membership in a room, as a mapping
# key
RoomMember = namedtuple("RoomMember", ("room_id", "user_id"))
@attr.s(slots=True, frozen=True, auto_attribs=True)
class RoomMember:
room_id: str
user_id: str


# How often we expect remote servers to resend us presence.
Expand Down Expand Up @@ -119,7 +123,7 @@ def _handle_timeout_for_member(self, now: int, member: RoomMember) -> None:
self.wheel_timer.insert(now=now, obj=member, then=now + 60 * 1000)

def is_typing(self, member: RoomMember) -> bool:
return member.user_id in self._room_typing.get(member.room_id, [])
return member.user_id in self._room_typing.get(member.room_id, set())

async def _push_remote(self, member: RoomMember, typing: bool) -> None:
if not self.federation:
Expand Down Expand Up @@ -166,9 +170,9 @@ def process_replication_rows(
for row in rows:
self._room_serials[row.room_id] = token

prev_typing = set(self._room_typing.get(row.room_id, []))
prev_typing = self._room_typing.get(row.room_id, set())
now_typing = set(row.user_ids)
self._room_typing[row.room_id] = row.user_ids
self._room_typing[row.room_id] = now_typing

if self.federation:
run_as_background_process(
Expand Down
10 changes: 6 additions & 4 deletions synapse/http/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
# limitations under the License.

import abc
import collections
import html
import logging
import types
Expand All @@ -37,6 +36,7 @@
Union,
)

import attr
import jinja2
from canonicaljson import encode_canonical_json
from typing_extensions import Protocol
Expand Down Expand Up @@ -354,9 +354,11 @@ def _send_error_response(
return_json_error(f, request)


_PathEntry = collections.namedtuple(
"_PathEntry", ["pattern", "callback", "servlet_classname"]
)
@attr.s(slots=True, frozen=True, auto_attribs=True)
class _PathEntry:
pattern: Pattern
callback: ServletCallback
servlet_classname: str


class JsonResource(DirectServeJsonResource):
Expand Down
Loading

0 comments on commit cbd82d0

Please sign in to comment.