Skip to content

Commit 6efdfc9

Browse files
committed
add plain validator ok tests
1 parent 2faf807 commit 6efdfc9

File tree

1 file changed

+117
-2
lines changed

1 file changed

+117
-2
lines changed

tests/test_prebuilt.py

Lines changed: 117 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class InnerModel:
5555
def __init__(self, x: str) -> None:
5656
self.x = x
5757

58-
def serialize_inner(v: InnerModel, serializer) -> str:
58+
def serialize_inner(v: InnerModel, serializer) -> dict[str, str] | str:
5959
v.x = v.x + ' modified'
6060
return serializer(v)
6161

@@ -114,7 +114,7 @@ class InnerModel:
114114
def __init__(self, x: str) -> None:
115115
self.x = x
116116

117-
def validate_inner(data, validator) -> str:
117+
def validate_inner(data, validator) -> InnerModel:
118118
data['x'] = data['x'] + ' modified'
119119
return validator(data)
120120

@@ -166,3 +166,118 @@ def __init__(self, inner: InnerModel) -> None:
166166
# but the outer model doesn't reuse the custom wrap validator function, so we see simple str val
167167
result_outer = outer_validator.validate_python({'inner': {'x': 'hello'}})
168168
assert result_outer.inner.x == 'hello'
169+
170+
171+
def test_reuse_plain_serializer_ok() -> None:
172+
class InnerModel:
173+
x: str
174+
175+
def __init__(self, x: str) -> None:
176+
self.x = x
177+
178+
def serialize_inner(v: InnerModel) -> str:
179+
return v.x + ' modified'
180+
181+
inner_schema = core_schema.model_schema(
182+
InnerModel,
183+
schema=core_schema.model_fields_schema(
184+
{'x': core_schema.model_field(schema=core_schema.str_schema())},
185+
),
186+
serialization=core_schema.plain_serializer_function_ser_schema(serialize_inner),
187+
)
188+
189+
inner_schema_serializer = SchemaSerializer(inner_schema)
190+
InnerModel.__pydantic_complete__ = True # pyright: ignore[reportAttributeAccessIssue]
191+
InnerModel.__pydantic_serializer__ = inner_schema_serializer # pyright: ignore[reportAttributeAccessIssue]
192+
193+
class OuterModel:
194+
inner: InnerModel
195+
196+
def __init__(self, inner: InnerModel) -> None:
197+
self.inner = inner
198+
199+
outer_schema = core_schema.model_schema(
200+
OuterModel,
201+
schema=core_schema.model_fields_schema(
202+
{
203+
'inner': core_schema.model_field(
204+
schema=core_schema.model_schema(
205+
InnerModel,
206+
schema=core_schema.model_fields_schema(
207+
# note, we use a simple str schema (with no custom serialization)
208+
# in order to verify that the prebuilt serializer from InnerModel is used instead
209+
{'x': core_schema.model_field(schema=core_schema.str_schema())},
210+
),
211+
)
212+
)
213+
}
214+
),
215+
)
216+
217+
inner_serializer = SchemaSerializer(inner_schema)
218+
outer_serializer = SchemaSerializer(outer_schema)
219+
220+
# the custom serialization function does apply for the inner model
221+
inner_instance = InnerModel(x='hello')
222+
assert inner_serializer.to_python(inner_instance) == 'hello modified'
223+
assert 'FunctionPlainSerializer' in repr(inner_serializer)
224+
225+
# the custom ser function applies for the outer model as well, a plain serializer is permitted as a prebuilt candidate
226+
outer_instance = OuterModel(inner=InnerModel(x='hello'))
227+
assert outer_serializer.to_python(outer_instance) == {'inner': 'hello modified'}
228+
assert 'PrebuiltSerializer' in repr(outer_serializer)
229+
230+
231+
def test_reuse_plain_validator_ok() -> None:
232+
class InnerModel:
233+
x: str
234+
235+
def __init__(self, x: str) -> None:
236+
self.x = x
237+
238+
def validate_inner(data) -> InnerModel:
239+
data['x'] = data['x'] + ' modified'
240+
return InnerModel(**data)
241+
242+
inner_schema = core_schema.no_info_plain_validator_function(validate_inner)
243+
244+
inner_schema_validator = SchemaValidator(inner_schema)
245+
InnerModel.__pydantic_complete__ = True # pyright: ignore[reportAttributeAccessIssue]
246+
InnerModel.__pydantic_validator__ = inner_schema_validator # pyright: ignore[reportAttributeAccessIssue]
247+
248+
class OuterModel:
249+
inner: InnerModel
250+
251+
def __init__(self, inner: InnerModel) -> None:
252+
self.inner = inner
253+
254+
outer_schema = core_schema.model_schema(
255+
OuterModel,
256+
schema=core_schema.model_fields_schema(
257+
{
258+
'inner': core_schema.model_field(
259+
schema=core_schema.model_schema(
260+
InnerModel,
261+
schema=core_schema.model_fields_schema(
262+
# note, we use a simple str schema (with no custom validation)
263+
# in order to verify that the prebuilt validator from InnerModel is used instead
264+
{'x': core_schema.model_field(schema=core_schema.str_schema())},
265+
),
266+
)
267+
)
268+
}
269+
),
270+
)
271+
272+
inner_validator = SchemaValidator(inner_schema)
273+
outer_validator = SchemaValidator(outer_schema)
274+
275+
# the custom validation function does apply for the inner model
276+
result_inner = inner_validator.validate_python({'x': 'hello'})
277+
assert result_inner.x == 'hello modified'
278+
assert 'FunctionPlainValidator' in repr(inner_validator)
279+
280+
# the custom validation function does apply for the outer model as well, a plain validator is permitted as a prebuilt candidate
281+
result_outer = outer_validator.validate_python({'inner': {'x': 'hello'}})
282+
assert result_outer.inner.x == 'hello modified'
283+
assert 'PrebuiltValidator' in repr(outer_validator)

0 commit comments

Comments
 (0)