Skip to content

Commit 7b5c8ce

Browse files
committed
fix serialize_as_any with recursive ref
1 parent a017bd9 commit 7b5c8ce

File tree

2 files changed

+51
-6
lines changed

2 files changed

+51
-6
lines changed

src/serializers/type_serializers/definitions.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use pyo3::types::{PyDict, PyList};
77

88
use crate::definitions::DefinitionsBuilder;
99
use crate::definitions::{DefinitionRef, RecursionSafeCache};
10+
use crate::serializers::DuckTypingSerMode;
1011

1112
use crate::tools::SchemaDict;
1213

@@ -93,8 +94,12 @@ impl TypeSerializer for DefinitionRefSerializer {
9394
) -> PyResult<PyObject> {
9495
self.definition.read(|comb_serializer| {
9596
let comb_serializer = comb_serializer.unwrap();
96-
let mut guard = extra.recursion_guard(value, self.definition.id())?;
97-
comb_serializer.to_python(value, include, exclude, guard.state())
97+
if extra.duck_typing_ser_mode != DuckTypingSerMode::Inferred {
98+
comb_serializer.to_python(value, include, exclude, extra)
99+
} else {
100+
let mut guard = extra.recursion_guard(value, self.definition.id())?;
101+
comb_serializer.to_python(value, include, exclude, guard.state())
102+
}
98103
})
99104
}
100105

@@ -112,10 +117,14 @@ impl TypeSerializer for DefinitionRefSerializer {
112117
) -> Result<S::Ok, S::Error> {
113118
self.definition.read(|comb_serializer| {
114119
let comb_serializer = comb_serializer.unwrap();
115-
let mut guard = extra
116-
.recursion_guard(value, self.definition.id())
117-
.map_err(py_err_se_err)?;
118-
comb_serializer.serde_serialize(value, serializer, include, exclude, guard.state())
120+
if extra.duck_typing_ser_mode != DuckTypingSerMode::Inferred {
121+
comb_serializer.serde_serialize(value, serializer, include, exclude, extra)
122+
} else {
123+
let mut guard = extra
124+
.recursion_guard(value, self.definition.id())
125+
.map_err(py_err_se_err)?;
126+
comb_serializer.serde_serialize(value, serializer, include, exclude, guard.state())
127+
}
119128
})
120129
}
121130

tests/serializers/test_serialize_as_any.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from dataclasses import dataclass
2+
from typing import Optional
23

34
from typing_extensions import TypedDict
45

@@ -155,3 +156,38 @@ class Other:
155156
'x': 1,
156157
'y': 'hopefully not a secret',
157158
}
159+
160+
161+
def test_serialize_with_recursive_models() -> None:
162+
163+
class Node:
164+
next: Optional['Node'] = None
165+
value: int = 42
166+
167+
schema = core_schema.definitions_schema(
168+
core_schema.definition_reference_schema('Node'),
169+
[
170+
core_schema.model_schema(
171+
Node,
172+
core_schema.model_fields_schema(
173+
{
174+
'value': core_schema.model_field(core_schema.with_default_schema(core_schema.int_schema(), default=42)),
175+
'next': core_schema.model_field(
176+
core_schema.with_default_schema(
177+
core_schema.nullable_schema(
178+
core_schema.definition_reference_schema('Node')
179+
),
180+
default=None,
181+
)
182+
),
183+
}
184+
),
185+
ref='Node',
186+
)
187+
],
188+
)
189+
190+
s = SchemaSerializer(schema)
191+
v = SchemaValidator(schema)
192+
193+
obj = v.validate_python({'value': 2, 'asdas': 1})

0 commit comments

Comments
 (0)