This is an automated email from the ASF dual-hosted git repository. potiuk pushed a commit to branch ci-upgrade-main in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 7aa3e0e30878408720d08acd26e6edb98b11e8d2 Author: Jarek Potiuk <[email protected]> AuthorDate: Mon Oct 19 13:04:26 2026 +0200 Make fab and standard provider typing hold for SQLAlchemy 2.1 The CI upgrade moves uv.lock to SQLAlchemy 2.1.4, where Select is parametrised by column types (Select[int]) and asc()/desc() of an InstrumentedAttribute return OrderByList | UnaryExpression. Use a bare Select alias (as airflow-core does since #74629) and narrow the ordering column to ColumnElement so the types hold on both 2.0 and 2.1. Generated-by: Claude Opus 5 --- .../src/airflow/providers/fab/auth_manager/api_fastapi/sorting.py | 6 ++++-- .../standard/src/airflow/providers/standard/utils/sensor_helper.py | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/providers/fab/src/airflow/providers/fab/auth_manager/api_fastapi/sorting.py b/providers/fab/src/airflow/providers/fab/auth_manager/api_fastapi/sorting.py index b19d43cb9c8..6933f6da425 100644 --- a/providers/fab/src/airflow/providers/fab/auth_manager/api_fastapi/sorting.py +++ b/providers/fab/src/airflow/providers/fab/auth_manager/api_fastapi/sorting.py @@ -17,7 +17,7 @@ from __future__ import annotations from collections.abc import Mapping -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, cast from fastapi import HTTPException, status from sqlalchemy import asc, desc @@ -45,5 +45,7 @@ def build_ordering( detail=f"Ordering with '{order_by}' is disallowed or the attribute does not exist on the model", ) - col = allowed[key] + # SQLAlchemy 2.1 types asc()/desc() of an InstrumentedAttribute as ``OrderByList | UnaryExpression``; + # narrowing to ColumnElement selects the overload returning UnaryExpression on both 2.0 and 2.1. + col = cast("ColumnElement[Any]", allowed[key]) return desc(col) if is_desc else asc(col) diff --git a/providers/standard/src/airflow/providers/standard/utils/sensor_helper.py b/providers/standard/src/airflow/providers/standard/utils/sensor_helper.py index f16e86bf34a..7562c67b68d 100644 --- a/providers/standard/src/airflow/providers/standard/utils/sensor_helper.py +++ b/providers/standard/src/airflow/providers/standard/utils/sensor_helper.py @@ -30,6 +30,9 @@ if TYPE_CHECKING: from sqlalchemy.orm import Session from sqlalchemy.sql import Select + # TODO: use Select[int] once the minimum SQLAlchemy is 2.1; 2.0 uses Select[tuple[int]]. + CountSelect = Select + @provide_session def _get_count( @@ -89,7 +92,7 @@ def _get_count( def _count_stmt( model: type[DagRun] | type[TaskInstance], states: list[str], dttm_filter: list[Any], external_dag_id: str -) -> Select[tuple[int]]: +) -> CountSelect: """ Get the count of records against dttm filter and states.
