This repository has been archived by the owner on Apr 26, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Add types to StreamToken and RoomStreamToken #8279
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add type hints to `StreamToken` and `RoomStreamToken` classes. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,7 @@ | |
import string | ||
import sys | ||
from collections import namedtuple | ||
from typing import Any, Dict, Mapping, MutableMapping, Tuple, Type, TypeVar | ||
from typing import Any, Dict, Mapping, MutableMapping, Optional, Tuple, Type, TypeVar | ||
|
||
import attr | ||
from signedjson.key import decode_verify_key_bytes | ||
|
@@ -362,38 +362,95 @@ def f2(m): | |
return username.decode("ascii") | ||
|
||
|
||
class StreamToken( | ||
namedtuple( | ||
"Token", | ||
( | ||
"room_key", | ||
"presence_key", | ||
"typing_key", | ||
"receipt_key", | ||
"account_data_key", | ||
"push_rules_key", | ||
"to_device_key", | ||
"device_list_key", | ||
"groups_key", | ||
), | ||
@attr.s(frozen=True, slots=True) | ||
class RoomStreamToken: | ||
"""Tokens are positions between events. The token "s1" comes after event 1. | ||
|
||
s0 s1 | ||
| | | ||
[0] V [1] V [2] | ||
|
||
Tokens can either be a point in the live event stream or a cursor going | ||
through historic events. | ||
|
||
When traversing the live event stream events are ordered by when they | ||
arrived at the homeserver. | ||
|
||
When traversing historic events the events are ordered by their depth in | ||
the event graph "topological_ordering" and then by when they arrived at the | ||
homeserver "stream_ordering". | ||
|
||
Live tokens start with an "s" followed by the "stream_ordering" id of the | ||
event it comes after. Historic tokens start with a "t" followed by the | ||
"topological_ordering" id of the event it comes after, followed by "-", | ||
followed by the "stream_ordering" id of the event it comes after. | ||
""" | ||
|
||
topological = attr.ib( | ||
type=Optional[int], | ||
validator=attr.validators.optional(attr.validators.instance_of(int)), | ||
) | ||
): | ||
stream = attr.ib(type=int, validator=attr.validators.instance_of(int)) | ||
|
||
@classmethod | ||
def parse(cls, string: str) -> "RoomStreamToken": | ||
try: | ||
if string[0] == "s": | ||
return cls(topological=None, stream=int(string[1:])) | ||
if string[0] == "t": | ||
parts = string[1:].split("-", 1) | ||
return cls(topological=int(parts[0]), stream=int(parts[1])) | ||
except Exception: | ||
pass | ||
raise SynapseError(400, "Invalid token %r" % (string,)) | ||
|
||
@classmethod | ||
def parse_stream_token(cls, string: str) -> "RoomStreamToken": | ||
try: | ||
if string[0] == "s": | ||
return cls(topological=None, stream=int(string[1:])) | ||
except Exception: | ||
pass | ||
raise SynapseError(400, "Invalid token %r" % (string,)) | ||
|
||
def as_tuple(self) -> Tuple[Optional[int], int]: | ||
return (self.topological, self.stream) | ||
|
||
def __str__(self) -> str: | ||
if self.topological is not None: | ||
return "t%d-%d" % (self.topological, self.stream) | ||
else: | ||
return "s%d" % (self.stream,) | ||
|
||
|
||
@attr.s(slots=True, frozen=True) | ||
class StreamToken: | ||
room_key = attr.ib(type=str) | ||
presence_key = attr.ib(type=int) | ||
typing_key = attr.ib(type=int) | ||
receipt_key = attr.ib(type=int) | ||
account_data_key = attr.ib(type=int) | ||
push_rules_key = attr.ib(type=int) | ||
to_device_key = attr.ib(type=int) | ||
device_list_key = attr.ib(type=int) | ||
groups_key = attr.ib(type=int) | ||
|
||
_SEPARATOR = "_" | ||
START = None # type: StreamToken | ||
|
||
@classmethod | ||
def from_string(cls, string): | ||
try: | ||
keys = string.split(cls._SEPARATOR) | ||
while len(keys) < len(cls._fields): | ||
while len(keys) < len(attr.fields(cls)): | ||
# i.e. old token from before receipt_key | ||
keys.append("0") | ||
return cls(*keys) | ||
return cls(keys[0], *(int(k) for k in keys[1:])) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this what allows the removal of the type casts in e.g. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah. Yes. I seem to have squashed away the commit that changes from sometimes storing strings to always storing ints |
||
except Exception: | ||
raise SynapseError(400, "Invalid Token") | ||
|
||
def to_string(self): | ||
return self._SEPARATOR.join([str(k) for k in self]) | ||
return self._SEPARATOR.join([str(k) for k in attr.astuple(self)]) | ||
|
||
@property | ||
def room_stream_id(self): | ||
|
@@ -435,63 +492,10 @@ def copy_and_advance(self, key, new_value): | |
return self | ||
|
||
def copy_and_replace(self, key, new_value): | ||
return self._replace(**{key: new_value}) | ||
|
||
|
||
StreamToken.START = StreamToken(*(["s0"] + ["0"] * (len(StreamToken._fields) - 1))) | ||
|
||
|
||
class RoomStreamToken(namedtuple("_StreamToken", "topological stream")): | ||
"""Tokens are positions between events. The token "s1" comes after event 1. | ||
|
||
s0 s1 | ||
| | | ||
[0] V [1] V [2] | ||
|
||
Tokens can either be a point in the live event stream or a cursor going | ||
through historic events. | ||
|
||
When traversing the live event stream events are ordered by when they | ||
arrived at the homeserver. | ||
|
||
When traversing historic events the events are ordered by their depth in | ||
the event graph "topological_ordering" and then by when they arrived at the | ||
homeserver "stream_ordering". | ||
|
||
Live tokens start with an "s" followed by the "stream_ordering" id of the | ||
event it comes after. Historic tokens start with a "t" followed by the | ||
"topological_ordering" id of the event it comes after, followed by "-", | ||
followed by the "stream_ordering" id of the event it comes after. | ||
""" | ||
return attr.evolve(self, **{key: new_value}) | ||
|
||
__slots__ = [] # type: list | ||
|
||
@classmethod | ||
def parse(cls, string): | ||
try: | ||
if string[0] == "s": | ||
return cls(topological=None, stream=int(string[1:])) | ||
if string[0] == "t": | ||
parts = string[1:].split("-", 1) | ||
return cls(topological=int(parts[0]), stream=int(parts[1])) | ||
except Exception: | ||
pass | ||
raise SynapseError(400, "Invalid token %r" % (string,)) | ||
|
||
@classmethod | ||
def parse_stream_token(cls, string): | ||
try: | ||
if string[0] == "s": | ||
return cls(topological=None, stream=int(string[1:])) | ||
except Exception: | ||
pass | ||
raise SynapseError(400, "Invalid token %r" % (string,)) | ||
|
||
def __str__(self): | ||
if self.topological is not None: | ||
return "t%d-%d" % (self.topological, self.stream) | ||
else: | ||
return "s%d" % (self.stream,) | ||
StreamToken.START = StreamToken.from_string("s0_0") | ||
|
||
|
||
class ThirdPartyInstanceID( | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious why you used
attr.astuple
below (inStreamToken.to_string
) and not here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only because I think
astuple
is a bit magical so I would like to avoid it for this, butStreamToken
already acts a bit like a tuple in a number of places and so may as well justattr.astuple
rather than writing it out. 🤷