You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ru...@apache.org on 2026/06/03 00:30:23 UTC

(superset) 01/01: fix(reports): stamp email subject date at send time, not import time

This is an automated email from the ASF dual-hosted git repository.

rusackas pushed a commit to branch fix/report-email-subject-send-time
in repository https://gitbox.apache.org/repos/asf/superset.git

commit f97a68ed1cb2ca16d8f31b6eca4f42890d53240d
Author: Evan <ev...@preset.io>
AuthorDate: Tue Jun 2 17:29:56 2026 -0700

    fix(reports): stamp email subject date at send time, not import time
    
    `EmailNotification.now` was a class attribute evaluated once when the module
    is first imported. In a long-running worker that means every report email with
    DATE_FORMAT_IN_EMAIL_SUBJECT enabled renders the date the process started rather
    than the actual send date. It also made test_email_subject_with_datetime flaky:
    the test sampled its own clock separately from the frozen class attribute, so a
    run crossing the UTC midnight boundary compared two different dates and failed
    (e.g. `assert '2026-06-03' in '... 2026-06-02'`).
    
    Move the timestamp to a per-instance value set in __init__ so each notification
    reflects its real creation/send time, and assert against the notification's own
    `now` in the test so it can't flake at the day boundary.
    
    Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
---
 superset/reports/notifications/email.py               | 15 ++++++++++++---
 tests/unit_tests/reports/notifications/email_tests.py | 15 +++++++--------
 2 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/superset/reports/notifications/email.py b/superset/reports/notifications/email.py
index 4c172afd791..062a5c4c016 100644
--- a/superset/reports/notifications/email.py
+++ b/superset/reports/notifications/email.py
@@ -28,8 +28,8 @@ from pytz import timezone
 
 from superset import is_feature_enabled
 from superset.exceptions import SupersetErrorsException
-from superset.reports.models import ReportRecipientType
-from superset.reports.notifications.base import BaseNotification
+from superset.reports.models import ReportRecipients, ReportRecipientType
+from superset.reports.notifications.base import BaseNotification, NotificationContent
 from superset.reports.notifications.exceptions import NotificationError
 from superset.utils import json
 from superset.utils.core import HeaderDataType, send_email_smtp
@@ -83,7 +83,16 @@ class EmailNotification(BaseNotification):  # pylint: disable=too-few-public-met
     """
 
     type = ReportRecipientType.EMAIL
-    now = datetime.now(timezone("UTC"))
+
+    def __init__(
+        self, recipient: ReportRecipients, content: NotificationContent
+    ) -> None:
+        super().__init__(recipient, content)
+        # Stamp the notification's creation time once, at send time, so the date
+        # rendered into the subject (when DATE_FORMAT_IN_EMAIL_SUBJECT is enabled)
+        # reflects the actual send time rather than the moment this module was
+        # first imported by the worker process.
+        self.now = datetime.now(timezone("UTC"))
 
     @property
     def _name(self) -> str:
diff --git a/tests/unit_tests/reports/notifications/email_tests.py b/tests/unit_tests/reports/notifications/email_tests.py
index 54fb2d4b30e..5441596cfef 100644
--- a/tests/unit_tests/reports/notifications/email_tests.py
+++ b/tests/unit_tests/reports/notifications/email_tests.py
@@ -14,10 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-from datetime import datetime
-
 import pandas as pd
-from pytz import timezone
 
 from tests.unit_tests.conftest import with_feature_flags
 
@@ -107,8 +104,6 @@ def test_email_subject_with_datetime() -> None:
     from superset.reports.notifications.base import NotificationContent
     from superset.reports.notifications.email import EmailNotification
 
-    now = datetime.now(timezone("UTC"))
-
     datetime_pattern = "%Y-%m-%d"
 
     content = NotificationContent(
@@ -130,8 +125,12 @@ def test_email_subject_with_datetime() -> None:
             "execution_id": "test-execution-id",
         },
     )
-    subject = EmailNotification(
+    notification = EmailNotification(
         recipient=ReportRecipients(type=ReportRecipientType.EMAIL), content=content
-    )._get_subject()
+    )
+    subject = notification._get_subject()
     assert datetime_pattern not in subject
-    assert now.strftime(datetime_pattern) in subject
+    # Compare against the notification's own stamped timestamp rather than a
+    # separately-sampled clock, so the assertion can't flake when the test runs
+    # across the UTC midnight boundary.
+    assert notification.now.strftime(datetime_pattern) in subject