diff --git a/synapse/events/__init__.py b/synapse/events/__init__.py
index 88ed6d764f..72c09327f4 100644
--- a/synapse/events/__init__.py
+++ b/synapse/events/__init__.py
@@ -116,16 +116,32 @@ class _EventInternalMetadata(object):
return getattr(self, "redacted", False)
-def _event_dict_property(key):
+_SENTINEL = object()
+
+
+def _event_dict_property(key, default=_SENTINEL):
+ """Creates a new property for the given key that delegates access to
+ `self._event_dict`.
+
+ The default is used if the key is missing from the `_event_dict`, if given,
+ otherwise an AttributeError will be raised.
+
+ Note: If a default is given then `hasattr` will always return true.
+ """
+
# We want to be able to use hasattr with the event dict properties.
# However, (on python3) hasattr expects AttributeError to be raised. Hence,
# we need to transform the KeyError into an AttributeError
- def getter(self):
+
+ def getter_raises(self):
try:
return self._event_dict[key]
except KeyError:
raise AttributeError(key)
+ def getter_default(self):
+ return self._event_dict.get(key, default)
+
def setter(self, v):
try:
self._event_dict[key] = v
@@ -138,7 +154,11 @@ def _event_dict_property(key):
except KeyError:
raise AttributeError(key)
- return property(getter, setter, delete)
+ if default is _SENTINEL:
+ # No default given, so use the getter that raises
+ return property(getter_raises, setter, delete)
+ else:
+ return property(getter_default, setter, delete)
class EventBase(object):
@@ -165,7 +185,7 @@ class EventBase(object):
origin = _event_dict_property("origin")
origin_server_ts = _event_dict_property("origin_server_ts")
prev_events = _event_dict_property("prev_events")
- redacts = _event_dict_property("redacts")
+ redacts = _event_dict_property("redacts", None)
room_id = _event_dict_property("room_id")
sender = _event_dict_property("sender")
user_id = _event_dict_property("sender")
diff --git a/synapse/storage/data_stores/main/events.py b/synapse/storage/data_stores/main/events.py
index 596daf8909..ce553566a5 100644
--- a/synapse/storage/data_stores/main/events.py
+++ b/synapse/storage/data_stores/main/events.py
@@ -951,7 +951,7 @@ class EventsStore(
elif event.type == EventTypes.Message:
# Insert into the event_search table.
self._store_room_message_txn(txn, event)
- elif event.type == EventTypes.Redaction:
+ elif event.type == EventTypes.Redaction and event.redacts is not None:
# Insert into the redactions table.
self._store_redaction(txn, event)
elif event.type == EventTypes.Retention:
diff --git a/synapse/storage/data_stores/main/events_worker.py b/synapse/storage/data_stores/main/events_worker.py
index 3b93e0597a..7251e819f5 100644
--- a/synapse/storage/data_stores/main/events_worker.py
+++ b/synapse/storage/data_stores/main/events_worker.py
@@ -287,7 +287,7 @@ class EventsWorkerStore(SQLBaseStore):
# we have to recheck auth now.
if not allow_rejected and entry.event.type == EventTypes.Redaction:
- if not hasattr(entry.event, "redacts"):
+ if entry.event.redacts is None:
# A redacted redaction doesn't have a `redacts` key, in
# which case lets just withhold the event.
#
|