remove all functionality deprecated in PyO3 0.21 (#4323)

* remove all functionality deprecated in PyO3 0.21

* further adjustments after removing deprecated APIs
This commit is contained in:
David Hewitt 2024-07-10 14:38:30 +01:00 committed by GitHub
parent 32b6a1aef1
commit 3c65132da5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 9 additions and 494 deletions

View File

@ -235,8 +235,7 @@ The `__next__` and `__anext__` magic methods can now return any type convertible
Starting with an implementation of a Python iterator using `IterNextOutput`, e.g.
```rust
#![allow(deprecated)]
```rust,ignore
use pyo3::prelude::*;
use pyo3::iter::IterNextOutput;

View File

@ -0,0 +1 @@
Remove all functionality deprecated in PyO3 0.21.

View File

@ -8,10 +8,7 @@ use crate::types::PyTuple;
use crate::{ffi, Borrowed, Bound, Py, PyAny, PyClass, PyObject, PyRef, PyRefMut, Python};
#[cfg(feature = "gil-refs")]
use {
crate::{
err::{self, PyDowncastError},
gil, PyNativeType,
},
crate::{err, gil, PyNativeType},
std::ptr::NonNull,
};
@ -395,121 +392,6 @@ where
}
}
/// Trait implemented by Python object types that allow a checked downcast.
/// If `T` implements `PyTryFrom`, we can convert `&PyAny` to `&T`.
///
/// This trait is similar to `std::convert::TryFrom`
#[cfg(feature = "gil-refs")]
#[deprecated(since = "0.21.0")]
pub trait PyTryFrom<'v>: Sized + PyNativeType {
/// 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>>;
/// 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>>;
/// Cast a PyAny to a specific type of PyObject. The caller must
/// have already verified the reference is for this type.
///
/// # Safety
///
/// 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;
}
/// Trait implemented by Python object types that allow a checked downcast.
/// This trait is similar to `std::convert::TryInto`
#[cfg(feature = "gil-refs")]
#[deprecated(since = "0.21.0")]
pub trait PyTryInto<T>: Sized {
/// 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<'_>>;
/// 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<'_>>;
}
#[cfg(feature = "gil-refs")]
#[allow(deprecated)]
mod implementations {
use super::*;
use crate::type_object::PyTypeInfo;
// TryFrom implies TryInto
impl<U> PyTryInto<U> for PyAny
where
U: for<'v> PyTryFrom<'v>,
{
fn try_into(&self) -> Result<&U, PyDowncastError<'_>> {
<U as PyTryFrom<'_>>::try_from(self)
}
fn try_into_exact(&self) -> Result<&U, PyDowncastError<'_>> {
U::try_from_exact(self)
}
}
impl<'v, T> PyTryFrom<'v> for T
where
T: PyTypeInfo<AsRefTarget = Self> + PyNativeType,
{
fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>> {
value.into().downcast()
}
fn try_from_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>> {
value.into().downcast_exact()
}
#[inline]
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v Self {
value.into().downcast_unchecked()
}
}
impl<'v, T> PyTryFrom<'v> for crate::PyCell<T>
where
T: 'v + PyClass,
{
fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>> {
value.into().downcast()
}
fn try_from_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>> {
let value = value.into();
unsafe {
if T::is_exact_type_of(value) {
Ok(Self::try_from_unchecked(value))
} else {
Err(PyDowncastError::new(value, T::NAME))
}
}
}
#[inline]
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v Self {
value.into().downcast_unchecked()
}
}
}
/// Converts `()` to an empty Python tuple.
impl IntoPy<Py<PyTuple>> for () {
fn into_py(self, py: Python<'_>) -> Py<PyTuple> {
@ -665,51 +547,3 @@ where
/// })
/// ```
mod test_no_clone {}
#[cfg(test)]
mod tests {
#[cfg(feature = "gil-refs")]
#[allow(deprecated)]
mod deprecated {
use super::super::PyTryFrom;
use crate::types::{IntoPyDict, PyAny, PyDict, PyList};
use crate::{Python, ToPyObject};
#[test]
fn test_try_from() {
Python::with_gil(|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();
assert!(<PyList as PyTryFrom<'_>>::try_from(list).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(dict).is_ok());
});
}
#[test]
fn test_try_from_exact() {
Python::with_gil(|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();
assert!(PyList::try_from_exact(list).is_ok());
assert!(PyDict::try_from_exact(dict).is_ok());
assert!(PyAny::try_from_exact(list).is_err());
assert!(PyAny::try_from_exact(dict).is_err());
});
}
#[test]
fn test_try_from_unchecked() {
Python::with_gil(|py| {
let list = PyList::new(py, [1, 2, 3]);
let val = unsafe { <PyList as PyTryFrom>::try_from_unchecked(list.as_ref()) };
assert!(list.is(val));
});
}
}
}

View File

@ -1385,14 +1385,6 @@ impl<T> Py<T> {
unsafe { ffi::Py_None() == self.as_ptr() }
}
/// Returns whether the object is considered to be true.
///
/// This is equivalent to the Python expression `bool(self)`.
#[deprecated(since = "0.21.0", note = "use `.is_truthy()` instead")]
pub fn is_true(&self, py: Python<'_>) -> PyResult<bool> {
self.is_truthy(py)
}
/// Returns whether the object is considered to be true.
///
/// This applies truth value testing equivalent to the Python expression `bool(self)`.
@ -2365,18 +2357,5 @@ a = A()
}
})
}
#[test]
#[cfg(feature = "gil-refs")]
#[allow(deprecated)]
fn cell_tryfrom() {
use crate::{PyCell, PyTryInto};
// More detailed tests of the underlying semantics in pycell.rs
Python::with_gil(|py| {
let instance: &PyAny = Py::new(py, SomeClass(0)).unwrap().into_ref(py);
let _: &PyCell<SomeClass> = PyTryInto::try_into(instance).unwrap();
let _: &PyCell<SomeClass> = PyTryInto::try_into_exact(instance).unwrap();
})
}
}
}

View File

@ -318,9 +318,6 @@
pub use crate::class::*;
pub use crate::conversion::{AsPyPointer, FromPyObject, IntoPy, ToPyObject};
#[cfg(feature = "gil-refs")]
#[allow(deprecated)]
pub use crate::conversion::{FromPyPointer, PyTryFrom, PyTryInto};
#[cfg(feature = "gil-refs")]
pub use crate::err::PyDowncastError;
pub use crate::err::{DowncastError, DowncastIntoError, PyErr, PyErrArguments, PyResult, ToPyErr};
#[cfg(feature = "gil-refs")]
@ -382,30 +379,6 @@ pub mod class {
pub use crate::pyclass::CompareOp;
}
/// Old module which contained some implementation details of the `#[pyproto]` module.
///
/// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::IterANextOutput` instead
/// of `use pyo3::class::pyasync::IterANextOutput`.
///
/// For compatibility reasons this has not yet been removed, however will be done so
/// once <https://github.com/rust-lang/rust/issues/30827> is resolved.
pub mod pyasync {
#[allow(deprecated)]
pub use crate::pyclass::{IterANextOutput, PyIterANextOutput};
}
/// Old module which contained some implementation details of the `#[pyproto]` module.
///
/// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::IterNextOutput` instead
/// of `use pyo3::class::pyasync::IterNextOutput`.
///
/// For compatibility reasons this has not yet been removed, however will be done so
/// once <https://github.com/rust-lang/rust/issues/30827> is resolved.
pub mod iter {
#[allow(deprecated)]
pub use crate::pyclass::{IterNextOutput, PyIterNextOutput};
}
/// Old module which contained some implementation details of the `#[pyproto]` module.
///
/// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::PyTraverseError` instead

View File

@ -126,10 +126,10 @@ use crate::types::{
PyAny, PyDict, PyEllipsis, PyModule, PyNone, PyNotImplemented, PyString, PyType,
};
use crate::version::PythonVersionInfo;
use crate::{ffi, Bound, IntoPy, Py, PyObject, PyTypeInfo};
#[allow(deprecated)]
#[cfg(feature = "gil-refs")]
use crate::{gil::GILPool, FromPyPointer, PyNativeType};
use crate::{conversion::FromPyPointer, gil::GILPool, PyNativeType};
use crate::{ffi, Bound, IntoPy, Py, PyObject, PyTypeInfo};
use std::ffi::{CStr, CString};
use std::marker::PhantomData;
use std::os::raw::c_int;
@ -801,42 +801,6 @@ impl<'py> Python<'py> {
PythonVersionInfo::from_str(version_number_str).unwrap()
}
/// Registers the object in the release pool, and tries to downcast to specific type.
#[cfg(feature = "gil-refs")]
#[deprecated(
since = "0.21.0",
note = "use `obj.downcast_bound::<T>(py)` instead of `py.checked_cast_as::<T>(obj)`"
)]
pub fn checked_cast_as<T>(
self,
obj: PyObject,
) -> Result<&'py T, crate::err::PyDowncastError<'py>>
where
T: crate::PyTypeCheck<AsRefTarget = T>,
{
#[allow(deprecated)]
obj.into_ref(self).downcast()
}
/// Registers the object in the release pool, and does an unchecked downcast
/// to the specific type.
///
/// # Safety
///
/// Callers must ensure that ensure that the cast is valid.
#[cfg(feature = "gil-refs")]
#[deprecated(
since = "0.21.0",
note = "use `obj.downcast_bound_unchecked::<T>(py)` instead of `py.cast_as::<T>(obj)`"
)]
pub unsafe fn cast_as<T>(self, obj: PyObject) -> &'py T
where
T: crate::type_object::HasPyGilRef<AsRefTarget = T>,
{
#[allow(deprecated)]
obj.into_ref(self).downcast_unchecked()
}
/// Registers the object pointer in the release pool,
/// and does an unchecked downcast to the specific type.
///

View File

@ -9,9 +9,6 @@
//! ```
pub use crate::conversion::{FromPyObject, IntoPy, ToPyObject};
#[cfg(feature = "gil-refs")]
#[allow(deprecated)]
pub use crate::conversion::{PyTryFrom, PyTryInto};
pub use crate::err::{PyErr, PyResult};
pub use crate::instance::{Borrowed, Bound, Py, PyObject};
pub use crate::marker::Python;

View File

@ -1,8 +1,5 @@
//! `PyClass` and related traits.
use crate::{
callback::IntoPyCallbackOutput, ffi, impl_::pyclass::PyClassImpl, IntoPy, PyObject, PyResult,
PyTypeInfo, Python,
};
use crate::{ffi, impl_::pyclass::PyClassImpl, PyTypeInfo};
use std::{cmp::Ordering, os::raw::c_int};
mod create_type_object;
@ -99,111 +96,6 @@ impl CompareOp {
}
}
/// Output of `__next__` which can either `yield` the next value in the iteration, or
/// `return` a value to raise `StopIteration` in Python.
///
/// Usage example:
///
/// ```rust
/// # #![allow(deprecated)]
/// use pyo3::prelude::*;
/// use pyo3::iter::IterNextOutput;
///
/// #[pyclass]
/// struct PyClassIter {
/// count: usize,
/// }
///
/// #[pymethods]
/// impl PyClassIter {
/// #[new]
/// pub fn new() -> Self {
/// PyClassIter { count: 0 }
/// }
///
/// fn __next__(&mut self) -> IterNextOutput<usize, &'static str> {
/// if self.count < 5 {
/// self.count += 1;
/// // Given an instance `counter`, First five `next(counter)` calls yield 1, 2, 3, 4, 5.
/// IterNextOutput::Yield(self.count)
/// } else {
/// // At the sixth time, we get a `StopIteration` with `'Ended'`.
/// // try:
/// // next(counter)
/// // except StopIteration as e:
/// // assert e.value == 'Ended'
/// IterNextOutput::Return("Ended")
/// }
/// }
/// }
/// ```
#[deprecated(since = "0.21.0", note = "Use `Option` or `PyStopIteration` instead.")]
pub enum IterNextOutput<T, U> {
/// The value yielded by the iterator.
Yield(T),
/// The `StopIteration` object.
Return(U),
}
/// Alias of `IterNextOutput` with `PyObject` yield & return values.
#[deprecated(since = "0.21.0", note = "Use `Option` or `PyStopIteration` instead.")]
#[allow(deprecated)]
pub type PyIterNextOutput = IterNextOutput<PyObject, PyObject>;
#[allow(deprecated)]
impl<T, U> IntoPyCallbackOutput<*mut ffi::PyObject> for IterNextOutput<T, U>
where
T: IntoPy<PyObject>,
U: IntoPy<PyObject>,
{
fn convert(self, py: Python<'_>) -> PyResult<*mut ffi::PyObject> {
match self {
IterNextOutput::Yield(o) => Ok(o.into_py(py).into_ptr()),
IterNextOutput::Return(o) => {
Err(crate::exceptions::PyStopIteration::new_err(o.into_py(py)))
}
}
}
}
/// Output of `__anext__`.
///
/// <https://docs.python.org/3/reference/expressions.html#agen.__anext__>
#[deprecated(
since = "0.21.0",
note = "Use `Option` or `PyStopAsyncIteration` instead."
)]
pub enum IterANextOutput<T, U> {
/// An expression which the generator yielded.
Yield(T),
/// A `StopAsyncIteration` object.
Return(U),
}
/// An [IterANextOutput] of Python objects.
#[deprecated(
since = "0.21.0",
note = "Use `Option` or `PyStopAsyncIteration` instead."
)]
#[allow(deprecated)]
pub type PyIterANextOutput = IterANextOutput<PyObject, PyObject>;
#[allow(deprecated)]
impl<T, U> IntoPyCallbackOutput<*mut ffi::PyObject> for IterANextOutput<T, U>
where
T: IntoPy<PyObject>,
U: IntoPy<PyObject>,
{
fn convert(self, py: Python<'_>) -> PyResult<*mut ffi::PyObject> {
match self {
IterANextOutput::Yield(o) => Ok(o.into_py(py).into_ptr()),
IterANextOutput::Return(o) => Err(crate::exceptions::PyStopAsyncIteration::new_err(
o.into_py(py),
)),
}
}
}
/// A workaround for [associated const equality](https://github.com/rust-lang/rust/issues/92827).
///
/// This serves to have True / False values in the [`PyClass`] trait's `Frozen` type.

View File

@ -581,14 +581,6 @@ impl PyAny {
.map(Bound::into_gil_ref)
}
/// Returns whether the object is considered to be true.
///
/// This is equivalent to the Python expression `bool(self)`.
#[deprecated(since = "0.21.0", note = "use `.is_truthy()` instead")]
pub fn is_true(&self) -> PyResult<bool> {
self.is_truthy()
}
/// Returns whether the object is considered to be true.
///
/// This applies truth value testing equivalent to the Python expression `bool(self)`.

View File

@ -3,7 +3,7 @@ use crate::instance::Borrowed;
use crate::py_result_ext::PyResultExt;
use crate::{ffi, Bound, PyAny, PyErr, PyResult, PyTypeCheck};
#[cfg(feature = "gil-refs")]
use crate::{AsPyPointer, PyDowncastError, PyNativeType};
use crate::{AsPyPointer, PyNativeType};
/// A Python iterator object.
///
@ -130,31 +130,6 @@ impl PyTypeCheck for PyIterator {
}
}
#[cfg(feature = "gil-refs")]
#[allow(deprecated)]
impl<'v> crate::PyTryFrom<'v> for PyIterator {
fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v PyIterator, PyDowncastError<'v>> {
let value = value.into();
unsafe {
if ffi::PyIter_Check(value.as_ptr()) != 0 {
Ok(value.downcast_unchecked())
} else {
Err(PyDowncastError::new(value, "Iterator"))
}
}
}
fn try_from_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v PyIterator, PyDowncastError<'v>> {
value.into().downcast()
}
#[inline]
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v PyIterator {
let ptr = value.into() as *const _ as *const PyIterator;
&*ptr
}
}
#[cfg(test)]
mod tests {
use super::PyIterator;
@ -298,18 +273,6 @@ def fibonacci(target):
});
}
#[test]
#[cfg(feature = "gil-refs")]
#[allow(deprecated)]
fn iterator_try_from() {
Python::with_gil(|py| {
let obj: crate::Py<crate::PyAny> =
vec![10, 20].to_object(py).as_ref(py).iter().unwrap().into();
let iter = <PyIterator as crate::PyTryFrom>::try_from(obj.as_ref(py)).unwrap();
assert!(obj.is(iter));
});
}
#[test]
#[cfg(feature = "macros")]
fn python_class_not_iterator() {

View File

@ -7,7 +7,7 @@ use crate::type_object::PyTypeInfo;
use crate::types::any::PyAnyMethods;
use crate::types::{PyAny, PyDict, PySequence, PyType};
#[cfg(feature = "gil-refs")]
use crate::{err::PyDowncastError, PyNativeType};
use crate::PyNativeType;
use crate::{ffi, Py, PyTypeCheck, Python, ToPyObject};
/// Represents a reference to a Python object supporting the mapping protocol.
@ -266,34 +266,6 @@ impl PyTypeCheck for PyMapping {
}
}
#[cfg(feature = "gil-refs")]
#[allow(deprecated)]
impl<'v> crate::PyTryFrom<'v> for PyMapping {
/// 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.
/// `isinstance(<class>, collections.abc.Mapping) == True`.
fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v PyMapping, PyDowncastError<'v>> {
let value = value.into();
if PyMapping::type_check(&value.as_borrowed()) {
unsafe { return Ok(value.downcast_unchecked()) }
}
Err(PyDowncastError::new(value, "Mapping"))
}
#[inline]
fn try_from_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v PyMapping, PyDowncastError<'v>> {
value.into().downcast()
}
#[inline]
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v PyMapping {
let ptr = value.into() as *const _ as *const PyMapping;
&*ptr
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
@ -445,16 +417,4 @@ mod tests {
assert_eq!(32 + 42 + 123, values_sum);
});
}
#[test]
#[cfg(feature = "gil-refs")]
#[allow(deprecated)]
fn test_mapping_try_from() {
use crate::PyTryFrom;
Python::with_gil(|py| {
let dict = PyDict::new(py);
let _ = <PyMapping as PyTryFrom>::try_from(dict).unwrap();
let _ = PyMapping::try_from_exact(dict).unwrap();
});
}
}

View File

@ -10,7 +10,7 @@ use crate::sync::GILOnceCell;
use crate::type_object::PyTypeInfo;
use crate::types::{any::PyAnyMethods, PyAny, PyList, PyString, PyTuple, PyType};
#[cfg(feature = "gil-refs")]
use crate::{err::PyDowncastError, PyNativeType};
use crate::PyNativeType;
use crate::{ffi, FromPyObject, Py, PyTypeCheck, Python, ToPyObject};
/// Represents a reference to a Python object supporting the sequence protocol.
@ -553,33 +553,6 @@ impl PyTypeCheck for PySequence {
}
}
#[cfg(feature = "gil-refs")]
#[allow(deprecated)]
impl<'v> crate::PyTryFrom<'v> for PySequence {
/// 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.
/// `isinstance(<class>, collections.abc.Sequence) == True`.
fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v PySequence, PyDowncastError<'v>> {
let value = value.into();
if PySequence::type_check(&value.as_borrowed()) {
unsafe { return Ok(value.downcast_unchecked::<PySequence>()) }
}
Err(PyDowncastError::new(value, "Sequence"))
}
fn try_from_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v PySequence, PyDowncastError<'v>> {
value.into().downcast()
}
#[inline]
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v PySequence {
let ptr = value.into() as *const _ as *const PySequence;
&*ptr
}
}
#[cfg(test)]
mod tests {
use crate::types::{PyAnyMethods, PyList, PySequence, PySequenceMethods, PyTuple};
@ -1107,16 +1080,4 @@ mod tests {
assert!(seq_from.to_list().is_ok());
});
}
#[test]
#[cfg(feature = "gil-refs")]
#[allow(deprecated)]
fn test_seq_try_from() {
use crate::PyTryFrom;
Python::with_gil(|py| {
let list = PyList::empty(py);
let _ = <PySequence as PyTryFrom>::try_from(list).unwrap();
let _ = PySequence::try_from_exact(list).unwrap();
});
}
}