amoghrajesh commented on code in PR #58992: URL: https://github.com/apache/airflow/pull/58992#discussion_r2588343602
########## airflow-core/src/airflow/serialization/stringify.py: ########## @@ -0,0 +1,131 @@ +# +# 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 Any, TypeVar + +T = TypeVar("T", bool, float, int, dict, list, str, tuple, set) + +CLASSNAME = "__classname__" +VERSION = "__version__" +DATA = "__data__" +OLD_TYPE = "__type" +OLD_DATA = "__var" +OLD_DICT = "dict" +DEFAULT_VERSION = 0 + +_primitives = (int, bool, float, str) +_builtin_collections = (frozenset, list, set, tuple) + + +def _convert(old: dict) -> dict: + """Convert an old style serialization to new style.""" + if OLD_TYPE in old and OLD_DATA in old: + # Return old style dicts directly as they do not need wrapping + if old[OLD_TYPE] == OLD_DICT: + return old[OLD_DATA] + return {CLASSNAME: old[OLD_TYPE], VERSION: DEFAULT_VERSION, DATA: old[OLD_DATA]} + + return old + + +def decode(d: dict[str, Any]) -> tuple[str, int, Any]: + """Extract classname, version, and data from a serialized dict.""" + classname = d[CLASSNAME] + version = d[VERSION] + + if not isinstance(classname, str) or not isinstance(version, int): + raise ValueError(f"cannot decode {d!r}") + + data = d.get(DATA) + + return classname, version, data + + +def _stringify_builtin_collection(classname: str, value: Any): + if classname in ("builtins.tuple", "builtins.set", "builtins.frozenset"): + if isinstance(value, (list, tuple, set, frozenset)): + items = [str(stringify(v)) for v in value] + return f"({','.join(items)})" + return None + + +def stringify(o: T | None) -> object: + """ + Convert a serialized object to a human readable representation. + + Matches the behavior of deserialize(full=False) exactly: + - Returns objects as-is for primitives, collections, plain dicts + - Only returns string when encountering a serialized object (__classname__) + """ + if o is None: + return o + + if isinstance(o, _primitives): + return o + + # tuples, sets are included here for backwards compatibility + if isinstance(o, _builtin_collections): + col = [stringify(d) for d in o] + if isinstance(o, tuple): + return tuple(col) + + if isinstance(o, set): + return set(col) + + return col + + if not isinstance(o, dict): + # if o is not a dict, then it's already deserialized + # in this case we should return it as is + return o + + o = _convert(o) + + # plain dict and no type hint + if CLASSNAME not in o or VERSION not in o: + return {str(k): stringify(v) for k, v in o.items()} + + classname, version, value = decode(o) + + if not classname: + raise TypeError("classname cannot be empty") + + # Early detection for `airflow.` classes. These classes will need full deserialization, not just stringification + if isinstance(classname, str) and classname.startswith("airflow."): + raise ValueError( Review Comment: And at that time, if it detects that is is trying to deser a `airflow.sdk` class, it fails this way: ```python airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_xcom.py:221 (TestGetXComEntry.test_stringify_false[nonjsonable]) ../src/airflow/api_fastapi/core_api/routes/public/xcom.py:120: in get_xcom_entry item.value = stringify_xcom(parsed_value) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../src/airflow/serialization/stringify.py:111: in stringify raise ValueError( E ValueError: Cannot stringify Airflow class 'airflow.sdk.definitions.asset.AssetAlias'. Use XComModel.deserialize_value() to deserialize Airflow classes. During handling of the above exception, another exception occurred: ../src/airflow/utils/json.py:64: in __init__ import airflow.sdk.serialization.serde # noqa: F401 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../task-sdk/src/airflow/sdk/serialization/serde.py:409: in <module> _register() ../../task-sdk/src/airflow/sdk/serialization/serde.py:368: in _register for _, module_name, _ in iter_namespace(airflow.sdk.serialization.serializers): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E AttributeError: module 'airflow.sdk.serialization' has no attribute 'serializers' The above exception was the direct cause of the following exception: unit/api_fastapi/core_api/routes/public/test_xcom.py:235: in test_stringify_false response = test_client.get(url, params={"deserialize": True, "stringify": False}) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/starlette/testclient.py:479: in get return super().get( ../../.venv/lib/python3.13/site-packages/httpx/_client.py:1053: in get return self.request( ../../.venv/lib/python3.13/site-packages/starlette/testclient.py:451: in request return super().request( ../../.venv/lib/python3.13/site-packages/httpx/_client.py:825: in request return self.send(request, auth=auth, follow_redirects=follow_redirects) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/httpx/_client.py:914: in send response = self._send_handling_auth( ../../.venv/lib/python3.13/site-packages/httpx/_client.py:942: in _send_handling_auth response = self._send_handling_redirects( ../../.venv/lib/python3.13/site-packages/httpx/_client.py:979: in _send_handling_redirects response = self._send_single_request(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/httpx/_client.py:1014: in _send_single_request response = transport.handle_request(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/starlette/testclient.py:354: in handle_request raise exc ../../.venv/lib/python3.13/site-packages/starlette/testclient.py:351: in handle_request portal.call(self.app, scope, receive, send) ../../.venv/lib/python3.13/site-packages/anyio/from_thread.py:291: in call return cast(T_Retval, self.start_task_soon(func, *args).result()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /opt/homebrew/Cellar/[email protected]/3.13.3_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/concurrent/futures/_base.py:456: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ /opt/homebrew/Cellar/[email protected]/3.13.3_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/concurrent/futures/_base.py:401: in __get_result raise self._exception ../../.venv/lib/python3.13/site-packages/anyio/from_thread.py:222: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/fastapi/applications.py:1134: in __call__ await super().__call__(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/applications.py:113: in __call__ await self.middleware_stack(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/middleware/errors.py:186: in __call__ raise exc ../../.venv/lib/python3.13/site-packages/starlette/middleware/errors.py:164: in __call__ await self.app(scope, receive, _send) ../../.venv/lib/python3.13/site-packages/starlette/middleware/gzip.py:29: in __call__ await responder(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/middleware/gzip.py:130: in __call__ await super().__call__(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/middleware/gzip.py:46: in __call__ await self.app(scope, receive, self.send_with_compression) ../../.venv/lib/python3.13/site-packages/starlette/middleware/cors.py:85: in __call__ await self.app(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:182: in __call__ with recv_stream, send_stream, collapse_excgroups(): ^^^^^^^^^^^^^^^^^^^^ /opt/homebrew/Cellar/[email protected]/3.13.3_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/contextlib.py:162: in __exit__ self.gen.throw(value) ../../.venv/lib/python3.13/site-packages/starlette/_utils.py:85: in collapse_excgroups raise exc ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:184: in __call__ response = await self.dispatch_func(request, call_next) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../src/airflow/api_fastapi/auth/middlewares/refresh_token.py:51: in dispatch response = await call_next(request) ^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:159: in call_next raise app_exc ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:144: in coro await self.app(scope, receive_or_disconnect, send_no_error) ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:182: in __call__ with recv_stream, send_stream, collapse_excgroups(): ^^^^^^^^^^^^^^^^^^^^ /opt/homebrew/Cellar/[email protected]/3.13.3_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/contextlib.py:162: in __exit__ self.gen.throw(value) ../../.venv/lib/python3.13/site-packages/starlette/_utils.py:85: in collapse_excgroups raise exc ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:184: in __call__ response = await self.dispatch_func(request, call_next) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unit/plugins/test_plugin.py:115: in dispatch return await call_next(request) ^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:159: in call_next raise app_exc ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:144: in coro await self.app(scope, receive_or_disconnect, send_no_error) ../../.venv/lib/python3.13/site-packages/starlette/middleware/exceptions.py:63: in __call__ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/_exception_handler.py:53: in wrapped_app raise exc ../../.venv/lib/python3.13/site-packages/starlette/_exception_handler.py:42: in wrapped_app await app(scope, receive, sender) ../../.venv/lib/python3.13/site-packages/fastapi/middleware/asyncexitstack.py:18: in __call__ await self.app(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/routing.py:716: in __call__ await self.middleware_stack(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/routing.py:736: in app await route.handle(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/routing.py:290: in handle await self.app(scope, receive, send) ../../.venv/lib/python3.13/site-packages/fastapi/routing.py:125: in app await wrap_app_handling_exceptions(app, request)(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/_exception_handler.py:53: in wrapped_app raise exc ../../.venv/lib/python3.13/site-packages/starlette/_exception_handler.py:42: in wrapped_app await app(scope, receive, sender) ../../.venv/lib/python3.13/site-packages/fastapi/routing.py:111: in app response = await f(request) ^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/fastapi/routing.py:391: in app raw_response = await run_endpoint_function( ../../.venv/lib/python3.13/site-packages/fastapi/routing.py:292: in run_endpoint_function return await run_in_threadpool(dependant.call, **values) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/starlette/concurrency.py:38: in run_in_threadpool return await anyio.to_thread.run_sync(func) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/anyio/to_thread.py:56: in run_sync return await get_async_backend().run_sync_in_worker_thread( ../../.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py:2476: in run_sync_in_worker_thread return await future ^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py:967: in run result = context.run(func, *args) ^^^^^^^^^^^^^^^^^^^^^^^^ ../src/airflow/api_fastapi/core_api/routes/public/xcom.py:122: in get_xcom_entry item.value = XComModel.deserialize_value(result) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../src/airflow/models/xcom.py:389: in deserialize_value return json.loads(result.value, cls=XComDecoder) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /opt/homebrew/Cellar/[email protected]/3.13.3_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/json/__init__.py:359: in loads return cls(**kw).decode(s) ^^^^^^^^^ ../src/airflow/utils/json.py:66: in __init__ raise ImportError( E ImportError: apache-airflow-task-sdk is required for XCom serialization. Install the package to use XcomDecoder. 2025-12-04T09:59:12.734488Z [info ] Filling up the DagBag from /dev/null [airflow.dag_processing.dagbag.DagBag] 2025-12-04T09:59:12.743171Z [info ] Creating ORM DAG for test-dag-id [airflow.dag_processing.collection] 2025-12-04T09:59:12.742168Z [info ] Sync 1 DAGs [airflow.serialization.serialized_objects] 2025-12-04T09:59:12.751668Z [info ] Sync 1 DAGs [airflow.serialization.serialized_objects] 2025-12-04T09:59:12.787515Z [info ] Some Airflow 2 plugins have been detected in your environment. Currently FAB provider does not support Python 3.13, so you cannot use Airflow 2 plugins with Airflow 3 until FAB provider will be Python 3.13 compatible. [airflow.api_fastapi.core_api.app] FAILED [100%] airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_xcom.py:221 (TestGetXComEntry.test_stringify_false[nested]) ../src/airflow/api_fastapi/core_api/routes/public/xcom.py:120: in get_xcom_entry item.value = stringify_xcom(parsed_value) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../src/airflow/serialization/stringify.py:84: in stringify col = [stringify(d) for d in o] ^^^^^^^^^^^^ ../src/airflow/serialization/stringify.py:111: in stringify raise ValueError( E ValueError: Cannot stringify Airflow class 'airflow.sdk.definitions.asset.AssetAlias'. Use XComModel.deserialize_value() to deserialize Airflow classes. During handling of the above exception, another exception occurred: ../src/airflow/utils/json.py:64: in __init__ import airflow.sdk.serialization.serde # noqa: F401 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../task-sdk/src/airflow/sdk/serialization/serde.py:409: in <module> _register() ../../task-sdk/src/airflow/sdk/serialization/serde.py:368: in _register for _, module_name, _ in iter_namespace(airflow.sdk.serialization.serializers): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E AttributeError: module 'airflow.sdk.serialization' has no attribute 'serializers' The above exception was the direct cause of the following exception: unit/api_fastapi/core_api/routes/public/test_xcom.py:235: in test_stringify_false response = test_client.get(url, params={"deserialize": True, "stringify": False}) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/starlette/testclient.py:479: in get return super().get( ../../.venv/lib/python3.13/site-packages/httpx/_client.py:1053: in get return self.request( ../../.venv/lib/python3.13/site-packages/starlette/testclient.py:451: in request return super().request( ../../.venv/lib/python3.13/site-packages/httpx/_client.py:825: in request return self.send(request, auth=auth, follow_redirects=follow_redirects) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/httpx/_client.py:914: in send response = self._send_handling_auth( ../../.venv/lib/python3.13/site-packages/httpx/_client.py:942: in _send_handling_auth response = self._send_handling_redirects( ../../.venv/lib/python3.13/site-packages/httpx/_client.py:979: in _send_handling_redirects response = self._send_single_request(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/httpx/_client.py:1014: in _send_single_request response = transport.handle_request(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/starlette/testclient.py:354: in handle_request raise exc ../../.venv/lib/python3.13/site-packages/starlette/testclient.py:351: in handle_request portal.call(self.app, scope, receive, send) ../../.venv/lib/python3.13/site-packages/anyio/from_thread.py:291: in call return cast(T_Retval, self.start_task_soon(func, *args).result()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /opt/homebrew/Cellar/[email protected]/3.13.3_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/concurrent/futures/_base.py:456: in result return self.__get_result() ^^^^^^^^^^^^^^^^^^^ /opt/homebrew/Cellar/[email protected]/3.13.3_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/concurrent/futures/_base.py:401: in __get_result raise self._exception ../../.venv/lib/python3.13/site-packages/anyio/from_thread.py:222: in _call_func retval = await retval_or_awaitable ^^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/fastapi/applications.py:1134: in __call__ await super().__call__(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/applications.py:113: in __call__ await self.middleware_stack(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/middleware/errors.py:186: in __call__ raise exc ../../.venv/lib/python3.13/site-packages/starlette/middleware/errors.py:164: in __call__ await self.app(scope, receive, _send) ../../.venv/lib/python3.13/site-packages/starlette/middleware/gzip.py:29: in __call__ await responder(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/middleware/gzip.py:130: in __call__ await super().__call__(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/middleware/gzip.py:46: in __call__ await self.app(scope, receive, self.send_with_compression) ../../.venv/lib/python3.13/site-packages/starlette/middleware/cors.py:85: in __call__ await self.app(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:182: in __call__ with recv_stream, send_stream, collapse_excgroups(): ^^^^^^^^^^^^^^^^^^^^ /opt/homebrew/Cellar/[email protected]/3.13.3_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/contextlib.py:162: in __exit__ self.gen.throw(value) ../../.venv/lib/python3.13/site-packages/starlette/_utils.py:85: in collapse_excgroups raise exc ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:184: in __call__ response = await self.dispatch_func(request, call_next) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../src/airflow/api_fastapi/auth/middlewares/refresh_token.py:51: in dispatch response = await call_next(request) ^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:159: in call_next raise app_exc ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:144: in coro await self.app(scope, receive_or_disconnect, send_no_error) ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:182: in __call__ with recv_stream, send_stream, collapse_excgroups(): ^^^^^^^^^^^^^^^^^^^^ /opt/homebrew/Cellar/[email protected]/3.13.3_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/contextlib.py:162: in __exit__ self.gen.throw(value) ../../.venv/lib/python3.13/site-packages/starlette/_utils.py:85: in collapse_excgroups raise exc ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:184: in __call__ response = await self.dispatch_func(request, call_next) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unit/plugins/test_plugin.py:115: in dispatch return await call_next(request) ^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:159: in call_next raise app_exc ../../.venv/lib/python3.13/site-packages/starlette/middleware/base.py:144: in coro await self.app(scope, receive_or_disconnect, send_no_error) ../../.venv/lib/python3.13/site-packages/starlette/middleware/exceptions.py:63: in __call__ await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/_exception_handler.py:53: in wrapped_app raise exc ../../.venv/lib/python3.13/site-packages/starlette/_exception_handler.py:42: in wrapped_app await app(scope, receive, sender) ../../.venv/lib/python3.13/site-packages/fastapi/middleware/asyncexitstack.py:18: in __call__ await self.app(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/routing.py:716: in __call__ await self.middleware_stack(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/routing.py:736: in app await route.handle(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/routing.py:290: in handle await self.app(scope, receive, send) ../../.venv/lib/python3.13/site-packages/fastapi/routing.py:125: in app await wrap_app_handling_exceptions(app, request)(scope, receive, send) ../../.venv/lib/python3.13/site-packages/starlette/_exception_handler.py:53: in wrapped_app raise exc ../../.venv/lib/python3.13/site-packages/starlette/_exception_handler.py:42: in wrapped_app await app(scope, receive, sender) ../../.venv/lib/python3.13/site-packages/fastapi/routing.py:111: in app response = await f(request) ^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/fastapi/routing.py:391: in app raw_response = await run_endpoint_function( ../../.venv/lib/python3.13/site-packages/fastapi/routing.py:292: in run_endpoint_function return await run_in_threadpool(dependant.call, **values) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/starlette/concurrency.py:38: in run_in_threadpool return await anyio.to_thread.run_sync(func) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/anyio/to_thread.py:56: in run_sync return await get_async_backend().run_sync_in_worker_thread( ../../.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py:2476: in run_sync_in_worker_thread return await future ^^^^^^^^^^^^ ../../.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py:967: in run result = context.run(func, *args) ^^^^^^^^^^^^^^^^^^^^^^^^ ../src/airflow/api_fastapi/core_api/routes/public/xcom.py:122: in get_xcom_entry item.value = XComModel.deserialize_value(result) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../src/airflow/models/xcom.py:389: in deserialize_value return json.loads(result.value, cls=XComDecoder) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /opt/homebrew/Cellar/[email protected]/3.13.3_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/json/__init__.py:359: in loads return cls(**kw).decode(s) ^^^^^^^^^ ../src/airflow/utils/json.py:66: in __init__ raise ImportError( E ImportError: apache-airflow-task-sdk is required for XCom serialization. Install the package to use XcomDecoder. ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
