Skip to content
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

Rename validation and serialization schema types to be unique #1629

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
40 changes: 20 additions & 20 deletions python/pydantic_core/core_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ def simple_ser_schema(type: ExpectedSerializationTypes) -> SimpleSerSchema:


class PlainSerializerFunctionSerSchema(TypedDict, total=False):
type: Required[Literal['function-plain']]
type: Required[Literal['serializer-function-plain']]
function: Required[SerializerFunction]
is_field_serializer: bool # default False
info_arg: bool # default False
Expand Down Expand Up @@ -292,7 +292,7 @@ def plain_serializer_function_ser_schema(
# just to avoid extra elements in schema, and to use the actual default defined in rust
when_used = None # type: ignore
return _dict_not_none(
type='function-plain',
type='serializer-function-plain',
function=function,
is_field_serializer=is_field_serializer,
info_arg=info_arg,
Expand Down Expand Up @@ -322,7 +322,7 @@ def __call__(self, input_value: Any, index_key: int | str | None = None, /) -> A


class WrapSerializerFunctionSerSchema(TypedDict, total=False):
type: Required[Literal['function-wrap']]
type: Required[Literal['serializer-function-wrap']]
function: Required[WrapSerializerFunction]
is_field_serializer: bool # default False
info_arg: bool # default False
Expand Down Expand Up @@ -356,7 +356,7 @@ def wrap_serializer_function_ser_schema(
# just to avoid extra elements in schema, and to use the actual default defined in rust
when_used = None # type: ignore
return _dict_not_none(
type='function-wrap',
type='serializer-function-wrap',
function=function,
is_field_serializer=is_field_serializer,
info_arg=info_arg,
Expand Down Expand Up @@ -1966,7 +1966,7 @@ class _ValidatorFunctionSchema(TypedDict, total=False):


class BeforeValidatorFunctionSchema(_ValidatorFunctionSchema, total=False):
type: Required[Literal['function-before']]
type: Required[Literal['validator-function-before']]
json_schema_input_schema: CoreSchema


Expand Down Expand Up @@ -2006,7 +2006,7 @@ def fn(v: bytes) -> str:
serialization: Custom serialization schema
"""
return _dict_not_none(
type='function-before',
type='validator-function-before',
function={'type': 'no-info', 'function': function},
schema=schema,
ref=ref,
Expand Down Expand Up @@ -2057,7 +2057,7 @@ def fn(v: bytes, info: core_schema.ValidationInfo) -> str:
serialization: Custom serialization schema
"""
return _dict_not_none(
type='function-before',
type='validator-function-before',
function=_dict_not_none(type='with-info', function=function, field_name=field_name),
schema=schema,
ref=ref,
Expand All @@ -2068,7 +2068,7 @@ def fn(v: bytes, info: core_schema.ValidationInfo) -> str:


class AfterValidatorFunctionSchema(_ValidatorFunctionSchema, total=False):
type: Required[Literal['function-after']]
type: Required[Literal['validator-function-after']]


def no_info_after_validator_function(
Expand Down Expand Up @@ -2105,7 +2105,7 @@ def fn(v: str) -> str:
serialization: Custom serialization schema
"""
return _dict_not_none(
type='function-after',
type='validator-function-after',
function={'type': 'no-info', 'function': function},
schema=schema,
ref=ref,
Expand Down Expand Up @@ -2154,7 +2154,7 @@ def fn(v: str, info: core_schema.ValidationInfo) -> str:
serialization: Custom serialization schema
"""
return _dict_not_none(
type='function-after',
type='validator-function-after',
function=_dict_not_none(type='with-info', function=function, field_name=field_name),
schema=schema,
ref=ref,
Expand Down Expand Up @@ -2191,7 +2191,7 @@ class WithInfoWrapValidatorFunctionSchema(TypedDict, total=False):


class WrapValidatorFunctionSchema(TypedDict, total=False):
type: Required[Literal['function-wrap']]
type: Required[Literal['validator-function-wrap']]
function: Required[WrapValidatorFunction]
schema: Required[CoreSchema]
ref: str
Expand Down Expand Up @@ -2239,7 +2239,7 @@ def fn(
serialization: Custom serialization schema
"""
return _dict_not_none(
type='function-wrap',
type='validator-function-wrap',
function={'type': 'no-info', 'function': function},
schema=schema,
json_schema_input_schema=json_schema_input_schema,
Expand Down Expand Up @@ -2291,7 +2291,7 @@ def fn(
serialization: Custom serialization schema
"""
return _dict_not_none(
type='function-wrap',
type='validator-function-wrap',
function=_dict_not_none(type='with-info', function=function, field_name=field_name),
schema=schema,
json_schema_input_schema=json_schema_input_schema,
Expand All @@ -2302,7 +2302,7 @@ def fn(


class PlainValidatorFunctionSchema(TypedDict, total=False):
type: Required[Literal['function-plain']]
type: Required[Literal['validator-function-plain']]
function: Required[ValidationFunction]
ref: str
json_schema_input_schema: CoreSchema
Expand Down Expand Up @@ -2341,7 +2341,7 @@ def fn(v: str) -> str:
serialization: Custom serialization schema
"""
return _dict_not_none(
type='function-plain',
type='validator-function-plain',
function={'type': 'no-info', 'function': function},
ref=ref,
json_schema_input_schema=json_schema_input_schema,
Expand Down Expand Up @@ -2383,7 +2383,7 @@ def fn(v: str, info: core_schema.ValidationInfo) -> str:
serialization: Custom serialization schema
"""
return _dict_not_none(
type='function-plain',
type='validator-function-plain',
function=_dict_not_none(type='with-info', function=function, field_name=field_name),
ref=ref,
json_schema_input_schema=json_schema_input_schema,
Expand Down Expand Up @@ -3965,10 +3965,10 @@ def definition_reference_schema(
'frozenset',
'generator',
'dict',
'function-after',
'function-before',
'function-wrap',
'function-plain',
'validator-function-after',
'validator-function-before',
'validator-function-wrap',
'validator-function-plain',
'default',
'nullable',
'union',
Expand Down
45 changes: 38 additions & 7 deletions src/serializers/shared.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::borrow::Cow;
use std::ffi::CString;
use std::fmt::Debug;

use pyo3::exceptions::PyTypeError;
Expand Down Expand Up @@ -148,6 +149,29 @@ combined_serializer! {
}
}

fn get_new_type(py: Python, type_: &str) -> PyResult<String> {
Copy link
Contributor

Choose a reason for hiding this comment

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

To avoid allocating:

Suggested change
fn get_new_type(py: Python, type_: &str) -> PyResult<String> {
fn get_new_type<'a>(py: Python, type_: &'a str) -> PyResult<&'a str> {

(and then drop the .to_owned() calls below)

let maybe_new_type = match type_ {
"function-plain" => Some("serializer-function-plain"),
"function-wrap" => Some("serializer-function-wrap"),
_ => None,
};

match maybe_new_type {
Some(new_type) => {
let deprecation_message =
format!("Serialization core schema type '{type_}' is deprecated, use '{new_type}'");
let _ = PyErr::warn(
py,
&py.get_type::<pyo3::exceptions::PyDeprecationWarning>(),
&CString::new(deprecation_message)?,
1,
);
Ok(new_type.to_owned())
}
None => Ok(type_.to_owned()),
}
}

impl CombinedSerializer {
fn _build(
schema: &Bound<'_, PyDict>,
Expand All @@ -159,28 +183,35 @@ impl CombinedSerializer {

if let Some(ser_schema) = schema.get_as::<Bound<'_, PyDict>>(intern!(py, "serialization"))? {
let op_ser_type: Option<Bound<'_, PyString>> = ser_schema.get_as(type_key)?;
match op_ser_type.as_ref().map(|py_str| py_str.to_str()).transpose()? {
Some("function-plain") => {
// `function-plain` is a special case, not included in `find_serializer` since it means
let op_ser_type = op_ser_type.as_ref().map(|py_str| py_str.to_str()).transpose()?;
let new_type = op_ser_type.map(|typ| get_new_type(schema.py(), typ).unwrap());

match new_type.as_deref() {
Some("serializer-function-plain") => {
// `serializer-function-plain` is a special case, not included in `find_serializer` since it means
// something different in `schema.type`
// NOTE! we use the `schema` here, not `ser_schema`
return super::type_serializers::function::FunctionPlainSerializer::build(
schema,
config,
definitions,
)
.map_err(|err| py_schema_error_type!("Error building `function-plain` serializer:\n {}", err));
.map_err(|err| {
py_schema_error_type!("Error building `serializer-function-plain` serializer:\n {}", err)
});
}
Some("function-wrap") => {
// `function-wrap` is also a special case, not included in `find_serializer` since it mean
Some("serializer-function-wrap") => {
// `serializer-function-wrap` is also a special case, not included in `find_serializer` since it mean
// something different in `schema.type`
// NOTE! we use the `schema` here, not `ser_schema`
return super::type_serializers::function::FunctionWrapSerializer::build(
schema,
config,
definitions,
)
.map_err(|err| py_schema_error_type!("Error building `function-wrap` serializer:\n {}", err));
.map_err(|err| {
py_schema_error_type!("Error building `serializer-function-wrap` serializer:\n {}", err)
});
}
// applies to lists tuples and dicts, does not override the main schema `type`
Some("include-exclude-sequence" | "include-exclude-dict") => (),
Expand Down
12 changes: 6 additions & 6 deletions src/serializers/type_serializers/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl BuildSerializer for FunctionAfterSerializerBuilder {
pub struct FunctionPlainSerializerBuilder;

impl BuildSerializer for FunctionPlainSerializerBuilder {
const EXPECTED_TYPE: &'static str = "function-plain";
const EXPECTED_TYPE: &'static str = "serializer-function-plain";
fn build(
schema: &Bound<'_, PyDict>,
config: Option<&Bound<'_, PyDict>>,
Expand Down Expand Up @@ -95,7 +95,7 @@ fn destructure_function_schema<'py>(schema: &Bound<'py, PyDict>) -> PyResult<(bo
}

impl BuildSerializer for FunctionPlainSerializer {
const EXPECTED_TYPE: &'static str = "function-plain";
const EXPECTED_TYPE: &'static str = "serializer-function-plain";

/// NOTE! `schema` here is the actual `CoreSchema`, not `schema.serialization` as in the other builders
/// (done this way to match `FunctionWrapSerializer` which requires the full schema)
Expand Down Expand Up @@ -125,7 +125,7 @@ impl BuildSerializer for FunctionPlainSerializer {
}
};

let name = format!("plain_function[{function_name}]");
let name = format!("serializer-function-plain[{function_name}]");
Ok(Self {
func: function.unbind(),
function_name,
Expand Down Expand Up @@ -310,7 +310,7 @@ fn copy_outer_schema<'py>(schema: &Bound<'py, PyDict>) -> PyResult<Bound<'py, Py
pub struct FunctionWrapSerializerBuilder;

impl BuildSerializer for FunctionWrapSerializerBuilder {
const EXPECTED_TYPE: &'static str = "function-wrap";
const EXPECTED_TYPE: &'static str = "serializer-function-wrap";
fn build(
schema: &Bound<'_, PyDict>,
config: Option<&Bound<'_, PyDict>>,
Expand Down Expand Up @@ -339,7 +339,7 @@ pub struct FunctionWrapSerializer {
}

impl BuildSerializer for FunctionWrapSerializer {
const EXPECTED_TYPE: &'static str = "function-wrap";
const EXPECTED_TYPE: &'static str = "serializer-function-wrap";

/// NOTE! `schema` here is the actual `CoreSchema`, not `schema.serialization` as in the other builders
/// (done this way since we need the `CoreSchema`)
Expand Down Expand Up @@ -368,7 +368,7 @@ impl BuildSerializer for FunctionWrapSerializer {
None => AnySerializer::build(schema, config, definitions)?,
};

let name = format!("wrap_function[{function_name}, {}]", serializer.get_name());
let name = format!("serializer-function-wrap[{function_name}, {}]", serializer.get_name());
Ok(Self {
serializer: Arc::new(serializer),
func: function.into(),
Expand Down
18 changes: 12 additions & 6 deletions src/validators/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ pub struct FunctionBeforeValidator {
info_arg: bool,
}

impl_build!(FunctionBeforeValidator, "function-before");
impl_build!(FunctionBeforeValidator, "validator-function-before");

impl FunctionBeforeValidator {
fn _validate<'s, 'py>(
Expand Down Expand Up @@ -157,7 +157,7 @@ pub struct FunctionAfterValidator {
info_arg: bool,
}

impl_build!(FunctionAfterValidator, "function-after");
impl_build!(FunctionAfterValidator, "validator-function-after");

impl FunctionAfterValidator {
fn _validate<'py, I: Input<'py> + ?Sized>(
Expand Down Expand Up @@ -225,7 +225,7 @@ pub struct FunctionPlainValidator {
}

impl BuildValidator for FunctionPlainValidator {
const EXPECTED_TYPE: &'static str = "function-plain";
const EXPECTED_TYPE: &'static str = "validator-function-plain";

fn build(
schema: &Bound<'_, PyDict>,
Expand All @@ -240,7 +240,10 @@ impl BuildValidator for FunctionPlainValidator {
Some(c) => c.clone().into(),
None => py.None(),
},
name: format!("function-plain[{}()]", function_name(function_info.function.bind(py))?),
name: format!(
"validator-function-plain[{}()]",
function_name(function_info.function.bind(py))?
),
field_name: function_info.field_name.clone(),
info_arg: function_info.info_arg,
}
Expand Down Expand Up @@ -284,7 +287,7 @@ pub struct FunctionWrapValidator {
}

impl BuildValidator for FunctionWrapValidator {
const EXPECTED_TYPE: &'static str = "function-wrap";
const EXPECTED_TYPE: &'static str = "validator-function-wrap";

fn build(
schema: &Bound<'_, PyDict>,
Expand All @@ -303,7 +306,10 @@ impl BuildValidator for FunctionWrapValidator {
Some(c) => c.clone().into(),
None => py.None(),
},
name: format!("function-wrap[{}()]", function_name(function_info.function.bind(py))?),
name: format!(
"validator-function-wrap[{}()]",
function_name(function_info.function.bind(py))?
),
field_name: function_info.field_name.clone(),
info_arg: function_info.info_arg,
hide_input_in_errors,
Expand Down
Loading
Loading