Skip to content

Commit 570d448

Browse files
authored
move include / exclude into SerializationState (#1859)
1 parent 49b72b2 commit 570d448

38 files changed

+326
-740
lines changed

‎src/errors/validation_exception.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ impl ValidationError {
339339
include_input: bool,
340340
) -> PyResult<Bound<'py, PyString>> {
341341
let config = SerializationConfig::from_args("iso8601", "iso8601", "utf8", "constants")?;
342-
let mut state = SerializationState::new(config, WarningsMode::None)?;
342+
let mut state = SerializationState::new(config, WarningsMode::None, None, None)?;
343343
let extra = Extra::new(
344344
py,
345345
&SerMode::Json,

‎src/serializers/computed_fields.rs‎

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -43,102 +43,72 @@ impl ComputedFields {
4343
self.0.len()
4444
}
4545

46-
#[allow(clippy::too_many_arguments)]
4746
pub fn to_python<'py>(
4847
&self,
4948
model: &Bound<'py, PyAny>,
5049
output_dict: &Bound<'py, PyDict>,
5150
filter: &SchemaFilter<isize>,
52-
include: Option<&Bound<'py, PyAny>>,
53-
exclude: Option<&Bound<'py, PyAny>>,
5451
state: &mut SerializationState<'py>,
5552
extra: &Extra<'_, 'py>,
5653
) -> PyResult<()> {
5754
self.serialize_fields(
5855
model,
5956
filter,
60-
include,
61-
exclude,
6257
state,
6358
extra,
6459
|e| e,
6560
|ComputedFieldToSerialize {
6661
computed_field,
6762
value,
68-
include,
69-
exclude,
7063
state,
7164
field_extra,
7265
}| {
7366
let key = match field_extra.serialize_by_alias_or(computed_field.serialize_by_alias) {
7467
true => computed_field.alias_py.bind(model.py()),
7568
false => computed_field.property_name_py.bind(model.py()),
7669
};
77-
let value = computed_field.serializer.to_python(
78-
&value,
79-
include.as_ref(),
80-
exclude.as_ref(),
81-
state,
82-
field_extra,
83-
)?;
70+
let value = computed_field.serializer.to_python(&value, state, field_extra)?;
8471
output_dict.set_item(key, value)
8572
},
8673
)
8774
}
8875

89-
#[allow(clippy::too_many_arguments)]
9076
pub fn serde_serialize<'py, S: serde::ser::Serializer>(
9177
&self,
9278
model: &Bound<'py, PyAny>,
9379
map: &mut S::SerializeMap,
9480
filter: &SchemaFilter<isize>,
95-
include: Option<&Bound<'py, PyAny>>,
96-
exclude: Option<&Bound<'py, PyAny>>,
9781
state: &mut SerializationState<'py>,
9882
extra: &Extra<'_, 'py>,
9983
) -> Result<(), S::Error> {
10084
self.serialize_fields(
10185
model,
10286
filter,
103-
include,
104-
exclude,
10587
state,
10688
extra,
10789
py_err_se_err,
10890
|ComputedFieldToSerialize {
10991
computed_field,
11092
value,
111-
include,
112-
exclude,
11393
state,
11494
field_extra,
11595
}| {
11696
let key = match field_extra.serialize_by_alias_or(computed_field.serialize_by_alias) {
11797
true => &computed_field.alias,
11898
false => &computed_field.property_name,
11999
};
120-
let s = PydanticSerializer::new(
121-
&value,
122-
&computed_field.serializer,
123-
include.as_ref(),
124-
exclude.as_ref(),
125-
state,
126-
field_extra,
127-
);
100+
let s = PydanticSerializer::new(&value, &computed_field.serializer, state, field_extra);
128101
map.serialize_entry(key, &s)
129102
},
130103
)
131104
}
132105

133106
/// Iterate each field for serialization, filtering on
134107
/// `include` and `exclude` if provided.
135-
#[allow(clippy::too_many_arguments)]
136108
fn serialize_fields<'a, 'py, E>(
137109
&'a self,
138110
model: &'a Bound<'py, PyAny>,
139111
filter: &'a SchemaFilter<isize>,
140-
include: Option<&'a Bound<'py, PyAny>>,
141-
exclude: Option<&'a Bound<'py, PyAny>>,
142112
state: &mut SerializationState<'py>,
143113
extra: &'a Extra<'_, 'py>,
144114
convert_error: impl FnOnce(PyErr) -> E,
@@ -151,7 +121,7 @@ impl ComputedFields {
151121

152122
for computed_field in &self.0 {
153123
let property_name_py = computed_field.property_name_py.bind(model.py());
154-
let (next_include, next_exclude) = match filter.key_filter(property_name_py, include, exclude) {
124+
let (next_include, next_exclude) = match filter.key_filter(property_name_py, state) {
155125
Ok(Some((next_include, next_exclude))) => (next_include, next_exclude),
156126
Ok(None) => continue,
157127
Err(e) => return Err(convert_error(e)),
@@ -173,11 +143,10 @@ impl ComputedFields {
173143

174144
let field_name = FieldName::from(computed_field.property_name_py.bind(model.py()).clone());
175145
let state = &mut state.scoped_set(|s| &mut s.field_name, Some(field_name));
146+
let state = &mut state.scoped_include_exclude(next_include, next_exclude);
176147
serialize(ComputedFieldToSerialize {
177148
computed_field,
178149
value,
179-
include: next_include,
180-
exclude: next_exclude,
181150
state,
182151
field_extra: extra,
183152
})?;
@@ -189,8 +158,6 @@ impl ComputedFields {
189158
struct ComputedFieldToSerialize<'a, 'slf, 'py> {
190159
computed_field: &'a ComputedField,
191160
value: Bound<'py, PyAny>,
192-
include: Option<Bound<'py, PyAny>>,
193-
exclude: Option<Bound<'py, PyAny>>,
194161
state: &'slf mut SerializationState<'py>,
195162
field_extra: &'slf Extra<'a, 'py>,
196163
}

‎src/serializers/extra.rs‎

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub(crate) struct SerializationState<'py> {
2727
pub rec_guard: RecursionState,
2828
pub config: SerializationConfig,
2929
pub field_name: Option<FieldName<'py>>,
30+
pub include_exclude: (Option<Bound<'py, PyAny>>, Option<Bound<'py, PyAny>>),
3031
}
3132

3233
#[derive(Clone)]
@@ -50,18 +51,26 @@ impl fmt::Display for FieldName<'_> {
5051
}
5152
}
5253

53-
impl SerializationState<'_> {
54-
pub fn new(config: SerializationConfig, warnings_mode: WarningsMode) -> PyResult<Self> {
54+
impl<'py> SerializationState<'py> {
55+
pub fn new(
56+
config: SerializationConfig,
57+
warnings_mode: WarningsMode,
58+
include: Option<Bound<'py, PyAny>>,
59+
exclude: Option<Bound<'py, PyAny>>,
60+
) -> PyResult<Self> {
5561
let warnings = CollectWarnings::new(warnings_mode);
5662
let rec_guard = RecursionState::default();
5763
Ok(Self {
5864
warnings,
5965
rec_guard,
6066
config,
6167
field_name: None,
68+
include_exclude: (include, exclude),
6269
})
6370
}
71+
}
6472

73+
impl SerializationState<'_> {
6574
pub fn recursion_guard(
6675
&mut self,
6776
value: &Bound<'_, PyAny>,
@@ -109,6 +118,26 @@ impl<'py> SerializationState<'py> {
109118
value,
110119
}
111120
}
121+
122+
pub fn scoped_include_exclude<'scope>(
123+
&'scope mut self,
124+
next_include: Option<Bound<'py, PyAny>>,
125+
next_exclude: Option<Bound<'py, PyAny>>,
126+
) -> ScopedIncludeExcludeState<'scope, 'py> {
127+
self.scoped_set(SerializationState::include_exclude_mut, (next_include, next_exclude))
128+
}
129+
130+
pub fn include(&self) -> Option<&Bound<'py, PyAny>> {
131+
self.include_exclude.0.as_ref()
132+
}
133+
134+
pub fn exclude(&self) -> Option<&Bound<'py, PyAny>> {
135+
self.include_exclude.1.as_ref()
136+
}
137+
138+
fn include_exclude_mut(&mut self) -> &mut (Option<Bound<'py, PyAny>>, Option<Bound<'py, PyAny>>) {
139+
&mut self.include_exclude
140+
}
112141
}
113142

114143
/// Useful things which are passed around by type_serializers
@@ -174,7 +203,7 @@ impl<'a, 'py> Extra<'a, 'py> {
174203
value: &'slf Bound<'py, PyAny>,
175204
state: &'slf mut SerializationState<'py>,
176205
) -> super::infer::SerializeInfer<'slf, 'py> {
177-
super::infer::SerializeInfer::new(value, None, None, state, self)
206+
super::infer::SerializeInfer::new(value, state, self)
178207
}
179208

180209
pub(crate) fn model_type_name(&self) -> Option<Bound<'a, PyString>> {
@@ -223,6 +252,8 @@ pub(crate) struct ExtraOwned {
223252
pub fallback: Option<Py<PyAny>>,
224253
serialize_as_any: bool,
225254
pub context: Option<Py<PyAny>>,
255+
include: Option<Py<PyAny>>,
256+
exclude: Option<Py<PyAny>>,
226257
}
227258

228259
#[derive(Clone)]
@@ -263,6 +294,8 @@ impl ExtraOwned {
263294
fallback: extra.fallback.map(|model| model.clone().into()),
264295
serialize_as_any: extra.serialize_as_any,
265296
context: extra.context.map(|model| model.clone().into()),
297+
include: state.include().map(|m| m.clone().into()),
298+
exclude: state.exclude().map(|m| m.clone().into()),
266299
}
267300
}
268301

@@ -295,6 +328,10 @@ impl ExtraOwned {
295328
Some(FieldNameOwned::Regular(b)) => Some(FieldName::Regular(b.bind(py).clone())),
296329
None => None,
297330
},
331+
include_exclude: (
332+
self.include.as_ref().map(|m| m.bind(py).clone()),
333+
self.exclude.as_ref().map(|m| m.bind(py).clone()),
334+
),
298335
}
299336
}
300337
}
@@ -528,3 +565,10 @@ where
528565
self.state
529566
}
530567
}
568+
569+
type ScopedIncludeExcludeState<'scope, 'py> = ScopedSetState<
570+
'scope,
571+
'py,
572+
for<'s> fn(&'s mut SerializationState<'py>) -> &'s mut (Option<Bound<'py, PyAny>>, Option<Bound<'py, PyAny>>),
573+
(Option<Bound<'py, PyAny>>, Option<Bound<'py, PyAny>>),
574+
>;

0 commit comments

Comments
 (0)