Skip to content

Skip reusing wrap validators / serializers for prebuilt variants #1660

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

Merged
merged 4 commits into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/common/prebuilt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub fn get_prebuilt<T>(
type_: &str,
schema: &Bound<'_, PyDict>,
prebuilt_attr_name: &str,
extractor: impl FnOnce(Bound<'_, PyAny>) -> PyResult<T>,
extractor: impl FnOnce(Bound<'_, PyAny>) -> PyResult<Option<T>>,
) -> PyResult<Option<T>> {
let py = schema.py();

Expand Down Expand Up @@ -40,5 +40,5 @@ pub fn get_prebuilt<T>(

// Retrieve the prebuilt validator / serializer if available
let prebuilt: Bound<'_, PyAny> = class_dict.get_item(prebuilt_attr_name)?;
extractor(prebuilt).map(Some)
extractor(prebuilt)
}
8 changes: 5 additions & 3 deletions src/serializers/prebuilt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ pub struct PrebuiltSerializer {
impl PrebuiltSerializer {
pub fn try_get_from_schema(type_: &str, schema: &Bound<'_, PyDict>) -> PyResult<Option<CombinedSerializer>> {
get_prebuilt(type_, schema, "__pydantic_serializer__", |py_any| {
py_any
.extract::<Py<SchemaSerializer>>()
.map(|schema_serializer| Self { schema_serializer }.into())
let schema_serializer = py_any.extract::<Py<SchemaSerializer>>()?;
if matches!(schema_serializer.get().serializer, CombinedSerializer::FunctionWrap(_)) {
return Ok(None);
}
Comment on lines +21 to +23
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather we check against disallowed variants here rather than all allowed variants - it keeps things cleaner.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we go further and check that schema's type matches the type of the serializer?

e.g. maybe

match &schema_serializer.get().serializer {
    CombinedSerializer::Model(_) => // check schema[type] is model
    ... same for other expected types
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, because I think it would be acceptable to have a PlainSerialier, for example for a model?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we perhaps write a test to demonstrate that case? (We can use the repr to show that a prebuilt serializer is used.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely, happy to!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done via 6efdfc9

Ok(Some(Self { schema_serializer }.into()))
})
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/validators/prebuilt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ pub struct PrebuiltValidator {
impl PrebuiltValidator {
pub fn try_get_from_schema(type_: &str, schema: &Bound<'_, PyDict>) -> PyResult<Option<CombinedValidator>> {
get_prebuilt(type_, schema, "__pydantic_validator__", |py_any| {
py_any
.extract::<Py<SchemaValidator>>()
.map(|schema_validator| Self { schema_validator }.into())
let schema_validator = py_any.extract::<Py<SchemaValidator>>()?;
if matches!(schema_validator.get().validator, CombinedValidator::FunctionWrap(_)) {
return Ok(None);
}
Ok(Some(Self { schema_validator }.into()))
})
}
}
Expand Down
Loading