This is an automated email from the ASF dual-hosted git repository.
jasonliu 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 ab1e0c21809 Add description field for filter_param_factory (#54903)
ab1e0c21809 is described below
commit ab1e0c218097437d8811d238a434778042e34961
Author: LIU ZHE YOU <[email protected]>
AuthorDate: Wed Sep 3 00:04:24 2025 +0800
Add description field for filter_param_factory (#54903)
* Add description field for filter_param_factory
* Make 'description' kwarg only, add unit test
* Fix Dag typo
---
.../src/airflow/api_fastapi/common/parameters.py | 6 +-
.../unit/api_fastapi/common/test_parameters.py | 65 +++++++++++++++++++++-
2 files changed, 67 insertions(+), 4 deletions(-)
diff --git a/airflow-core/src/airflow/api_fastapi/common/parameters.py
b/airflow-core/src/airflow/api_fastapi/common/parameters.py
index 5dcecc6bb5c..592f08cdf12 100644
--- a/airflow-core/src/airflow/api_fastapi/common/parameters.py
+++ b/airflow-core/src/airflow/api_fastapi/common/parameters.py
@@ -379,14 +379,16 @@ def filter_param_factory(
default_factory: Callable[[], T | None] | None = None,
skip_none: bool = True,
transform_callable: Callable[[T | None], Any] | None = None,
+ *,
+ description: str | None = None,
) -> Callable[[T | None], FilterParam[T | None]]:
# if filter_name is not provided, use the attribute name as the default
filter_name = filter_name or attribute.name
# can only set either default_value or default_factory
query = (
- Query(alias=filter_name, default_factory=default_factory)
+ Query(alias=filter_name, default_factory=default_factory,
description=description)
if default_factory is not None
- else Query(alias=filter_name, default=default_value)
+ else Query(alias=filter_name, default=default_value,
description=description)
)
def depends_filter(value: T | None = query) -> FilterParam[T | None]:
diff --git a/airflow-core/tests/unit/api_fastapi/common/test_parameters.py
b/airflow-core/tests/unit/api_fastapi/common/test_parameters.py
index cd77ded8ace..5e3a523c0bd 100644
--- a/airflow-core/tests/unit/api_fastapi/common/test_parameters.py
+++ b/airflow-core/tests/unit/api_fastapi/common/test_parameters.py
@@ -18,11 +18,72 @@
from __future__ import annotations
import re
+from typing import Annotated
import pytest
-from fastapi import HTTPException
+from fastapi import Depends, FastAPI, HTTPException
-from airflow.api_fastapi.common.parameters import SortParam
+from airflow.api_fastapi.common.parameters import FilterParam, SortParam,
filter_param_factory
+from airflow.models import DagRun, Log
+
+
+class TestFilterParam:
+ def test_filter_param_factory_description(self):
+ app = FastAPI() # Create a FastAPI app to test OpenAPI generation
+ expected_descriptions = {
+ "dag_id": "Filter by Dag ID Description",
+ "task_id": "Filter by Task ID Description",
+ "map_index": None, # No description for map_index
+ "run_id": "Filter by Run ID Description",
+ }
+
+ @app.get("/test")
+ def test_route(
+ dag_id: Annotated[
+ FilterParam[str | None],
+ Depends(
+ filter_param_factory(Log.dag_id, str | None,
description="Filter by Dag ID Description")
+ ),
+ ],
+ task_id: Annotated[
+ FilterParam[str | None],
+ Depends(
+ filter_param_factory(Log.task_id, str | None,
description="Filter by Task ID Description")
+ ),
+ ],
+ map_index: Annotated[
+ FilterParam[int | None],
+ Depends(filter_param_factory(Log.map_index, int | None)),
+ ],
+ run_id: Annotated[
+ FilterParam[str | None],
+ Depends(
+ filter_param_factory(
+ DagRun.run_id, str | None, description="Filter by Run
ID Description"
+ )
+ ),
+ ],
+ ):
+ return {"message": "test"}
+
+ # Get the OpenAPI spec
+ openapi_spec = app.openapi()
+
+ # Check if the description is in the parameters
+ parameters = openapi_spec["paths"]["/test"]["get"]["parameters"]
+ for param_name, expected_description in expected_descriptions.items():
+ param = next((p for p in parameters if p.get("name") ==
param_name), None)
+ assert param is not None, f"{param_name} parameter not found in
OpenAPI"
+
+ if expected_description is None:
+ assert "description" not in param, (
+ f"Description should not be present in {param_name}
parameter"
+ )
+ else:
+ assert "description" in param, f"Description not found in
{param_name} parameter"
+ assert param["description"] == expected_description, (
+ f"Expected description '{expected_description}', got
'{param['description']}'"
+ )
class TestSortParam: