Skip to content

Commit 17037e6

Browse files
potiukkaxil
andauthored
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]>
1 parent 98eb4fb commit 17037e6

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

airflow-core/src/airflow/serialization/serialized_objects.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -925,8 +925,13 @@ def deserialize(cls, encoded_var: Any) -> Any:
925925
elif type_ == DAT.DATETIME:
926926
return from_timestamp(var)
927927
elif type_ == DAT.POD:
928-
if not _has_kubernetes():
929-
raise RuntimeError("Cannot deserialize POD objects without kubernetes libraries installed!")
928+
# Attempt to import kubernetes for deserialization. Using attempt_import=True allows
929+
# lazy loading of kubernetes libraries only when actually needed for POD deserialization.
930+
if not _has_kubernetes(attempt_import=True):
931+
raise RuntimeError(
932+
"Cannot deserialize POD objects without kubernetes libraries. "
933+
"Please install the cncf.kubernetes provider."
934+
)
930935
pod = PodGenerator.deserialize_model_dict(var)
931936
return pod
932937
elif type_ == DAT.TIMEDELTA:
@@ -3799,13 +3804,20 @@ class SerializedAssetWatcher(AssetWatcher):
37993804
trigger: dict
38003805

38013806

3802-
def _has_kubernetes() -> bool:
3807+
def _has_kubernetes(attempt_import: bool = False) -> bool:
3808+
"""
3809+
Check if kubernetes libraries are available.
3810+
3811+
:param attempt_import: If true, attempt to import kubernetes libraries if not already loaded. If
3812+
False, only check if already in sys.modules (avoids expensive import).
3813+
:return: True if kubernetes libraries are available, False otherwise.
3814+
"""
38033815
global HAS_KUBERNETES
38043816
if "HAS_KUBERNETES" in globals():
38053817
return HAS_KUBERNETES
38063818

38073819
# Check if kubernetes is already imported before triggering expensive import
3808-
if "kubernetes.client" not in sys.modules:
3820+
if "kubernetes.client" not in sys.modules and not attempt_import:
38093821
HAS_KUBERNETES = False
38103822
return False
38113823

airflow-core/tests/unit/serialization/test_dag_serialization.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2531,7 +2531,7 @@ def execute_complete(self):
25312531

25322532

25332533
def test_kubernetes_optional():
2534-
"""Serialisation / deserialisation continues to work without kubernetes installed"""
2534+
"""Test that serialization module loads without kubernetes, but deserialization of PODs requires it"""
25352535

25362536
def mock__import__(name, globals_=None, locals_=None, fromlist=(), level=0):
25372537
if level == 0 and name.partition(".")[0] == "kubernetes":
@@ -2558,7 +2558,8 @@ def mock__import__(name, globals_=None, locals_=None, fromlist=(), level=0):
25582558
"__var": PodGenerator.serialize_pod(executor_config_pod),
25592559
}
25602560

2561-
with pytest.raises(RuntimeError):
2561+
# we should error if attempting to deserialize POD without kubernetes installed
2562+
with pytest.raises(RuntimeError, match="Cannot deserialize POD objects without kubernetes"):
25622563
module.BaseSerialization.from_dict(pod_override)
25632564

25642565
# basic serialization should succeed

0 commit comments

Comments
 (0)