From 04d6b7a205af13113b45065ece1eb4f726d8adae Mon Sep 17 00:00:00 2001 From: themavik Date: Tue, 10 Feb 2026 14:03:04 -0500 Subject: [PATCH] fix: replace deprecated datetime.utcnow() with datetime.now(tz=timezone.utc) `datetime.utcnow()` has been deprecated since Python 3.12 because it returns a naive datetime that carries no timezone information, making it error-prone when mixed with timezone-aware datetimes. Replace all 8 occurrences across 7 files (5 source, 2 test) with the recommended `datetime.now(tz=timezone.utc)` which returns a proper timezone-aware datetime. Files changed: - elementary/utils/time.py - elementary/monitor/fetchers/alerts/schema/pending_alerts.py - elementary/monitor/data_monitoring/alerts/data_monitoring_alerts.py - elementary/messages/messaging_integrations/teams_webhook.py - elementary/messages/messaging_integrations/slack_webhook.py - elementary/messages/messaging_integrations/file_system.py - tests/unit/monitor/fetchers/alerts/schemas/test_alert_data_schema.py - tests/mocks/fetchers/alerts_fetcher_mock.py --- elementary/messages/messaging_integrations/file_system.py | 6 +++--- elementary/messages/messaging_integrations/slack_webhook.py | 4 ++-- elementary/messages/messaging_integrations/teams_webhook.py | 4 ++-- .../data_monitoring/alerts/data_monitoring_alerts.py | 4 ++-- elementary/monitor/fetchers/alerts/schema/pending_alerts.py | 4 ++-- elementary/utils/time.py | 2 +- tests/mocks/fetchers/alerts_fetcher_mock.py | 4 ++-- .../fetchers/alerts/schemas/test_alert_data_schema.py | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/elementary/messages/messaging_integrations/file_system.py b/elementary/messages/messaging_integrations/file_system.py index 2fa1f0332..0d6af5d23 100644 --- a/elementary/messages/messaging_integrations/file_system.py +++ b/elementary/messages/messaging_integrations/file_system.py @@ -1,5 +1,5 @@ import json -from datetime import datetime +from datetime import datetime, timezone from pathlib import Path from typing import Any @@ -55,7 +55,7 @@ def send_message( f"Channel directory {channel_dir} does not exist and create_if_missing is False" ) - filename = datetime.utcnow().strftime("%Y%m%dT%H%M%S_%fZ.json") + filename = datetime.now(tz=timezone.utc).strftime("%Y%m%dT%H%M%S_%fZ.json") file_path = channel_dir / filename try: @@ -71,7 +71,7 @@ def send_message( ) from exc return MessageSendResult( - timestamp=datetime.utcnow(), + timestamp=datetime.now(tz=timezone.utc), message_format="json", message_context=EmptyMessageContext(), ) diff --git a/elementary/messages/messaging_integrations/slack_webhook.py b/elementary/messages/messaging_integrations/slack_webhook.py index 32624f0b2..8e465b7a0 100644 --- a/elementary/messages/messaging_integrations/slack_webhook.py +++ b/elementary/messages/messaging_integrations/slack_webhook.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timezone from http import HTTPStatus from typing import Any, Optional @@ -65,7 +65,7 @@ def send_message( self._send_message(formatted_message) return MessageSendResult( message_context=EmptyMessageContext(), - timestamp=datetime.utcnow(), + timestamp=datetime.now(tz=timezone.utc), message_format="block_kit", ) diff --git a/elementary/messages/messaging_integrations/teams_webhook.py b/elementary/messages/messaging_integrations/teams_webhook.py index 30b6d81b1..6c4fa7feb 100644 --- a/elementary/messages/messaging_integrations/teams_webhook.py +++ b/elementary/messages/messaging_integrations/teams_webhook.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timezone from http import HTTPStatus from typing import Any, Optional @@ -94,7 +94,7 @@ def send_message( ) return MessageSendResult( message_context=EmptyMessageContext(), - timestamp=datetime.utcnow(), + timestamp=datetime.now(tz=timezone.utc), message_format="adaptive_cards", ) except requests.HTTPError as e: diff --git a/elementary/monitor/data_monitoring/alerts/data_monitoring_alerts.py b/elementary/monitor/data_monitoring/alerts/data_monitoring_alerts.py index 8b24e3be2..ed0b78fd8 100644 --- a/elementary/monitor/data_monitoring/alerts/data_monitoring_alerts.py +++ b/elementary/monitor/data_monitoring/alerts/data_monitoring_alerts.py @@ -1,6 +1,6 @@ import json from collections import defaultdict -from datetime import datetime +from datetime import datetime, timezone from typing import DefaultDict, Dict, List, Optional, Union from alive_progress import alive_bar @@ -201,7 +201,7 @@ def _get_suppressed_alerts( alerts_last_sent_times: Dict[str, datetime], ) -> List[str]: suppressed_alerts = [] - current_time_utc = convert_time_to_timezone(datetime.utcnow()) + current_time_utc = convert_time_to_timezone(datetime.now(tz=timezone.utc)) for alert in alerts: alert_class_id = alert.alert_class_id suppression_interval = alert.data.get_suppression_interval( diff --git a/elementary/monitor/fetchers/alerts/schema/pending_alerts.py b/elementary/monitor/fetchers/alerts/schema/pending_alerts.py index 7dbf1affc..89edfc59c 100644 --- a/elementary/monitor/fetchers/alerts/schema/pending_alerts.py +++ b/elementary/monitor/fetchers/alerts/schema/pending_alerts.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timezone from enum import Enum from typing import Optional, Union @@ -54,7 +54,7 @@ class Config: def validate_times(cls, values: dict) -> dict: new_values = {**values} - current_datetime = datetime.utcnow() + current_datetime = datetime.now(tz=timezone.utc) if not values.get("detected_at"): new_values["detected_at"] = current_datetime if not values.get("created_at"): diff --git a/elementary/utils/time.py b/elementary/utils/time.py index e3a09ff60..96f0cfce3 100644 --- a/elementary/utils/time.py +++ b/elementary/utils/time.py @@ -51,7 +51,7 @@ def convert_time_to_timezone( def get_now_utc_str(format: str = DATETIME_FORMAT) -> str: - return datetime.utcnow().strftime(format) + return datetime.now(timezone.utc).strftime(format) def get_now_utc_iso_format() -> str: diff --git a/tests/mocks/fetchers/alerts_fetcher_mock.py b/tests/mocks/fetchers/alerts_fetcher_mock.py index 1e35c56fd..eb9551aa4 100644 --- a/tests/mocks/fetchers/alerts_fetcher_mock.py +++ b/tests/mocks/fetchers/alerts_fetcher_mock.py @@ -1,4 +1,4 @@ -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from typing import List from elementary.config.config import Config @@ -10,7 +10,7 @@ from elementary.utils.time import DATETIME_FORMAT from tests.mocks.dbt_runner_mock import MockDbtRunner -CURRENT_DATETIME_UTC = datetime.utcnow() +CURRENT_DATETIME_UTC = datetime.now(tz=timezone.utc) CURRENT_TIMESTAMP_UTC = CURRENT_DATETIME_UTC.strftime(DATETIME_FORMAT) PENDDING_TEST_ALERTS_MOCK_DATA = [ diff --git a/tests/unit/monitor/fetchers/alerts/schemas/test_alert_data_schema.py b/tests/unit/monitor/fetchers/alerts/schemas/test_alert_data_schema.py index b66721e22..aeff6cdc7 100644 --- a/tests/unit/monitor/fetchers/alerts/schemas/test_alert_data_schema.py +++ b/tests/unit/monitor/fetchers/alerts/schemas/test_alert_data_schema.py @@ -1,5 +1,5 @@ import json -from datetime import datetime +from datetime import datetime, timezone import pytest @@ -9,7 +9,7 @@ ) from elementary.utils.time import DATETIME_FORMAT -CURRENT_DATETIME_UTC = datetime.utcnow() +CURRENT_DATETIME_UTC = datetime.now(tz=timezone.utc) CURRENT_TIMESTAMP_UTC = CURRENT_DATETIME_UTC.strftime(DATETIME_FORMAT) BASE_ALERT = dict(