Skip to content

Commit 40e161d

Browse files
authored
Some fixes for notifications (#11094)
This includes a few fixes and small restructuring to the notification/message classes. - Centralize message lookup and format string population on the registry model instead of the Notification model. This change will make more sense with my next PR - Use `copy()` when setting the format values, as to ensure thread safety, these shouldn't be set on the static instance class in the registry. - Add a base class for notifications, for messages/notifications that fall outside doc building.
1 parent cee310d commit 40e161d

File tree

4 files changed

+43
-22
lines changed

4 files changed

+43
-22
lines changed

readthedocs/doc_builder/exceptions.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,18 @@
1111
Then the header/body texts should be defined in ``readthedocs/notifications/messages.py``.
1212
"""
1313

14+
from django.utils.translation import gettext_lazy as _
1415

16+
from readthedocs.notifications.exceptions import NotificationBaseException
1517

16-
class BuildBaseException(Exception):
1718

18-
default_message = "Build user exception"
19+
class BuildBaseException(NotificationBaseException):
1920

20-
def __init__(self, message_id, format_values=None, **kwargs):
21-
self.message_id = message_id
22-
self.format_values = format_values
23-
super().__init__(self.default_message, **kwargs)
21+
default_message = _("Build user exception")
2422

2523

2624
class BuildAppError(BuildBaseException):
27-
default_message = "Build app exception"
25+
default_message = _("Build application exception")
2826

2927
GENERIC_WITH_BUILD_ID = "build:app:generic-with-build-id"
3028
BUILDS_DISABLED = "build:app:project-builds-disabled"
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from django.utils.translation import gettext_lazy as _
2+
3+
4+
class NotificationBaseException(Exception):
5+
6+
"""
7+
The base exception class for notification and messages.
8+
9+
This provides the additional ``message_id`` and ``format_values`` attributes
10+
that are used for message display and registry lookup.
11+
"""
12+
13+
default_message = _("Undefined error")
14+
15+
def __init__(self, message_id, format_values=None, **kwargs):
16+
self.message_id = message_id
17+
self.format_values = format_values
18+
super().__init__(self.default_message, **kwargs)

readthedocs/notifications/messages.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import copy
12
import textwrap
23

34
import structlog
45
from django.template import Context, Template
56
from django.utils.translation import gettext_noop as _
67

8+
from readthedocs.core.context_processors import readthedocs_processor
79
from readthedocs.doc_builder.exceptions import (
810
BuildAppError,
911
BuildCancelled,
@@ -514,8 +516,18 @@ def add(self, messages):
514516
raise ValueError("A message with the same 'id' is already registered.")
515517
self.messages[message.id] = message
516518

517-
def get(self, message_id):
518-
return self.messages.get(message_id)
519+
def get(self, message_id, format_values=None):
520+
# Copy to avoid setting format values on the static instance of the
521+
# message inside the registry, set on a per-request instance instead.
522+
message = copy.copy(self.messages.get(message_id))
523+
524+
if message is not None:
525+
# Always include global variables, override with provided values
526+
all_format_values = readthedocs_processor(None)
527+
all_format_values.update(format_values or {})
528+
message.set_format_values(all_format_values)
529+
530+
return message
519531

520532

521533
registry = MessagesRegistry()

readthedocs/notifications/models.py

+6-13
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
from django.utils.translation import gettext_noop as _
88
from django_extensions.db.models import TimeStampedModel
99

10-
from readthedocs.core.context_processors import readthedocs_processor
1110

1211
from .constants import CANCELLED, DISMISSED, READ, UNREAD, WARNING
1312
from .messages import Message, registry
@@ -67,7 +66,12 @@ def __str__(self):
6766
return self.message_id
6867

6968
def get_message(self):
70-
message = registry.get(self.message_id)
69+
# Pass the instance attached to this notification
70+
format_values = {
71+
"instance": self.attached_to,
72+
}
73+
74+
message = registry.get(self.message_id, format_values=format_values)
7175
if message is None:
7276
# Log the error and return an unknown error to avoid breaking the response.
7377
log.error(
@@ -88,15 +92,4 @@ def get_message(self):
8892
type=WARNING,
8993
)
9094

91-
# Pass the instance attached to this notification
92-
all_format_values = {
93-
"instance": self.attached_to,
94-
}
95-
96-
# Always include global variables
97-
all_format_values.update(readthedocs_processor(None))
98-
99-
# Pass the values stored in the database
100-
all_format_values.update(self.format_values or {})
101-
message.set_format_values(all_format_values)
10295
return message

0 commit comments

Comments
 (0)