Skip to content

Commit 1308fa0

Browse files
committed
validate_assignment use Py2
1 parent 16af73a commit 1308fa0

File tree

10 files changed

+149
-108
lines changed

10 files changed

+149
-108
lines changed

src/input/input_json.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ impl<'a> Input<'a> for JsonValue {
5050
fn as_kwargs(&'a self, py: Python<'a>) -> Option<&'a PyDict> {
5151
match self {
5252
JsonValue::Object(object) => {
53-
let dict = PyDict::new2(py);
53+
let dict = PyDict::new(py);
5454
for (k, v) in object.iter() {
5555
dict.set_item(k, v.to_object(py)).unwrap();
5656
}
57-
Some(dict.into_gil_ref())
57+
Some(dict)
5858
}
5959
_ => None,
6060
}
@@ -156,7 +156,7 @@ impl<'a> Input<'a> for JsonValue {
156156

157157
fn strict_decimal(&'a self, py: Python<'a>) -> ValResult<&'a PyAny> {
158158
match self {
159-
JsonValue::Float(f) => create_decimal(PyString::new2(py, &f.to_string()).into_gil_ref(), self, py),
159+
JsonValue::Float(f) => create_decimal(PyString::new(py, &f.to_string()), self, py),
160160

161161
JsonValue::Str(..) | JsonValue::Int(..) | JsonValue::BigInt(..) => {
162162
create_decimal(self.to_object(py).into_ref(py), self, py)

src/serializers/infer.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ pub(crate) fn infer_to_python_known(
195195
uuid.into_py(py)
196196
}
197197
ObType::PydanticSerializable => serialize_with_serializer()?,
198-
ObType::Dataclass => serialize_dict(dataclass_to_dict(value)?)?,
198+
ObType::Dataclass => serialize_dict(dataclass_to_dict(Py2::borrowed_from_gil_ref(&value))?.as_gil_ref())?,
199199
ObType::Enum => {
200200
let v = value.getattr(intern!(py, "value"))?;
201201
infer_to_python(v, include, exclude, extra)?.into_py(py)
@@ -261,7 +261,7 @@ pub(crate) fn infer_to_python_known(
261261
new_dict.into_py(py)
262262
}
263263
ObType::PydanticSerializable => serialize_with_serializer()?,
264-
ObType::Dataclass => serialize_dict(dataclass_to_dict(value)?)?,
264+
ObType::Dataclass => serialize_dict(dataclass_to_dict(Py2::borrowed_from_gil_ref(&value))?.as_gil_ref())?,
265265
ObType::Generator => {
266266
let iter = super::type_serializers::generator::SerializationIterator::new(
267267
value.downcast()?,
@@ -493,7 +493,9 @@ pub(crate) fn infer_serialize_known<S: Serializer>(
493493
PydanticSerializer::new(value, &extracted_serializer.serializer, include, exclude, &extra);
494494
pydantic_serializer.serialize(serializer)
495495
}
496-
ObType::Dataclass => serialize_dict!(dataclass_to_dict(value).map_err(py_err_se_err)?),
496+
ObType::Dataclass => serialize_dict!(dataclass_to_dict(Py2::borrowed_from_gil_ref(&value))
497+
.map_err(py_err_se_err)?
498+
.as_gil_ref()),
497499
ObType::Uuid => {
498500
let py_uuid: &PyAny = value.downcast().map_err(py_err_se_err)?;
499501
let uuid = super::type_serializers::uuid::uuid_to_string(py_uuid).map_err(py_err_se_err)?;

src/serializers/shared.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use std::borrow::Cow;
22
use std::fmt::Debug;
33

44
use pyo3::exceptions::PyTypeError;
5-
use pyo3::prelude::*;
65
use pyo3::sync::GILOnceCell;
76
use pyo3::types::{PyDict, PyString};
87
use pyo3::{intern, PyTraverseError, PyVisit};
8+
use pyo3::{intern2, prelude::*};
99

1010
use enum_dispatch::enum_dispatch;
1111
use serde::Serialize;
@@ -377,18 +377,20 @@ pub(super) fn get_field_marker(py: Python<'_>) -> PyResult<&PyAny> {
377377
Ok(field_type_marker_obj.as_ref(py))
378378
}
379379

380-
pub(super) fn dataclass_to_dict(dc: &PyAny) -> PyResult<&PyDict> {
380+
pub(super) fn dataclass_to_dict<'py>(dc: &Py2<'py, PyAny>) -> PyResult<Py2<'py, PyDict>> {
381381
let py = dc.py();
382-
let dc_fields: &PyDict = dc.getattr(intern!(py, "__dataclass_fields__"))?.downcast()?;
382+
let dc_fields = dc
383+
.getattr(intern2!(py, "__dataclass_fields__"))?
384+
.downcast_into::<PyDict>()?;
383385
let dict = PyDict::new2(py);
384386

385387
let field_type_marker = get_field_marker(py)?;
386388
for (field_name, field) in dc_fields {
387-
let field_type = field.getattr(intern!(py, "_field_type"))?;
389+
let field_type = field.getattr(intern2!(py, "_field_type"))?;
388390
if field_type.is(field_type_marker) {
389-
let field_name: &PyString = field_name.downcast()?;
391+
let field_name = field_name.downcast::<PyString>()?;
390392
dict.set_item(field_name, dc.getattr(field_name)?)?;
391393
}
392394
}
393-
Ok(dict.into_gil_ref())
395+
Ok(dict)
394396
}

src/validators/dataclass.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -368,12 +368,12 @@ impl Validator for DataclassArgsValidator {
368368
fn validate_assignment<'data>(
369369
&self,
370370
py: Python<'data>,
371-
obj: &'data PyAny,
372-
field_name: &'data str,
373-
field_value: &'data PyAny,
371+
obj: &Py2<'data, PyAny>,
372+
field_name: &str,
373+
field_value: &Py2<'data, PyAny>,
374374
state: &mut ValidationState,
375375
) -> ValResult<PyObject> {
376-
let dict = Py2::borrowed_from_gil_ref(&obj).downcast::<PyDict>()?;
376+
let dict = obj.downcast::<PyDict>()?;
377377

378378
let ok = |output: PyObject| {
379379
dict.set_item(field_name, output)?;
@@ -525,8 +525,8 @@ impl Validator for DataclassValidator {
525525
let class = self.class.as_ref(py);
526526
if let Some(py_input) = input.input_is_instance(class) {
527527
if self.revalidate.should_revalidate(py_input, class) {
528-
let input_dict: &PyAny = self.dataclass_to_dict(py, py_input)?;
529-
let val_output = self.validator.validate(py, input_dict, state)?;
528+
let input_dict = self.dataclass_to_dict(Py2::borrowed_from_gil_ref(&py_input))?;
529+
let val_output = self.validator.validate(py, input_dict.as_any(), state)?;
530530
let dc = create_class(self.class.as_ref(py))?;
531531
self.set_dict_call(py, dc.as_ref(py), val_output, input)?;
532532
Ok(dc)
@@ -553,32 +553,32 @@ impl Validator for DataclassValidator {
553553
fn validate_assignment<'data>(
554554
&self,
555555
py: Python<'data>,
556-
obj: &'data PyAny,
557-
field_name: &'data str,
558-
field_value: &'data PyAny,
556+
obj: &Py2<'data, PyAny>,
557+
field_name: &str,
558+
field_value: &Py2<'data, PyAny>,
559559
state: &mut ValidationState,
560560
) -> ValResult<PyObject> {
561561
if self.frozen {
562562
return Err(ValError::new(ErrorTypeDefaults::FrozenInstance, field_value));
563563
}
564564

565-
let new_dict = self.dataclass_to_dict(py, obj)?;
565+
let new_dict = self.dataclass_to_dict(obj)?;
566566

567567
new_dict.set_item(field_name, field_value)?;
568568

569-
let val_assignment_result = self
570-
.validator
571-
.validate_assignment(py, new_dict, field_name, field_value, state)?;
569+
let val_assignment_result =
570+
self.validator
571+
.validate_assignment(py, new_dict.as_any(), field_name, field_value, state)?;
572572

573573
let (dc_dict, _): (&PyDict, PyObject) = val_assignment_result.extract(py)?;
574574

575575
if self.slots {
576576
let value = dc_dict
577577
.get_item(field_name)?
578578
.ok_or_else(|| PyKeyError::new_err(field_name.to_string()))?;
579-
force_setattr(py, obj, field_name, value)?;
579+
force_setattr(py, obj.as_gil_ref(), field_name, value)?;
580580
} else {
581-
force_setattr(py, obj, intern!(py, "__dict__"), dc_dict)?;
581+
force_setattr(py, obj.as_gil_ref(), intern!(py, "__dict__"), dc_dict)?;
582582
}
583583

584584
Ok(obj.to_object(py))
@@ -608,14 +608,14 @@ impl DataclassValidator {
608608
Ok(self_instance.into_py(py))
609609
}
610610

611-
fn dataclass_to_dict<'py>(&self, py: Python<'py>, dc: &'py PyAny) -> PyResult<&'py PyDict> {
611+
fn dataclass_to_dict<'py>(&self, dc: &Py2<'py, PyAny>) -> PyResult<Py2<'py, PyDict>> {
612+
let py = dc.py();
612613
let dict = PyDict::new2(py);
613614

614615
for field_name in &self.fields {
615-
let field_name = field_name.as_ref(py);
616616
dict.set_item(field_name, dc.getattr(field_name)?)?;
617617
}
618-
Ok(dict.into_gil_ref())
618+
Ok(dict)
619619
}
620620

621621
fn set_dict_call<'s, 'data>(

src/validators/definitions.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ impl Validator for DefinitionRefValidator {
9595
fn validate_assignment<'data>(
9696
&self,
9797
py: Python<'data>,
98-
obj: &'data PyAny,
99-
field_name: &'data str,
100-
field_value: &'data PyAny,
98+
obj: &Py2<'data, PyAny>,
99+
field_name: &str,
100+
field_value: &Py2<'data, PyAny>,
101101
state: &mut ValidationState,
102102
) -> ValResult<PyObject> {
103103
let validator = self.definition.get().unwrap();

src/validators/function.rs

Lines changed: 80 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -80,46 +80,6 @@ macro_rules! impl_build {
8080
};
8181
}
8282

83-
macro_rules! impl_validator {
84-
($name:ident) => {
85-
impl_py_gc_traverse!($name {
86-
validator,
87-
func,
88-
config
89-
});
90-
91-
impl Validator for $name {
92-
fn validate<'data>(
93-
&self,
94-
py: Python<'data>,
95-
input: &'data impl Input<'data>,
96-
state: &mut ValidationState<'_>,
97-
) -> ValResult<PyObject> {
98-
let validate = |v, s: &mut ValidationState<'_>| self.validator.validate(py, v, s);
99-
self._validate(validate, py, input, state)
100-
}
101-
fn validate_assignment<'data>(
102-
&self,
103-
py: Python<'data>,
104-
obj: &'data PyAny,
105-
field_name: &'data str,
106-
field_value: &'data PyAny,
107-
state: &mut ValidationState,
108-
) -> ValResult<PyObject> {
109-
let validate = move |v, s: &mut ValidationState<'_>| {
110-
self.validator
111-
.validate_assignment(py, v, field_name, field_value, s)
112-
};
113-
self._validate(validate, py, obj, state)
114-
}
115-
116-
fn get_name(&self) -> &str {
117-
&self.name
118-
}
119-
}
120-
};
121-
}
122-
12383
#[derive(Debug)]
12484
pub struct FunctionBeforeValidator {
12585
validator: Box<CombinedValidator>,
@@ -135,7 +95,7 @@ impl_build!(FunctionBeforeValidator, "function-before");
13595
impl FunctionBeforeValidator {
13696
fn _validate<'s, 'data>(
13797
&'s self,
138-
call: impl FnOnce(&'data PyAny, &mut ValidationState<'_>) -> ValResult<PyObject>,
98+
call: impl FnOnce(Py2<'data, PyAny>, &mut ValidationState<'_>) -> ValResult<PyObject>,
13999
py: Python<'data>,
140100
input: &'data impl Input<'data>,
141101
state: &'s mut ValidationState<'_>,
@@ -147,11 +107,44 @@ impl FunctionBeforeValidator {
147107
self.func.call1(py, (input.to_object(py),))
148108
};
149109
let value = r.map_err(|e| convert_err(py, e, input))?;
150-
call(value.into_ref(py), state)
110+
call(value.attach_into(py), state)
151111
}
152112
}
153113

154-
impl_validator!(FunctionBeforeValidator);
114+
impl_py_gc_traverse!(FunctionBeforeValidator {
115+
validator,
116+
func,
117+
config
118+
});
119+
120+
impl Validator for FunctionBeforeValidator {
121+
fn validate<'data>(
122+
&self,
123+
py: Python<'data>,
124+
input: &'data impl Input<'data>,
125+
state: &mut ValidationState<'_>,
126+
) -> ValResult<PyObject> {
127+
let validate = |v, s: &mut ValidationState<'_>| self.validator.validate(py, &v, s);
128+
self._validate(validate, py, input, state)
129+
}
130+
fn validate_assignment<'data>(
131+
&self,
132+
py: Python<'data>,
133+
obj: &Py2<'data, PyAny>,
134+
field_name: &str,
135+
field_value: &Py2<'data, PyAny>,
136+
state: &mut ValidationState,
137+
) -> ValResult<PyObject> {
138+
let validate = move |v, s: &mut ValidationState<'_>| {
139+
self.validator.validate_assignment(py, &v, field_name, field_value, s)
140+
};
141+
self._validate(validate, py, obj, state)
142+
}
143+
144+
fn get_name(&self) -> &str {
145+
&self.name
146+
}
147+
}
155148

156149
#[derive(Debug)]
157150
pub struct FunctionAfterValidator {
@@ -184,7 +177,39 @@ impl FunctionAfterValidator {
184177
}
185178
}
186179

187-
impl_validator!(FunctionAfterValidator);
180+
impl_py_gc_traverse!(FunctionAfterValidator {
181+
validator,
182+
func,
183+
config
184+
});
185+
186+
impl Validator for FunctionAfterValidator {
187+
fn validate<'data>(
188+
&self,
189+
py: Python<'data>,
190+
input: &'data impl Input<'data>,
191+
state: &mut ValidationState<'_>,
192+
) -> ValResult<PyObject> {
193+
let validate = |v, s: &mut ValidationState<'_>| self.validator.validate(py, v, s);
194+
self._validate(validate, py, input, state)
195+
}
196+
fn validate_assignment<'data>(
197+
&self,
198+
py: Python<'data>,
199+
obj: &Py2<'data, PyAny>,
200+
field_name: &str,
201+
field_value: &Py2<'data, PyAny>,
202+
state: &mut ValidationState,
203+
) -> ValResult<PyObject> {
204+
let validate =
205+
move |v, s: &mut ValidationState<'_>| self.validator.validate_assignment(py, v, field_name, field_value, s);
206+
self._validate(validate, py, obj, state)
207+
}
208+
209+
fn get_name(&self) -> &str {
210+
&self.name
211+
}
212+
}
188213

189214
#[derive(Debug, Clone)]
190215
pub struct FunctionPlainValidator {
@@ -337,9 +362,9 @@ impl Validator for FunctionWrapValidator {
337362
fn validate_assignment<'data>(
338363
&self,
339364
py: Python<'data>,
340-
obj: &'data PyAny,
341-
field_name: &'data str,
342-
field_value: &'data PyAny,
365+
obj: &Py2<'data, PyAny>,
366+
field_name: &str,
367+
field_value: &Py2<'data, PyAny>,
343368
state: &mut ValidationState,
344369
) -> ValResult<PyObject> {
345370
let handler = AssignmentValidatorCallable {
@@ -398,13 +423,18 @@ struct AssignmentValidatorCallable {
398423

399424
#[pymethods]
400425
impl AssignmentValidatorCallable {
401-
fn __call__(&mut self, py: Python, input_value: &PyAny, outer_location: Option<&PyAny>) -> PyResult<PyObject> {
426+
fn __call__(
427+
&mut self,
428+
py: Python,
429+
input_value: Py2<'_, PyAny>,
430+
outer_location: Option<&PyAny>,
431+
) -> PyResult<PyObject> {
402432
let outer_location = outer_location.map(AsLocItem::as_loc_item);
403433
self.validator.validate_assignment(
404434
py,
405-
input_value,
435+
&input_value,
406436
self.updated_field_name.as_str(),
407-
self.updated_field_value.as_ref(py),
437+
self.updated_field_value.attach(py),
408438
outer_location,
409439
)
410440
}

src/validators/generator.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,9 @@ impl InternalValidator {
254254
pub fn validate_assignment<'data>(
255255
&mut self,
256256
py: Python<'data>,
257-
model: &'data PyAny,
258-
field_name: &'data str,
259-
field_value: &'data PyAny,
257+
model: &Py2<'data, PyAny>,
258+
field_name: &str,
259+
field_value: &Py2<'data, PyAny>,
260260
outer_location: Option<LocItem>,
261261
) -> PyResult<PyObject> {
262262
let extra = Extra {

0 commit comments

Comments
 (0)