From 4d6d07263f6dec96311a9a099fb6de488ca7535b Mon Sep 17 00:00:00 2001 From: Md Zeeshan Alam Date: Sat, 18 Apr 2026 20:52:46 +0530 Subject: [PATCH 1/3] Fix REST API pools: serialize unlimited open_slots as -1 instead of inf --- airflow/api_connexion/schemas/pool_schema.py | 14 +++++++++++--- tests/api_connexion/schemas/test_pool_schemas.py | 11 +++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/airflow/api_connexion/schemas/pool_schema.py b/airflow/api_connexion/schemas/pool_schema.py index fd42d71e89578..17992f2d0f1cc 100644 --- a/airflow/api_connexion/schemas/pool_schema.py +++ b/airflow/api_connexion/schemas/pool_schema.py @@ -70,9 +70,17 @@ def get_deferred_slots(obj: Pool) -> int: return obj.deferred_slots() @staticmethod - def get_open_slots(obj: Pool) -> float: - """Return the open slots of the pool.""" - return obj.open_slots() + def get_open_slots(obj: Pool) -> int: + """Return the open slots of the pool. + + Unlimited pools (``slots == -1``) use ``float('inf')`` internally; the REST API + schema requires an integer, so we serialize that as ``-1`` (same convention as + ``slots`` for unlimited). + """ + open_slots = obj.open_slots() + if isinstance(open_slots, float) and open_slots == float("inf"): + return -1 + return int(open_slots) class PoolCollection(NamedTuple): diff --git a/tests/api_connexion/schemas/test_pool_schemas.py b/tests/api_connexion/schemas/test_pool_schemas.py index 110103073aaa5..c17e258a64e58 100644 --- a/tests/api_connexion/schemas/test_pool_schemas.py +++ b/tests/api_connexion/schemas/test_pool_schemas.py @@ -53,6 +53,17 @@ def test_serialize(self, session): "include_deferred": False, } + @provide_session + def test_serialize_unlimited_pool_open_slots_as_minus_one(self, session): + """Unlimited pools must not serialize open_slots as inf (OpenAPI integer).""" + pool_model = Pool(pool="unlimited_pool", slots=-1, include_deferred=False) + session.add(pool_model) + session.commit() + pool_instance = session.query(Pool).filter(Pool.pool == pool_model.pool).first() + serialized_pool = pool_schema.dump(pool_instance) + assert serialized_pool["slots"] == -1 + assert serialized_pool["open_slots"] == -1 + @provide_session def test_deserialize(self, session): pool_dict = {"name": "test_pool", "slots": 3, "include_deferred": True} From ff34c6502dce31e4ab8e42dd471d15cd7f3360d5 Mon Sep 17 00:00:00 2001 From: Md Zeeshan Alam Date: Sun, 19 Apr 2026 00:52:18 +0530 Subject: [PATCH 2/3] Combining two tests using pytest.mark.parametrize --- .../schemas/test_pool_schemas.py | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/tests/api_connexion/schemas/test_pool_schemas.py b/tests/api_connexion/schemas/test_pool_schemas.py index c17e258a64e58..b9a7c6fdecbcc 100644 --- a/tests/api_connexion/schemas/test_pool_schemas.py +++ b/tests/api_connexion/schemas/test_pool_schemas.py @@ -33,37 +33,38 @@ def setup_method(self) -> None: def teardown_method(self) -> None: clear_db_pools() + @pytest.mark.parametrize( + ("pool_name", "slots", "expected_open_slots"), + [ + pytest.param("test_pool", 2, 2, id="finite_slots"), + pytest.param("unlimited_pool", -1, -1, id="unlimited_slots_serialized_as_minus_one"), + ], + ) @provide_session - def test_serialize(self, session): - pool_model = Pool(pool="test_pool", slots=2, include_deferred=False) + def test_serialize(self, pool_name, slots, expected_open_slots, session): + """Pools must serialize open_slots as an integer. + + Unlimited pools (``slots == -1``) must not leak ``inf`` into the JSON + response since the OpenAPI schema declares ``open_slots`` as an integer. + """ + pool_model = Pool(pool=pool_name, slots=slots, include_deferred=False) session.add(pool_model) session.commit() pool_instance = session.query(Pool).filter(Pool.pool == pool_model.pool).first() serialized_pool = pool_schema.dump(pool_instance) assert serialized_pool == { - "name": "test_pool", - "slots": 2, + "name": pool_name, + "slots": slots, "occupied_slots": 0, "running_slots": 0, "queued_slots": 0, "scheduled_slots": 0, "deferred_slots": 0, - "open_slots": 2, + "open_slots": expected_open_slots, "description": None, "include_deferred": False, } - @provide_session - def test_serialize_unlimited_pool_open_slots_as_minus_one(self, session): - """Unlimited pools must not serialize open_slots as inf (OpenAPI integer).""" - pool_model = Pool(pool="unlimited_pool", slots=-1, include_deferred=False) - session.add(pool_model) - session.commit() - pool_instance = session.query(Pool).filter(Pool.pool == pool_model.pool).first() - serialized_pool = pool_schema.dump(pool_instance) - assert serialized_pool["slots"] == -1 - assert serialized_pool["open_slots"] == -1 - @provide_session def test_deserialize(self, session): pool_dict = {"name": "test_pool", "slots": 3, "include_deferred": True} From ed03dec35bb09cc412e501711ab5171fc6d3f092 Mon Sep 17 00:00:00 2001 From: Md Zeeshan Alam Date: Tue, 21 Apr 2026 00:55:21 +0530 Subject: [PATCH 3/3] Fix docstring formatting in PoolSchema.get_open_slots --- airflow/api_connexion/schemas/pool_schema.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/airflow/api_connexion/schemas/pool_schema.py b/airflow/api_connexion/schemas/pool_schema.py index 17992f2d0f1cc..59b58b4adcc36 100644 --- a/airflow/api_connexion/schemas/pool_schema.py +++ b/airflow/api_connexion/schemas/pool_schema.py @@ -71,7 +71,8 @@ def get_deferred_slots(obj: Pool) -> int: @staticmethod def get_open_slots(obj: Pool) -> int: - """Return the open slots of the pool. + """ + Return the open slots of the pool. Unlimited pools (``slots == -1``) use ``float('inf')`` internally; the REST API schema requires an integer, so we serialize that as ``-1`` (same convention as