Merge branch 'develop' into comp-worker-shorthand
This commit is contained in:
+87
@@ -1,3 +1,90 @@
|
||||
Synapse 1.76.0rc1 (2023-01-25)
|
||||
==============================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- Update the default room version to [v10](https://spec.matrix.org/v1.5/rooms/v10/) ([MSC 3904](https://github.com/matrix-org/matrix-spec-proposals/pull/3904)). Contributed by @FSG-Cat. ([\#14111](https://github.com/matrix-org/synapse/issues/14111))
|
||||
- Adds a `set_displayname()` method to the module API for setting a user's display name. ([\#14629](https://github.com/matrix-org/synapse/issues/14629))
|
||||
- Add a dedicated listener configuration for `health` endpoint. ([\#14747](https://github.com/matrix-org/synapse/issues/14747))
|
||||
- Implement support for MSC3890: Remotely silence local notifications. ([\#14775](https://github.com/matrix-org/synapse/issues/14775))
|
||||
- Implement experimental support for MSC3930: Push rules for (MSC3381) Polls. ([\#14787](https://github.com/matrix-org/synapse/issues/14787))
|
||||
- Per [MSC3925](https://github.com/matrix-org/matrix-spec-proposals/pull/3925), bundle the whole of the replacement with any edited events, and optionally inhibit server-side replacement. ([\#14811](https://github.com/matrix-org/synapse/issues/14811))
|
||||
- Faster joins: always serve a partial join response to servers that request it with the stable query param. ([\#14839](https://github.com/matrix-org/synapse/issues/14839))
|
||||
- Faster joins: allow non-lazy-loading ("eager") syncs to complete after a partial join by omitting partial state rooms until they become fully stated. ([\#14870](https://github.com/matrix-org/synapse/issues/14870))
|
||||
- Faster joins: request partial joins by default. Admins can opt-out of this for the time being---see the upgrade notes. ([\#14905](https://github.com/matrix-org/synapse/issues/14905))
|
||||
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add index to improve performance of the `/timestamp_to_event` endpoint used for jumping to a specific date in the timeline of a room. ([\#14799](https://github.com/matrix-org/synapse/issues/14799))
|
||||
- Fix a long-standing bug where Synapse would exhaust the stack when processing many federation requests where the remote homeserver has disconencted early. ([\#14812](https://github.com/matrix-org/synapse/issues/14812), [\#14842](https://github.com/matrix-org/synapse/issues/14842))
|
||||
- Fix rare races when using workers. ([\#14820](https://github.com/matrix-org/synapse/issues/14820))
|
||||
- Fix a bug introduced in Synapse 1.64.0 when using room version 10 with frozen events enabled. ([\#14864](https://github.com/matrix-org/synapse/issues/14864))
|
||||
- Fix a long-standing bug where the `populate_room_stats` background job could fail on broken rooms. ([\#14873](https://github.com/matrix-org/synapse/issues/14873))
|
||||
- Faster joins: Fix a bug in worker deployments where the room stats and user directory would not get updated when finishing a fast join until another event is sent or received. ([\#14874](https://github.com/matrix-org/synapse/issues/14874))
|
||||
- Faster joins: Fix incompatibility with joins into restricted rooms where no local users have the ability to invite. ([\#14882](https://github.com/matrix-org/synapse/issues/14882))
|
||||
- Fix a regression introduced in Synapse 1.69.0 which can result in database corruption when database migrations are interrupted on sqlite. ([\#14910](https://github.com/matrix-org/synapse/issues/14910))
|
||||
|
||||
|
||||
Updates to the Docker image
|
||||
---------------------------
|
||||
|
||||
- Bump default Python version in the Dockerfile from 3.9 to 3.11. ([\#14875](https://github.com/matrix-org/synapse/issues/14875))
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- Include `x_forwarded` entry in the HTTP listener example configs and remove the remaining `worker_main_http_uri` entries. ([\#14667](https://github.com/matrix-org/synapse/issues/14667))
|
||||
- Remove duplicate commands from the Code Style documentation page; point to the Contributing Guide instead. ([\#14773](https://github.com/matrix-org/synapse/issues/14773))
|
||||
- Add missing documentation for `tag` to `listeners` section. ([\#14803](https://github.com/matrix-org/synapse/issues/14803))
|
||||
- Updated documentation in configuration manual for `user_directory.search_all_users`. ([\#14818](https://github.com/matrix-org/synapse/issues/14818))
|
||||
- Add `worker_manhole` to configuration manual. ([\#14824](https://github.com/matrix-org/synapse/issues/14824))
|
||||
- Fix the example config missing the `id` field in [application service documentation](https://matrix-org.github.io/synapse/latest/application_services.html). ([\#14845](https://github.com/matrix-org/synapse/issues/14845))
|
||||
- Minor corrections to the logging configuration documentation. ([\#14868](https://github.com/matrix-org/synapse/issues/14868))
|
||||
- Document the export user data command. Contributed by @thezaidbintariq. ([\#14883](https://github.com/matrix-org/synapse/issues/14883))
|
||||
|
||||
|
||||
Deprecations and Removals
|
||||
-------------------------
|
||||
|
||||
- Poetry 1.3.2 or higher is now required when `poetry install`ing from source. ([\#14860](https://github.com/matrix-org/synapse/issues/14860))
|
||||
|
||||
|
||||
Internal Changes
|
||||
----------------
|
||||
|
||||
- Faster remote room joins (worker mode): do not populate external hosts-in-room cache when sending events as this requires blocking for full state. ([\#14749](https://github.com/matrix-org/synapse/issues/14749))
|
||||
- Enable Complement tests for Faster Remote Room Joins against worker-mode Synapse. ([\#14752](https://github.com/matrix-org/synapse/issues/14752))
|
||||
- Add some clarifying comments and refactor a portion of the `Keyring` class for readability. ([\#14804](https://github.com/matrix-org/synapse/issues/14804))
|
||||
- Add local poetry config files (`poetry.toml`) to `.gitignore`. ([\#14807](https://github.com/matrix-org/synapse/issues/14807))
|
||||
- Add missing type hints. ([\#14816](https://github.com/matrix-org/synapse/issues/14816), [\#14885](https://github.com/matrix-org/synapse/issues/14885), [\#14889](https://github.com/matrix-org/synapse/issues/14889))
|
||||
- Refactor push tests. ([\#14819](https://github.com/matrix-org/synapse/issues/14819))
|
||||
- Re-enable some linting that was disabled when we switched to ruff. ([\#14821](https://github.com/matrix-org/synapse/issues/14821))
|
||||
- Add `cargo fmt` and `cargo clippy` to the lint script. ([\#14822](https://github.com/matrix-org/synapse/issues/14822))
|
||||
- Drop unused table `presence`. ([\#14825](https://github.com/matrix-org/synapse/issues/14825))
|
||||
- Merge the two account data and the two device list replication streams. ([\#14826](https://github.com/matrix-org/synapse/issues/14826), [\#14833](https://github.com/matrix-org/synapse/issues/14833))
|
||||
- Faster joins: use stable identifiers from [MSC3706](https://github.com/matrix-org/matrix-spec-proposals/pull/3706). ([\#14832](https://github.com/matrix-org/synapse/issues/14832), [\#14841](https://github.com/matrix-org/synapse/issues/14841))
|
||||
- Add a parameter to control whether the federation client performs a partial state join. ([\#14843](https://github.com/matrix-org/synapse/issues/14843))
|
||||
- Add check to avoid starting duplicate partial state syncs. ([\#14844](https://github.com/matrix-org/synapse/issues/14844))
|
||||
- Bump regex from 1.7.0 to 1.7.1. ([\#14848](https://github.com/matrix-org/synapse/issues/14848))
|
||||
- Add an early return when handling no-op presence updates. ([\#14855](https://github.com/matrix-org/synapse/issues/14855))
|
||||
- Fix `wait_for_stream_position` to correctly wait for the right instance to advance its token. ([\#14856](https://github.com/matrix-org/synapse/issues/14856), [\#14872](https://github.com/matrix-org/synapse/issues/14872))
|
||||
- Bump peaceiris/actions-gh-pages from 3.9.1 to 3.9.2. ([\#14861](https://github.com/matrix-org/synapse/issues/14861))
|
||||
- Bump ruff from 0.0.215 to 0.0.224. ([\#14862](https://github.com/matrix-org/synapse/issues/14862))
|
||||
- Bump types-pillow from 9.4.0.0 to 9.4.0.3. ([\#14863](https://github.com/matrix-org/synapse/issues/14863))
|
||||
- Always notify replication when a stream advances automatically. ([\#14877](https://github.com/matrix-org/synapse/issues/14877))
|
||||
- Reduce max time we wait for stream positions. ([\#14881](https://github.com/matrix-org/synapse/issues/14881))
|
||||
- Bump types-opentracing from 2.4.10 to 2.4.10.1. ([\#14896](https://github.com/matrix-org/synapse/issues/14896))
|
||||
- Bump ruff from 0.0.224 to 0.0.230. ([\#14897](https://github.com/matrix-org/synapse/issues/14897))
|
||||
- Bump types-requests from 2.28.11.7 to 2.28.11.8. ([\#14899](https://github.com/matrix-org/synapse/issues/14899))
|
||||
- Bump types-psycopg2 from 2.9.21.2 to 2.9.21.4. ([\#14900](https://github.com/matrix-org/synapse/issues/14900))
|
||||
- Bump types-commonmark from 0.9.2 to 0.9.2.1. ([\#14901](https://github.com/matrix-org/synapse/issues/14901))
|
||||
- Faster joins: allow the resync process more time to fetch `/state` ids. ([\#14912](https://github.com/matrix-org/synapse/issues/14912))
|
||||
|
||||
|
||||
Synapse 1.75.0 (2023-01-17)
|
||||
===========================
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Update the default room version to [v10](https://spec.matrix.org/v1.5/rooms/v10/) ([MSC 3904](https://github.com/matrix-org/matrix-spec-proposals/pull/3904)). Contributed by @FSG-Cat.
|
||||
@@ -1 +0,0 @@
|
||||
Adds a `set_displayname()` method to the module API for setting a user's display name.
|
||||
@@ -1 +0,0 @@
|
||||
Include `x_forwarded` entry in the HTTP listener example configs and remove the remaining `worker_main_http_uri` entries.
|
||||
@@ -1 +0,0 @@
|
||||
Add a dedicated listener configuration for `health` endpoint.
|
||||
@@ -1 +0,0 @@
|
||||
Faster remote room joins (worker mode): do not populate external hosts-in-room cache when sending events as this requires blocking for full state.
|
||||
@@ -1 +0,0 @@
|
||||
Enable Complement tests for Faster Remote Room Joins against worker-mode Synapse.
|
||||
@@ -1 +0,0 @@
|
||||
Remove duplicate commands from the Code Style documentation page; point to the Contributing Guide instead.
|
||||
@@ -1 +0,0 @@
|
||||
Implement support for MSC3890: Remotely silence local notifications.
|
||||
@@ -1 +0,0 @@
|
||||
Implement experimental support for MSC3930: Push rules for (MSC3381) Polls.
|
||||
@@ -1 +0,0 @@
|
||||
Add index to improve performance of the `/timestamp_to_event` endpoint used for jumping to a specific date in the timeline of a room.
|
||||
@@ -1 +0,0 @@
|
||||
Add missing documentation for `tag` to `listeners` section.
|
||||
@@ -1 +0,0 @@
|
||||
Add some clarifying comments and refactor a portion of the `Keyring` class for readability.
|
||||
@@ -1 +0,0 @@
|
||||
Add local poetry config files (`poetry.toml`) to `.gitignore`.
|
||||
@@ -1 +0,0 @@
|
||||
Per [MSC3925](https://github.com/matrix-org/matrix-spec-proposals/pull/3925), bundle the whole of the replacement with any edited events, and optionally inhibit server-side replacement.
|
||||
@@ -1 +0,0 @@
|
||||
Fix a long-standing bug where Synapse would exhaust the stack when processing many federation requests where the remote homeserver has disconencted early.
|
||||
@@ -1 +0,0 @@
|
||||
Updated documentation in configuration manual for `user_directory.search_all_users`.
|
||||
@@ -1 +0,0 @@
|
||||
Refactor push tests.
|
||||
@@ -1 +0,0 @@
|
||||
Fix rare races when using workers.
|
||||
@@ -1 +0,0 @@
|
||||
Re-enable some linting that was disabled when we switched to ruff.
|
||||
@@ -1 +0,0 @@
|
||||
Add `cargo fmt` and `cargo clippy` to the lint script.
|
||||
@@ -1 +0,0 @@
|
||||
Add `worker_manhole` to configuration manual.
|
||||
@@ -1 +0,0 @@
|
||||
Drop unused table `presence`.
|
||||
@@ -1 +0,0 @@
|
||||
Merge the two account data and the two device list replication streams.
|
||||
@@ -1 +0,0 @@
|
||||
Faster joins: use stable identifiers from [MSC3706](https://github.com/matrix-org/matrix-spec-proposals/pull/3706).
|
||||
@@ -1 +0,0 @@
|
||||
Merge the two account data and the two device list replication streams.
|
||||
@@ -1 +0,0 @@
|
||||
Faster joins: always serve a partial join response to servers that request it with the stable query param.
|
||||
@@ -1 +0,0 @@
|
||||
Faster joins: use stable identifiers from [MSC3706](https://github.com/matrix-org/matrix-spec-proposals/pull/3706).
|
||||
@@ -1 +0,0 @@
|
||||
Fix a long-standing bug where Synapse would exhaust the stack when processing many federation requests where the remote homeserver has disconencted early.
|
||||
@@ -1 +0,0 @@
|
||||
Add a parameter to control whether the federation client performs a partial state join.
|
||||
@@ -1 +0,0 @@
|
||||
Add check to avoid starting duplicate partial state syncs.
|
||||
@@ -1 +0,0 @@
|
||||
Fix the example config missing the `id` field in [application service documentation](https://matrix-org.github.io/synapse/latest/application_services.html).
|
||||
@@ -1 +0,0 @@
|
||||
Bump regex from 1.7.0 to 1.7.1.
|
||||
@@ -1 +0,0 @@
|
||||
Add an early return when handling no-op presence updates.
|
||||
@@ -1 +0,0 @@
|
||||
Fix `wait_for_stream_position` to correctly wait for the right instance to advance its token.
|
||||
@@ -1 +0,0 @@
|
||||
Poetry 1.3.2 or higher is now required when `poetry install`ing from source.
|
||||
@@ -1 +0,0 @@
|
||||
Bump peaceiris/actions-gh-pages from 3.9.1 to 3.9.2.
|
||||
@@ -1 +0,0 @@
|
||||
Bump ruff from 0.0.215 to 0.0.224.
|
||||
@@ -1 +0,0 @@
|
||||
Bump types-pillow from 9.4.0.0 to 9.4.0.3.
|
||||
@@ -1 +0,0 @@
|
||||
Fix a bug introduced in Synapse 1.64.0 when using room version 10 with frozen events enabled.
|
||||
@@ -1 +0,0 @@
|
||||
Minor corrections to the logging configuration documentation.
|
||||
@@ -1 +0,0 @@
|
||||
Faster joins: allow non-lazy-loading ("eager") syncs to complete after a partial join by omitting partial state rooms until they become fully stated.
|
||||
@@ -1 +0,0 @@
|
||||
Fix `wait_for_stream_position` to correctly wait for the right instance to advance its token.
|
||||
@@ -1 +0,0 @@
|
||||
Fix a long-standing bug where the `populate_room_stats` background job could fail on broken rooms.
|
||||
@@ -1 +0,0 @@
|
||||
Faster joins: Fix a bug in worker deployments where the room stats and user directory would not get updated when finishing a fast join until another event is sent or received.
|
||||
@@ -1 +0,0 @@
|
||||
Bump default Python version in the Dockerfile from 3.9 to 3.11.
|
||||
@@ -1 +0,0 @@
|
||||
Always notify replication when a stream advances automatically.
|
||||
@@ -0,0 +1 @@
|
||||
Fix a bug when using the `send_local_online_presence_to` module API.
|
||||
@@ -1 +0,0 @@
|
||||
Reduce max time we wait for stream positions.
|
||||
@@ -1 +0,0 @@
|
||||
Faster joins: Fix incompatibility with joins into restricted rooms where no local users have the ability to invite.
|
||||
@@ -1 +0,0 @@
|
||||
Bump types-opentracing from 2.4.10 to 2.4.10.1.
|
||||
@@ -1 +0,0 @@
|
||||
Bump ruff from 0.0.224 to 0.0.230.
|
||||
@@ -1 +0,0 @@
|
||||
Bump types-requests from 2.28.11.7 to 2.28.11.8.
|
||||
@@ -1 +0,0 @@
|
||||
Bump types-psycopg2 from 2.9.21.2 to 2.9.21.4.
|
||||
@@ -1 +0,0 @@
|
||||
Bump types-commonmark from 0.9.2 to 0.9.2.1.
|
||||
@@ -1 +0,0 @@
|
||||
Faster joins: request partial joins by default. Admins can opt-out of this for the time being---see the upgrade notes.
|
||||
@@ -0,0 +1 @@
|
||||
Document how to handle Dependabot pull requests.
|
||||
Vendored
+3
-2
@@ -1,8 +1,9 @@
|
||||
matrix-synapse-py3 (1.75.1) UNRELEASED; urgency=medium
|
||||
matrix-synapse-py3 (1.76.0~rc1) stable; urgency=medium
|
||||
|
||||
* Use Poetry 1.3.2 to manage the bundled virtualenv included with this package.
|
||||
* New Synapse release 1.76.0rc1.
|
||||
|
||||
-- Synapse Packaging team <packages@matrix.org> Tue, 17 Jan 2023 15:08:00 +0000
|
||||
-- Synapse Packaging team <packages@matrix.org> Wed, 25 Jan 2023 16:21:16 +0000
|
||||
|
||||
matrix-synapse-py3 (1.75.0) stable; urgency=medium
|
||||
|
||||
|
||||
@@ -258,6 +258,20 @@ because [`build`](https://github.com/pypa/build) is a standardish tool which
|
||||
doesn't require poetry. (It's what we use in CI too). However, you could try
|
||||
`poetry build` too.
|
||||
|
||||
## ...handle a Dependabot pull request?
|
||||
|
||||
Synapse uses Dependabot to keep the `poetry.lock` file up-to-date. When it
|
||||
creates a pull request a GitHub Action will run to automatically create a changelog
|
||||
file. Ensure that:
|
||||
|
||||
* the lockfile changes look reasonable;
|
||||
* the upstream changelog file (linked in the description) doesn't include any
|
||||
breaking changes;
|
||||
* continuous integration passes (due to permissions, the GitHub Actions run on
|
||||
the changelog commit will fail, look at the initial commit of the pull request);
|
||||
|
||||
In particular, any updates to the type hints (usually packages which start with `types-`)
|
||||
should be safe to merge if linting passes.
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
|
||||
@@ -32,6 +32,14 @@ What users are registered on my server?
|
||||
SELECT NAME from users;
|
||||
```
|
||||
|
||||
How can I export user data?
|
||||
---
|
||||
Synapse includes a Python command to export data for a specific user. It takes the homeserver
|
||||
configuration file and the full Matrix ID of the user to export:
|
||||
```console
|
||||
python -m synapse.app.admin_cmd -c <config_file> export-data <user_id>
|
||||
```
|
||||
|
||||
Manually resetting passwords
|
||||
---
|
||||
Users can reset their password through their client. Alternatively, a server admin
|
||||
|
||||
@@ -35,12 +35,8 @@ exclude = (?x)
|
||||
|tests/api/test_auth.py
|
||||
|tests/app/test_openid_listener.py
|
||||
|tests/appservice/test_scheduler.py
|
||||
|tests/events/test_presence_router.py
|
||||
|tests/events/test_utils.py
|
||||
|tests/federation/test_federation_catch_up.py
|
||||
|tests/federation/test_federation_sender.py
|
||||
|tests/federation/transport/test_knocking.py
|
||||
|tests/handlers/test_typing.py
|
||||
|tests/http/federation/test_matrix_federation_agent.py
|
||||
|tests/http/federation/test_srv_resolver.py
|
||||
|tests/http/test_proxyagent.py
|
||||
@@ -87,6 +83,9 @@ disallow_untyped_defs = True
|
||||
[mypy-tests.crypto.*]
|
||||
disallow_untyped_defs = True
|
||||
|
||||
[mypy-tests.events.*]
|
||||
disallow_untyped_defs = True
|
||||
|
||||
[mypy-tests.federation.transport.test_client]
|
||||
disallow_untyped_defs = True
|
||||
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ manifest-path = "rust/Cargo.toml"
|
||||
|
||||
[tool.poetry]
|
||||
name = "matrix-synapse"
|
||||
version = "1.75.0"
|
||||
version = "1.76.0rc1"
|
||||
description = "Homeserver for the Matrix decentralised comms protocol"
|
||||
authors = ["Matrix.org Team and Contributors <packages@matrix.org>"]
|
||||
license = "Apache-2.0"
|
||||
|
||||
@@ -605,10 +605,11 @@ class EventClientSerializer:
|
||||
|
||||
|
||||
_PowerLevel = Union[str, int]
|
||||
PowerLevelsContent = Mapping[str, Union[_PowerLevel, Mapping[str, _PowerLevel]]]
|
||||
|
||||
|
||||
def copy_and_fixup_power_levels_contents(
|
||||
old_power_levels: Mapping[str, Union[_PowerLevel, Mapping[str, _PowerLevel]]]
|
||||
old_power_levels: PowerLevelsContent,
|
||||
) -> Dict[str, Union[int, Dict[str, int]]]:
|
||||
"""Copy the content of a power_levels event, unfreezing frozendicts along the way.
|
||||
|
||||
|
||||
@@ -102,6 +102,10 @@ class TransportLayerClient:
|
||||
destination,
|
||||
path=path,
|
||||
args={"event_id": event_id},
|
||||
# This can take a looooooong time for large rooms. Give this a generous
|
||||
# timeout of 10 minutes to avoid the partial state resync timing out early
|
||||
# and trying a bunch of servers who haven't seen our join yet.
|
||||
timeout=600_000,
|
||||
parser=_StateParser(room_version),
|
||||
)
|
||||
|
||||
|
||||
@@ -64,7 +64,13 @@ from synapse.replication.tcp.commands import ClearUserSyncsCommand
|
||||
from synapse.replication.tcp.streams import PresenceFederationStream, PresenceStream
|
||||
from synapse.storage.databases.main import DataStore
|
||||
from synapse.streams import EventSource
|
||||
from synapse.types import JsonDict, StreamKeyType, UserID, get_domain_from_id
|
||||
from synapse.types import (
|
||||
JsonDict,
|
||||
StrCollection,
|
||||
StreamKeyType,
|
||||
UserID,
|
||||
get_domain_from_id,
|
||||
)
|
||||
from synapse.util.async_helpers import Linearizer
|
||||
from synapse.util.metrics import Measure
|
||||
from synapse.util.wheel_timer import WheelTimer
|
||||
@@ -320,7 +326,7 @@ class BasePresenceHandler(abc.ABC):
|
||||
for destination, host_states in hosts_to_states.items():
|
||||
self._federation.send_presence_to_destinations(host_states, [destination])
|
||||
|
||||
async def send_full_presence_to_users(self, user_ids: Collection[str]) -> None:
|
||||
async def send_full_presence_to_users(self, user_ids: StrCollection) -> None:
|
||||
"""
|
||||
Adds to the list of users who should receive a full snapshot of presence
|
||||
upon their next sync. Note that this only works for local users.
|
||||
@@ -1601,7 +1607,7 @@ class PresenceEventSource(EventSource[int, UserPresenceState]):
|
||||
# Having a default limit doesn't match the EventSource API, but some
|
||||
# callers do not provide it. It is unused in this class.
|
||||
limit: int = 0,
|
||||
room_ids: Optional[Collection[str]] = None,
|
||||
room_ids: Optional[StrCollection] = None,
|
||||
is_guest: bool = False,
|
||||
explicit_room_id: Optional[str] = None,
|
||||
include_offline: bool = True,
|
||||
@@ -1688,7 +1694,7 @@ class PresenceEventSource(EventSource[int, UserPresenceState]):
|
||||
|
||||
# The set of users that we're interested in and that have had a presence update.
|
||||
# We'll actually pull the presence updates for these users at the end.
|
||||
interested_and_updated_users: Collection[str]
|
||||
interested_and_updated_users: StrCollection
|
||||
|
||||
if from_key is not None:
|
||||
# First get all users that have had a presence update
|
||||
@@ -2120,7 +2126,7 @@ class PresenceFederationQueue:
|
||||
# stream_id, destinations, user_ids)`. We don't store the full states
|
||||
# for efficiency, and remote workers will already have the full states
|
||||
# cached.
|
||||
self._queue: List[Tuple[int, int, Collection[str], Set[str]]] = []
|
||||
self._queue: List[Tuple[int, int, StrCollection, Set[str]]] = []
|
||||
|
||||
self._next_id = 1
|
||||
|
||||
@@ -2142,7 +2148,7 @@ class PresenceFederationQueue:
|
||||
self._queue = self._queue[index:]
|
||||
|
||||
def send_presence_to_destinations(
|
||||
self, states: Collection[UserPresenceState], destinations: Collection[str]
|
||||
self, states: Collection[UserPresenceState], destinations: StrCollection
|
||||
) -> None:
|
||||
"""Send the presence states to the given destinations.
|
||||
|
||||
|
||||
@@ -1158,7 +1158,7 @@ class ModuleApi:
|
||||
# Send to remote destinations.
|
||||
destination = UserID.from_string(user).domain
|
||||
presence_handler.get_federation_queue().send_presence_to_destinations(
|
||||
presence_events, destination
|
||||
presence_events, [destination]
|
||||
)
|
||||
|
||||
def looping_background_call(
|
||||
|
||||
+2
-1
@@ -46,6 +46,7 @@ from synapse.types import (
|
||||
JsonDict,
|
||||
PersistedEventPosition,
|
||||
RoomStreamToken,
|
||||
StrCollection,
|
||||
StreamKeyType,
|
||||
StreamToken,
|
||||
UserID,
|
||||
@@ -716,7 +717,7 @@ class Notifier:
|
||||
|
||||
async def _get_room_ids(
|
||||
self, user: UserID, explicit_room_id: Optional[str]
|
||||
) -> Tuple[Collection[str], bool]:
|
||||
) -> Tuple[StrCollection, bool]:
|
||||
joined_room_ids = await self.store.get_rooms_for_user(user.to_string())
|
||||
if explicit_room_id:
|
||||
if explicit_room_id in joined_room_ids:
|
||||
|
||||
@@ -132,6 +132,9 @@ class BaseDatabaseEngine(Generic[ConnectionType, CursorType], metaclass=abc.ABCM
|
||||
"""Execute a chunk of SQL containing multiple semicolon-delimited statements.
|
||||
|
||||
This is not provided by DBAPI2, and so needs engine-specific support.
|
||||
|
||||
Some database engines may automatically COMMIT the ongoing transaction both
|
||||
before and after executing the script.
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
@@ -135,13 +135,14 @@ class Sqlite3Engine(BaseDatabaseEngine[sqlite3.Connection, sqlite3.Cursor]):
|
||||
> than one statement with it, it will raise a Warning. Use executescript() if
|
||||
> you want to execute multiple SQL statements with one call.
|
||||
|
||||
Though the docs for `executescript` warn:
|
||||
The script is wrapped in transaction control statemnets, since the docs for
|
||||
`executescript` warn:
|
||||
|
||||
> If there is a pending transaction, an implicit COMMIT statement is executed
|
||||
> first. No other implicit transaction control is performed; any transaction
|
||||
> control must be added to sql_script.
|
||||
"""
|
||||
cursor.executescript(script)
|
||||
cursor.executescript(f"BEGIN TRANSACTION;\n{script}\nCOMMIT;")
|
||||
|
||||
|
||||
# Following functions taken from: https://github.com/coleifer/peewee
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from typing import Collection, Generic, List, Optional, Tuple, TypeVar
|
||||
from typing import Generic, List, Optional, Tuple, TypeVar
|
||||
|
||||
from synapse.types import UserID
|
||||
from synapse.types import StrCollection, UserID
|
||||
|
||||
# The key, this is either a stream token or int.
|
||||
K = TypeVar("K")
|
||||
@@ -28,7 +28,7 @@ class EventSource(Generic[K, R]):
|
||||
user: UserID,
|
||||
from_key: K,
|
||||
limit: int,
|
||||
room_ids: Collection[str],
|
||||
room_ids: StrCollection,
|
||||
is_guest: bool,
|
||||
explicit_room_id: Optional[str] = None,
|
||||
) -> Tuple[List[R], K]:
|
||||
|
||||
@@ -16,6 +16,8 @@ from unittest.mock import Mock
|
||||
|
||||
import attr
|
||||
|
||||
from twisted.test.proto_helpers import MemoryReactor
|
||||
|
||||
from synapse.api.constants import EduTypes
|
||||
from synapse.events.presence_router import PresenceRouter, load_legacy_presence_router
|
||||
from synapse.federation.units import Transaction
|
||||
@@ -23,11 +25,13 @@ from synapse.handlers.presence import UserPresenceState
|
||||
from synapse.module_api import ModuleApi
|
||||
from synapse.rest import admin
|
||||
from synapse.rest.client import login, presence, room
|
||||
from synapse.server import HomeServer
|
||||
from synapse.types import JsonDict, StreamToken, create_requester
|
||||
from synapse.util import Clock
|
||||
|
||||
from tests.handlers.test_sync import generate_sync_config
|
||||
from tests.test_utils import simple_async_mock
|
||||
from tests.unittest import FederatingHomeserverTestCase, TestCase, override_config
|
||||
from tests.unittest import FederatingHomeserverTestCase, override_config
|
||||
|
||||
|
||||
@attr.s
|
||||
@@ -49,9 +53,7 @@ class LegacyPresenceRouterTestModule:
|
||||
}
|
||||
return users_to_state
|
||||
|
||||
async def get_interested_users(
|
||||
self, user_id: str
|
||||
) -> Union[Set[str], PresenceRouter.ALL_USERS]:
|
||||
async def get_interested_users(self, user_id: str) -> Union[Set[str], str]:
|
||||
if user_id in self._config.users_who_should_receive_all_presence:
|
||||
return PresenceRouter.ALL_USERS
|
||||
|
||||
@@ -71,9 +73,14 @@ class LegacyPresenceRouterTestModule:
|
||||
# Initialise a typed config object
|
||||
config = PresenceRouterTestConfig()
|
||||
|
||||
config.users_who_should_receive_all_presence = config_dict.get(
|
||||
users_who_should_receive_all_presence = config_dict.get(
|
||||
"users_who_should_receive_all_presence"
|
||||
)
|
||||
assert isinstance(users_who_should_receive_all_presence, list)
|
||||
|
||||
config.users_who_should_receive_all_presence = (
|
||||
users_who_should_receive_all_presence
|
||||
)
|
||||
|
||||
return config
|
||||
|
||||
@@ -96,9 +103,7 @@ class PresenceRouterTestModule:
|
||||
}
|
||||
return users_to_state
|
||||
|
||||
async def get_interested_users(
|
||||
self, user_id: str
|
||||
) -> Union[Set[str], PresenceRouter.ALL_USERS]:
|
||||
async def get_interested_users(self, user_id: str) -> Union[Set[str], str]:
|
||||
if user_id in self._config.users_who_should_receive_all_presence:
|
||||
return PresenceRouter.ALL_USERS
|
||||
|
||||
@@ -118,9 +123,14 @@ class PresenceRouterTestModule:
|
||||
# Initialise a typed config object
|
||||
config = PresenceRouterTestConfig()
|
||||
|
||||
config.users_who_should_receive_all_presence = config_dict.get(
|
||||
users_who_should_receive_all_presence = config_dict.get(
|
||||
"users_who_should_receive_all_presence"
|
||||
)
|
||||
assert isinstance(users_who_should_receive_all_presence, list)
|
||||
|
||||
config.users_who_should_receive_all_presence = (
|
||||
users_who_should_receive_all_presence
|
||||
)
|
||||
|
||||
return config
|
||||
|
||||
@@ -140,7 +150,7 @@ class PresenceRouterTestCase(FederatingHomeserverTestCase):
|
||||
presence.register_servlets,
|
||||
]
|
||||
|
||||
def make_homeserver(self, reactor, clock):
|
||||
def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer:
|
||||
# Mock out the calls over federation.
|
||||
fed_transport_client = Mock(spec=["send_transaction"])
|
||||
fed_transport_client.send_transaction = simple_async_mock({})
|
||||
@@ -153,7 +163,9 @@ class PresenceRouterTestCase(FederatingHomeserverTestCase):
|
||||
|
||||
return hs
|
||||
|
||||
def prepare(self, reactor, clock, homeserver):
|
||||
def prepare(
|
||||
self, reactor: MemoryReactor, clock: Clock, homeserver: HomeServer
|
||||
) -> None:
|
||||
self.sync_handler = self.hs.get_sync_handler()
|
||||
self.module_api = homeserver.get_module_api()
|
||||
|
||||
@@ -176,7 +188,7 @@ class PresenceRouterTestCase(FederatingHomeserverTestCase):
|
||||
},
|
||||
}
|
||||
)
|
||||
def test_receiving_all_presence_legacy(self):
|
||||
def test_receiving_all_presence_legacy(self) -> None:
|
||||
self.receiving_all_presence_test_body()
|
||||
|
||||
@override_config(
|
||||
@@ -193,10 +205,10 @@ class PresenceRouterTestCase(FederatingHomeserverTestCase):
|
||||
],
|
||||
}
|
||||
)
|
||||
def test_receiving_all_presence(self):
|
||||
def test_receiving_all_presence(self) -> None:
|
||||
self.receiving_all_presence_test_body()
|
||||
|
||||
def receiving_all_presence_test_body(self):
|
||||
def receiving_all_presence_test_body(self) -> None:
|
||||
"""Test that a user that does not share a room with another other can receive
|
||||
presence for them, due to presence routing.
|
||||
"""
|
||||
@@ -302,7 +314,7 @@ class PresenceRouterTestCase(FederatingHomeserverTestCase):
|
||||
},
|
||||
}
|
||||
)
|
||||
def test_send_local_online_presence_to_with_module_legacy(self):
|
||||
def test_send_local_online_presence_to_with_module_legacy(self) -> None:
|
||||
self.send_local_online_presence_to_with_module_test_body()
|
||||
|
||||
@override_config(
|
||||
@@ -321,10 +333,10 @@ class PresenceRouterTestCase(FederatingHomeserverTestCase):
|
||||
],
|
||||
}
|
||||
)
|
||||
def test_send_local_online_presence_to_with_module(self):
|
||||
def test_send_local_online_presence_to_with_module(self) -> None:
|
||||
self.send_local_online_presence_to_with_module_test_body()
|
||||
|
||||
def send_local_online_presence_to_with_module_test_body(self):
|
||||
def send_local_online_presence_to_with_module_test_body(self) -> None:
|
||||
"""Tests that send_local_presence_to_users sends local online presence to a set
|
||||
of specified local and remote users, with a custom PresenceRouter module enabled.
|
||||
"""
|
||||
@@ -447,18 +459,18 @@ class PresenceRouterTestCase(FederatingHomeserverTestCase):
|
||||
continue
|
||||
|
||||
# EDUs can contain multiple presence updates
|
||||
for presence_update in edu["content"]["push"]:
|
||||
for presence_edu in edu["content"]["push"]:
|
||||
# Check for presence updates that contain the user IDs we're after
|
||||
found_users.add(presence_update["user_id"])
|
||||
found_users.add(presence_edu["user_id"])
|
||||
|
||||
# Ensure that no offline states are being sent out
|
||||
self.assertNotEqual(presence_update["presence"], "offline")
|
||||
self.assertNotEqual(presence_edu["presence"], "offline")
|
||||
|
||||
self.assertEqual(found_users, expected_users)
|
||||
|
||||
|
||||
def send_presence_update(
|
||||
testcase: TestCase,
|
||||
testcase: FederatingHomeserverTestCase,
|
||||
user_id: str,
|
||||
access_token: str,
|
||||
presence_state: str,
|
||||
@@ -479,7 +491,7 @@ def send_presence_update(
|
||||
|
||||
|
||||
def sync_presence(
|
||||
testcase: TestCase,
|
||||
testcase: FederatingHomeserverTestCase,
|
||||
user_id: str,
|
||||
since_token: Optional[StreamToken] = None,
|
||||
) -> Tuple[List[UserPresenceState], StreamToken]:
|
||||
@@ -500,7 +512,7 @@ def sync_presence(
|
||||
requester = create_requester(user_id)
|
||||
sync_config = generate_sync_config(requester.user.to_string())
|
||||
sync_result = testcase.get_success(
|
||||
testcase.sync_handler.wait_for_sync_for_user(
|
||||
testcase.hs.get_sync_handler().wait_for_sync_for_user(
|
||||
requester, sync_config, since_token
|
||||
)
|
||||
)
|
||||
|
||||
@@ -12,9 +12,14 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from twisted.test.proto_helpers import MemoryReactor
|
||||
|
||||
from synapse.events import EventBase
|
||||
from synapse.events.snapshot import EventContext
|
||||
from synapse.rest import admin
|
||||
from synapse.rest.client import login, room
|
||||
from synapse.server import HomeServer
|
||||
from synapse.util import Clock
|
||||
|
||||
from tests import unittest
|
||||
from tests.test_utils.event_injection import create_event
|
||||
@@ -27,7 +32,7 @@ class TestEventContext(unittest.HomeserverTestCase):
|
||||
room.register_servlets,
|
||||
]
|
||||
|
||||
def prepare(self, reactor, clock, hs):
|
||||
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
|
||||
self.store = hs.get_datastores().main
|
||||
self._storage_controllers = hs.get_storage_controllers()
|
||||
|
||||
@@ -35,7 +40,7 @@ class TestEventContext(unittest.HomeserverTestCase):
|
||||
self.user_tok = self.login("u1", "pass")
|
||||
self.room_id = self.helper.create_room_as(tok=self.user_tok)
|
||||
|
||||
def test_serialize_deserialize_msg(self):
|
||||
def test_serialize_deserialize_msg(self) -> None:
|
||||
"""Test that an EventContext for a message event is the same after
|
||||
serialize/deserialize.
|
||||
"""
|
||||
@@ -51,7 +56,7 @@ class TestEventContext(unittest.HomeserverTestCase):
|
||||
|
||||
self._check_serialize_deserialize(event, context)
|
||||
|
||||
def test_serialize_deserialize_state_no_prev(self):
|
||||
def test_serialize_deserialize_state_no_prev(self) -> None:
|
||||
"""Test that an EventContext for a state event (with not previous entry)
|
||||
is the same after serialize/deserialize.
|
||||
"""
|
||||
@@ -67,7 +72,7 @@ class TestEventContext(unittest.HomeserverTestCase):
|
||||
|
||||
self._check_serialize_deserialize(event, context)
|
||||
|
||||
def test_serialize_deserialize_state_prev(self):
|
||||
def test_serialize_deserialize_state_prev(self) -> None:
|
||||
"""Test that an EventContext for a state event (which replaces a
|
||||
previous entry) is the same after serialize/deserialize.
|
||||
"""
|
||||
@@ -84,7 +89,9 @@ class TestEventContext(unittest.HomeserverTestCase):
|
||||
|
||||
self._check_serialize_deserialize(event, context)
|
||||
|
||||
def _check_serialize_deserialize(self, event, context):
|
||||
def _check_serialize_deserialize(
|
||||
self, event: EventBase, context: EventContext
|
||||
) -> None:
|
||||
serialized = self.get_success(context.serialize(event, self.store))
|
||||
|
||||
d_context = EventContext.deserialize(self._storage_controllers, serialized)
|
||||
|
||||
+38
-33
@@ -13,21 +13,24 @@
|
||||
# limitations under the License.
|
||||
|
||||
import unittest as stdlib_unittest
|
||||
from typing import Any, List, Mapping, Optional
|
||||
|
||||
from synapse.api.constants import EventContentFields
|
||||
from synapse.api.room_versions import RoomVersions
|
||||
from synapse.events import make_event_from_dict
|
||||
from synapse.events import EventBase, make_event_from_dict
|
||||
from synapse.events.utils import (
|
||||
PowerLevelsContent,
|
||||
SerializeEventConfig,
|
||||
copy_and_fixup_power_levels_contents,
|
||||
maybe_upsert_event_field,
|
||||
prune_event,
|
||||
serialize_event,
|
||||
)
|
||||
from synapse.types import JsonDict
|
||||
from synapse.util.frozenutils import freeze
|
||||
|
||||
|
||||
def MockEvent(**kwargs):
|
||||
def MockEvent(**kwargs: Any) -> EventBase:
|
||||
if "event_id" not in kwargs:
|
||||
kwargs["event_id"] = "fake_event_id"
|
||||
if "type" not in kwargs:
|
||||
@@ -60,7 +63,7 @@ class TestMaybeUpsertEventField(stdlib_unittest.TestCase):
|
||||
|
||||
|
||||
class PruneEventTestCase(stdlib_unittest.TestCase):
|
||||
def run_test(self, evdict, matchdict, **kwargs):
|
||||
def run_test(self, evdict: JsonDict, matchdict: JsonDict, **kwargs: Any) -> None:
|
||||
"""
|
||||
Asserts that a new event constructed with `evdict` will look like
|
||||
`matchdict` when it is redacted.
|
||||
@@ -74,7 +77,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
|
||||
prune_event(make_event_from_dict(evdict, **kwargs)).get_dict(), matchdict
|
||||
)
|
||||
|
||||
def test_minimal(self):
|
||||
def test_minimal(self) -> None:
|
||||
self.run_test(
|
||||
{"type": "A", "event_id": "$test:domain"},
|
||||
{
|
||||
@@ -86,7 +89,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
|
||||
},
|
||||
)
|
||||
|
||||
def test_basic_keys(self):
|
||||
def test_basic_keys(self) -> None:
|
||||
"""Ensure that the keys that should be untouched are kept."""
|
||||
# Note that some of the values below don't really make sense, but the
|
||||
# pruning of events doesn't worry about the values of any fields (with
|
||||
@@ -138,7 +141,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
|
||||
room_version=RoomVersions.MSC2176,
|
||||
)
|
||||
|
||||
def test_unsigned(self):
|
||||
def test_unsigned(self) -> None:
|
||||
"""Ensure that unsigned properties get stripped (except age_ts and replaces_state)."""
|
||||
self.run_test(
|
||||
{
|
||||
@@ -159,7 +162,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
|
||||
},
|
||||
)
|
||||
|
||||
def test_content(self):
|
||||
def test_content(self) -> None:
|
||||
"""The content dictionary should be stripped in most cases."""
|
||||
self.run_test(
|
||||
{"type": "C", "event_id": "$test:domain", "content": {"things": "here"}},
|
||||
@@ -194,7 +197,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
|
||||
},
|
||||
)
|
||||
|
||||
def test_create(self):
|
||||
def test_create(self) -> None:
|
||||
"""Create events are partially redacted until MSC2176."""
|
||||
self.run_test(
|
||||
{
|
||||
@@ -223,7 +226,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
|
||||
room_version=RoomVersions.MSC2176,
|
||||
)
|
||||
|
||||
def test_power_levels(self):
|
||||
def test_power_levels(self) -> None:
|
||||
"""Power level events keep a variety of content keys."""
|
||||
self.run_test(
|
||||
{
|
||||
@@ -273,7 +276,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
|
||||
room_version=RoomVersions.MSC2176,
|
||||
)
|
||||
|
||||
def test_alias_event(self):
|
||||
def test_alias_event(self) -> None:
|
||||
"""Alias events have special behavior up through room version 6."""
|
||||
self.run_test(
|
||||
{
|
||||
@@ -302,7 +305,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
|
||||
room_version=RoomVersions.V6,
|
||||
)
|
||||
|
||||
def test_redacts(self):
|
||||
def test_redacts(self) -> None:
|
||||
"""Redaction events have no special behaviour until MSC2174/MSC2176."""
|
||||
|
||||
self.run_test(
|
||||
@@ -328,7 +331,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
|
||||
room_version=RoomVersions.MSC2176,
|
||||
)
|
||||
|
||||
def test_join_rules(self):
|
||||
def test_join_rules(self) -> None:
|
||||
"""Join rules events have changed behavior starting with MSC3083."""
|
||||
self.run_test(
|
||||
{
|
||||
@@ -371,7 +374,7 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
|
||||
room_version=RoomVersions.V8,
|
||||
)
|
||||
|
||||
def test_member(self):
|
||||
def test_member(self) -> None:
|
||||
"""Member events have changed behavior starting with MSC3375."""
|
||||
self.run_test(
|
||||
{
|
||||
@@ -417,12 +420,12 @@ class PruneEventTestCase(stdlib_unittest.TestCase):
|
||||
|
||||
|
||||
class SerializeEventTestCase(stdlib_unittest.TestCase):
|
||||
def serialize(self, ev, fields):
|
||||
def serialize(self, ev: EventBase, fields: Optional[List[str]]) -> JsonDict:
|
||||
return serialize_event(
|
||||
ev, 1479807801915, config=SerializeEventConfig(only_event_fields=fields)
|
||||
)
|
||||
|
||||
def test_event_fields_works_with_keys(self):
|
||||
def test_event_fields_works_with_keys(self) -> None:
|
||||
self.assertEqual(
|
||||
self.serialize(
|
||||
MockEvent(sender="@alice:localhost", room_id="!foo:bar"), ["room_id"]
|
||||
@@ -430,7 +433,7 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
|
||||
{"room_id": "!foo:bar"},
|
||||
)
|
||||
|
||||
def test_event_fields_works_with_nested_keys(self):
|
||||
def test_event_fields_works_with_nested_keys(self) -> None:
|
||||
self.assertEqual(
|
||||
self.serialize(
|
||||
MockEvent(
|
||||
@@ -443,7 +446,7 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
|
||||
{"content": {"body": "A message"}},
|
||||
)
|
||||
|
||||
def test_event_fields_works_with_dot_keys(self):
|
||||
def test_event_fields_works_with_dot_keys(self) -> None:
|
||||
self.assertEqual(
|
||||
self.serialize(
|
||||
MockEvent(
|
||||
@@ -456,7 +459,7 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
|
||||
{"content": {"key.with.dots": {}}},
|
||||
)
|
||||
|
||||
def test_event_fields_works_with_nested_dot_keys(self):
|
||||
def test_event_fields_works_with_nested_dot_keys(self) -> None:
|
||||
self.assertEqual(
|
||||
self.serialize(
|
||||
MockEvent(
|
||||
@@ -472,7 +475,7 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
|
||||
{"content": {"nested.dot.key": {"leaf.key": 42}}},
|
||||
)
|
||||
|
||||
def test_event_fields_nops_with_unknown_keys(self):
|
||||
def test_event_fields_nops_with_unknown_keys(self) -> None:
|
||||
self.assertEqual(
|
||||
self.serialize(
|
||||
MockEvent(
|
||||
@@ -485,7 +488,7 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
|
||||
{"content": {"foo": "bar"}},
|
||||
)
|
||||
|
||||
def test_event_fields_nops_with_non_dict_keys(self):
|
||||
def test_event_fields_nops_with_non_dict_keys(self) -> None:
|
||||
self.assertEqual(
|
||||
self.serialize(
|
||||
MockEvent(
|
||||
@@ -498,7 +501,7 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
|
||||
{},
|
||||
)
|
||||
|
||||
def test_event_fields_nops_with_array_keys(self):
|
||||
def test_event_fields_nops_with_array_keys(self) -> None:
|
||||
self.assertEqual(
|
||||
self.serialize(
|
||||
MockEvent(
|
||||
@@ -511,7 +514,7 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
|
||||
{},
|
||||
)
|
||||
|
||||
def test_event_fields_all_fields_if_empty(self):
|
||||
def test_event_fields_all_fields_if_empty(self) -> None:
|
||||
self.assertEqual(
|
||||
self.serialize(
|
||||
MockEvent(
|
||||
@@ -531,16 +534,16 @@ class SerializeEventTestCase(stdlib_unittest.TestCase):
|
||||
},
|
||||
)
|
||||
|
||||
def test_event_fields_fail_if_fields_not_str(self):
|
||||
def test_event_fields_fail_if_fields_not_str(self) -> None:
|
||||
with self.assertRaises(TypeError):
|
||||
self.serialize(
|
||||
MockEvent(room_id="!foo:bar", content={"foo": "bar"}), ["room_id", 4]
|
||||
MockEvent(room_id="!foo:bar", content={"foo": "bar"}), ["room_id", 4] # type: ignore[list-item]
|
||||
)
|
||||
|
||||
|
||||
class CopyPowerLevelsContentTestCase(stdlib_unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.test_content = {
|
||||
self.test_content: PowerLevelsContent = {
|
||||
"ban": 50,
|
||||
"events": {"m.room.name": 100, "m.room.power_levels": 100},
|
||||
"events_default": 0,
|
||||
@@ -553,10 +556,11 @@ class CopyPowerLevelsContentTestCase(stdlib_unittest.TestCase):
|
||||
"users_default": 0,
|
||||
}
|
||||
|
||||
def _test(self, input):
|
||||
def _test(self, input: PowerLevelsContent) -> None:
|
||||
a = copy_and_fixup_power_levels_contents(input)
|
||||
|
||||
self.assertEqual(a["ban"], 50)
|
||||
assert isinstance(a["events"], Mapping)
|
||||
self.assertEqual(a["events"]["m.room.name"], 100)
|
||||
|
||||
# make sure that changing the copy changes the copy and not the orig
|
||||
@@ -564,18 +568,19 @@ class CopyPowerLevelsContentTestCase(stdlib_unittest.TestCase):
|
||||
a["events"]["m.room.power_levels"] = 20
|
||||
|
||||
self.assertEqual(input["ban"], 50)
|
||||
assert isinstance(input["events"], Mapping)
|
||||
self.assertEqual(input["events"]["m.room.power_levels"], 100)
|
||||
|
||||
def test_unfrozen(self):
|
||||
def test_unfrozen(self) -> None:
|
||||
self._test(self.test_content)
|
||||
|
||||
def test_frozen(self):
|
||||
def test_frozen(self) -> None:
|
||||
input = freeze(self.test_content)
|
||||
self._test(input)
|
||||
|
||||
def test_stringy_integers(self):
|
||||
def test_stringy_integers(self) -> None:
|
||||
"""String representations of decimal integers are converted to integers."""
|
||||
input = {
|
||||
input: PowerLevelsContent = {
|
||||
"a": "100",
|
||||
"b": {
|
||||
"foo": 99,
|
||||
@@ -603,9 +608,9 @@ class CopyPowerLevelsContentTestCase(stdlib_unittest.TestCase):
|
||||
|
||||
def test_invalid_types_raise_type_error(self) -> None:
|
||||
with self.assertRaises(TypeError):
|
||||
copy_and_fixup_power_levels_contents({"a": ["hello", "grandma"]}) # type: ignore[arg-type]
|
||||
copy_and_fixup_power_levels_contents({"a": None}) # type: ignore[arg-type]
|
||||
copy_and_fixup_power_levels_contents({"a": ["hello", "grandma"]}) # type: ignore[dict-item]
|
||||
copy_and_fixup_power_levels_contents({"a": None}) # type: ignore[dict-item]
|
||||
|
||||
def test_invalid_nesting_raises_type_error(self) -> None:
|
||||
with self.assertRaises(TypeError):
|
||||
copy_and_fixup_power_levels_contents({"a": {"b": {"c": 1}}})
|
||||
copy_and_fixup_power_levels_contents({"a": {"b": {"c": 1}}}) # type: ignore[dict-item]
|
||||
|
||||
@@ -23,10 +23,10 @@ from synapse.server import HomeServer
|
||||
from synapse.types import RoomAlias
|
||||
|
||||
from tests.test_utils import event_injection
|
||||
from tests.unittest import FederatingHomeserverTestCase, TestCase
|
||||
from tests.unittest import FederatingHomeserverTestCase, HomeserverTestCase
|
||||
|
||||
|
||||
class KnockingStrippedStateEventHelperMixin(TestCase):
|
||||
class KnockingStrippedStateEventHelperMixin(HomeserverTestCase):
|
||||
def send_example_state_events_to_room(
|
||||
self,
|
||||
hs: "HomeServer",
|
||||
@@ -49,7 +49,7 @@ class KnockingStrippedStateEventHelperMixin(TestCase):
|
||||
# To set a canonical alias, we'll need to point an alias at the room first.
|
||||
canonical_alias = "#fancy_alias:test"
|
||||
self.get_success(
|
||||
self.store.create_room_alias_association(
|
||||
self.hs.get_datastores().main.create_room_alias_association(
|
||||
RoomAlias.from_string(canonical_alias), room_id, ["test"]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -14,21 +14,22 @@
|
||||
|
||||
|
||||
import json
|
||||
from typing import Dict
|
||||
from typing import Dict, List, Set
|
||||
from unittest.mock import ANY, Mock, call
|
||||
|
||||
from twisted.internet import defer
|
||||
from twisted.test.proto_helpers import MemoryReactor
|
||||
from twisted.web.resource import Resource
|
||||
|
||||
from synapse.api.constants import EduTypes
|
||||
from synapse.api.errors import AuthError
|
||||
from synapse.federation.transport.server import TransportLayerServer
|
||||
from synapse.handlers.typing import TypingWriterHandler
|
||||
from synapse.server import HomeServer
|
||||
from synapse.types import JsonDict, Requester, UserID, create_requester
|
||||
from synapse.util import Clock
|
||||
|
||||
from tests import unittest
|
||||
from tests.server import ThreadedMemoryReactorClock
|
||||
from tests.test_utils import make_awaitable
|
||||
from tests.unittest import override_config
|
||||
|
||||
@@ -62,7 +63,11 @@ def _make_edu_transaction_json(edu_type: str, content: JsonDict) -> bytes:
|
||||
|
||||
|
||||
class TypingNotificationsTestCase(unittest.HomeserverTestCase):
|
||||
def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer:
|
||||
def make_homeserver(
|
||||
self,
|
||||
reactor: ThreadedMemoryReactorClock,
|
||||
clock: Clock,
|
||||
) -> HomeServer:
|
||||
# we mock out the keyring so as to skip the authentication check on the
|
||||
# federation API call.
|
||||
mock_keyring = Mock(spec=["verify_json_for_server"])
|
||||
@@ -75,8 +80,9 @@ class TypingNotificationsTestCase(unittest.HomeserverTestCase):
|
||||
# the tests assume that we are starting at unix time 1000
|
||||
reactor.pump((1000,))
|
||||
|
||||
self.mock_hs_notifier = Mock()
|
||||
hs = self.setup_test_homeserver(
|
||||
notifier=Mock(),
|
||||
notifier=self.mock_hs_notifier,
|
||||
federation_http_client=mock_federation_client,
|
||||
keyring=mock_keyring,
|
||||
replication_streams={},
|
||||
@@ -90,32 +96,38 @@ class TypingNotificationsTestCase(unittest.HomeserverTestCase):
|
||||
return d
|
||||
|
||||
def prepare(self, reactor: MemoryReactor, clock: Clock, hs: HomeServer) -> None:
|
||||
mock_notifier = hs.get_notifier()
|
||||
self.on_new_event = mock_notifier.on_new_event
|
||||
self.on_new_event = self.mock_hs_notifier.on_new_event
|
||||
|
||||
self.handler = hs.get_typing_handler()
|
||||
# hs.get_typing_handler will return a TypingWriterHandler when calling it
|
||||
# from the main process, and a FollowerTypingHandler on workers.
|
||||
# We rely on methods only available on the former, so assert we have the
|
||||
# correct type here. We have to assign self.handler after the assert,
|
||||
# otherwise mypy will treat it as a FollowerTypingHandler
|
||||
handler = hs.get_typing_handler()
|
||||
assert isinstance(handler, TypingWriterHandler)
|
||||
self.handler = handler
|
||||
|
||||
self.event_source = hs.get_event_sources().sources.typing
|
||||
|
||||
self.datastore = hs.get_datastores().main
|
||||
|
||||
self.datastore.get_destination_retry_timings = Mock(
|
||||
return_value=make_awaitable(None)
|
||||
)
|
||||
|
||||
self.datastore.get_device_updates_by_remote = Mock(
|
||||
self.datastore.get_device_updates_by_remote = Mock( # type: ignore[assignment]
|
||||
return_value=make_awaitable((0, []))
|
||||
)
|
||||
|
||||
self.datastore.get_destination_last_successful_stream_ordering = Mock(
|
||||
self.datastore.get_destination_last_successful_stream_ordering = Mock( # type: ignore[assignment]
|
||||
return_value=make_awaitable(None)
|
||||
)
|
||||
|
||||
def get_received_txn_response(*args):
|
||||
return defer.succeed(None)
|
||||
self.datastore.get_received_txn_response = Mock( # type: ignore[assignment]
|
||||
return_value=make_awaitable(None)
|
||||
)
|
||||
|
||||
self.datastore.get_received_txn_response = get_received_txn_response
|
||||
|
||||
self.room_members = []
|
||||
self.room_members: List[UserID] = []
|
||||
|
||||
async def check_user_in_room(room_id: str, requester: Requester) -> None:
|
||||
if requester.user.to_string() not in [
|
||||
@@ -124,47 +136,54 @@ class TypingNotificationsTestCase(unittest.HomeserverTestCase):
|
||||
raise AuthError(401, "User is not in the room")
|
||||
return None
|
||||
|
||||
hs.get_auth().check_user_in_room = check_user_in_room
|
||||
hs.get_auth().check_user_in_room = Mock( # type: ignore[assignment]
|
||||
side_effect=check_user_in_room
|
||||
)
|
||||
|
||||
async def check_host_in_room(room_id: str, server_name: str) -> bool:
|
||||
return room_id == ROOM_ID
|
||||
|
||||
hs.get_event_auth_handler().is_host_in_room = check_host_in_room
|
||||
hs.get_event_auth_handler().is_host_in_room = Mock( # type: ignore[assignment]
|
||||
side_effect=check_host_in_room
|
||||
)
|
||||
|
||||
async def get_current_hosts_in_room(room_id: str):
|
||||
async def get_current_hosts_in_room(room_id: str) -> Set[str]:
|
||||
return {member.domain for member in self.room_members}
|
||||
|
||||
hs.get_storage_controllers().state.get_current_hosts_in_room = (
|
||||
get_current_hosts_in_room
|
||||
hs.get_storage_controllers().state.get_current_hosts_in_room = Mock( # type: ignore[assignment]
|
||||
side_effect=get_current_hosts_in_room
|
||||
)
|
||||
|
||||
hs.get_storage_controllers().state.get_current_hosts_in_room_or_partial_state_approximation = (
|
||||
get_current_hosts_in_room
|
||||
hs.get_storage_controllers().state.get_current_hosts_in_room_or_partial_state_approximation = Mock( # type: ignore[assignment]
|
||||
side_effect=get_current_hosts_in_room
|
||||
)
|
||||
|
||||
async def get_users_in_room(room_id: str):
|
||||
async def get_users_in_room(room_id: str) -> Set[str]:
|
||||
return {str(u) for u in self.room_members}
|
||||
|
||||
self.datastore.get_users_in_room = get_users_in_room
|
||||
self.datastore.get_users_in_room = Mock(side_effect=get_users_in_room)
|
||||
|
||||
self.datastore.get_user_directory_stream_pos = Mock(
|
||||
self.datastore.get_user_directory_stream_pos = Mock( # type: ignore[assignment]
|
||||
side_effect=(
|
||||
# we deliberately return a non-None stream pos to avoid doing an initial_spam
|
||||
# we deliberately return a non-None stream pos to avoid
|
||||
# doing an initial_sync
|
||||
lambda: make_awaitable(1)
|
||||
)
|
||||
)
|
||||
|
||||
self.datastore.get_partial_current_state_deltas = Mock(return_value=(0, None))
|
||||
self.datastore.get_partial_current_state_deltas = Mock(return_value=(0, None)) # type: ignore[assignment]
|
||||
|
||||
self.datastore.get_to_device_stream_token = lambda: 0
|
||||
self.datastore.get_new_device_msgs_for_remote = (
|
||||
lambda *args, **kargs: make_awaitable(([], 0))
|
||||
self.datastore.get_to_device_stream_token = Mock( # type: ignore[assignment]
|
||||
side_effect=lambda: 0
|
||||
)
|
||||
self.datastore.delete_device_msgs_for_remote = (
|
||||
lambda *args, **kargs: make_awaitable(None)
|
||||
self.datastore.get_new_device_msgs_for_remote = Mock( # type: ignore[assignment]
|
||||
side_effect=lambda *args, **kargs: make_awaitable(([], 0))
|
||||
)
|
||||
self.datastore.set_received_txn_response = (
|
||||
lambda *args, **kwargs: make_awaitable(None)
|
||||
self.datastore.delete_device_msgs_for_remote = Mock( # type: ignore[assignment]
|
||||
side_effect=lambda *args, **kargs: make_awaitable(None)
|
||||
)
|
||||
self.datastore.set_received_txn_response = Mock( # type: ignore[assignment]
|
||||
side_effect=lambda *args, **kwargs: make_awaitable(None)
|
||||
)
|
||||
|
||||
def test_started_typing_local(self) -> None:
|
||||
@@ -186,7 +205,7 @@ class TypingNotificationsTestCase(unittest.HomeserverTestCase):
|
||||
self.assertEqual(self.event_source.get_current_key(), 1)
|
||||
events = self.get_success(
|
||||
self.event_source.get_new_events(
|
||||
user=U_APPLE, from_key=0, limit=None, room_ids=[ROOM_ID], is_guest=False
|
||||
user=U_APPLE, from_key=0, limit=0, room_ids=[ROOM_ID], is_guest=False
|
||||
)
|
||||
)
|
||||
self.assertEqual(
|
||||
@@ -257,7 +276,7 @@ class TypingNotificationsTestCase(unittest.HomeserverTestCase):
|
||||
self.assertEqual(self.event_source.get_current_key(), 1)
|
||||
events = self.get_success(
|
||||
self.event_source.get_new_events(
|
||||
user=U_APPLE, from_key=0, limit=None, room_ids=[ROOM_ID], is_guest=False
|
||||
user=U_APPLE, from_key=0, limit=0, room_ids=[ROOM_ID], is_guest=False
|
||||
)
|
||||
)
|
||||
self.assertEqual(
|
||||
@@ -298,7 +317,7 @@ class TypingNotificationsTestCase(unittest.HomeserverTestCase):
|
||||
self.event_source.get_new_events(
|
||||
user=U_APPLE,
|
||||
from_key=0,
|
||||
limit=None,
|
||||
limit=0,
|
||||
room_ids=[OTHER_ROOM_ID],
|
||||
is_guest=False,
|
||||
)
|
||||
@@ -351,7 +370,7 @@ class TypingNotificationsTestCase(unittest.HomeserverTestCase):
|
||||
self.assertEqual(self.event_source.get_current_key(), 1)
|
||||
events = self.get_success(
|
||||
self.event_source.get_new_events(
|
||||
user=U_APPLE, from_key=0, limit=None, room_ids=[ROOM_ID], is_guest=False
|
||||
user=U_APPLE, from_key=0, limit=0, room_ids=[ROOM_ID], is_guest=False
|
||||
)
|
||||
)
|
||||
self.assertEqual(
|
||||
@@ -387,7 +406,7 @@ class TypingNotificationsTestCase(unittest.HomeserverTestCase):
|
||||
self.event_source.get_new_events(
|
||||
user=U_APPLE,
|
||||
from_key=0,
|
||||
limit=None,
|
||||
limit=0,
|
||||
room_ids=[ROOM_ID],
|
||||
is_guest=False,
|
||||
)
|
||||
@@ -412,7 +431,7 @@ class TypingNotificationsTestCase(unittest.HomeserverTestCase):
|
||||
self.event_source.get_new_events(
|
||||
user=U_APPLE,
|
||||
from_key=1,
|
||||
limit=None,
|
||||
limit=0,
|
||||
room_ids=[ROOM_ID],
|
||||
is_guest=False,
|
||||
)
|
||||
@@ -447,7 +466,7 @@ class TypingNotificationsTestCase(unittest.HomeserverTestCase):
|
||||
self.event_source.get_new_events(
|
||||
user=U_APPLE,
|
||||
from_key=0,
|
||||
limit=None,
|
||||
limit=0,
|
||||
room_ids=[ROOM_ID],
|
||||
is_guest=False,
|
||||
)
|
||||
|
||||
@@ -294,9 +294,7 @@ class SyncTypingTests(unittest.HomeserverTestCase):
|
||||
self.make_request("GET", sync_url % (access_token, next_batch))
|
||||
|
||||
|
||||
class SyncKnockTestCase(
|
||||
unittest.HomeserverTestCase, KnockingStrippedStateEventHelperMixin
|
||||
):
|
||||
class SyncKnockTestCase(KnockingStrippedStateEventHelperMixin):
|
||||
servlets = [
|
||||
synapse.rest.admin.register_servlets,
|
||||
login.register_servlets,
|
||||
|
||||
@@ -28,6 +28,7 @@ from synapse.storage.background_updates import _BackgroundUpdateHandler
|
||||
from synapse.storage.roommember import ProfileInfo
|
||||
from synapse.util import Clock
|
||||
|
||||
from tests.server import ThreadedMemoryReactorClock
|
||||
from tests.test_utils.event_injection import inject_member_event
|
||||
from tests.unittest import HomeserverTestCase, override_config
|
||||
|
||||
@@ -138,7 +139,9 @@ class UserDirectoryInitialPopulationTestcase(HomeserverTestCase):
|
||||
register.register_servlets,
|
||||
]
|
||||
|
||||
def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer:
|
||||
def make_homeserver(
|
||||
self, reactor: ThreadedMemoryReactorClock, clock: Clock
|
||||
) -> HomeServer:
|
||||
self.appservice = ApplicationService(
|
||||
token="i_am_an_app_service",
|
||||
id="1234",
|
||||
|
||||
+2
-1
@@ -75,6 +75,7 @@ from synapse.util.httpresourcetree import create_resource_tree
|
||||
from tests.server import (
|
||||
CustomHeaderType,
|
||||
FakeChannel,
|
||||
ThreadedMemoryReactorClock,
|
||||
get_clock,
|
||||
make_request,
|
||||
setup_test_homeserver,
|
||||
@@ -360,7 +361,7 @@ class HomeserverTestCase(TestCase):
|
||||
store.db_pool.updates.do_next_background_update(False), by=0.1
|
||||
)
|
||||
|
||||
def make_homeserver(self, reactor: MemoryReactor, clock: Clock):
|
||||
def make_homeserver(self, reactor: ThreadedMemoryReactorClock, clock: Clock):
|
||||
"""
|
||||
Make and return a homeserver.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user