tomrutter opened a new issue, #38540:
URL: https://github.com/apache/airflow/issues/38540

   ### Apache Airflow version
   
   2.8.4
   
   ### If "Other Airflow 2 version" selected, which one?
   
   _No response_
   
   ### What happened?
   
   I am passing values between tasks using xcom. These values are instances of 
a attrs class that has another attrs class as a member. The serialisation 
currently fails to correctly mark the inner class with the __class__ tags to 
allow it to be deserialized back to the attrs class (it remains as a dict after 
loading into the downstream task).
   
   ### What you think should happen instead?
   
   I think that the nested attrs objects should be returned unchanged after 
deserialization.
   
   ### How to reproduce
   
   The value of `foo` passed to `task2` has the `inner_value` as a `dict` 
rather than a `InnerClass` instance.
   
   ```
   import attrs
   
   @attrs.define(kw_only=True, frozen=True, slots=False)
   class OuterClass:
     inner_value: InnerClass
   
   @attrs.define(kw_only=True, frozen=True, slots=False)
   class InnerClass:
     x: str
   
   
   @task
   def task1():
       return OuterClass(inner_value=InnerClass("test!")
   
   @task
   def task2(foo: OuterClass):
       print(foo)  # foo here is OuterClass(inner_value={"x": "test!"})
   
   @dag
   def my_dag():
       task2(task1())
   
   ```
   
   ### Operating System
   
   linux (standard airflow slim images extended with airflow providers running 
on kubernetes)
   
   ### Versions of Apache Airflow Providers
   
   defaults for 2.8.4
   
   ### Deployment
   
   Official Apache Airflow Helm Chart
   
   ### Deployment details
   
   Airflow deployment on Azure Kubernetes using postgres backend db.
   
   ### Anything else?
   
   I think a simple solution would be to update the following code in 
`airflow.serialization.serde.py` (lines 182 to 187), to change the value of 
`recurse` in the call to `attr.asdict` from `True` to `False`, leaving the 
serialization of inner classes to the subsequent call to `serialize`.
   
   Before:
   ```
       # attr annotated
       if attr.has(cls):
           # Only include attributes which we can pass back to the classes 
constructor
           data = attr.asdict(cast(attr.AttrsInstance, o), recurse=True, 
filter=lambda a, v: a.init)
           dct[DATA] = serialize(data, depth + 1)
           return dct
   ```
   
   After:
   ```
       # attr annotated
       if attr.has(cls):
           # Only include attributes which we can pass back to the classes 
constructor
           data = attr.asdict(cast(attr.AttrsInstance, o), recurse=False, 
filter=lambda a, v: a.init)
           dct[DATA] = serialize(data, depth + 1)
           return dct
   ```
   
   That is 
   
   ### Are you willing to submit PR?
   
   - [X] Yes I am willing to submit a PR!
   
   ### Code of Conduct
   
   - [X] I agree to follow this project's [Code of 
Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)
   


-- 
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]

Reply via email to