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

amoghdesai 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 ee5e21bb8a2 Support uuid ser/deser in serde (#59783)
ee5e21bb8a2 is described below

commit ee5e21bb8a286addf4571b45e19d8d30cb24f8dc
Author: Amogh Desai <[email protected]>
AuthorDate: Wed Dec 24 19:54:41 2025 +0530

    Support uuid ser/deser in serde (#59783)
---
 task-sdk/src/airflow/sdk/serde/serializers/uuid.py | 50 ++++++++++++++++++++++
 task-sdk/tests/task_sdk/serde/test_serializers.py  | 14 ++++++
 2 files changed, 64 insertions(+)

diff --git a/task-sdk/src/airflow/sdk/serde/serializers/uuid.py 
b/task-sdk/src/airflow/sdk/serde/serializers/uuid.py
new file mode 100644
index 00000000000..b1cdd4e5581
--- /dev/null
+++ b/task-sdk/src/airflow/sdk/serde/serializers/uuid.py
@@ -0,0 +1,50 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING
+
+from airflow.sdk.module_loading import qualname
+
+if TYPE_CHECKING:
+    import uuid
+
+    from airflow.sdk.serde import U
+
+__version__ = 1
+
+serializers = ["uuid.UUID"]
+deserializers = serializers
+
+
+def serialize(o: object) -> tuple[U, str, int, bool]:
+    """Serialize a UUID object to a string representation."""
+    import uuid
+
+    if isinstance(o, uuid.UUID):
+        return str(o), qualname(o), __version__, True
+    return "", "", 0, False
+
+
+def deserialize(cls: type, version: int, data: str) -> uuid.UUID:
+    """Deserialize a string back to a UUID object."""
+    import uuid
+
+    if cls is uuid.UUID and isinstance(data, str):
+        return uuid.UUID(data)
+    raise TypeError(f"cannot deserialize {qualname(cls)} from {type(data)}")
diff --git a/task-sdk/tests/task_sdk/serde/test_serializers.py 
b/task-sdk/tests/task_sdk/serde/test_serializers.py
index 58a9e701866..f8a57caa50f 100644
--- a/task-sdk/tests/task_sdk/serde/test_serializers.py
+++ b/task-sdk/tests/task_sdk/serde/test_serializers.py
@@ -18,6 +18,7 @@ from __future__ import annotations
 
 import datetime
 import decimal
+import uuid
 from importlib import metadata
 from typing import ClassVar
 from unittest.mock import patch
@@ -661,3 +662,16 @@ class TestSerializers:
         bad = {CLASSNAME: "", VERSION: 1, DATA: {}}
         with pytest.raises(TypeError, match="classname cannot be empty"):
             deserialize(bad)
+
+    @pytest.mark.parametrize(
+        "uuid_value",
+        [
+            pytest.param(uuid.uuid4(), id="uuid4"),
+            pytest.param(uuid.uuid1(), id="uuid1"),
+        ],
+    )
+    def test_uuid_roundtrip(self, uuid_value):
+        serialized = serialize(uuid_value)
+        deserialized = deserialize(serialized)
+        assert isinstance(deserialized, uuid.UUID)
+        assert uuid_value == deserialized

Reply via email to