This is an automated email from the ASF dual-hosted git repository.

kaxilnaik pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git

commit 7d2b1bdc34bdc752af4e74135a164b730868b859
Author: Jarek Potiuk <[email protected]>
AuthorDate: Thu Oct 16 21:14:38 2025 +0200

    Lazy import PodGenerator for deserialization  (#56733)
    
    The #56692 introduced optimization for PodGenerator imports - but there
    was a problem that when deserializing Pod it failed when no k8s classes
    were loaded - but it really is not optimisation but failure - nothing
    actually prevents us from importing the k8s classes and we actually have
    to do it in case we want to deserialize serialized Pod.  # Please enter
    the commit message for your changes. Lines starting
    
    * fixup! Skip PodGenerator import for deserialization when no k8s installed
    
    * fixup! fixup! Skip PodGenerator import for deserialization when no k8s 
installed
    
    ---------
    
    Co-authored-by: Kaxil Naik <[email protected]>
    (cherry picked from commit 17037e6a2cf7151c361bd611e20e96b68d3f6096)
---
 .../src/airflow/serialization/serialized_objects.py  | 20 ++++++++++++++++----
 .../unit/serialization/test_dag_serialization.py     |  5 +++--
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/airflow-core/src/airflow/serialization/serialized_objects.py 
b/airflow-core/src/airflow/serialization/serialized_objects.py
index 3a075469d4a..aed682f4337 100644
--- a/airflow-core/src/airflow/serialization/serialized_objects.py
+++ b/airflow-core/src/airflow/serialization/serialized_objects.py
@@ -923,8 +923,13 @@ class BaseSerialization:
         elif type_ == DAT.DATETIME:
             return from_timestamp(var)
         elif type_ == DAT.POD:
-            if not _has_kubernetes():
-                raise RuntimeError("Cannot deserialize POD objects without 
kubernetes libraries installed!")
+            # Attempt to import kubernetes for deserialization. Using 
attempt_import=True allows
+            # lazy loading of kubernetes libraries only when actually needed 
for POD deserialization.
+            if not _has_kubernetes(attempt_import=True):
+                raise RuntimeError(
+                    "Cannot deserialize POD objects without kubernetes 
libraries. "
+                    "Please install the cncf.kubernetes provider."
+                )
             pod = PodGenerator.deserialize_model_dict(var)
             return pod
         elif type_ == DAT.TIMEDELTA:
@@ -3809,13 +3814,20 @@ class SerializedAssetWatcher(AssetWatcher):
     trigger: dict
 
 
-def _has_kubernetes() -> bool:
+def _has_kubernetes(attempt_import: bool = False) -> bool:
+    """
+    Check if kubernetes libraries are available.
+
+    :param attempt_import: If true, attempt to import kubernetes libraries if 
not already loaded. If
+        False, only check if already in sys.modules (avoids expensive import).
+    :return: True if kubernetes libraries are available, False otherwise.
+    """
     global HAS_KUBERNETES
     if "HAS_KUBERNETES" in globals():
         return HAS_KUBERNETES
 
     # Check if kubernetes is already imported before triggering expensive 
import
-    if "kubernetes.client" not in sys.modules:
+    if "kubernetes.client" not in sys.modules and not attempt_import:
         HAS_KUBERNETES = False
         return False
 
diff --git a/airflow-core/tests/unit/serialization/test_dag_serialization.py 
b/airflow-core/tests/unit/serialization/test_dag_serialization.py
index 7e2bb6e5a59..80c08b23ee0 100644
--- a/airflow-core/tests/unit/serialization/test_dag_serialization.py
+++ b/airflow-core/tests/unit/serialization/test_dag_serialization.py
@@ -2528,7 +2528,7 @@ class TestStringifiedDAGs:
 
 
 def test_kubernetes_optional():
-    """Serialisation / deserialisation continues to work without kubernetes 
installed"""
+    """Test that serialization module loads without kubernetes, but 
deserialization of PODs requires it"""
 
     def mock__import__(name, globals_=None, locals_=None, fromlist=(), 
level=0):
         if level == 0 and name.partition(".")[0] == "kubernetes":
@@ -2555,7 +2555,8 @@ def test_kubernetes_optional():
             "__var": PodGenerator.serialize_pod(executor_config_pod),
         }
 
-        with pytest.raises(RuntimeError):
+        # we should error if attempting to deserialize POD without kubernetes 
installed
+        with pytest.raises(RuntimeError, match="Cannot deserialize POD objects 
without kubernetes"):
             module.BaseSerialization.from_dict(pod_override)
 
         # basic serialization should succeed

Reply via email to