-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add warning and direct to Pydantic converter sample if Pydantic models are detected #249
Conversation
temporalio/converter.py
Outdated
@@ -474,12 +474,21 @@ def encoding(self) -> str: | |||
|
|||
def to_payload(self, value: Any) -> Optional[temporalio.api.common.v1.Payload]: | |||
"""See base class.""" | |||
# Check for json callable, and invoke it | |||
# This covers Pydantic models. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My primary concern is we guarantee all of our serializable things work with lists, dictionaries, etc. What if I had a list of Pydantic models? The better way is to have full Pydantic JSON support through a custom converter which I need to write at temporalio/samples-python#25. That would use pydantic.json.pydantic_encoder
as mentioned at https://docs.pydantic.dev/usage/dataclasses/#json-dumping which would solve all issues. This is only solving some.
I wrote this class knowing it might be given a different encoder when instantiated. I will try to get to that sample soon. We may consider dropping/deprecating the limited Pydantic support we have in favor of a custom converter once I have that sample written.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought its quite odd to send a List[PydanticModels] since Temporal recommend sending a single struct as params.. But its arguably correct too since its still a single struct.
I think having limited support is fine, if ppl want to use List[PydanticModels] then they can go for the custom converter? Otherwise the current support is enough to convert most of the use cases?
Writing it like this wont have any problem though, like in the test.
class MyPydanticDTClassList(pydantic.BaseModel): foo_list: List[MyPydanticDTClass]
Since am sending my payload from GO, if i use a custom converter, i need to create one for GO too to send the correct encoding type right? I think thats alot of effort, if we want to make cross language calling easier.
Anyway do you want me to drop this PR, since custom pydantic converter is probably the correct and best solution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think having limited support is fine, if ppl want to use List[PydanticModels] then they can go for the custom converter? Otherwise the current support is enough to convert most of the use cases?
Why not always go for custom converter if it's a short bit of code? Then you get guaranteed Pydantic support in all cases and you don't have to think about it. I will write it soon and if it seems easy enough to incorporate for users, will suggest that and deprecate/warn against built-in Pydantic use which is known to be hacky.
Otherwise, I'd just suggest putting this json()
dump into the recursive value dumper and parse it right back out to a dictionary, but that has perf concerns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure I will do the latter first, if performance is a concern. I will try the custom converter out to see if i can get it right.
temporalio/converter.py
Outdated
@@ -474,12 +474,21 @@ def encoding(self) -> str: | |||
|
|||
def to_payload(self, value: Any) -> Optional[temporalio.api.common.v1.Payload]: | |||
"""See base class.""" | |||
# Check for json callable, and invoke it | |||
# This covers Pydantic models. | |||
parse_obj_attr = inspect.getattr_static(value, "json", None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parse_obj_attr = inspect.getattr_static(value, "json", None) | |
json_method = getattr(value, "json", None) |
And just use that method if present. We need to make sure we work with proxied pydantic models which can happen in a sandbox so we need to not bypass __getattribute__
.
temporalio/converter.py
Outdated
json_data = json_method( | ||
cls=self._encoder, separators=(",", ":"), sort_keys=True | ||
).encode() | ||
elif isinstance(value, list): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we for loop for pydantic obj here.
I created this as a custom converter and uses GO custom converter to send encoding
If we add it to the source code, we can have a flag to use pydantic json converter instead ?
|
I think we want it in the sample. I don't want to add a dependency on Pydantic. As for your implementation, I'd do it a bit differently (I was gonna write this sample maybe as soon as today/tomorrow). Specifically:
If you'd like, you can wait just a bit until I write it |
Sure, i can help to add the warnings. I will wait for ur sample converter and learn from it. :) |
I have opened temporalio/samples-python#44. The converter code is quite small. |
Updated to show warning for only the function we are overwriting in the sample custom converter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry it took so long to get back to this
What was changed
Add warning and direct to Pydantic converter sample if Pydantic models are detected
Why?
In order to support those, custom converter is needed. It will be better if we warn and redirect the users.
Checklist
Closes
should close Pydantic models with nested non-JSON-friendly field types cannot be serialized #143 in term of warning user to use custom converter
How was this tested:
Please refer to pytest
Any docs updates needed?
Lets add an example if the idea is accepted.
Please let me know if any changes are needed, feel free to edit as well.