Skip to content

Commit 58b000e

Browse files
Merge branch 'main' into union-ser-fixes
2 parents bf45409 + 39a6b10 commit 58b000e

33 files changed

+85
-59
lines changed

src/serializers/computed_fields.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::tools::SchemaDict;
1414
use super::errors::py_err_se_err;
1515
use super::Extra;
1616

17-
#[derive(Debug, Clone)]
17+
#[derive(Debug)]
1818
pub(super) struct ComputedFields(Vec<ComputedField>);
1919

2020
impl ComputedFields {
@@ -109,7 +109,7 @@ impl ComputedFields {
109109
}
110110
}
111111

112-
#[derive(Debug, Clone)]
112+
#[derive(Debug)]
113113
struct ComputedField {
114114
property_name: String,
115115
property_name_py: Py<PyString>,

src/serializers/fields.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use super::shared::PydanticSerializer;
2020
use super::shared::{CombinedSerializer, TypeSerializer};
2121

2222
/// representation of a field for serialization
23-
#[derive(Debug, Clone)]
23+
#[derive(Debug)]
2424
pub(super) struct SerField {
2525
pub key_py: Py<PyString>,
2626
pub alias: Option<String>,
@@ -93,7 +93,7 @@ pub(super) enum FieldsMode {
9393
}
9494

9595
/// General purpose serializer for fields - used by dataclasses, models and typed_dicts
96-
#[derive(Debug, Clone)]
96+
#[derive(Debug)]
9797
pub struct GeneralFieldsSerializer {
9898
fields: AHashMap<String, SerField>,
9999
computed_fields: Option<ComputedFields>,

src/serializers/infer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ pub(crate) fn infer_to_python_known(
266266
ObType::Generator => {
267267
let iter = super::type_serializers::generator::SerializationIterator::new(
268268
value.downcast()?,
269-
super::type_serializers::any::AnySerializer.into(),
269+
super::type_serializers::any::AnySerializer::get(),
270270
SchemaFilter::default(),
271271
include,
272272
exclude,

src/serializers/shared.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ macro_rules! combined_serializer {
4040
find_only: {$($builder:path;)*}
4141
both: {$($b_key:ident: $b_serializer:path;)*}
4242
) => {
43-
#[derive(Debug, Clone)]
43+
#[derive(Debug)]
4444
#[enum_dispatch]
4545
pub enum CombinedSerializer {
4646
$($e_key($e_serializer),)*
@@ -257,7 +257,7 @@ impl PyGcTraverse for CombinedSerializer {
257257
}
258258

259259
#[enum_dispatch(CombinedSerializer)]
260-
pub(crate) trait TypeSerializer: Send + Sync + Clone + Debug {
260+
pub(crate) trait TypeSerializer: Send + Sync + Debug {
261261
fn to_python(
262262
&self,
263263
value: &Bound<'_, PyAny>,

src/serializers/type_serializers/any.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use std::borrow::Cow;
1+
use std::{
2+
borrow::Cow,
3+
sync::{Arc, OnceLock},
4+
};
25

36
use pyo3::prelude::*;
47
use pyo3::types::PyDict;
@@ -14,6 +17,13 @@ use super::{
1417
#[derive(Debug, Clone, Default)]
1518
pub struct AnySerializer;
1619

20+
impl AnySerializer {
21+
pub fn get() -> &'static Arc<CombinedSerializer> {
22+
static ANY_SERIALIZER: OnceLock<Arc<CombinedSerializer>> = OnceLock::new();
23+
ANY_SERIALIZER.get_or_init(|| Arc::new(Self.into()))
24+
}
25+
}
26+
1727
impl BuildSerializer for AnySerializer {
1828
const EXPECTED_TYPE: &'static str = "any";
1929

src/serializers/type_serializers/bytes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use super::{
1111
TypeSerializer,
1212
};
1313

14-
#[derive(Debug, Clone)]
14+
#[derive(Debug)]
1515
pub struct BytesSerializer {
1616
bytes_mode: BytesMode,
1717
}

src/serializers/type_serializers/dataclass.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl BuildSerializer for DataclassArgsBuilder {
6161
}
6262
}
6363

64-
#[derive(Debug, Clone)]
64+
#[derive(Debug)]
6565
pub struct DataclassSerializer {
6666
class: Py<PyType>,
6767
serializer: Box<CombinedSerializer>,

src/serializers/type_serializers/datetime_etc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ fn downcast_date_reject_datetime<'a, 'py>(py_date: &'a Bound<'py, PyAny>) -> PyR
3838

3939
macro_rules! build_serializer {
4040
($struct_name:ident, $expected_type:literal, $downcast:path, $convert_func:ident $(, $json_check_func:ident)?) => {
41-
#[derive(Debug, Clone)]
41+
#[derive(Debug)]
4242
pub struct $struct_name;
4343

4444
impl BuildSerializer for $struct_name {

src/serializers/type_serializers/decimal.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use super::{
1111
infer_json_key, infer_serialize, infer_to_python, BuildSerializer, CombinedSerializer, Extra, TypeSerializer,
1212
};
1313

14-
#[derive(Debug, Clone)]
14+
#[derive(Debug)]
1515
pub struct DecimalSerializer {}
1616

1717
impl BuildSerializer for DecimalSerializer {

src/serializers/type_serializers/definitions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::tools::SchemaDict;
1212

1313
use super::{py_err_se_err, BuildSerializer, CombinedSerializer, Extra, TypeSerializer};
1414

15-
#[derive(Debug, Clone)]
15+
#[derive(Debug)]
1616
pub struct DefinitionsSerializerBuilder;
1717

1818
impl BuildSerializer for DefinitionsSerializerBuilder {

src/serializers/type_serializers/dict.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use super::{
1515
SchemaFilter, SerMode, TypeSerializer,
1616
};
1717

18-
#[derive(Debug, Clone)]
18+
#[derive(Debug)]
1919
pub struct DictSerializer {
2020
key_serializer: Box<CombinedSerializer>,
2121
value_serializer: Box<CombinedSerializer>,

src/serializers/type_serializers/enum_.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use super::simple::IntSerializer;
1515
use super::string::StrSerializer;
1616
use super::{BuildSerializer, CombinedSerializer, Extra, TypeSerializer};
1717

18-
#[derive(Debug, Clone)]
18+
#[derive(Debug)]
1919
pub struct EnumSerializer {
2020
class: Py<PyType>,
2121
serializer: Option<Box<CombinedSerializer>>,

src/serializers/type_serializers/float.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ use crate::tools::SchemaDict;
1212
use super::simple::to_str_json_key;
1313
use super::{
1414
infer_json_key, infer_serialize, infer_to_python, BuildSerializer, CombinedSerializer, Extra, IsType, ObType,
15-
SerMode, TypeSerializer,
15+
SerCheck, SerMode, TypeSerializer,
1616
};
17+
use crate::serializers::errors::PydanticSerializationUnexpectedValue;
1718

18-
#[derive(Debug, Clone)]
19+
#[derive(Debug)]
1920
pub struct FloatSerializer {
2021
inf_nan_mode: InfNanMode,
2122
}
@@ -73,12 +74,15 @@ impl TypeSerializer for FloatSerializer {
7374
let py = value.py();
7475
match extra.ob_type_lookup.is_type(value, ObType::Float) {
7576
IsType::Exact => Ok(value.into_py(py)),
76-
IsType::Subclass => match extra.mode {
77-
SerMode::Json => {
78-
let rust_value = value.extract::<f64>()?;
79-
Ok(rust_value.to_object(py))
80-
}
81-
_ => infer_to_python(value, include, exclude, extra),
77+
IsType::Subclass => match extra.check {
78+
SerCheck::Strict => Err(PydanticSerializationUnexpectedValue::new_err(None)),
79+
SerCheck::Lax | SerCheck::None => match extra.mode {
80+
SerMode::Json => {
81+
let rust_value = value.extract::<f64>()?;
82+
Ok(rust_value.to_object(py))
83+
}
84+
_ => infer_to_python(value, include, exclude, extra),
85+
},
8286
},
8387
IsType::False => {
8488
extra.warnings.on_fallback_py(self.get_name(), value, extra)?;

src/serializers/type_serializers/format.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl WhenUsed {
5353
}
5454
}
5555

56-
#[derive(Debug, Clone)]
56+
#[derive(Debug)]
5757
pub struct FormatSerializer {
5858
format_func: PyObject,
5959
formatting_string: Py<PyString>,
@@ -161,7 +161,7 @@ impl TypeSerializer for FormatSerializer {
161161
}
162162
}
163163

164-
#[derive(Debug, Clone)]
164+
#[derive(Debug)]
165165
pub struct ToStringSerializer {
166166
when_used: WhenUsed,
167167
}

src/serializers/type_serializers/function.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::borrow::Cow;
2+
use std::sync::Arc;
23

34
use pyo3::exceptions::{PyAttributeError, PyRecursionError, PyRuntimeError};
45
use pyo3::gc::PyVisit;
@@ -71,7 +72,7 @@ impl BuildSerializer for FunctionPlainSerializerBuilder {
7172
}
7273
}
7374

74-
#[derive(Debug, Clone)]
75+
#[derive(Debug)]
7576
pub struct FunctionPlainSerializer {
7677
func: PyObject,
7778
name: String,
@@ -314,13 +315,13 @@ impl BuildSerializer for FunctionWrapSerializerBuilder {
314315
}
315316
}
316317

317-
#[derive(Debug, Clone)]
318+
#[derive(Debug)]
318319
pub struct FunctionWrapSerializer {
319-
serializer: Box<CombinedSerializer>,
320+
serializer: Arc<CombinedSerializer>,
320321
func: PyObject,
321322
name: String,
322323
function_name: String,
323-
return_serializer: Box<CombinedSerializer>,
324+
return_serializer: Arc<CombinedSerializer>,
324325
when_used: WhenUsed,
325326
is_field_serializer: bool,
326327
info_arg: bool,
@@ -358,11 +359,11 @@ impl BuildSerializer for FunctionWrapSerializer {
358359

359360
let name = format!("wrap_function[{function_name}, {}]", serializer.get_name());
360361
Ok(Self {
361-
serializer: Box::new(serializer),
362+
serializer: Arc::new(serializer),
362363
func: function.into_py(py),
363364
function_name,
364365
name,
365-
return_serializer: Box::new(return_serializer),
366+
return_serializer: Arc::new(return_serializer),
366367
when_used: WhenUsed::new(&ser_schema, WhenUsed::Always)?,
367368
is_field_serializer,
368369
info_arg,
@@ -419,10 +420,9 @@ impl_py_gc_traverse!(FunctionWrapSerializer {
419420
function_type_serializer!(FunctionWrapSerializer);
420421

421422
#[pyclass(module = "pydantic_core._pydantic_core")]
422-
#[derive(Clone)]
423423
#[cfg_attr(debug_assertions, derive(Debug))]
424424
pub(crate) struct SerializationCallable {
425-
serializer: CombinedSerializer,
425+
serializer: Arc<CombinedSerializer>,
426426
extra_owned: ExtraOwned,
427427
filter: AnyFilter,
428428
include: Option<PyObject>,
@@ -432,7 +432,7 @@ pub(crate) struct SerializationCallable {
432432
impl SerializationCallable {
433433
pub fn new(
434434
py: Python,
435-
serializer: &CombinedSerializer,
435+
serializer: &Arc<CombinedSerializer>,
436436
include: Option<&Bound<'_, PyAny>>,
437437
exclude: Option<&Bound<'_, PyAny>>,
438438
extra: &Extra,

src/serializers/type_serializers/generator.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::borrow::Cow;
2+
use std::sync::Arc;
23

34
use pyo3::gc::PyVisit;
45
use pyo3::intern;
@@ -17,9 +18,9 @@ use super::{
1718
PydanticSerializer, SchemaFilter, SerMode, TypeSerializer,
1819
};
1920

20-
#[derive(Debug, Clone)]
21+
#[derive(Debug)]
2122
pub struct GeneratorSerializer {
22-
item_serializer: Box<CombinedSerializer>,
23+
item_serializer: Arc<CombinedSerializer>,
2324
filter: SchemaFilter<usize>,
2425
}
2526

@@ -37,7 +38,7 @@ impl BuildSerializer for GeneratorSerializer {
3738
None => AnySerializer::build(schema, config, definitions)?,
3839
};
3940
Ok(Self {
40-
item_serializer: Box::new(item_serializer),
41+
item_serializer: Arc::new(item_serializer),
4142
filter: SchemaFilter::from_schema(schema)?,
4243
}
4344
.into())
@@ -82,7 +83,7 @@ impl TypeSerializer for GeneratorSerializer {
8283
_ => {
8384
let iter = SerializationIterator::new(
8485
py_iter,
85-
self.item_serializer.as_ref().clone(),
86+
&self.item_serializer,
8687
self.filter.clone(),
8788
include,
8889
exclude,
@@ -152,13 +153,12 @@ impl TypeSerializer for GeneratorSerializer {
152153
}
153154

154155
#[pyclass(module = "pydantic_core._pydantic_core")]
155-
#[derive(Clone)]
156156
#[cfg_attr(debug_assertions, derive(Debug))]
157157
pub(crate) struct SerializationIterator {
158158
iterator: Py<PyIterator>,
159159
#[pyo3(get)]
160160
index: usize,
161-
item_serializer: CombinedSerializer,
161+
item_serializer: Arc<CombinedSerializer>,
162162
extra_owned: ExtraOwned,
163163
filter: SchemaFilter<usize>,
164164
include: Option<PyObject>,
@@ -168,7 +168,7 @@ pub(crate) struct SerializationIterator {
168168
impl SerializationIterator {
169169
pub fn new(
170170
py_iter: &Bound<'_, PyIterator>,
171-
item_serializer: CombinedSerializer,
171+
item_serializer: &Arc<CombinedSerializer>,
172172
filter: SchemaFilter<usize>,
173173
include: Option<&Bound<'_, PyAny>>,
174174
exclude: Option<&Bound<'_, PyAny>>,
@@ -177,7 +177,7 @@ impl SerializationIterator {
177177
Self {
178178
iterator: py_iter.clone().into(),
179179
index: 0,
180-
item_serializer,
180+
item_serializer: item_serializer.clone(),
181181
extra_owned: ExtraOwned::new(extra),
182182
filter,
183183
include: include.map(|v| v.clone().into()),

src/serializers/type_serializers/json.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use super::{
1616
TypeSerializer,
1717
};
1818

19-
#[derive(Debug, Clone)]
19+
#[derive(Debug)]
2020
pub struct JsonSerializer {
2121
serializer: Box<CombinedSerializer>,
2222
}

src/serializers/type_serializers/json_or_python.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use super::{BuildSerializer, CombinedSerializer, Extra, TypeSerializer};
88
use crate::definitions::DefinitionsBuilder;
99
use crate::tools::SchemaDict;
1010

11-
#[derive(Debug, Clone)]
11+
#[derive(Debug)]
1212
pub struct JsonOrPythonSerializer {
1313
json: Box<CombinedSerializer>,
1414
python: Box<CombinedSerializer>,

src/serializers/type_serializers/list.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use super::{
1515
SchemaFilter, TypeSerializer,
1616
};
1717

18-
#[derive(Debug, Clone)]
18+
#[derive(Debug)]
1919
pub struct ListSerializer {
2020
item_serializer: Box<CombinedSerializer>,
2121
filter: SchemaFilter<usize>,

src/serializers/type_serializers/literal.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use super::{
1616
SerMode, TypeSerializer,
1717
};
1818

19-
#[derive(Debug, Clone)]
19+
#[derive(Debug)]
2020
pub struct LiteralSerializer {
2121
expected_int: AHashSet<i64>,
2222
expected_str: AHashSet<String>,

src/serializers/type_serializers/model.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl BuildSerializer for ModelFieldsBuilder {
7272
}
7373
}
7474

75-
#[derive(Debug, Clone)]
75+
#[derive(Debug)]
7676
pub struct ModelSerializer {
7777
class: Py<PyType>,
7878
serializer: Box<CombinedSerializer>,

src/serializers/type_serializers/nullable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::tools::SchemaDict;
99

1010
use super::{infer_json_key_known, BuildSerializer, CombinedSerializer, Extra, IsType, ObType, TypeSerializer};
1111

12-
#[derive(Debug, Clone)]
12+
#[derive(Debug)]
1313
pub struct NullableSerializer {
1414
serializer: Box<CombinedSerializer>,
1515
}

0 commit comments

Comments
 (0)