Apply ruff Python 3.11 fixes to dev tooling, scripts and test suites (#74156)

Output of ruff --fix with the py311 target for dev/, scripts/ and the
e2e, integration and kubernetes test suites, followed by ruff format
where the shorter names let calls fit on one line: timezone.utc becomes
datetime.UTC. No behaviour change.

Four modules are left out: dev/registry/extract_metadata.py,
dev/registry/extract_versions.py and the update_airflow_pyproject_toml
and upgrade_dependency_floors prek scripts still fall back to tomli on
Python 3.10, so their UTC fixes land together with the removal of that
fallback in the requires-python bump.
This commit is contained in:
Shahar Epstein authored and GitHub committed 2026-10-06 23:20:49 +02:00
1 parent 0b7c7f2e19
commit dafc96e67c
31 files changed
+84 -101

No files matched your search

@@ -16,7 +16,7 @@
# under the License.
from __future__ import annotations
from datetime import datetime, timezone
from datetime import UTC, datetime
from airflow_e2e_tests.e2e_test_utils.clients import AirflowClient
@@ -28,7 +28,7 @@ class TestBasicDagFunctionality:
def test_xcom_value(self):
resp = self.airflow_client.trigger_dag(
"example_xcom_test", json={"logical_date": datetime.now(timezone.utc).isoformat()}
"example_xcom_test", json={"logical_date": datetime.now(UTC).isoformat()}
)
self.airflow_client.wait_for_dag_run(
dag_id="example_xcom_test",
@@ -17,7 +17,7 @@
from __future__ import annotations
import time
from datetime import datetime, timezone
from datetime import UTC, datetime
import pytest
@@ -62,7 +62,7 @@ class BaseRemoteLoggingSearchTest:
resp = self.airflow_client.trigger_dag(
self.dag_id,
json={"logical_date": datetime.now(timezone.utc).isoformat()},
json={"logical_date": datetime.now(UTC).isoformat()},
)
run_id = resp["dag_run_id"]
state = self.airflow_client.wait_for_dag_run(
@@ -117,7 +117,7 @@ class BaseRemoteLoggingSearchTest:
self.airflow_client.un_pause_dag(dag_id)
resp = self.airflow_client.trigger_dag(
dag_id,
json={"logical_date": datetime.now(timezone.utc).isoformat()},
json={"logical_date": datetime.now(UTC).isoformat()},
)
run_id = resp["dag_run_id"]
state = self.airflow_client.wait_for_dag_run(dag_id=dag_id, run_id=run_id)
@@ -17,7 +17,7 @@
from __future__ import annotations
import time
from datetime import datetime, timezone
from datetime import UTC, datetime
from functools import cached_property
import boto3
@@ -174,7 +174,7 @@ class AirflowClient:
"""Trigger a DAG and wait for it to complete."""
self.un_pause_dag(dag_id)
resp = self.trigger_dag(dag_id, json=json or {"logical_date": datetime.now(timezone.utc).isoformat()})
resp = self.trigger_dag(dag_id, json=json or {"logical_date": datetime.now(UTC).isoformat()})
# Wait for the DAG run to complete
return self.wait_for_dag_run(
@@ -24,7 +24,7 @@ Asserts the task succeeds and the concurrent pull beats the sequential one.
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime, timezone
from datetime import UTC, datetime
import pytest
@@ -57,7 +57,7 @@ class _CompletedRun:
def completed_run() -> _CompletedRun:
"""Trigger ``concurrent_xcom_dag`` once and wait for it to finish."""
client = AirflowClient()
resp = client.trigger_dag(_DAG_ID, json={"logical_date": datetime.now(timezone.utc).isoformat()})
resp = client.trigger_dag(_DAG_ID, json={"logical_date": datetime.now(UTC).isoformat()})
run_id = resp["dag_run_id"]
state = client.wait_for_dag_run(dag_id=_DAG_ID, run_id=run_id, timeout=_GO_TASK_TIMEOUT)
ti_resp = client.get_task_instances(dag_id=_DAG_ID, run_id=run_id)
@@ -68,7 +68,7 @@ from __future__ import annotations
import re
import time
from dataclasses import dataclass
from datetime import datetime, timezone
from datetime import UTC, datetime
import pytest
@@ -126,7 +126,7 @@ def completed_run() -> _CompletedRun:
in this module inspects the resulting states, XComs, and logs.
"""
client = AirflowClient()
resp = client.trigger_dag(_DAG_ID, json={"logical_date": datetime.now(timezone.utc).isoformat()})
resp = client.trigger_dag(_DAG_ID, json={"logical_date": datetime.now(UTC).isoformat()})
run_id = resp["dag_run_id"]
state = client.wait_for_dag_run(dag_id=_DAG_ID, run_id=run_id, timeout=_GO_TASK_TIMEOUT)
ti_resp = client.get_task_instances(dag_id=_DAG_ID, run_id=run_id)
@@ -23,7 +23,7 @@ proven to have reached the database.
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime, timedelta, timezone
from datetime import UTC, datetime, timedelta
from http import HTTPStatus
import pytest
@@ -54,7 +54,7 @@ class _CompletedRun:
@pytest.fixture(scope="module")
def completed_run() -> _CompletedRun:
client = AirflowClient()
resp = client.trigger_dag(_DAG_ID, json={"logical_date": datetime.now(timezone.utc).isoformat()})
resp = client.trigger_dag(_DAG_ID, json={"logical_date": datetime.now(UTC).isoformat()})
run_id = resp["dag_run_id"]
state = client.wait_for_dag_run(dag_id=_DAG_ID, run_id=run_id, timeout=_GO_TASK_TIMEOUT)
ti_resp = client.get_task_instances(dag_id=_DAG_ID, run_id=run_id)
@@ -28,7 +28,7 @@ from __future__ import annotations
import time
from dataclasses import dataclass
from datetime import datetime, timezone
from datetime import UTC, datetime
import pytest
@@ -86,7 +86,7 @@ class _CompletedRun:
def completed_run() -> _CompletedRun:
"""Trigger ``taskflow_binding_dag`` once and wait for it to finish."""
client = AirflowClient()
resp = client.trigger_dag(_DAG_ID, json={"logical_date": datetime.now(timezone.utc).isoformat()})
resp = client.trigger_dag(_DAG_ID, json={"logical_date": datetime.now(UTC).isoformat()})
run_id = resp["dag_run_id"]
state = client.wait_for_dag_run(dag_id=_DAG_ID, run_id=run_id, timeout=_GO_TASK_TIMEOUT)
ti_resp = client.get_task_instances(dag_id=_DAG_ID, run_id=run_id)
@@ -24,7 +24,7 @@ written, so both paths go through the supervisor and the Task Execution API.
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime, timezone
from datetime import UTC, datetime
from http import HTTPStatus
import pytest
@@ -52,7 +52,7 @@ class _CompletedRun:
def completed_run() -> _CompletedRun:
"""Trigger ``variable_write_dag`` once and wait for it to finish."""
client = AirflowClient()
resp = client.trigger_dag(_DAG_ID, json={"logical_date": datetime.now(timezone.utc).isoformat()})
resp = client.trigger_dag(_DAG_ID, json={"logical_date": datetime.now(UTC).isoformat()})
run_id = resp["dag_run_id"]
state = client.wait_for_dag_run(dag_id=_DAG_ID, run_id=run_id, timeout=_GO_TASK_TIMEOUT)
ti_resp = client.get_task_instances(dag_id=_DAG_ID, run_id=run_id)
@@ -69,7 +69,7 @@ from __future__ import annotations
import time
from dataclasses import dataclass, field
from datetime import datetime, timezone
from datetime import UTC, datetime
from http import HTTPStatus
from typing import TYPE_CHECKING
@@ -155,7 +155,7 @@ def _trigger_and_wait_for_dag(dag_id: str, timeout: int) -> _CompletedRun:
client = AirflowClient()
run_id = None
try:
resp = client.trigger_dag(dag_id, json={"logical_date": datetime.now(timezone.utc).isoformat()})
resp = client.trigger_dag(dag_id, json={"logical_date": datetime.now(UTC).isoformat()})
run_id = resp["dag_run_id"]
state = client.wait_for_dag_run(dag_id=dag_id, run_id=run_id, timeout=timeout)
ti_resp = client.get_task_instances(dag_id=dag_id, run_id=run_id)
@@ -75,7 +75,7 @@ class OpenLineageE2ERunner:
def __init__(self, client: AirflowClient):
self.client = client
now = dt.datetime.now(tz=dt.timezone.utc)
now = dt.datetime.now(tz=dt.UTC)
self.run_id = f"ci_triggered_{now.isoformat()}"
self.retry_run_id = f"{self.run_id}_retry1"
# dag_id -> whether its final state came from retry_run_id rather than run_id; populated by run().
@@ -110,7 +110,7 @@ class OpenLineageE2ERunner:
console.print(f"[red]Failed to unpause Dag `{dag_id}`: {exc}")
def trigger_dag_run(self, dag_id: str, run_id: str) -> bool:
now = dt.datetime.now(tz=dt.timezone.utc).isoformat()
now = dt.datetime.now(tz=dt.UTC).isoformat()
payload = {"dag_run_id": run_id, "logical_date": now, "conf": {}}
try:
self.client._make_request(method="POST", endpoint=f"dags/{dag_id}/dagRuns", json=payload)
@@ -17,7 +17,7 @@
from __future__ import annotations
import time
from datetime import datetime, timezone
from datetime import UTC, datetime
import pytest
@@ -37,7 +37,7 @@ class TestRemoteLogging:
self.airflow_client.un_pause_dag(TestRemoteLogging.dag_id)
resp = self.airflow_client.trigger_dag(
TestRemoteLogging.dag_id, json={"logical_date": datetime.now(timezone.utc).isoformat()}
TestRemoteLogging.dag_id, json={"logical_date": datetime.now(UTC).isoformat()}
)
state = self.airflow_client.wait_for_dag_run(
dag_id=TestRemoteLogging.dag_id,
@@ -37,7 +37,7 @@ from __future__ import annotations
import time
from dataclasses import dataclass
from datetime import datetime, timezone
from datetime import UTC, datetime
from http import HTTPStatus
import pytest
@@ -89,7 +89,7 @@ class _CompletedRun:
def _trigger_and_wait(dag_id: str) -> _CompletedRun:
client = AirflowClient()
resp = client.trigger_dag(dag_id, json={"logical_date": datetime.now(timezone.utc).isoformat()})
resp = client.trigger_dag(dag_id, json={"logical_date": datetime.now(UTC).isoformat()})
run_id = resp["dag_run_id"]
state = client.wait_for_dag_run(dag_id=dag_id, run_id=run_id, timeout=_TS_TASK_TIMEOUT)
ti_resp = client.get_task_instances(dag_id=dag_id, run_id=run_id)
@@ -17,7 +17,7 @@
from __future__ import annotations
import time
from datetime import datetime, timezone
from datetime import UTC, datetime
from pprint import pprint
from uuid import uuid4
@@ -41,7 +41,7 @@ class TestXComObjectStorageBackend:
self.dag_id,
json={
"dag_run_id": f"test_xcom_object_storage_backend_{uuid4()}",
"logical_date": datetime.now(timezone.utc).isoformat(),
"logical_date": datetime.now(UTC).isoformat(),
},
)
dag_run_id = trigger_resp["dag_run_id"]
@@ -23,7 +23,7 @@ import sys
import tempfile
import zipfile
from collections.abc import Mapping, Sequence
from datetime import datetime, timezone
from datetime import UTC, datetime
from pathlib import Path
from typing import TYPE_CHECKING, Any, cast
@@ -159,7 +159,7 @@ def log_github_rate_limit_error(response: Response) -> None:
remaining_int = int(remaining) if remaining and remaining.isdigit() else None
if reset and reset.isdigit():
reset_dt = datetime.fromtimestamp(int(reset), tz=timezone.utc)
reset_dt = datetime.fromtimestamp(int(reset), tz=UTC)
reset_time = reset_dt.strftime("%Y-%m-%d %H:%M:%S UTC")
else:
reset_time = "unknown"
@@ -342,7 +342,7 @@ def get_tag_date(tag: str) -> str | None:
timestamp: int = (
tag_object.committed_date if hasattr(tag_object, "committed_date") else tag_object.tagged_date
)
return datetime.fromtimestamp(timestamp, tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
return datetime.fromtimestamp(timestamp, tz=UTC).strftime("%Y-%m-%dT%H:%M:%SZ")
def download_artifact_from_run_id(run_id: str, output_file: Path, github_repository: str, github_token: str):
@@ -26,7 +26,7 @@ import stat
import sys
import tarfile
import tempfile
from datetime import datetime, timedelta, timezone
from datetime import UTC, datetime, timedelta
from pathlib import Path
from time import sleep
from typing import Any, NamedTuple
@@ -414,7 +414,7 @@ def get_kubernetes_port_numbers(python: str, kubernetes_version: str) -> tuple[i
def _attempt_to_connect(port_number: int, output: Output | None, wait_seconds: int = 0) -> bool:
import requests
start_time = datetime.now(timezone.utc)
start_time = datetime.now(UTC)
sleep_seconds = 5
for attempt in itertools.count(1):
get_console(output=output).print(f"[info]Connecting to localhost:{port_number}. Num try: {attempt}")
@@ -437,7 +437,7 @@ def _attempt_to_connect(port_number: int, output: Output | None, wait_seconds: i
f"[warning]Error when connecting to localhost:{port_number} "
f"{response.status_code}: {response.reason}"
)
current_time = datetime.now(timezone.utc)
current_time = datetime.now(UTC)
if current_time - start_time > timedelta(seconds=wait_seconds):
if wait_seconds > 0:
get_console(output=output).print(f"[error]More than {wait_seconds} passed. Exiting.")
@@ -283,7 +283,7 @@ class ParallelMonitor(Thread):
self.time_in_seconds = time_in_seconds
self.debug_resources = debug_resources
self.progress_matcher = progress_matcher
self.start_time = datetime.datetime.now(tz=datetime.timezone.utc)
self.start_time = datetime.datetime.now(tz=datetime.UTC)
def print_single_progress(self, output: Output):
if self.progress_matcher:
@@ -312,7 +312,7 @@ class ParallelMonitor(Thread):
def print_summary(self):
import psutil
time_passed = datetime.datetime.now(tz=datetime.timezone.utc) - self.start_time
time_passed = datetime.datetime.now(tz=datetime.UTC) - self.start_time
get_console().rule()
for output in self.outputs:
self.print_single_progress(output)
+11 -29
View File
@@ -18,7 +18,7 @@ from __future__ import annotations
import json
import re
from datetime import datetime, timezone
from datetime import UTC, datetime
from unittest.mock import MagicMock, patch
import pytest
@@ -202,21 +202,13 @@ class TestShouldSkipMilestoneTagging:
def test_skip_when_backport_unlabeled_with_no_replacement(self):
# Events show backport removal, no backport on PR now → skip (check 2).
events = [
_unlabel_event(
"backport-to-v3-1-test", "alice", datetime(2026, 5, 23, 12, 0, tzinfo=timezone.utc)
)
]
events = [_unlabel_event("backport-to-v3-1-test", "alice", datetime(2026, 5, 23, 12, 0, tzinfo=UTC))]
assert _should_skip_milestone_tagging(["kind:bug"], events=events)
def test_no_skip_when_backport_replaced(self):
# Events show backport-to-v3-1 removal but v3-2 remains on the PR → no skip.
# The caller's regular evaluation will pick up the new label.
events = [
_unlabel_event(
"backport-to-v3-1-test", "alice", datetime(2026, 5, 23, 12, 0, tzinfo=timezone.utc)
)
]
events = [_unlabel_event("backport-to-v3-1-test", "alice", datetime(2026, 5, 23, 12, 0, tzinfo=UTC))]
assert not _should_skip_milestone_tagging(["backport-to-v3-2-test", "kind:bug"], events=events)
def test_no_skip_when_no_removal_event(self):
@@ -224,20 +216,14 @@ class TestShouldSkipMilestoneTagging:
assert not _should_skip_milestone_tagging(["backport-to-v3-1-test", "kind:bug"], events=[])
def test_no_skip_when_unrelated_label_removed(self):
events = [
_unlabel_event("kind:documentation", "alice", datetime(2026, 5, 23, 12, 0, tzinfo=timezone.utc))
]
events = [_unlabel_event("kind:documentation", "alice", datetime(2026, 5, 23, 12, 0, tzinfo=UTC))]
assert not _should_skip_milestone_tagging(["kind:bug"], events=events)
def test_events_check_takes_precedence_over_static_labels(self):
# Both check 2 (events) and check 3 (static label) would fire here;
# the function returns True on the first one — events — and never logs
# the static-label reason.
events = [
_unlabel_event(
"backport-to-v3-1-test", "alice", datetime(2026, 5, 23, 12, 0, tzinfo=timezone.utc)
)
]
events = [_unlabel_event("backport-to-v3-1-test", "alice", datetime(2026, 5, 23, 12, 0, tzinfo=UTC))]
assert _should_skip_milestone_tagging(["area:CI"], events=events)
def test_events_none_disables_events_check(self):
@@ -251,10 +237,8 @@ class TestGetRemovedBackportLabelsFromEvents:
def test_returns_all_unlabel_events_for_backports(self):
events = [
_unlabel_event(
"backport-to-v3-1-test", "alice", datetime(2026, 5, 23, 12, 0, tzinfo=timezone.utc)
),
_unlabel_event("backport-to-v3-2-test", "bob", datetime(2026, 5, 23, 14, 0, tzinfo=timezone.utc)),
_unlabel_event("backport-to-v3-1-test", "alice", datetime(2026, 5, 23, 12, 0, tzinfo=UTC)),
_unlabel_event("backport-to-v3-2-test", "bob", datetime(2026, 5, 23, 14, 0, tzinfo=UTC)),
]
assert _get_removed_backport_labels_from_events(events) == {
"backport-to-v3-1-test",
@@ -262,9 +246,7 @@ class TestGetRemovedBackportLabelsFromEvents:
}
def test_ignores_unrelated_label_unlabel_events(self):
events = [
_unlabel_event("kind:documentation", "alice", datetime(2026, 5, 23, 12, 0, tzinfo=timezone.utc))
]
events = [_unlabel_event("kind:documentation", "alice", datetime(2026, 5, 23, 12, 0, tzinfo=UTC))]
assert _get_removed_backport_labels_from_events(events) == set()
def test_ignores_non_unlabeled_events(self):
@@ -733,7 +715,7 @@ However, **no open milestone was found** matching: {expected_search_criteria}
_unlabel_event(
"backport-to-v3-2-test",
"shahar1",
datetime(2026, 5, 23, 20, 32, 17, tzinfo=timezone.utc),
datetime(2026, 5, 23, 20, 32, 17, tzinfo=UTC),
),
]
mock_get_client.return_value = mock_gh
@@ -785,7 +767,7 @@ However, **no open milestone was found** matching: {expected_search_criteria}
_unlabel_event(
"backport-to-v3-2-test",
"testuser",
datetime(2026, 5, 23, 20, 32, 17, tzinfo=timezone.utc),
datetime(2026, 5, 23, 20, 32, 17, tzinfo=UTC),
),
]
mock_get_client.return_value = mock_gh
@@ -834,7 +816,7 @@ However, **no open milestone was found** matching: {expected_search_criteria}
_unlabel_event(
"backport-to-v3-1-test",
"testuser",
datetime(2026, 5, 23, 20, 30, 0, tzinfo=timezone.utc),
datetime(2026, 5, 23, 20, 30, 0, tzinfo=UTC),
),
]
mock_milestone = MagicMock()
+2 -2
View File
@@ -39,7 +39,7 @@ import argparse
import json
import sys
from collections import defaultdict
from datetime import datetime, timezone
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
@@ -204,7 +204,7 @@ def main():
hooks, form_widgets, field_behaviours = HookMetaService._get_hooks_with_mocked_fab()
generated_at = datetime.now(timezone.utc).isoformat()
generated_at = datetime.now(UTC).isoformat()
# Group connection types by provider
provider_connections: dict[str, list[dict]] = defaultdict(list)
+2 -2
View File
@@ -50,7 +50,7 @@ import textwrap
import typing
from collections import defaultdict
from dataclasses import dataclass
from datetime import datetime, timezone
from datetime import UTC, datetime
from pathlib import Path
import yaml
@@ -1233,7 +1233,7 @@ def main():
for p in providers_data.get("providers", []):
provider_versions[p["id"]] = p["version"]
generated_at = datetime.now(timezone.utc).isoformat()
generated_at = datetime.now(UTC).isoformat()
_main_discover(
provider_versions,
generated_at,
@@ -22,7 +22,7 @@ import re
import subprocess
import tempfile
import time
from datetime import datetime, timezone
from datetime import UTC, datetime
from pathlib import Path
from subprocess import check_call, check_output
from typing import Literal
@@ -100,7 +100,7 @@ class BaseK8STest:
with open(output_file_path, "w") as output_file:
print("=" * 80, file=output_file)
print(f"Describe resources for namespace {namespace}", file=output_file)
print(f"Datetime: {datetime.now(tz=timezone.utc)}", file=output_file)
print(f"Datetime: {datetime.now(tz=UTC)}", file=output_file)
print("=" * 80, file=output_file)
print("Describing pods", file=output_file)
print("-" * 80, file=output_file)
@@ -349,7 +349,7 @@ class BaseK8STest:
post_string = f"http://{host}/dags/{dag_id}/dagRuns"
print(f"Calling [start_dag]#2 {post_string}")
logical_date = datetime.now(timezone.utc).isoformat()
logical_date = datetime.now(UTC).isoformat()
# Trigger a new dagrun
result = self.session.post(post_string, json={"logical_date": logical_date})
try:
+2 -2
View File
@@ -75,7 +75,7 @@ import json
import os
import subprocess
import sys
from datetime import datetime, timezone
from datetime import UTC, datetime
from pathlib import Path
from typing import TypedDict
@@ -725,7 +725,7 @@ def main() -> None:
runs = get_recent_runs(repo, workflow, branch, max_runs, only_successful, event)
# A degraded Actions API can return an old page of runs, and without this check its
# weeks-old durations were reported as "latest" and raised a false alert.
newest_age_days = compute_run_age_days(runs[0], datetime.now(timezone.utc)) if runs else None
newest_age_days = compute_run_age_days(runs[0], datetime.now(UTC)) if runs else None
if newest_age_days is not None and newest_age_days > max_latest_run_age_days:
print(
f"::warning::The newest usable run (#{runs[0]['run_number']}) is "
+2 -2
View File
@@ -49,7 +49,7 @@ import re
import sys
import time
from dataclasses import dataclass
from datetime import datetime, timedelta, timezone
from datetime import UTC, datetime, timedelta
from typing import Any
import httpx
@@ -428,7 +428,7 @@ def main() -> int:
short_sha = sha[:7]
commit_url = f"https://github.com/{owner}/{repo}/commit/{sha}"
stale_cut = datetime.now(tz=timezone.utc) - timedelta(days=STALE_DAYS)
stale_cut = datetime.now(tz=UTC) - timedelta(days=STALE_DAYS)
with GitHubGraphQL(token) as client:
source_pr = resolve_source_pr(client, owner, repo, sha, short_sha)
@@ -37,7 +37,7 @@ import os
import re
import subprocess
import sys
from datetime import datetime, timedelta, timezone
from datetime import UTC, datetime, timedelta
from enum import Enum
from pathlib import Path
@@ -277,7 +277,7 @@ def _is_version_within_cooldown(releases: dict, version: str, cooldown_hours: fl
return False
upload_time = datetime.fromisoformat(files[0]["upload_time_iso_8601"].replace("Z", "+00:00"))
effective_hours = COOLDOWN_DAYS * 24 if cooldown_hours is None else cooldown_hours
cutoff = datetime.now(timezone.utc) - timedelta(hours=effective_hours)
cutoff = datetime.now(UTC) - timedelta(hours=effective_hours)
return upload_time > cutoff
+3 -3
View File
@@ -44,7 +44,7 @@ import json
import os
import subprocess
import sys
from datetime import datetime, timezone
from datetime import UTC, datetime
from pathlib import Path
REMINDER_INTERVAL_HOURS = 24
@@ -140,7 +140,7 @@ def determine_action(current_failures: list[str], prev_state: dict | None) -> st
"""
prev_failures = sorted(prev_state.get("failures", [])) if prev_state else []
prev_notified = prev_state.get("last_notified") if prev_state else None
now = datetime.now(timezone.utc)
now = datetime.now(UTC)
if current_failures:
if not prev_failures:
@@ -164,7 +164,7 @@ def determine_action(current_failures: list[str], prev_state: dict | None) -> st
def save_state(current_failures: list[str], action: str, prev_notified: str | None) -> None:
"""Save current state to file for upload as artifact."""
now = datetime.now(timezone.utc)
now = datetime.now(UTC)
STATE_DIR.mkdir(parents=True, exist_ok=True)
new_state = {
@@ -20,7 +20,7 @@ from __future__ import annotations
import os
import re
import sys
from datetime import datetime, timezone
from datetime import UTC, datetime
from pathlib import Path
from typing import NamedTuple
from urllib.parse import urlsplit
@@ -244,7 +244,7 @@ if __name__ == "__main__":
print()
with Path(__file__).resolve().with_name("quarantine_issue_header.md").open() as f:
header = jinja2.Template(f.read(), autoescape=True, undefined=StrictUndefined).render(
DATE_UTC_NOW=datetime.now(tz=timezone.utc).isoformat("T", timespec="seconds")
DATE_UTC_NOW=datetime.now(tz=UTC).isoformat("T", timespec="seconds")
)
quarantined_issue.edit(
title=None, body=f"{header}\n\n{table}", state="open" if test_results else "closed"
@@ -18,7 +18,7 @@ from __future__ import annotations
import subprocess
import textwrap
from datetime import datetime, timedelta, timezone
from datetime import UTC, datetime, timedelta
from pathlib import Path
from unittest import mock
@@ -202,7 +202,7 @@ def test_no_exclusion_for_plain_floor(tmp_path):
assert get_exclusion_reason("boto3", [_site("boto3>=1.40; python_version < '3.14'")], config) is None
NOW = datetime(2026, 9, 24, tzinfo=timezone.utc)
NOW = datetime(2026, 9, 24, tzinfo=UTC)
AGE = timedelta(days=180)
@@ -19,6 +19,7 @@
from __future__ import annotations
from datetime import UTC
from unittest import mock
import pytest
@@ -199,12 +200,12 @@ def test_remove_override_entry_no_match_is_noop():
def test_is_version_within_cooldown_uses_per_package_override():
"""A shorter per-package cooldown lets a release through that the global window would block."""
from datetime import datetime, timedelta, timezone
from datetime import datetime, timedelta
from ci.prek.upgrade_important_versions import _is_version_within_cooldown
# Published 2 days ago — inside the 4-day global window, outside a 6-hour window.
two_days_ago = (datetime.now(timezone.utc) - timedelta(days=2)).isoformat()
two_days_ago = (datetime.now(UTC) - timedelta(days=2)).isoformat()
releases = {"1.0.1": [{"upload_time_iso_8601": two_days_ago.replace("+00:00", "Z")}]}
# No override → global 4-day cooldown applies → version is "within cooldown".
@@ -19,7 +19,7 @@ from __future__ import annotations
import importlib.util
import sys
import types
from datetime import datetime, timedelta, timezone
from datetime import UTC, datetime, timedelta
from pathlib import Path
from typing import Any
from unittest.mock import MagicMock
@@ -56,7 +56,7 @@ def mod():
# A recent timestamp — well inside the stale window — used by fixture PRs.
FRESH_ISO = "2099-01-01T12:00:00Z"
STALE_CUT = datetime(1970, 1, 1, tzinfo=timezone.utc)
STALE_CUT = datetime(1970, 1, 1, tzinfo=UTC)
SHORT_SHA = "abc1234"
@@ -113,11 +113,11 @@ class TestPrNumberRegex:
class TestParseUpdatedAt:
def test_handles_zulu_suffix(self, mod):
dt = mod.parse_updated_at("2025-04-24T10:20:30Z")
assert dt == datetime(2025, 4, 24, 10, 20, 30, tzinfo=timezone.utc)
assert dt == datetime(2025, 4, 24, 10, 20, 30, tzinfo=UTC)
def test_handles_explicit_offset(self, mod):
dt = mod.parse_updated_at("2025-04-24T10:20:30+00:00")
assert dt == datetime(2025, 4, 24, 10, 20, 30, tzinfo=timezone.utc)
assert dt == datetime(2025, 4, 24, 10, 20, 30, tzinfo=UTC)
class TestClassify:
@@ -126,7 +126,7 @@ class TestClassify:
assert kind == "drafts" and entry is None
def test_stale(self, mod):
cutoff = datetime.now(tz=timezone.utc) - timedelta(days=14)
cutoff = datetime.now(tz=UTC) - timedelta(days=14)
old_pr = make_pr(updated_at="2000-01-01T00:00:00Z")
kind, entry = mod.classify(old_pr, cutoff, SHORT_SHA)
assert kind == "stale" and entry is None
@@ -237,9 +237,9 @@ class TestScanOpenPrs:
def test_early_exit_on_stale(self, mod):
"""A stale PR stops pagination even if hasNextPage is True."""
client = MagicMock()
recent_cut = datetime.now(tz=timezone.utc) - timedelta(days=1)
fresh = (datetime.now(tz=timezone.utc)).isoformat().replace("+00:00", "Z")
stale = (datetime.now(tz=timezone.utc) - timedelta(days=30)).isoformat().replace("+00:00", "Z")
recent_cut = datetime.now(tz=UTC) - timedelta(days=1)
fresh = (datetime.now(tz=UTC)).isoformat().replace("+00:00", "Z")
stale = (datetime.now(tz=UTC) - timedelta(days=30)).isoformat().replace("+00:00", "Z")
client.call.return_value = self._page(
[
make_pr(number=1, updated_at=fresh, mergeable="CONFLICTING"),
@@ -18,7 +18,7 @@ from __future__ import annotations
import importlib.util
import sys
from datetime import datetime, timezone
from datetime import UTC, datetime
from pathlib import Path
import pytest
@@ -61,7 +61,7 @@ def test_compute_remaining_test_timeout(
@time_machine.travel("2026-08-29 12:10:00+00:00", tick=False)
def test_main_derives_the_budget_left_from_the_job_start_time(timeout_module, monkeypatch, capsys):
job_start_epoch = int(datetime(2026, 8, 29, 12, 0, tzinfo=timezone.utc).timestamp())
job_start_epoch = int(datetime(2026, 8, 29, 12, 0, tzinfo=UTC).timestamp())
monkeypatch.setattr(
sys,
"argv",
@@ -21,7 +21,7 @@ from __future__ import annotations
import os
import uuid
from datetime import datetime, timezone
from datetime import UTC, datetime
from typing import Any
import jwt
@@ -57,7 +57,7 @@ class JWTTokenGenerator:
Returns:
JWT token as a string
"""
now = int(datetime.now(timezone.utc).timestamp())
now = int(datetime.now(UTC).timestamp())
claims = {
"jti": uuid.uuid4().hex,
@@ -26,7 +26,7 @@ These tests validate the Execution API endpoints for DAG Run operations:
from __future__ import annotations
from datetime import datetime, timedelta, timezone
from datetime import UTC, datetime, timedelta
import pytest
@@ -145,7 +145,7 @@ def test_dag_run_get_previous(sdk_client, dag_info):
response = sdk_client.dag_runs.get_previous(
dag_id=dag_info["dag_id"],
logical_date=datetime.now(timezone.utc) + timedelta(seconds=10),
logical_date=datetime.now(UTC) + timedelta(seconds=10),
)
console.print(" Previous DAG Run Response ".center(72, "="))
@@ -169,7 +169,7 @@ def test_dag_run_get_previous_not_found(sdk_client):
response = sdk_client.dag_runs.get_previous(
dag_id="not_exist",
logical_date=datetime.now(timezone.utc) + timedelta(seconds=10),
logical_date=datetime.now(UTC) + timedelta(seconds=10),
)
console.print(" Non-existent Previous DAG Run Response ".center(72, "="))