Skip to content

Commit 8758528

Browse files
authored
resolve remaining deprecation warnings from PyO3 0.23 (#1584)
1 parent 261c7ab commit 8758528

Some content is hidden

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

42 files changed

+214
-230
lines changed

src/build_tools.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,12 @@ impl SchemaError {
9393
Ok(errors) => errors,
9494
Err(err) => return err,
9595
};
96-
let validation_error =
97-
ValidationError::new(line_errors, "Schema".to_object(py), InputType::Python, false);
96+
let validation_error = ValidationError::new(
97+
line_errors,
98+
PyString::new(py, "Schema").into(),
99+
InputType::Python,
100+
false,
101+
);
98102
let schema_error = SchemaError(SchemaErrorEnum::ValidationError(validation_error));
99103
match Py::new(py, schema_error) {
100104
Ok(err) => PyErr::from_value(err.into_bound(py).into_any()),

src/common/union.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub enum Discriminator {
1515
impl Discriminator {
1616
pub fn new(py: Python, raw: &Bound<'_, PyAny>) -> PyResult<Self> {
1717
if raw.is_callable() {
18-
return Ok(Self::Function(raw.to_object(py)));
18+
return Ok(Self::Function(raw.clone().unbind()));
1919
}
2020

2121
let lookup_key = LookupKey::from_py(py, raw, None)?;

src/errors/line_error.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,3 @@ pub enum InputValue {
169169
Python(PyObject),
170170
Json(JsonValue<'static>),
171171
}
172-
173-
impl ToPyObject for InputValue {
174-
fn to_object(&self, py: Python) -> PyObject {
175-
match self {
176-
Self::Python(input) => input.clone_ref(py),
177-
Self::Json(input) => input.to_object(py),
178-
}
179-
}
180-
}

src/errors/location.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,6 @@ impl From<PathItem> for LocItem {
8585
}
8686
}
8787

88-
impl ToPyObject for LocItem {
89-
fn to_object(&self, py: Python<'_>) -> PyObject {
90-
match self {
91-
Self::S(val) => val.to_object(py),
92-
Self::I(val) => val.to_object(py),
93-
}
94-
}
95-
}
96-
9788
impl Serialize for LocItem {
9889
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
9990
where
@@ -128,15 +119,20 @@ impl Default for Location {
128119
}
129120
}
130121

131-
static EMPTY_TUPLE: GILOnceCell<PyObject> = GILOnceCell::new();
122+
static EMPTY_TUPLE: GILOnceCell<Py<PyTuple>> = GILOnceCell::new();
123+
124+
impl<'py> IntoPyObject<'py> for &'_ Location {
125+
type Target = PyTuple;
126+
type Output = Bound<'py, PyTuple>;
127+
type Error = PyErr;
132128

133-
impl ToPyObject for Location {
134-
fn to_object(&self, py: Python<'_>) -> PyObject {
129+
fn into_pyobject(self, py: Python<'py>) -> PyResult<Bound<'py, PyTuple>> {
135130
match self {
136-
Self::List(loc) => PyTuple::new(py, loc.iter().rev()).unwrap().to_object(py),
137-
Self::Empty => EMPTY_TUPLE
138-
.get_or_init(py, || PyTuple::empty(py).to_object(py))
139-
.clone_ref(py),
131+
Location::List(loc) => PyTuple::new(py, loc.iter().rev()),
132+
Location::Empty => Ok(EMPTY_TUPLE
133+
.get_or_init(py, || PyTuple::empty(py).unbind())
134+
.bind(py)
135+
.clone()),
140136
}
141137
}
142138
}

src/errors/types.rs

Lines changed: 2 additions & 7 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::*;
67
use pyo3::sync::GILOnceCell;
78
use pyo3::types::{PyDict, PyList};
8-
use pyo3::{prelude::*, IntoPyObjectExt};
99

1010
use ahash::AHashMap;
1111
use num_bigint::BigInt;
@@ -124,7 +124,7 @@ macro_rules! error_types {
124124
$(
125125
Self::$item { context, $($key,)* } => {
126126
$(
127-
dict.set_item::<&str, Py<PyAny>>(stringify!($key), $key.to_object(py))?;
127+
dict.set_item(stringify!($key), $key)?;
128128
)*
129129
if let Some(ctx) = context {
130130
dict.update(ctx.bind(py).downcast::<PyMapping>()?)?;
@@ -824,8 +824,3 @@ impl fmt::Display for Number {
824824
}
825825
}
826826
}
827-
impl ToPyObject for Number {
828-
fn to_object(&self, py: Python<'_>) -> PyObject {
829-
self.into_py_any(py).unwrap()
830-
}
831-
}

src/errors/validation_exception.rs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::borrow::Cow;
12
use std::fmt;
23
use std::fmt::{Display, Write};
34
use std::str::from_utf8;
@@ -72,15 +73,15 @@ impl ValidationError {
7273
Err(err) => return err,
7374
};
7475
let validation_error = Self::new(line_errors, title, input_type, hide_input);
75-
match Py::new(py, validation_error) {
76+
match Bound::new(py, validation_error) {
7677
Ok(err) => {
7778
if validation_error_cause {
7879
// Will return an import error if the backport was needed and not installed:
79-
if let Some(cause_problem) = ValidationError::maybe_add_cause(err.borrow(py), py) {
80+
if let Some(cause_problem) = ValidationError::maybe_add_cause(err.borrow(), py) {
8081
return cause_problem;
8182
}
8283
}
83-
PyErr::from_value(err.into_bound(py).into_any())
84+
PyErr::from_value(err.into_any())
8485
}
8586
Err(err) => err,
8687
}
@@ -125,16 +126,13 @@ impl ValidationError {
125126
} = &line_error.error_type
126127
{
127128
let note = if let Location::Empty = &line_error.location {
128-
PyString::new(py, "Pydantic: cause of loc: root")
129+
Cow::Borrowed("Pydantic: cause of loc: root")
129130
} else {
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-
),
137-
)
131+
Cow::Owned(format!(
132+
"Pydantic: cause of loc: {}",
133+
// Location formats with a newline at the end, hence the trim()
134+
line_error.location.to_string().trim()
135+
))
138136
};
139137

140138
// Notes only support 3.11 upwards:
@@ -153,7 +151,7 @@ impl ValidationError {
153151
{
154152
use pyo3::exceptions::PyUserWarning;
155153

156-
let wrapped = PyUserWarning::new_err((note.unbind(),));
154+
let wrapped = PyUserWarning::new_err((note,));
157155
wrapped.set_cause(py, Some(PyErr::from_value(err.clone_ref(py).into_bound(py))));
158156
user_py_errs.push(wrapped);
159157
}
@@ -329,7 +327,7 @@ impl ValidationError {
329327
if let Some(err) = iteration_error {
330328
Err(err)
331329
} else {
332-
Ok(list.into())
330+
Ok(list.unbind())
333331
}
334332
}
335333

@@ -396,12 +394,12 @@ impl ValidationError {
396394
let callable = slf.getattr("from_exception_data")?;
397395
let borrow = slf.try_borrow()?;
398396
let args = (
399-
borrow.title.bind(py),
397+
&borrow.title,
400398
borrow.errors(py, include_url_env(py), true, true)?,
401-
borrow.input_type.into_pyobject(py)?,
399+
borrow.input_type,
402400
borrow.hide_input,
403401
)
404-
.into_pyobject(slf.py())?;
402+
.into_pyobject(py)?;
405403
Ok((callable, args))
406404
}
407405
}
@@ -501,7 +499,7 @@ impl PyLineError {
501499
) -> PyResult<Bound<'py, PyDict>> {
502500
let dict = PyDict::new(py);
503501
dict.set_item("type", self.error_type.type_string())?;
504-
dict.set_item("loc", self.location.to_object(py))?;
502+
dict.set_item("loc", &self.location)?;
505503
dict.set_item("msg", self.error_type.render_message(py, input_type)?)?;
506504
if include_input {
507505
dict.set_item("input", &self.input_value)?;

src/input/input_abstract.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::fmt;
33

44
use pyo3::exceptions::PyValueError;
55
use pyo3::types::{PyDict, PyList, PyString};
6-
use pyo3::{intern, prelude::*};
6+
use pyo3::{intern, prelude::*, IntoPyObjectExt};
77

88
use crate::errors::{ErrorTypeDefaults, InputValue, LocItem, ValError, ValResult};
99
use crate::lookup_key::{LookupKey, LookupPath};
@@ -23,15 +23,16 @@ pub enum InputType {
2323

2424
impl<'py> IntoPyObject<'py> for InputType {
2525
type Target = PyString;
26-
type Output = Bound<'py, PyString>;
26+
type Output = Borrowed<'py, 'py, PyString>;
2727
type Error = Infallible;
2828

29-
fn into_pyobject(self, py: Python<'_>) -> Result<Bound<'_, PyString>, Infallible> {
30-
Ok(match self {
31-
Self::Json => intern!(py, "json").clone(),
32-
Self::Python => intern!(py, "python").clone(),
33-
Self::String => intern!(py, "string").clone(),
34-
})
29+
fn into_pyobject(self, py: Python<'py>) -> Result<Borrowed<'py, 'py, PyString>, Infallible> {
30+
let text = match self {
31+
Self::Json => intern!(py, "json"),
32+
Self::Python => intern!(py, "python"),
33+
Self::String => intern!(py, "string"),
34+
};
35+
Ok(text.as_borrowed())
3536
}
3637
}
3738

@@ -54,7 +55,14 @@ pub type ValMatch<T> = ValResult<ValidationMatch<T>>;
5455
/// the convention is to either implement:
5556
/// * `strict_*` & `lax_*` if they have different behavior
5657
/// * or, `validate_*` and `strict_*` to just call `validate_*` if the behavior for strict and lax is the same
57-
pub trait Input<'py>: fmt::Debug + ToPyObject {
58+
pub trait Input<'py>: fmt::Debug {
59+
fn py_converter(&self) -> impl IntoPyObject<'py> + '_;
60+
61+
#[inline]
62+
fn to_object<'a>(&'a self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
63+
self.py_converter().into_bound_py_any(py)
64+
}
65+
5866
fn as_error_value(&self) -> InputValue;
5967

6068
fn is_none(&self) -> bool {
@@ -208,7 +216,7 @@ pub trait KeywordArgs<'py> {
208216
type Key<'a>: BorrowInput<'py> + Clone + Into<LocItem>
209217
where
210218
Self: 'a;
211-
type Item<'a>: BorrowInput<'py> + ToPyObject
219+
type Item<'a>: BorrowInput<'py>
212220
where
213221
Self: 'a;
214222
fn len(&self) -> usize;

src/input/input_json.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ impl From<JsonValue<'_>> for LocItem {
4444
}
4545

4646
impl<'py, 'data> Input<'py> for JsonValue<'data> {
47+
#[inline]
48+
fn py_converter(&self) -> impl IntoPyObject<'py> + '_ {
49+
self
50+
}
51+
4752
fn as_error_value(&self) -> InputValue {
4853
// cloning JsonValue is cheap due to use of Arc
4954
InputValue::Json(self.to_static())
@@ -58,7 +63,7 @@ impl<'py, 'data> Input<'py> for JsonValue<'data> {
5863
JsonValue::Object(object) => {
5964
let dict = PyDict::new(py);
6065
for (k, v) in LazyIndexMap::iter(object) {
61-
dict.set_item(k, v.to_object(py)).unwrap();
66+
dict.set_item(k, v).unwrap();
6267
}
6368
Some(dict)
6469
}
@@ -174,7 +179,7 @@ impl<'py, 'data> Input<'py> for JsonValue<'data> {
174179
create_decimal(&PyString::new(py, &f.to_string()), self).map(ValidationMatch::strict)
175180
}
176181
JsonValue::Str(..) | JsonValue::Int(..) | JsonValue::BigInt(..) => {
177-
create_decimal(self.to_object(py).bind(py), self).map(ValidationMatch::strict)
182+
create_decimal(&self.into_pyobject(py)?, self).map(ValidationMatch::strict)
178183
}
179184
_ => Err(ValError::new(ErrorTypeDefaults::DecimalType, self)),
180185
}
@@ -348,6 +353,11 @@ impl<'py, 'data> Input<'py> for JsonValue<'data> {
348353

349354
/// Required for JSON Object keys so the string can behave like an Input
350355
impl<'py> Input<'py> for str {
356+
#[inline]
357+
fn py_converter(&self) -> impl IntoPyObject<'py> + '_ {
358+
self
359+
}
360+
351361
fn as_error_value(&self) -> InputValue {
352362
// Justification for the clone: this is on the error pathway and we are generally ok
353363
// with errors having a performance penalty
@@ -414,7 +424,7 @@ impl<'py> Input<'py> for str {
414424
}
415425

416426
fn validate_decimal(&self, _strict: bool, py: Python<'py>) -> ValMatch<Bound<'py, PyAny>> {
417-
create_decimal(self.to_object(py).bind(py), self).map(ValidationMatch::lax)
427+
create_decimal(self.into_pyobject(py)?.as_any(), self).map(ValidationMatch::lax)
418428
}
419429

420430
type Dict<'a> = Never;
@@ -483,7 +493,7 @@ impl<'py> Input<'py> for str {
483493

484494
fn validate_complex(&self, _strict: bool, py: Python<'py>) -> ValResult<ValidationMatch<EitherComplex<'py>>> {
485495
Ok(ValidationMatch::strict(EitherComplex::Py(string_to_complex(
486-
self.to_object(py).downcast_bound::<PyString>(py)?,
496+
&self.into_pyobject(py)?,
487497
self,
488498
)?)))
489499
}

src/input/input_python.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ impl From<Bound<'_, PyAny>> for LocItem {
7575
}
7676

7777
impl<'py> Input<'py> for Bound<'py, PyAny> {
78+
#[inline]
79+
fn py_converter(&self) -> impl IntoPyObject<'py> + '_ {
80+
self
81+
}
82+
7883
fn as_error_value(&self) -> InputValue {
7984
InputValue::Python(self.clone().into())
8085
}
@@ -472,7 +477,7 @@ impl<'py> Input<'py> for Bound<'py, PyAny> {
472477
}
473478

474479
fn validate_iter(&self) -> ValResult<GenericIterator<'static>> {
475-
if self.iter().is_ok() {
480+
if self.try_iter().is_ok() {
476481
Ok(self.into())
477482
} else {
478483
Err(ValError::new(ErrorTypeDefaults::IterableType, self))
@@ -851,7 +856,7 @@ impl<'py> ValidatedDict<'py> for GenericPyMapping<'_, 'py> {
851856
Self::Mapping(mapping) => mapping
852857
.call_method0(intern!(mapping.py(), "keys"))
853858
.ok()?
854-
.iter()
859+
.try_iter()
855860
.ok()?
856861
.last()?
857862
.ok(),
@@ -891,7 +896,7 @@ fn extract_sequence_iterable<'a, 'py>(obj: &'a Bound<'py, PyAny>) -> ValResult<P
891896
|| obj.is_instance_of::<PyDict>()
892897
|| obj.downcast::<PyMapping>().is_ok())
893898
{
894-
if let Ok(iter) = obj.iter() {
899+
if let Ok(iter) = obj.try_iter() {
895900
return Ok(PySequenceIterable::Iterator(iter));
896901
}
897902
}
@@ -920,7 +925,7 @@ impl<'py> PySequenceIterable<'_, 'py> {
920925
PySequenceIterable::Tuple(iter) => Ok(consumer.consume_iterator(iter.iter().map(Ok))),
921926
PySequenceIterable::Set(iter) => Ok(consumer.consume_iterator(iter.iter().map(Ok))),
922927
PySequenceIterable::FrozenSet(iter) => Ok(consumer.consume_iterator(iter.iter().map(Ok))),
923-
PySequenceIterable::Iterator(iter) => Ok(consumer.consume_iterator(iter.iter()?)),
928+
PySequenceIterable::Iterator(iter) => Ok(consumer.consume_iterator(iter.try_iter()?)),
924929
}
925930
}
926931
}

0 commit comments

Comments
 (0)