Skip to content

Commit c437ac6

Browse files
committed
deprecate PyTryFrom and PyTryInto
1 parent 7ecd127 commit c437ac6

File tree

8 files changed

+61
-38
lines changed

8 files changed

+61
-38
lines changed

newsfragments/3601.changed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Deprecate `PyTryFrom` and `PyTryInto` traits.

src/conversion.rs

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -355,11 +355,20 @@ where
355355
/// If `T` implements `PyTryFrom`, we can convert `&PyAny` to `&T`.
356356
///
357357
/// This trait is similar to `std::convert::TryFrom`
358+
#[deprecated(since = "0.21.0")]
358359
pub trait PyTryFrom<'v>: Sized + PyNativeType {
359360
/// Cast from a concrete Python object type to PyObject.
361+
#[deprecated(
362+
since = "0.21.0",
363+
note = "use `value.downcast::<T>()` instead of `T::try_from(value)`"
364+
)]
360365
fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>>;
361366

362367
/// Cast from a concrete Python object type to PyObject. With exact type check.
368+
#[deprecated(
369+
since = "0.21.0",
370+
note = "use `value.downcast_exact::<T>()` instead of `T::try_from_exact(value)`"
371+
)]
363372
fn try_from_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>>;
364373

365374
/// Cast a PyAny to a specific type of PyObject. The caller must
@@ -368,11 +377,16 @@ pub trait PyTryFrom<'v>: Sized + PyNativeType {
368377
/// # Safety
369378
///
370379
/// Callers must ensure that the type is valid or risk type confusion.
380+
#[deprecated(
381+
since = "0.21.0",
382+
note = "use `value.downcast_unchecked::<T>()` instead of `T::try_from_unchecked(value)`"
383+
)]
371384
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v Self;
372385
}
373386

374387
/// Trait implemented by Python object types that allow a checked downcast.
375388
/// This trait is similar to `std::convert::TryInto`
389+
#[deprecated(since = "0.21.0")]
376390
pub trait PyTryInto<T>: Sized {
377391
/// Cast from PyObject to a concrete Python object type.
378392
fn try_into(&self) -> Result<&T, PyDowncastError<'_>>;
@@ -381,6 +395,7 @@ pub trait PyTryInto<T>: Sized {
381395
fn try_into_exact(&self) -> Result<&T, PyDowncastError<'_>>;
382396
}
383397

398+
#[allow(deprecated)]
384399
mod implementations {
385400
use super::*;
386401

@@ -555,47 +570,50 @@ mod test_no_clone {}
555570

556571
#[cfg(test)]
557572
mod tests {
558-
use crate::PyObject;
559-
560-
use super::super::PyTryFrom;
561-
use crate::types::{IntoPyDict, PyAny, PyDict, PyList};
562-
use crate::{Python, ToPyObject};
563-
564-
#[test]
565-
fn test_try_from() {
566-
Python::with_gil(|py| {
567-
let list: &PyAny = vec![3, 6, 5, 4, 7].to_object(py).into_ref(py);
568-
let dict: &PyAny = vec![("reverse", true)].into_py_dict(py).as_ref();
569-
570-
assert!(<PyList as PyTryFrom<'_>>::try_from(list).is_ok());
571-
assert!(<PyDict as PyTryFrom<'_>>::try_from(dict).is_ok());
572-
573-
assert!(<PyAny as PyTryFrom<'_>>::try_from(list).is_ok());
574-
assert!(<PyAny as PyTryFrom<'_>>::try_from(dict).is_ok());
575-
});
576-
}
573+
use crate::{PyObject, Python};
574+
575+
#[allow(deprecated)]
576+
mod deprecated {
577+
use super::super::PyTryFrom;
578+
use crate::types::{IntoPyDict, PyAny, PyDict, PyList};
579+
use crate::{Python, ToPyObject};
580+
581+
#[test]
582+
fn test_try_from() {
583+
Python::with_gil(|py| {
584+
let list: &PyAny = vec![3, 6, 5, 4, 7].to_object(py).into_ref(py);
585+
let dict: &PyAny = vec![("reverse", true)].into_py_dict(py).as_ref();
586+
587+
assert!(<PyList as PyTryFrom<'_>>::try_from(list).is_ok());
588+
assert!(<PyDict as PyTryFrom<'_>>::try_from(dict).is_ok());
589+
590+
assert!(<PyAny as PyTryFrom<'_>>::try_from(list).is_ok());
591+
assert!(<PyAny as PyTryFrom<'_>>::try_from(dict).is_ok());
592+
});
593+
}
577594

578-
#[test]
579-
fn test_try_from_exact() {
580-
Python::with_gil(|py| {
581-
let list: &PyAny = vec![3, 6, 5, 4, 7].to_object(py).into_ref(py);
582-
let dict: &PyAny = vec![("reverse", true)].into_py_dict(py).as_ref();
595+
#[test]
596+
fn test_try_from_exact() {
597+
Python::with_gil(|py| {
598+
let list: &PyAny = vec![3, 6, 5, 4, 7].to_object(py).into_ref(py);
599+
let dict: &PyAny = vec![("reverse", true)].into_py_dict(py).as_ref();
583600

584-
assert!(PyList::try_from_exact(list).is_ok());
585-
assert!(PyDict::try_from_exact(dict).is_ok());
601+
assert!(PyList::try_from_exact(list).is_ok());
602+
assert!(PyDict::try_from_exact(dict).is_ok());
586603

587-
assert!(PyAny::try_from_exact(list).is_err());
588-
assert!(PyAny::try_from_exact(dict).is_err());
589-
});
590-
}
604+
assert!(PyAny::try_from_exact(list).is_err());
605+
assert!(PyAny::try_from_exact(dict).is_err());
606+
});
607+
}
591608

592-
#[test]
593-
fn test_try_from_unchecked() {
594-
Python::with_gil(|py| {
595-
let list = PyList::new(py, [1, 2, 3]);
596-
let val = unsafe { <PyList as PyTryFrom>::try_from_unchecked(list.as_ref()) };
597-
assert!(list.is(val));
598-
});
609+
#[test]
610+
fn test_try_from_unchecked() {
611+
Python::with_gil(|py| {
612+
let list = PyList::new(py, [1, 2, 3]);
613+
let val = unsafe { <PyList as PyTryFrom>::try_from_unchecked(list.as_ref()) };
614+
assert!(list.is(val));
615+
});
616+
}
599617
}
600618

601619
#[test]

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@
295295
//! [`Ungil`]: crate::marker::Ungil
296296
pub use crate::class::*;
297297
pub use crate::conversion::{AsPyPointer, FromPyObject, FromPyPointer, IntoPy, ToPyObject};
298+
#[allow(deprecated)]
298299
pub use crate::conversion::{PyTryFrom, PyTryInto};
299300
pub use crate::err::{PyDowncastError, PyErr, PyErrArguments, PyResult};
300301
pub use crate::gil::GILPool;

src/prelude.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//! ```
1010
1111
pub use crate::conversion::{FromPyObject, IntoPy, ToPyObject};
12+
#[allow(deprecated)]
1213
pub use crate::conversion::{PyTryFrom, PyTryInto};
1314
pub use crate::err::{PyErr, PyResult};
1415
pub use crate::instance::{Py, PyObject};

src/type_object.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ pub trait PySizedLayout<T>: PyLayout<T> + Sized {}
2323
///
2424
/// This is expected to be deprecated in the near future, see <https://github.com/PyO3/pyo3/issues/3382>
2525
///
26-
///
2726
/// # Safety
2827
///
2928
/// - `Py<Self>::as_ref` will hand out references to `Self::AsRefTarget`.

src/types/iterator.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ impl PyTypeCheck for PyIterator {
7878
}
7979
}
8080

81+
#[allow(deprecated)]
8182
impl<'v> crate::PyTryFrom<'v> for PyIterator {
8283
fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v PyIterator, PyDowncastError<'v>> {
8384
let value = value.into();

src/types/mapping.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ impl PyTypeCheck for PyMapping {
132132
}
133133
}
134134

135+
#[allow(deprecated)]
135136
impl<'v> crate::PyTryFrom<'v> for PyMapping {
136137
/// Downcasting to `PyMapping` requires the concrete class to be a subclass (or registered
137138
/// subclass) of `collections.abc.Mapping` (from the Python standard library) - i.e.

src/types/sequence.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ impl PyTypeCheck for PySequence {
337337
}
338338
}
339339

340+
#[allow(deprecated)]
340341
impl<'v> crate::PyTryFrom<'v> for PySequence {
341342
/// Downcasting to `PySequence` requires the concrete class to be a subclass (or registered
342343
/// subclass) of `collections.abc.Sequence` (from the Python standard library) - i.e.

0 commit comments

Comments
 (0)