diff --git a/airflow/serialization/serde.py b/airflow/serialization/serde.py index 16621f9d947cd..924e9fa71977d 100644 --- a/airflow/serialization/serde.py +++ b/airflow/serialization/serde.py @@ -47,6 +47,7 @@ OLD_TYPE = "__type" OLD_SOURCE = "__source" OLD_DATA = "__var" +OLD_DICT = "dict" DEFAULT_VERSION = 0 @@ -276,7 +277,11 @@ def deserialize(o: T | None, full=True, type_hint: Any = None) -> object: def _convert(old: dict) -> dict: """Converts an old style serialization to new style.""" if OLD_TYPE in old and OLD_DATA in old: - return {CLASSNAME: old[OLD_TYPE], VERSION: DEFAULT_VERSION, DATA: old[OLD_DATA][OLD_DATA]} + # Return old style dicts directly as they do not need wrapping + if old[OLD_TYPE] == OLD_DICT: + return old[OLD_DATA] + else: + return {CLASSNAME: old[OLD_TYPE], VERSION: DEFAULT_VERSION, DATA: old[OLD_DATA]} return old diff --git a/tests/serialization/test_serde.py b/tests/serialization/test_serde.py index 1b2a426ac1717..23b4a2ea03055 100644 --- a/tests/serialization/test_serde.py +++ b/tests/serialization/test_serde.py @@ -257,6 +257,9 @@ def test_raise_undeserializable(self): deserialize(data) def test_backwards_compat(self): + """ + Verify deserialization of old-style encoded Xcom values including nested ones + """ uri = "s3://does_not_exist" data = { "__type": "airflow.datasets.Dataset", @@ -264,14 +267,28 @@ def test_backwards_compat(self): "__var": { "__var": { "uri": uri, - "extra": None, + "extra": { + "__var": {"hi": "bye"}, + "__type": "dict", + }, }, "__type": "dict", }, } dataset = deserialize(data) + assert dataset.extra == {"hi": "bye"} assert dataset.uri == uri + def test_backwards_compat_wrapped(self): + """ + Verify deserialization of old-style wrapped XCom value + """ + i = { + "extra": {"__var": {"hi": "bye"}, "__type": "dict"}, + } + e = deserialize(i) + assert e["extra"] == {"hi": "bye"} + def test_encode_dataset(self): dataset = Dataset("mytest://dataset") obj = deserialize(serialize(dataset))