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

vincbeck pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 657cde25713 SQLA2: fix mypy violations in 
`api_fastapi/.../calendar.py` (#56944)
657cde25713 is described below

commit 657cde257135519a1dba890182df4e684b68f282
Author: Dev-iL <[email protected]>
AuthorDate: Tue Oct 21 19:29:32 2025 +0300

    SQLA2: fix mypy violations in `api_fastapi/.../calendar.py` (#56944)
---
 .../api_fastapi/core_api/services/ui/calendar.py   | 36 +++++++++++-----------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git 
a/airflow-core/src/airflow/api_fastapi/core_api/services/ui/calendar.py 
b/airflow-core/src/airflow/api_fastapi/core_api/services/ui/calendar.py
index 2e352d26e24..912029e4845 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/services/ui/calendar.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/services/ui/calendar.py
@@ -17,8 +17,8 @@
 from __future__ import annotations
 
 import collections
-import datetime
-from collections.abc import Iterator
+from collections.abc import Iterator, Sequence
+from datetime import datetime
 from typing import Literal, cast
 
 import sqlalchemy as sa
@@ -26,7 +26,7 @@ import structlog
 from croniter.croniter import croniter
 from pendulum import DateTime
 from sqlalchemy.engine import Row
-from sqlalchemy.orm import Session
+from sqlalchemy.orm import InstrumentedAttribute, Session
 
 from airflow._shared.timezones import timezone
 from airflow.api_fastapi.common.parameters import RangeFilter
@@ -90,7 +90,7 @@ class CalendarService:
         session: Session,
         logical_date: RangeFilter,
         granularity: Literal["hourly", "daily"],
-    ) -> tuple[list[CalendarTimeRangeResponse], list[Row]]:
+    ) -> tuple[list[CalendarTimeRangeResponse], Sequence[Row]]:
         """Get historical DAG runs from the database."""
         dialect = session.bind.dialect.name
 
@@ -117,7 +117,7 @@ class CalendarService:
                 # ds.datetime in sqlite and mysql is a string, in postgresql 
it is a datetime
                 date=ds.datetime,
                 state=ds.state,
-                count=ds.count,
+                count=int(ds._mapping["count"]),
             )
             for ds in dag_states
         ]
@@ -127,7 +127,7 @@ class CalendarService:
     def _get_planned_dag_runs(
         self,
         dag: SerializedDAG,
-        raw_dag_states: list[Row],
+        raw_dag_states: Sequence[Row],
         logical_date: RangeFilter,
         granularity: Literal["hourly", "daily"],
     ) -> list[CalendarTimeRangeResponse]:
@@ -152,7 +152,7 @@ class CalendarService:
             dag, last_data_interval, year, restriction, logical_date, 
granularity
         )
 
-    def _should_calculate_planned_runs(self, dag: SerializedDAG, 
raw_dag_states: list[Row]) -> bool:
+    def _should_calculate_planned_runs(self, dag: SerializedDAG, 
raw_dag_states: Sequence[Row]) -> bool:
         """Check if we should calculate planned runs."""
         return (
             bool(raw_dag_states)
@@ -161,7 +161,7 @@ class CalendarService:
             and not isinstance(dag.timetable, ContinuousTimetable)
         )
 
-    def _get_last_data_interval(self, raw_dag_states: list[Row]) -> 
DataInterval | None:
+    def _get_last_data_interval(self, raw_dag_states: Sequence[Row]) -> 
DataInterval | None:
         """Extract the last data interval from raw database results."""
         if not raw_dag_states:
             return None
@@ -184,12 +184,12 @@ class CalendarService:
         granularity: Literal["hourly", "daily"],
     ) -> list[CalendarTimeRangeResponse]:
         """Calculate planned runs for cron-based timetables."""
-        dates: dict[datetime.datetime, int] = collections.Counter()
+        dates: dict[datetime, int] = collections.Counter()
 
-        dates_iter: Iterator[datetime.datetime | None] = croniter(
+        dates_iter: Iterator[datetime | None] = croniter(
             cast("CronMixin", dag.timetable)._expression,
             start_time=last_data_interval.end,
-            ret_type=datetime.datetime,
+            ret_type=datetime,
         )
 
         for dt in dates_iter:
@@ -216,7 +216,7 @@ class CalendarService:
         granularity: Literal["hourly", "daily"],
     ) -> list[CalendarTimeRangeResponse]:
         """Calculate planned runs for generic timetables."""
-        dates: dict[datetime.datetime, int] = collections.Counter()
+        dates: dict[datetime, int] = collections.Counter()
         prev_logical_date = DateTime.min
         total_planned = 0
 
@@ -251,10 +251,10 @@ class CalendarService:
 
     def _get_time_truncation_expression(
         self,
-        column: sa.Column,
+        column: InstrumentedAttribute[datetime | None],
         granularity: Literal["hourly", "daily"],
-        dialect: str,
-    ) -> sa.Column:
+        dialect: str | None,
+    ) -> sa.sql.elements.ColumnElement:
         """
         Get database-specific time truncation expression for SQLAlchemy.
 
@@ -295,9 +295,9 @@ class CalendarService:
 
     def _truncate_datetime_for_granularity(
         self,
-        dt: datetime.datetime,
+        dt: datetime,
         granularity: Literal["hourly", "daily"],
-    ) -> datetime.datetime:
+    ) -> datetime:
         """
         Truncate datetime based on granularity for planned tasks grouping.
 
@@ -312,7 +312,7 @@ class CalendarService:
             return dt.replace(minute=0, second=0, microsecond=0)
         return dt.replace(hour=0, minute=0, second=0, microsecond=0)
 
-    def _is_date_in_range(self, dt: datetime.datetime, logical_date: 
RangeFilter) -> bool:
+    def _is_date_in_range(self, dt: datetime, logical_date: RangeFilter) -> 
bool:
         """Check if a date is within the specified range filter."""
         if not logical_date.value:
             return True

Reply via email to