Skip to content

Commit

Permalink
fix borrow error when serializing recursive models
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Jul 11, 2023
1 parent 3e7cc4f commit 70e67e9
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 10 deletions.
4 changes: 2 additions & 2 deletions src/serializers/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub(crate) fn infer_to_python_known(

let serialize_with_serializer = || {
let py_serializer = value.getattr(intern!(py, "__pydantic_serializer__"))?;
let serializer: SchemaSerializer = py_serializer.extract()?;
let serializer: PyRef<SchemaSerializer> = py_serializer.extract()?;
let extra = serializer.build_extra(
py,
extra.mode,
Expand Down Expand Up @@ -464,7 +464,7 @@ pub(crate) fn infer_serialize_known<S: Serializer>(
let py_serializer = value
.getattr(intern!(py, "__pydantic_serializer__"))
.map_err(py_err_se_err)?;
let extracted_serializer: SchemaSerializer = py_serializer.extract().map_err(py_err_se_err)?;
let extracted_serializer: PyRef<SchemaSerializer> = py_serializer.extract().map_err(py_err_se_err)?;
let extra = extracted_serializer.build_extra(
py,
extra.mode,
Expand Down
13 changes: 7 additions & 6 deletions src/serializers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::fmt::Debug;
use std::sync::atomic::{AtomicUsize, Ordering};

use pyo3::prelude::*;
use pyo3::types::{PyBytes, PyDict};
Expand Down Expand Up @@ -26,11 +27,11 @@ mod shared;
mod type_serializers;

#[pyclass(module = "pydantic_core._pydantic_core")]
#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct SchemaSerializer {
serializer: CombinedSerializer,
definitions: Vec<CombinedSerializer>,
json_size: usize,
expected_json_size: AtomicUsize,
config: SerializationConfig,
}

Expand Down Expand Up @@ -80,7 +81,7 @@ impl SchemaSerializer {
Ok(Self {
serializer,
definitions: definitions_builder.finish()?,
json_size: 1024,
expected_json_size: AtomicUsize::new(1024),
config: SerializationConfig::from_config(config)?,
})
}
Expand Down Expand Up @@ -130,7 +131,7 @@ impl SchemaSerializer {
exclude_unset = false, exclude_defaults = false, exclude_none = false, round_trip = false, warnings = true,
fallback = None))]
pub fn to_json(
&mut self,
&self,
py: Python,
value: &PyAny,
indent: Option<usize>,
Expand Down Expand Up @@ -166,12 +167,12 @@ impl SchemaSerializer {
exclude,
&extra,
indent,
self.json_size,
self.expected_json_size.load(Ordering::Relaxed),
)?;

warnings.final_check(py)?;

self.json_size = bytes.len();
self.expected_json_size.store(bytes.len(), Ordering::Relaxed);
let py_bytes = PyBytes::new(py, &bytes);
Ok(py_bytes.into())
}
Expand Down
4 changes: 2 additions & 2 deletions src/serializers/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,11 +308,11 @@ pub(crate) fn to_json_bytes(
exclude: Option<&PyAny>,
extra: &Extra,
indent: Option<usize>,
json_size: usize,
expected_json_size: usize,
) -> PyResult<Vec<u8>> {
let serializer = PydanticSerializer::new(value, serializer, include, exclude, extra);

let writer: Vec<u8> = Vec::with_capacity(json_size);
let writer: Vec<u8> = Vec::with_capacity(expected_json_size);
let bytes = match indent {
Some(indent) => {
let indent = vec![b' '; indent];
Expand Down
16 changes: 16 additions & 0 deletions tests/serializers/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,22 @@ def test_model_allow_extra():
assert j == b'{"bar":"more","foo":1,"c":3}'


def test_model_recursive_in_extra():
# See https://github.com/pydantic/pydantic/issues/6571

class Model(BasicModel):
__slots__ = '__pydantic_extra__'

s = SchemaSerializer(
core_schema.model_schema(
Model, core_schema.model_fields_schema({}, extra_behavior='allow'), extra_behavior='allow'
)
)
Model.__pydantic_serializer__ = s

assert s.to_json(Model(__pydantic_extra__=dict(other=Model(__pydantic_extra__={})))) == b'{"other":{}}'


@pytest.mark.parametrize(
'params',
[
Expand Down

0 comments on commit 70e67e9

Please sign in to comment.