Adapt tests that mutated Python event internals (`_event_id`, `_dict`,
direct attribute assignment, `FrozenEventV3(...)` construction) to work
with the new Rust-backed `Event` class:
- Rebuild events via `make_event_from_dict` / `make_test_event` instead
of patching attributes in place.
- Plumb `rejected_reason` through `_join_rules_event` rather than
assigning to `rejected_reason` after construction.
- Replace the hand-built event in `test_msc4242_state_dag` with a
`Mock(spec=EventBase)` since the test only needs a handful of
attributes.
- Add `# type: ignore` for the deprecated `event.user_id` / `event[key]`
accessors and for assigning to `event.content`.
- In `make_test_event`, drop the default `room_id` for v11+ create
events so each gets a distinct hash-derived room ID.
Replace the abstract `synapse.events.EventBase` and the concrete
`FrozenEvent`, `FrozenEventV2`, `FrozenEventV3`, `FrozenEventV4`, and
`FrozenEventVMSC4242` Python classes with a single Rust-backed
`Event`, exposed via `synapse.synapse_rust.events.Event`. `EventBase`
becomes a `TypeAlias` for `Event` so that the existing type annotations
across the codebase keep working.
Notable behavioural notes:
- `make_event_from_dict()` now constructs the Rust class. Event IDs for
v3+ formats are computed in the constructor (instead of lazily on
first access).
- `clone_event()` is now a single `event.deep_copy()` call. The old
shallow copy of `unsigned` was effectively a deep copy in practice;
`deep_copy()` matches that.
- The third-party event-rules callback no longer needs to call
`event.freeze()` — Events are immutable from Python by construction.
- A small `assert_never` is added in `events_worker.py` to make the
`redact_behaviour` switch exhaustive now that the type checker can
see all branches.
All test fixtures that constructed `FrozenEventV3` etc. directly are
updated to construct `Event` instead.
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.