Skip to content

Commit 39435c2

Browse files
authored
remove uses of IntoPy (#1578)
1 parent bd91c18 commit 39435c2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+405
-411
lines changed

src/argument_markers.rs

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use pyo3::basic::CompareOp;
21
use pyo3::exceptions::PyNotImplementedError;
32
use pyo3::prelude::*;
43
use pyo3::sync::GILOnceCell;
@@ -13,45 +12,26 @@ pub struct ArgsKwargs {
1312
pub(crate) kwargs: Option<Py<PyDict>>,
1413
}
1514

16-
impl ArgsKwargs {
17-
fn eq(&self, py: Python, other: &Self) -> PyResult<bool> {
18-
if self.args.bind(py).eq(other.args.bind(py))? {
19-
match (&self.kwargs, &other.kwargs) {
20-
(Some(d1), Some(d2)) => d1.bind(py).eq(d2.bind(py)),
21-
(None, None) => Ok(true),
22-
_ => Ok(false),
23-
}
24-
} else {
25-
Ok(false)
26-
}
27-
}
28-
}
29-
3015
#[pymethods]
3116
impl ArgsKwargs {
3217
#[new]
3318
#[pyo3(signature = (args, kwargs = None))]
34-
fn py_new(py: Python, args: &Bound<'_, PyTuple>, kwargs: Option<&Bound<'_, PyDict>>) -> Self {
19+
fn py_new(args: Bound<'_, PyTuple>, kwargs: Option<Bound<'_, PyDict>>) -> Self {
3520
Self {
36-
args: args.into_py(py),
37-
kwargs: match kwargs {
38-
Some(d) if !d.is_empty() => Some(d.to_owned().unbind()),
39-
_ => None,
40-
},
21+
args: args.unbind(),
22+
kwargs: kwargs.filter(|d| !d.is_empty()).map(Bound::unbind),
4123
}
4224
}
4325

44-
fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> PyObject {
45-
match op {
46-
CompareOp::Eq => match self.eq(py, other) {
47-
Ok(b) => b.into_py(py),
48-
Err(e) => e.into_py(py),
49-
},
50-
CompareOp::Ne => match self.eq(py, other) {
51-
Ok(b) => (!b).into_py(py),
52-
Err(e) => e.into_py(py),
53-
},
54-
_ => py.NotImplemented(),
26+
fn __eq__(&self, py: Python, other: &Self) -> PyResult<bool> {
27+
if !self.args.bind(py).eq(&other.args)? {
28+
return Ok(false);
29+
}
30+
31+
match (&self.kwargs, &other.kwargs) {
32+
(Some(d1), Some(d2)) => d1.bind(py).eq(d2),
33+
(None, None) => Ok(true),
34+
_ => Ok(false),
5535
}
5636
}
5737

@@ -82,16 +62,16 @@ impl PydanticUndefinedType {
8262
#[staticmethod]
8363
pub fn new(py: Python) -> Py<Self> {
8464
UNDEFINED_CELL
85-
.get_or_init(py, || PydanticUndefinedType {}.into_py(py).extract(py).unwrap())
86-
.clone()
65+
.get_or_init(py, || Py::new(py, PydanticUndefinedType {}).unwrap())
66+
.clone_ref(py)
8767
}
8868

8969
fn __repr__(&self) -> &'static str {
9070
"PydanticUndefined"
9171
}
9272

9373
fn __copy__(&self, py: Python) -> Py<Self> {
94-
UNDEFINED_CELL.get(py).unwrap().clone()
74+
UNDEFINED_CELL.get(py).unwrap().clone_ref(py)
9575
}
9676

9777
#[pyo3(signature = (_memo, /))]

src/build_tools.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use pyo3::prelude::*;
66
use pyo3::types::{PyDict, PyList, PyString};
77
use pyo3::{intern, FromPyObject, PyErrArguments};
88

9-
use crate::errors::ValError;
9+
use crate::errors::{PyLineError, ValError};
1010
use crate::input::InputType;
1111
use crate::tools::SchemaDict;
1212
use crate::ValidationError;
@@ -85,7 +85,14 @@ impl SchemaError {
8585
pub fn from_val_error(py: Python, error: ValError) -> PyErr {
8686
match error {
8787
ValError::LineErrors(raw_errors) => {
88-
let line_errors = raw_errors.into_iter().map(|e| e.into_py(py)).collect();
88+
let line_errors = match raw_errors
89+
.into_iter()
90+
.map(|e| PyLineError::from_val_line_error(py, e))
91+
.collect::<PyResult<_>>()
92+
{
93+
Ok(errors) => errors,
94+
Err(err) => return err,
95+
};
8996
let validation_error =
9097
ValidationError::new(line_errors, "Schema".to_object(py), InputType::Python, false);
9198
let schema_error = SchemaError(SchemaErrorEnum::ValidationError(validation_error));

src/errors/line_error.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::convert::Infallible;
2+
13
use pyo3::exceptions::PyTypeError;
24
use pyo3::prelude::*;
35
use pyo3::DowncastError;
@@ -61,6 +63,12 @@ impl From<Vec<ValLineError>> for ValError {
6163
}
6264
}
6365

66+
impl From<Infallible> for ValError {
67+
fn from(infallible: Infallible) -> Self {
68+
match infallible {}
69+
}
70+
}
71+
6472
impl ValError {
6573
pub fn new(error_type: ErrorType, input: impl ToErrorValue) -> ValError {
6674
Self::LineErrors(vec![ValLineError::new(error_type, input)])
@@ -156,7 +164,7 @@ impl ValLineError {
156164
}
157165

158166
#[cfg_attr(debug_assertions, derive(Debug))]
159-
#[derive(Clone)]
167+
#[derive(Clone, IntoPyObject)]
160168
pub enum InputValue {
161169
Python(PyObject),
162170
Json(JsonValue<'static>),

src/errors/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mod value_exception;
99
pub use self::line_error::{InputValue, ToErrorValue, ValError, ValLineError, ValResult};
1010
pub use self::location::LocItem;
1111
pub use self::types::{list_all_errors, ErrorType, ErrorTypeDefaults, Number};
12-
pub use self::validation_exception::ValidationError;
12+
pub use self::validation_exception::{PyLineError, ValidationError};
1313
pub use self::value_exception::{PydanticCustomError, PydanticKnownError, PydanticOmit, PydanticUseDefault};
1414

1515
pub fn py_err_string(py: Python, err: PyErr) -> String {

src/errors/types.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ use std::borrow::Cow;
33
use std::fmt;
44

55
use pyo3::exceptions::{PyKeyError, PyTypeError};
6-
use pyo3::prelude::*;
76
use pyo3::sync::GILOnceCell;
87
use pyo3::types::{PyDict, PyList};
8+
use pyo3::{prelude::*, IntoPyObjectExt};
99

1010
use ahash::AHashMap;
1111
use num_bigint::BigInt;
@@ -766,7 +766,7 @@ impl ErrorType {
766766
}
767767
}
768768

769-
#[derive(Clone, Debug)]
769+
#[derive(Clone, Debug, IntoPyObject, IntoPyObjectRef)]
770770
pub enum Number {
771771
Int(i64),
772772
BigInt(BigInt),
@@ -826,11 +826,6 @@ impl fmt::Display for Number {
826826
}
827827
impl ToPyObject for Number {
828828
fn to_object(&self, py: Python<'_>) -> PyObject {
829-
match self {
830-
Self::Int(i) => i.into_py(py),
831-
Self::BigInt(i) => i.clone().into_py(py),
832-
Self::Float(f) => f.into_py(py),
833-
Self::String(s) => s.into_py(py),
834-
}
829+
self.into_py_any(py).unwrap()
835830
}
836831
}

src/errors/validation_exception.rs

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use pyo3::ffi::{self, c_str};
77
use pyo3::intern;
88
use pyo3::prelude::*;
99
use pyo3::sync::GILOnceCell;
10-
use pyo3::types::{PyDict, PyList, PyString, PyType};
10+
use pyo3::types::{PyDict, PyList, PyString, PyTuple, PyType};
1111
use serde::ser::{Error, SerializeMap, SerializeSeq};
1212
use serde::{Serialize, Serializer};
1313

@@ -57,12 +57,19 @@ impl ValidationError {
5757
) -> PyErr {
5858
match error {
5959
ValError::LineErrors(raw_errors) => {
60-
let line_errors: Vec<PyLineError> = match outer_location {
60+
let line_errors = match outer_location {
6161
Some(outer_location) => raw_errors
6262
.into_iter()
63-
.map(|e| e.with_outer_location(outer_location.clone()).into_py(py))
63+
.map(|e| PyLineError::from_val_line_error(py, e.with_outer_location(outer_location.clone())))
64+
.collect(),
65+
None => raw_errors
66+
.into_iter()
67+
.map(|e| PyLineError::from_val_line_error(py, e))
6468
.collect(),
65-
None => raw_errors.into_iter().map(|e| e.into_py(py)).collect(),
69+
};
70+
let line_errors = match line_errors {
71+
Ok(errors) => errors,
72+
Err(err) => return err,
6673
};
6774
let validation_error = Self::new(line_errors, title, input_type, hide_input);
6875
match Py::new(py, validation_error) {
@@ -117,15 +124,17 @@ impl ValidationError {
117124
context: _,
118125
} = &line_error.error_type
119126
{
120-
let note: PyObject = if let Location::Empty = &line_error.location {
121-
"Pydantic: cause of loc: root".into_py(py)
127+
let note = if let Location::Empty = &line_error.location {
128+
PyString::new(py, "Pydantic: cause of loc: root")
122129
} else {
123-
format!(
124-
"Pydantic: cause of loc: {}",
125-
// Location formats with a newline at the end, hence the trim()
126-
line_error.location.to_string().trim()
130+
PyString::new(
131+
py,
132+
&format!(
133+
"Pydantic: cause of loc: {}",
134+
// Location formats with a newline at the end, hence the trim()
135+
line_error.location.to_string().trim()
136+
),
127137
)
128-
.into_py(py)
129138
};
130139

131140
// Notes only support 3.11 upwards:
@@ -144,7 +153,7 @@ impl ValidationError {
144153
{
145154
use pyo3::exceptions::PyUserWarning;
146155

147-
let wrapped = PyUserWarning::new_err((note,));
156+
let wrapped = PyUserWarning::new_err((note.unbind(),));
148157
wrapped.set_cause(py, Some(PyErr::from_value(err.clone_ref(py).into_bound(py))));
149158
user_py_errs.push(wrapped);
150159
}
@@ -159,7 +168,7 @@ impl ValidationError {
159168
#[cfg(Py_3_11)]
160169
let cause = {
161170
use pyo3::exceptions::PyBaseExceptionGroup;
162-
Some(PyBaseExceptionGroup::new_err((title, user_py_errs)).into_py(py))
171+
Some(PyBaseExceptionGroup::new_err((title, user_py_errs)).into_value(py))
163172
};
164173

165174
// Pre 3.11 ExceptionGroup support, use the python backport instead:
@@ -170,7 +179,7 @@ impl ValidationError {
170179
match py.import("exceptiongroup") {
171180
Ok(py_mod) => match py_mod.getattr("ExceptionGroup") {
172181
Ok(group_cls) => match group_cls.call1((title, user_py_errs)) {
173-
Ok(group_instance) => Some(group_instance.into_py(py)),
182+
Ok(group_instance) => Some(group_instance),
174183
Err(_) => None,
175184
},
176185
Err(_) => None,
@@ -308,10 +317,13 @@ impl ValidationError {
308317
return py.None();
309318
}
310319
e.as_dict(py, url_prefix, include_context, self.input_type, include_input)
311-
.unwrap_or_else(|err| {
312-
iteration_error = Some(err);
313-
py.None()
314-
})
320+
.map_or_else(
321+
|err| {
322+
iteration_error = Some(err);
323+
py.None()
324+
},
325+
Into::into,
326+
)
315327
}),
316328
)?;
317329
if let Some(err) = iteration_error {
@@ -379,7 +391,7 @@ impl ValidationError {
379391
self.__repr__(py)
380392
}
381393

382-
fn __reduce__<'py>(slf: &Bound<'py, Self>) -> PyResult<(Bound<'py, PyAny>, PyObject)> {
394+
fn __reduce__<'py>(slf: &Bound<'py, Self>) -> PyResult<(Bound<'py, PyAny>, Bound<'py, PyTuple>)> {
383395
let py = slf.py();
384396
let callable = slf.getattr("from_exception_data")?;
385397
let borrow = slf.try_borrow()?;
@@ -389,7 +401,7 @@ impl ValidationError {
389401
borrow.input_type.into_pyobject(py)?,
390402
borrow.hide_input,
391403
)
392-
.into_py(slf.py());
404+
.into_pyobject(slf.py())?;
393405
Ok((callable, args))
394406
}
395407
}
@@ -418,16 +430,6 @@ pub struct PyLineError {
418430
input_value: PyObject,
419431
}
420432

421-
impl IntoPy<PyLineError> for ValLineError {
422-
fn into_py(self, py: Python<'_>) -> PyLineError {
423-
PyLineError {
424-
error_type: self.error_type,
425-
location: self.location,
426-
input_value: self.input_value.to_object(py),
427-
}
428-
}
429-
}
430-
431433
impl From<PyLineError> for ValLineError {
432434
/// Used to extract line errors from a validation error for wrap functions
433435
fn from(other: PyLineError) -> ValLineError {
@@ -464,7 +466,7 @@ impl TryFrom<&Bound<'_, PyAny>> for PyLineError {
464466
let location = Location::try_from(dict.get_item("loc")?.as_ref())?;
465467

466468
let input_value = match dict.get_item("input")? {
467-
Some(i) => i.into_py(py),
469+
Some(i) => i.unbind(),
468470
None => py.None(),
469471
};
470472

@@ -477,18 +479,26 @@ impl TryFrom<&Bound<'_, PyAny>> for PyLineError {
477479
}
478480

479481
impl PyLineError {
482+
pub fn from_val_line_error(py: Python, error: ValLineError) -> PyResult<Self> {
483+
Ok(Self {
484+
error_type: error.error_type,
485+
location: error.location,
486+
input_value: error.input_value.into_pyobject(py)?.unbind(),
487+
})
488+
}
489+
480490
fn get_error_url(&self, url_prefix: &str) -> String {
481491
format!("{url_prefix}{}", self.error_type.type_string())
482492
}
483493

484-
pub fn as_dict(
494+
pub fn as_dict<'py>(
485495
&self,
486-
py: Python,
496+
py: Python<'py>,
487497
url_prefix: Option<&str>,
488498
include_context: bool,
489499
input_type: InputType,
490500
include_input: bool,
491-
) -> PyResult<PyObject> {
501+
) -> PyResult<Bound<'py, PyDict>> {
492502
let dict = PyDict::new(py);
493503
dict.set_item("type", self.error_type.type_string())?;
494504
dict.set_item("loc", self.location.to_object(py))?;
@@ -511,7 +521,7 @@ impl PyLineError {
511521
}
512522
}
513523
}
514-
Ok(dict.into_py(py))
524+
Ok(dict)
515525
}
516526

517527
fn pretty(

0 commit comments

Comments
 (0)