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:

Reply via email to