mirror of
https://github.com/element-hq/synapse.git
synced 2026-06-03 21:21:25 +00:00
86a1e73ef4
The reason for the change is to make it easier to support these checks when porting event class to Rust. Previously, code that needed to access `prev_state_events` had to combine a `room_version.msc4242_state_dags` boolean check with an `isinstance(event, FrozenEventVMSC4242)` cast (or `cast()`) for the type checker. Introduce `supports_msc4242_state_dag()` in a new `synapse/events/py_protocol.py` which does both in one step via `TypeIs[MSC4242Event]`, removing the need to import the concrete `FrozenEventVMSC4242` class at every call site. `MSC4242Event` is an `EventBase` subclass used purely for type narrowing — it's marked with a metaclass that rejects `isinstance()` to make accidental runtime use loud. No behavioural change: callers continue to gate on the same room version flag and access the same `prev_state_events` attribute.
83 lines
3.0 KiB
Python
83 lines
3.0 KiB
Python
#
|
|
# This file is licensed under the Affero General Public License (AGPL) version 3.
|
|
#
|
|
# Copyright (C) 2026 Element Creations Ltd
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
# License, or (at your option) any later version.
|
|
#
|
|
# See the GNU Affero General Public License for more details:
|
|
# <https://www.gnu.org/licenses/agpl-3.0.html>.
|
|
#
|
|
#
|
|
|
|
from unittest.mock import Mock
|
|
|
|
from synapse.api.room_versions import RoomVersion, RoomVersions
|
|
from synapse.events import EventBase, FrozenEvent, make_event_from_dict
|
|
from synapse.events.py_protocol import (
|
|
EventProtocol,
|
|
MSC4242Event,
|
|
all_supports_msc4242_state_dag,
|
|
supports_msc4242_state_dag,
|
|
)
|
|
|
|
from tests.unittest import TestCase
|
|
|
|
|
|
def _make_event(room_version: RoomVersion) -> EventBase:
|
|
"""Helper to make an EventBase with the given room version."""
|
|
event_dict = {
|
|
"content": {},
|
|
"sender": "@user:example.com",
|
|
"type": "m.room.message",
|
|
"room_id": "!room:example.com",
|
|
}
|
|
if room_version.msc4242_state_dags:
|
|
event_dict["prev_state_events"] = []
|
|
return make_event_from_dict(event_dict, room_version=room_version)
|
|
|
|
|
|
class TestMetaClass(TestCase):
|
|
def test_is_instance(self) -> None:
|
|
"""Test that isinstance checks on EventProtocol raise
|
|
NotImplementedError, but that isinstance checks on EventBase and
|
|
FrozenEvent still work as normal.
|
|
"""
|
|
# EventBase and FrozenEvent should work as normal
|
|
self.assertFalse(isinstance(object(), EventBase))
|
|
self.assertFalse(isinstance(object(), FrozenEvent))
|
|
|
|
with self.assertRaises(NotImplementedError):
|
|
isinstance(object(), EventProtocol)
|
|
|
|
with self.assertRaises(NotImplementedError):
|
|
isinstance(object(), MSC4242Event)
|
|
|
|
|
|
class SupportsMSC4242StateDagTestCase(TestCase):
|
|
def test_single_event_msc4242(self) -> None:
|
|
"""A single event in an MSC4242 room is recognised."""
|
|
ev = _make_event(RoomVersions.MSC4242v12)
|
|
self.assertTrue(supports_msc4242_state_dag(ev))
|
|
|
|
def test_single_event_non_msc4242(self) -> None:
|
|
"""A single event in a non-MSC4242 room is not recognised."""
|
|
ev = _make_event(RoomVersions.V11)
|
|
self.assertFalse(supports_msc4242_state_dag(ev))
|
|
|
|
def test_sequence_all_msc4242(self) -> None:
|
|
"""A sequence of MSC4242 (event, context) pairs is recognised."""
|
|
pairs = [(_make_event(RoomVersions.MSC4242v12), Mock()) for _ in range(3)]
|
|
self.assertTrue(all_supports_msc4242_state_dag(pairs))
|
|
|
|
def test_sequence_mixed(self) -> None:
|
|
"""A sequence containing any non-MSC4242 event is not recognised."""
|
|
pairs = [
|
|
(_make_event(RoomVersions.MSC4242v12), Mock()),
|
|
(_make_event(RoomVersions.V11), Mock()),
|
|
]
|
|
self.assertFalse(all_supports_msc4242_state_dag(pairs))
|