Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions newsfragments/5472.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Deprecate `PyAnyMethods::downcast` functions in favour of `Bound::cast` functions
2 changes: 1 addition & 1 deletion src/conversions/std/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ where
// to support this function and if not, we will only fail extraction safely.
let seq = unsafe {
if ffi::PySequence_Check(obj.as_ptr()) != 0 {
obj.downcast_unchecked::<PySequence>()
obj.cast_unchecked::<PySequence>()
} else {
return Err(DowncastError::new_from_type(
obj,
Expand Down
4 changes: 2 additions & 2 deletions src/err/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -857,12 +857,12 @@ impl std::fmt::Display for TypeNameOrValue<'_> {
match self {
Self::Name(name) => name.fmt(f),
Self::Value(t) => {
if let Ok(t) = t.downcast::<PyType>() {
if let Ok(t) = t.cast::<PyType>() {
t.qualname()
.map_err(|_| std::fmt::Error)?
.to_string_lossy()
.fmt(f)
} else if let Ok(t) = t.downcast::<PyTuple>() {
} else if let Ok(t) = t.cast::<PyTuple>() {
for (i, t) in t.iter().enumerate() {
if i > 0 {
f.write_str(" | ")?;
Expand Down
6 changes: 2 additions & 4 deletions src/impl_/extract_argument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,17 +188,15 @@ pub fn extract_pyclass_ref<'a, 'holder, T: PyClass>(
obj: &'a Bound<'_, PyAny>,
holder: &'holder mut Option<PyClassGuard<'a, T>>,
) -> PyResult<&'holder T> {
Ok(&*holder.insert(PyClassGuard::try_borrow(obj.downcast()?.as_unbound())?))
Ok(&*holder.insert(PyClassGuard::try_borrow(obj.cast()?.as_unbound())?))
}

#[inline]
pub fn extract_pyclass_ref_mut<'a, 'holder, T: PyClass<Frozen = False>>(
obj: &'a Bound<'_, PyAny>,
holder: &'holder mut Option<PyClassGuardMut<'a, T>>,
) -> PyResult<&'holder mut T> {
Ok(&mut *holder.insert(PyClassGuardMut::try_borrow_mut(
obj.downcast()?.as_unbound(),
)?))
Ok(&mut *holder.insert(PyClassGuardMut::try_borrow_mut(obj.cast()?.as_unbound())?))
}

/// The standard implementation of how PyO3 extracts a `#[pyfunction]` or `#[pymethod]` function argument.
Expand Down
9 changes: 6 additions & 3 deletions src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2254,6 +2254,7 @@ impl Py<PyAny> {
/// # Example: Downcasting to a specific Python object
///
/// ```rust
/// # #![allow(deprecated)]
/// use pyo3::prelude::*;
/// use pyo3::types::{PyDict, PyList};
///
Expand All @@ -2270,6 +2271,7 @@ impl Py<PyAny> {
/// This is useful if you want to mutate a `Py<PyAny>` that might actually be a pyclass.
///
/// ```rust
/// # #![allow(deprecated)]
/// # fn main() -> Result<(), pyo3::PyErr> {
/// use pyo3::prelude::*;
///
Expand All @@ -2292,7 +2294,7 @@ impl Py<PyAny> {
/// })
/// # }
/// ```
// FIXME(icxolu) deprecate in favor of `Py::cast_bound`
#[deprecated(since = "0.27.0", note = "use `Py::cast_bound` instead")]
#[inline]
pub fn downcast_bound<'py, T>(
&self,
Expand All @@ -2301,15 +2303,16 @@ impl Py<PyAny> {
where
T: PyTypeCheck,
{
self.cast_bound(py)
#[allow(deprecated)]
self.bind(py).downcast()
}

/// Casts the `Py<PyAny>` to a concrete Python object type without checking validity.
///
/// # Safety
///
/// Callers must ensure that the type is valid or risk type confusion.
// FIXME(icxolu) deprecate in favor of `Py::cast_bound_unchecked`
#[deprecated(since = "0.27.0", note = "use `Py::cast_bound_unchecked` instead")]
#[inline]
pub unsafe fn downcast_bound_unchecked<'py, T>(&self, py: Python<'py>) -> &Bound<'py, T> {
// SAFETY: caller has upheld the safety contract
Expand Down
5 changes: 1 addition & 4 deletions src/sync/once_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,7 @@ where
attr_name: &str,
) -> PyResult<&Bound<'py, T>> {
self.get_or_try_init(py, || {
let type_object = py
.import(module_name)?
.getattr(attr_name)?
.downcast_into()?;
let type_object = py.import(module_name)?.getattr(attr_name)?.cast_into()?;
Ok(type_object.unbind())
})
.map(|ty| ty.bind(py))
Expand Down
44 changes: 34 additions & 10 deletions src/types/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ pub trait PyAnyMethods<'py>: crate::sealed::Sealed {
/// })
/// # }
/// ```
// FIXME(icxolu) deprecate in favor of `Bound::cast`
#[deprecated(since = "0.27.0", note = "use `Bound::cast` instead")]
fn downcast<T>(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>>
where
T: PyTypeCheck;
Expand Down Expand Up @@ -800,7 +800,7 @@ pub trait PyAnyMethods<'py>: crate::sealed::Sealed {
/// assert!(obj.downcast_into::<PyDict>().is_ok());
/// })
/// ```
// FIXME(icxolu) deprecate in favor of `Bound::cast_into`
#[deprecated(since = "0.27.0", note = "use `Bound::cast_into` instead")]
fn downcast_into<T>(self) -> Result<Bound<'py, T>, DowncastIntoError<'py>>
where
T: PyTypeCheck;
Expand Down Expand Up @@ -836,13 +836,13 @@ pub trait PyAnyMethods<'py>: crate::sealed::Sealed {
/// assert!(any.downcast_exact::<PyBool>().is_ok());
/// });
/// ```
// FIXME(icxolu) deprecate in favor of `Bound::cast_exact`
#[deprecated(since = "0.27.0", note = "use `Bound::cast_exact` instead")]
fn downcast_exact<T>(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>>
where
T: PyTypeInfo;

/// Like `downcast_exact` but takes ownership of `self`.
// FIXME(icxolu) deprecate in favor of `Bound::cast_into_exact`
#[deprecated(since = "0.27.0", note = "use `Bound::cast_into_exact` instead")]
fn downcast_into_exact<T>(self) -> Result<Bound<'py, T>, DowncastIntoError<'py>>
where
T: PyTypeInfo;
Expand All @@ -852,15 +852,15 @@ pub trait PyAnyMethods<'py>: crate::sealed::Sealed {
/// # Safety
///
/// Callers must ensure that the type is valid or risk type confusion.
// FIXME(icxolu) deprecate in favor of `Bound::cast_unchecked`
#[deprecated(since = "0.27.0", note = "use `Bound::cast_unchecked` instead")]
unsafe fn downcast_unchecked<T>(&self) -> &Bound<'py, T>;

/// Like `downcast_unchecked` but takes ownership of `self`.
///
/// # Safety
///
/// Callers must ensure that the type is valid or risk type confusion.
// FIXME(icxolu) deprecate in favor of `Bound::cast_into_unchecked`
#[deprecated(since = "0.27.0", note = "use `Bound::cast_into_unchecked` instead")]
unsafe fn downcast_into_unchecked<T>(self) -> Bound<'py, T>;

/// Extracts some type from the Python object.
Expand Down Expand Up @@ -1449,31 +1449,55 @@ impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {
where
T: PyTypeCheck,
{
self.cast()
if T::type_check(self) {
// Safety: type_check is responsible for ensuring that the type is correct
Ok(unsafe { self.cast_unchecked() })
} else {
#[allow(deprecated)]
Err(DowncastError::new(self, T::NAME))
}
}

#[inline]
fn downcast_into<T>(self) -> Result<Bound<'py, T>, DowncastIntoError<'py>>
where
T: PyTypeCheck,
{
self.cast_into()
if T::type_check(&self) {
// Safety: type_check is responsible for ensuring that the type is correct
Ok(unsafe { self.cast_into_unchecked() })
} else {
#[allow(deprecated)]
Err(DowncastIntoError::new(self, T::NAME))
}
}

#[inline]
fn downcast_exact<T>(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>>
where
T: PyTypeInfo,
{
self.cast_exact()
if T::is_exact_type_of(self) {
// Safety: is_exact_type_of is responsible for ensuring that the type is correct
Ok(unsafe { self.cast_unchecked() })
} else {
#[allow(deprecated)]
Err(DowncastError::new(self, T::NAME))
}
}

#[inline]
fn downcast_into_exact<T>(self) -> Result<Bound<'py, T>, DowncastIntoError<'py>>
where
T: PyTypeInfo,
{
self.cast_into_exact()
if T::is_exact_type_of(&self) {
// Safety: is_exact_type_of is responsible for ensuring that the type is correct
Ok(unsafe { self.cast_into_unchecked() })
} else {
#[allow(deprecated)]
Err(DowncastIntoError::new(self, T::NAME))
}
}

#[inline]
Expand Down
Loading