This is an automated email from the ASF dual-hosted git repository.
dabla 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 bbf2c5b1c47 Fix Lang-SDK decoder typing for pydantic 2.14 TypeForm
signature (#74628)
bbf2c5b1c47 is described below
commit bbf2c5b1c476ffb66267b0c1b9b8aa0f22d02b1f
Author: Dev-iL <[email protected]>
AuthorDate: Thu Oct 15 17:24:49 2026 +0300
Fix Lang-SDK decoder typing for pydantic 2.14 TypeForm signature (#74628)
pydantic 2.14 types TypeAdapter's argument as TypeForm[T], so mypy
rejects the Lang-SDK decoder built from get_args(ToManager)[0], which
is not a static type expression.
Name the ToManager message union ToManagerMessage and build the
Lang-SDK message type LangSDKToManager from it; the runtime union is
the same object as before. Declare each concrete processor's decoder
with its own precise TypeAdapter type instead of on
BaseDagFileProcessorProcess: TypeAdapter is invariant, so the Lang-SDK
decoder, which accepts a superset of ToManager, cannot override a base
TypeAdapter[ToManager].
---
airflow-core/src/airflow/dag_processing/lang_sdk_processor.py | 11 ++++++-----
airflow-core/src/airflow/dag_processing/processor.py | 11 ++++++-----
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/airflow-core/src/airflow/dag_processing/lang_sdk_processor.py
b/airflow-core/src/airflow/dag_processing/lang_sdk_processor.py
index 9a0998dd051..9e753e61059 100644
--- a/airflow-core/src/airflow/dag_processing/lang_sdk_processor.py
+++ b/airflow-core/src/airflow/dag_processing/lang_sdk_processor.py
@@ -26,7 +26,7 @@ import time
from contextlib import suppress
from pathlib import Path
from socket import socket
-from typing import TYPE_CHECKING, Annotated, ClassVar, Literal, cast, get_args
+from typing import TYPE_CHECKING, Annotated, ClassVar, Literal, cast
import attrs
import msgspec
@@ -42,7 +42,7 @@ from airflow.dag_processing.processor import (
BaseDagFileProcessorProcess,
DagFileParseRequest,
DagFileParsingResult,
- ToManager,
+ ToManagerMessage,
)
from airflow.exceptions import DeserializationError
from airflow.models.pool import Pool
@@ -101,6 +101,9 @@ class LangSDKRuntimeSchemaVersion(BaseModel):
type: Literal["LangSDKRuntimeSchemaVersion"] =
"LangSDKRuntimeSchemaVersion"
+LangSDKToManager = Annotated[LangSDKRuntimeSchemaVersion | ToManagerMessage,
Field(discriminator="type")]
+
+
def _get_import_timeout(path: str) -> float | None:
"""Return the ``get_dagbag_import_timeout`` policy's timeout for *path*;
``None`` means none."""
timeout = settings.get_dagbag_import_timeout(path)
@@ -165,9 +168,7 @@ class
LangSDKDagFileProcessorProcess(BaseDagFileProcessorProcess):
``DagFileParseRequest`` itself, so the request is sent once it has
connected.
"""
- decoder = TypeAdapter(
- Annotated[LangSDKRuntimeSchemaVersion | get_args(ToManager)[0],
Field(discriminator="type")]
- )
+ decoder: ClassVar[TypeAdapter[LangSDKToManager]] =
TypeAdapter[LangSDKToManager](LangSDKToManager)
_listeners: dict[_Channel, socket]
_parse_request: DagFileParseRequest
diff --git a/airflow-core/src/airflow/dag_processing/processor.py
b/airflow-core/src/airflow/dag_processing/processor.py
index e6f3f422a0a..9530d7be8c9 100644
--- a/airflow-core/src/airflow/dag_processing/processor.py
+++ b/airflow-core/src/airflow/dag_processing/processor.py
@@ -135,7 +135,7 @@ class DagFileParsingResult(BaseModel):
type: Literal["DagFileParsingResult"] = "DagFileParsingResult"
-ToManager = Annotated[
+ToManagerMessage = (
DagFileParsingResult
| GetConnection
| GetVariable
@@ -151,9 +151,10 @@ ToManager = Annotated[
| GetXComCount
| GetXComSequenceItem
| GetXComSequenceSlice
- | MaskSecret,
- Field(discriminator="type"),
-]
+ | MaskSecret
+)
+
+ToManager = Annotated[ToManagerMessage, Field(discriminator="type")]
ToDagProcessor = Annotated[
DagFileParseRequest
@@ -586,7 +587,6 @@ class BaseDagFileProcessorProcess(WatchedSubprocess,
LoggingMixin):
)
"""The file's parse log, which the process closes. Without one, the output
is discarded."""
parsing_result: DagFileParsingResult | None = None
- decoder: ClassVar[TypeAdapter[ToManager]] =
TypeAdapter[ToManager](ToManager)
had_callbacks: bool = False # Track if this process was started with
callbacks to prevent stale DAG detection false positives
client: Client | None = None
@@ -711,6 +711,7 @@ class DagFileProcessorProcess(BaseDagFileProcessorProcess):
"""
client: Client
+ decoder: ClassVar[TypeAdapter[ToManager]] =
TypeAdapter[ToManager](ToManager)
_request_handlers: ClassVar[dict[type[BaseModel],
RequestHandler[DagFileProcessorProcess]]] = {
**BaseDagFileProcessorProcess._common_request_handlers,