Skip to content

Commit 78f18b3

Browse files
committed
restructuring recs from david
1 parent a8a7c5e commit 78f18b3

File tree

4 files changed

+34
-41
lines changed

4 files changed

+34
-41
lines changed

src/serializers/prebuilt.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,33 @@
11
use std::borrow::Cow;
22

3-
use pyo3::exceptions::PyValueError;
43
use pyo3::intern;
54
use pyo3::prelude::*;
65
use pyo3::types::{PyDict, PyType};
76

8-
use crate::definitions::DefinitionsBuilder;
97
use crate::tools::SchemaDict;
108
use crate::SchemaSerializer;
119

1210
use super::extra::Extra;
13-
use super::shared::{BuildSerializer, CombinedSerializer, TypeSerializer};
11+
use super::shared::{CombinedSerializer, TypeSerializer};
1412

1513
#[derive(Debug)]
1614
pub struct PrebuiltSerializer {
1715
serializer: Py<SchemaSerializer>,
1816
}
1917

20-
impl BuildSerializer for PrebuiltSerializer {
21-
const EXPECTED_TYPE: &'static str = "prebuilt";
22-
23-
fn build(
24-
schema: &Bound<'_, PyDict>,
25-
_config: Option<&Bound<'_, PyDict>>,
26-
_definitions: &mut DefinitionsBuilder<CombinedSerializer>,
27-
) -> PyResult<CombinedSerializer> {
18+
impl PrebuiltSerializer {
19+
pub fn try_get_from_schema(type_: &str, schema: &Bound<'_, PyDict>) -> PyResult<Option<CombinedSerializer>> {
2820
let py = schema.py();
21+
22+
// we can only use prebuilt serializeres from models, typed dicts, and dataclasses
23+
// however, we don't want to use a prebuilt serializer for dataclasses if we have a generic_origin
24+
// because __pydantic_serializer__ is cached on the unparametrized dataclass
25+
if !matches!(type_, "model" | "typed-dict")
26+
|| matches!(type_, "dataclass") && schema.contains(intern!(py, "generic_origin"))?
27+
{
28+
return Ok(None);
29+
}
30+
2931
let class: Bound<'_, PyType> = schema.get_as_req(intern!(py, "cls"))?;
3032

3133
// Note: we NEED to use the __dict__ here (and perform get_item calls rather than getattr)
@@ -39,14 +41,14 @@ impl BuildSerializer for PrebuiltSerializer {
3941
.is_ok_and(|b| b.extract().unwrap_or(false));
4042

4143
if !is_complete {
42-
return Err(PyValueError::new_err("Prebuilt serializer not found."));
44+
return Ok(None);
4345
}
4446

4547
// Retrieve the prebuilt validator if available
4648
let prebuilt_serializer: Bound<'_, PyAny> = class_dict.get_item(intern!(py, "__pydantic_serializer__"))?;
4749
let serializer: Py<SchemaSerializer> = prebuilt_serializer.extract()?;
4850

49-
Ok(Self { serializer }.into())
51+
Ok(Some(Self { serializer }.into()))
5052
}
5153
}
5254

src/serializers/shared.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -200,14 +200,8 @@ impl CombinedSerializer {
200200
let type_ = type_.to_str()?;
201201

202202
// if we have a SchemaValidator on the type already, use it
203-
// however, we don't want to use a prebuilt validator for dataclasses if we have a generic_origin
204-
// because __pydantic_serializer__ is cached on the unparametrized dataclass
205-
if matches!(type_, "model" | "typed-dict")
206-
|| matches!(type_, "dataclass") && !schema.contains(intern!(py, "generic_origin"))?
207-
{
208-
if let Ok(prebuilt_serializer) = super::prebuilt::PrebuiltSerializer::build(schema, config, definitions) {
209-
return Ok(prebuilt_serializer);
210-
}
203+
if let Ok(Some(prebuilt_serializer)) = super::prebuilt::PrebuiltSerializer::try_get_from_schema(type_, schema) {
204+
return Ok(prebuilt_serializer);
211205
}
212206

213207
Self::find_serializer(type_, schema, config, definitions)

src/validators/mod.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -521,14 +521,8 @@ pub fn build_validator(
521521
let type_ = type_.to_str()?;
522522

523523
// if we have a SchemaValidator on the type already, use it
524-
// however, we don't want to use a prebuilt validator for dataclasses if we have a generic_origin
525-
// because __pydantic_validator__ is cached on the unparametrized dataclass
526-
if matches!(type_, "model" | "typed-dict")
527-
|| matches!(type_, "dataclass") && !dict.contains(intern!(py, "generic_origin"))?
528-
{
529-
if let Ok(prebuilt_validator) = prebuilt::PrebuiltValidator::build(dict, config, definitions) {
530-
return Ok(prebuilt_validator);
531-
}
524+
if let Ok(Some(prebuilt_validator)) = prebuilt::PrebuiltValidator::try_get_from_schema(type_, dict) {
525+
return Ok(prebuilt_validator);
532526
}
533527

534528
validator_match!(

src/validators/prebuilt.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use pyo3::exceptions::PyValueError;
21
use pyo3::intern;
32
use pyo3::prelude::*;
43
use pyo3::types::{PyDict, PyType};
@@ -8,22 +7,26 @@ use crate::input::Input;
87
use crate::tools::SchemaDict;
98

109
use super::ValidationState;
11-
use super::{BuildValidator, CombinedValidator, DefinitionsBuilder, SchemaValidator, Validator};
10+
use super::{CombinedValidator, SchemaValidator, Validator};
1211

1312
#[derive(Debug)]
1413
pub struct PrebuiltValidator {
1514
schema_validator: Py<SchemaValidator>,
1615
}
1716

18-
impl BuildValidator for PrebuiltValidator {
19-
const EXPECTED_TYPE: &'static str = "prebuilt";
20-
21-
fn build(
22-
schema: &Bound<'_, PyDict>,
23-
_config: Option<&Bound<'_, PyDict>>,
24-
_definitions: &mut DefinitionsBuilder<CombinedValidator>,
25-
) -> PyResult<CombinedValidator> {
17+
impl PrebuiltValidator {
18+
pub fn try_get_from_schema(type_: &str, schema: &Bound<'_, PyDict>) -> PyResult<Option<CombinedValidator>> {
2619
let py = schema.py();
20+
21+
// we can only use prebuilt validators from models, typed dicts, and dataclasses
22+
// however, we don't want to use a prebuilt validator for dataclasses if we have a generic_origin
23+
// because __pydantic_validator__ is cached on the unparametrized dataclass
24+
if !matches!(type_, "model" | "typed-dict")
25+
|| matches!(type_, "dataclass") && schema.contains(intern!(py, "generic_origin"))?
26+
{
27+
return Ok(None);
28+
}
29+
2730
let class: Bound<'_, PyType> = schema.get_as_req(intern!(py, "cls"))?;
2831

2932
// Note: we NEED to use the __dict__ here (and perform get_item calls rather than getattr)
@@ -37,14 +40,14 @@ impl BuildValidator for PrebuiltValidator {
3740
.is_ok_and(|b| b.extract().unwrap_or(false));
3841

3942
if !is_complete {
40-
return Err(PyValueError::new_err("Prebuilt validator not found."));
43+
return Ok(None);
4144
}
4245

4346
// Retrieve the prebuilt validator if available
4447
let prebuilt_validator = class_dict.get_item(intern!(py, "__pydantic_validator__"))?;
4548
let schema_validator = prebuilt_validator.extract::<Py<SchemaValidator>>()?;
4649

47-
Ok(Self { schema_validator }.into())
50+
Ok(Some(Self { schema_validator }.into()))
4851
}
4952
}
5053

0 commit comments

Comments
 (0)