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

Convert all namedtuples to attrs. #11665

Merged
merged 17 commits into from
Dec 30, 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/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