-
Notifications
You must be signed in to change notification settings - Fork 253
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 serialize_as_any
runtime flag support
#1194
Conversation
serialize_as_any
config flag + runtime supportserialize_as_any
config flag + runtime support
CodSpeed Performance ReportMerging #1194 will improve performances by 43.79%Comparing Summary
Benchmarks breakdown
|
|
||
// If there is no model, use duck typing ser logic for TypedDict | ||
// If there is a model, skip this step, as BaseModel and dataclass duck typing | ||
// is handled in their respective serializers | ||
if extra.model.is_none() { | ||
let duck_typing_ser_mode = extra.duck_typing_ser_mode.next_mode(); | ||
let td_extra = Extra { | ||
model, | ||
duck_typing_ser_mode, | ||
..*extra | ||
}; | ||
if td_extra.duck_typing_ser_mode == DuckTypingSerMode::Inferred { | ||
return infer_to_python(value, include, exclude, &td_extra); | ||
} | ||
} |
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'm not super happy with having this logic here, but this seems to be a consequence of not having a separate TypedDictSerializer
. I think we could revisit that in a different PR 👍
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.
What happens if we remove from basemodel and dataclass serializers and we instead always just apply the duck typing here ? e.g. remove the extra.model.is_none() check?
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.
@sydney-runkle I'm also curious about this
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.
@dmontagu I think we found that the model & dataclass serializers have some coupling here where they already transform the input into __dict__
and other subfields. Probably we could restructure both to improve performance and reduce coupling.
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 feel like there's a lot of complexity here which might get a bit messy.
e.g. what about list[int]
- if serialize_as_any
is set, can I pass a list[str]
and expect it to serialize without warnings?
Did you remove that from this PR? Sounds like it's probably orthogonal and might be irrelevant with the recent changes samuel and I made.
? :)
If you mean for the extra, IIRC the |
temp stash temp stash finalizing messy merge
Resolutions from my conversation with @davidhewitt:
|
serialize_as_any
config flag + runtime supportserialize_as_any
config flag + runtime support
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 don't really love DuckTypingSerMode
/duck_typing_ser_mode
given we already have ser_mode
and they are orthogonal. But I can't think of a great alternative so maybe it's fine. I was thinking something like SerSchemaOnly
or similar, but I guess DuckTypingSerMode
is more intuitive.
Otherwise this generally looks good to me, though I think DH had a good question
I see that maybe that was addressed in other discussion with DH. I have reviewed and don't have any objections, I'd feel better if @davidhewitt also approved though. |
So I'm generally happy with what's going on here. I think there are still cases that I'd like to at least ask about. For example, def test_serialize_as_any_list_types() -> None:
serializer = SchemaSerializer(core_schema.list_schema(core_schema.int_schema()))
assert serializer.to_python(['a', 'b', 'c'], serialize_as_any=True) == ['a', 'b', 'c'] The annotated code which I'd argue is equivalent doesn't warn: from pydantic import TypeAdapter, SerializeAsAny
TypeAdapter(SerializeAsAny[list[int]]).dump_python(["a", "b", "c"]) |
I think it makes sense to still warn here in general.
Hmm, well in this case, we're actually using an @adriangb at one point suggested:
|
I agree that That said, I'm not entirely sure on the right solution here. I think the point is that I would like to close that gap in the long term. Perfect being the enemy of the good and all that, maybe the approach is to proceed with what we have here, and create a tracking issue with follow ups of where |
I came here to ask the same question @davidhewitt asked about Perhaps we can resolve the confusion by calling this flag / feature Which does mean maybe we should have a |
Which does mean maybe we should have a DuckTypeSerialization[T] annotation. @adriangb I think that this was really well said and carefully thought out. @davidhewitt, are you ok with this change? I think it allows us to sidestep the surprising inconsistencies with |
I can see the purity in this argument but I worry it adds complexity to users by having "duck typed serialization" and "serialize as any" as separate concepts. Especially when the intended use for both of them is to serialize subtypes in full, and neither of them as implemented behave like what I'd expect from "duck typing". I would much prefer we just lived with this being called |
That makes sense, so perhaps we should proceed with this approach?
|
@sydney-runkle do you think we could make the annotation behave more like this? |
I think we would probably have to go the other way, that is, being more lax on the |
Just waiting on #1236 to fix the bug mentioned in the most recent test that I wrote |
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 we're ready to ship this and see how it pans out. Definitely some edge cases yet to discuss but it's a good tool to expose for users 👍
serialize_as_any
config flag + runtime supportserialize_as_any
runtime flag support
Contributing to pydantic/pydantic#6423
TODO:
mut
in model.rs