Merge pull request #3601 from davidhewitt/deprecate-pytryfrom
deprecate `PyTryFrom` and `PyTryInto`
This commit is contained in:
commit
a3c92fa319
|
@ -16,6 +16,7 @@ To migrate, switch all type casts to use `obj.downcast()` instead of `try_from(o
|
||||||
Before:
|
Before:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
# #![allow(deprecated)]
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::types::{PyInt, PyList};
|
# use pyo3::types::{PyInt, PyList};
|
||||||
# fn main() -> PyResult<()> {
|
# fn main() -> PyResult<()> {
|
||||||
|
|
1
newsfragments/3601.changed.md
Normal file
1
newsfragments/3601.changed.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Deprecate `PyTryFrom` and `PyTryInto` traits in favor of `any.downcast()` via the `PyTypeCheck` and `PyTypeInfo` traits.
|
|
@ -355,11 +355,20 @@ where
|
||||||
/// If `T` implements `PyTryFrom`, we can convert `&PyAny` to `&T`.
|
/// If `T` implements `PyTryFrom`, we can convert `&PyAny` to `&T`.
|
||||||
///
|
///
|
||||||
/// This trait is similar to `std::convert::TryFrom`
|
/// This trait is similar to `std::convert::TryFrom`
|
||||||
|
#[deprecated(since = "0.21.0")]
|
||||||
pub trait PyTryFrom<'v>: Sized + PyNativeType {
|
pub trait PyTryFrom<'v>: Sized + PyNativeType {
|
||||||
/// Cast from a concrete Python object type to PyObject.
|
/// Cast from a concrete Python object type to PyObject.
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.21.0",
|
||||||
|
note = "use `value.downcast::<T>()` instead of `T::try_from(value)`"
|
||||||
|
)]
|
||||||
fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>>;
|
fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>>;
|
||||||
|
|
||||||
/// Cast from a concrete Python object type to PyObject. With exact type check.
|
/// Cast from a concrete Python object type to PyObject. With exact type check.
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.21.0",
|
||||||
|
note = "use `value.downcast_exact::<T>()` instead of `T::try_from_exact(value)`"
|
||||||
|
)]
|
||||||
fn try_from_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>>;
|
fn try_from_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>>;
|
||||||
|
|
||||||
/// Cast a PyAny to a specific type of PyObject. The caller must
|
/// Cast a PyAny to a specific type of PyObject. The caller must
|
||||||
|
@ -368,19 +377,33 @@ pub trait PyTryFrom<'v>: Sized + PyNativeType {
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// Callers must ensure that the type is valid or risk type confusion.
|
/// Callers must ensure that the type is valid or risk type confusion.
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.21.0",
|
||||||
|
note = "use `value.downcast_unchecked::<T>()` instead of `T::try_from_unchecked(value)`"
|
||||||
|
)]
|
||||||
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v Self;
|
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait implemented by Python object types that allow a checked downcast.
|
/// Trait implemented by Python object types that allow a checked downcast.
|
||||||
/// This trait is similar to `std::convert::TryInto`
|
/// This trait is similar to `std::convert::TryInto`
|
||||||
|
#[deprecated(since = "0.21.0")]
|
||||||
pub trait PyTryInto<T>: Sized {
|
pub trait PyTryInto<T>: Sized {
|
||||||
/// Cast from PyObject to a concrete Python object type.
|
/// Cast from PyObject to a concrete Python object type.
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.21.0",
|
||||||
|
note = "use `value.downcast()` instead of `value.try_into()`"
|
||||||
|
)]
|
||||||
fn try_into(&self) -> Result<&T, PyDowncastError<'_>>;
|
fn try_into(&self) -> Result<&T, PyDowncastError<'_>>;
|
||||||
|
|
||||||
/// Cast from PyObject to a concrete Python object type. With exact type check.
|
/// Cast from PyObject to a concrete Python object type. With exact type check.
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.21.0",
|
||||||
|
note = "use `value.downcast()` instead of `value.try_into_exact()`"
|
||||||
|
)]
|
||||||
fn try_into_exact(&self) -> Result<&T, PyDowncastError<'_>>;
|
fn try_into_exact(&self) -> Result<&T, PyDowncastError<'_>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
mod implementations {
|
mod implementations {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -555,47 +578,50 @@ mod test_no_clone {}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::PyObject;
|
use crate::{PyObject, Python};
|
||||||
|
|
||||||
use super::super::PyTryFrom;
|
#[allow(deprecated)]
|
||||||
use crate::types::{IntoPyDict, PyAny, PyDict, PyList};
|
mod deprecated {
|
||||||
use crate::{Python, ToPyObject};
|
use super::super::PyTryFrom;
|
||||||
|
use crate::types::{IntoPyDict, PyAny, PyDict, PyList};
|
||||||
|
use crate::{Python, ToPyObject};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_try_from() {
|
fn test_try_from() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let list: &PyAny = vec![3, 6, 5, 4, 7].to_object(py).into_ref(py);
|
let list: &PyAny = vec![3, 6, 5, 4, 7].to_object(py).into_ref(py);
|
||||||
let dict: &PyAny = vec![("reverse", true)].into_py_dict(py).as_ref();
|
let dict: &PyAny = vec![("reverse", true)].into_py_dict(py).as_ref();
|
||||||
|
|
||||||
assert!(<PyList as PyTryFrom<'_>>::try_from(list).is_ok());
|
assert!(<PyList as PyTryFrom<'_>>::try_from(list).is_ok());
|
||||||
assert!(<PyDict as PyTryFrom<'_>>::try_from(dict).is_ok());
|
assert!(<PyDict as PyTryFrom<'_>>::try_from(dict).is_ok());
|
||||||
|
|
||||||
assert!(<PyAny as PyTryFrom<'_>>::try_from(list).is_ok());
|
assert!(<PyAny as PyTryFrom<'_>>::try_from(list).is_ok());
|
||||||
assert!(<PyAny as PyTryFrom<'_>>::try_from(dict).is_ok());
|
assert!(<PyAny as PyTryFrom<'_>>::try_from(dict).is_ok());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_try_from_exact() {
|
fn test_try_from_exact() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let list: &PyAny = vec![3, 6, 5, 4, 7].to_object(py).into_ref(py);
|
let list: &PyAny = vec![3, 6, 5, 4, 7].to_object(py).into_ref(py);
|
||||||
let dict: &PyAny = vec![("reverse", true)].into_py_dict(py).as_ref();
|
let dict: &PyAny = vec![("reverse", true)].into_py_dict(py).as_ref();
|
||||||
|
|
||||||
assert!(PyList::try_from_exact(list).is_ok());
|
assert!(PyList::try_from_exact(list).is_ok());
|
||||||
assert!(PyDict::try_from_exact(dict).is_ok());
|
assert!(PyDict::try_from_exact(dict).is_ok());
|
||||||
|
|
||||||
assert!(PyAny::try_from_exact(list).is_err());
|
assert!(PyAny::try_from_exact(list).is_err());
|
||||||
assert!(PyAny::try_from_exact(dict).is_err());
|
assert!(PyAny::try_from_exact(dict).is_err());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_try_from_unchecked() {
|
fn test_try_from_unchecked() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let list = PyList::new(py, [1, 2, 3]);
|
let list = PyList::new(py, [1, 2, 3]);
|
||||||
let val = unsafe { <PyList as PyTryFrom>::try_from_unchecked(list.as_ref()) };
|
let val = unsafe { <PyList as PyTryFrom>::try_from_unchecked(list.as_ref()) };
|
||||||
assert!(list.is(val));
|
assert!(list.is(val));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1614,7 +1614,7 @@ a = A()
|
||||||
|
|
||||||
#[cfg(feature = "macros")]
|
#[cfg(feature = "macros")]
|
||||||
mod using_macros {
|
mod using_macros {
|
||||||
use crate::{PyCell, PyTryInto};
|
use crate::PyCell;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -1642,7 +1642,9 @@ a = A()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[allow(deprecated)]
|
||||||
fn cell_tryfrom() {
|
fn cell_tryfrom() {
|
||||||
|
use crate::PyTryInto;
|
||||||
// More detailed tests of the underlying semantics in pycell.rs
|
// More detailed tests of the underlying semantics in pycell.rs
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let instance: &PyAny = Py::new(py, SomeClass(0)).unwrap().into_ref(py);
|
let instance: &PyAny = Py::new(py, SomeClass(0)).unwrap().into_ref(py);
|
||||||
|
|
|
@ -295,6 +295,7 @@
|
||||||
//! [`Ungil`]: crate::marker::Ungil
|
//! [`Ungil`]: crate::marker::Ungil
|
||||||
pub use crate::class::*;
|
pub use crate::class::*;
|
||||||
pub use crate::conversion::{AsPyPointer, FromPyObject, FromPyPointer, IntoPy, ToPyObject};
|
pub use crate::conversion::{AsPyPointer, FromPyObject, FromPyPointer, IntoPy, ToPyObject};
|
||||||
|
#[allow(deprecated)]
|
||||||
pub use crate::conversion::{PyTryFrom, PyTryInto};
|
pub use crate::conversion::{PyTryFrom, PyTryInto};
|
||||||
pub use crate::err::{PyDowncastError, PyErr, PyErrArguments, PyResult};
|
pub use crate::err::{PyDowncastError, PyErr, PyErrArguments, PyResult};
|
||||||
pub use crate::gil::GILPool;
|
pub use crate::gil::GILPool;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
pub use crate::conversion::{FromPyObject, IntoPy, ToPyObject};
|
pub use crate::conversion::{FromPyObject, IntoPy, ToPyObject};
|
||||||
|
#[allow(deprecated)]
|
||||||
pub use crate::conversion::{PyTryFrom, PyTryInto};
|
pub use crate::conversion::{PyTryFrom, PyTryInto};
|
||||||
pub use crate::err::{PyErr, PyResult};
|
pub use crate::err::{PyErr, PyResult};
|
||||||
pub use crate::instance::{Py, PyObject};
|
pub use crate::instance::{Py, PyObject};
|
||||||
|
|
|
@ -23,7 +23,6 @@ pub trait PySizedLayout<T>: PyLayout<T> + Sized {}
|
||||||
///
|
///
|
||||||
/// This is expected to be deprecated in the near future, see <https://github.com/PyO3/pyo3/issues/3382>
|
/// This is expected to be deprecated in the near future, see <https://github.com/PyO3/pyo3/issues/3382>
|
||||||
///
|
///
|
||||||
///
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// - `Py<Self>::as_ref` will hand out references to `Self::AsRefTarget`.
|
/// - `Py<Self>::as_ref` will hand out references to `Self::AsRefTarget`.
|
||||||
|
|
|
@ -79,6 +79,7 @@ impl PyTypeCheck for PyIterator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
impl<'v> crate::PyTryFrom<'v> for PyIterator {
|
impl<'v> crate::PyTryFrom<'v> for PyIterator {
|
||||||
fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v PyIterator, PyDowncastError<'v>> {
|
fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v PyIterator, PyDowncastError<'v>> {
|
||||||
let value = value.into();
|
let value = value.into();
|
||||||
|
|
|
@ -135,6 +135,7 @@ impl PyTypeCheck for PyMapping {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
impl<'v> crate::PyTryFrom<'v> for PyMapping {
|
impl<'v> crate::PyTryFrom<'v> for PyMapping {
|
||||||
/// Downcasting to `PyMapping` requires the concrete class to be a subclass (or registered
|
/// Downcasting to `PyMapping` requires the concrete class to be a subclass (or registered
|
||||||
/// subclass) of `collections.abc.Mapping` (from the Python standard library) - i.e.
|
/// subclass) of `collections.abc.Mapping` (from the Python standard library) - i.e.
|
||||||
|
@ -168,7 +169,7 @@ mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
exceptions::PyKeyError,
|
exceptions::PyKeyError,
|
||||||
types::{PyDict, PyTuple},
|
types::{PyDict, PyTuple},
|
||||||
PyTryFrom, Python,
|
Python,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -318,7 +319,9 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[allow(deprecated)]
|
||||||
fn test_mapping_try_from() {
|
fn test_mapping_try_from() {
|
||||||
|
use crate::PyTryFrom;
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new(py);
|
||||||
let _ = <PyMapping as PyTryFrom>::try_from(dict).unwrap();
|
let _ = <PyMapping as PyTryFrom>::try_from(dict).unwrap();
|
||||||
|
|
|
@ -549,6 +549,7 @@ impl PyTypeCheck for PySequence {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
impl<'v> crate::PyTryFrom<'v> for PySequence {
|
impl<'v> crate::PyTryFrom<'v> for PySequence {
|
||||||
/// Downcasting to `PySequence` requires the concrete class to be a subclass (or registered
|
/// Downcasting to `PySequence` requires the concrete class to be a subclass (or registered
|
||||||
/// subclass) of `collections.abc.Sequence` (from the Python standard library) - i.e.
|
/// subclass) of `collections.abc.Sequence` (from the Python standard library) - i.e.
|
||||||
|
@ -577,7 +578,7 @@ impl<'v> crate::PyTryFrom<'v> for PySequence {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::types::{PyList, PySequence, PyTuple};
|
use crate::types::{PyList, PySequence, PyTuple};
|
||||||
use crate::{PyObject, PyTryFrom, Python, ToPyObject};
|
use crate::{PyObject, Python, ToPyObject};
|
||||||
|
|
||||||
fn get_object() -> PyObject {
|
fn get_object() -> PyObject {
|
||||||
// Convenience function for getting a single unique object
|
// Convenience function for getting a single unique object
|
||||||
|
@ -1078,7 +1079,9 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[allow(deprecated)]
|
||||||
fn test_seq_try_from() {
|
fn test_seq_try_from() {
|
||||||
|
use crate::PyTryFrom;
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let list = PyList::empty(py);
|
let list = PyList::empty(py);
|
||||||
let _ = <PySequence as PyTryFrom>::try_from(list).unwrap();
|
let _ = <PySequence as PyTryFrom>::try_from(list).unwrap();
|
||||||
|
|
Loading…
Reference in a new issue