Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
12 changes: 8 additions & 4 deletions src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2244,7 +2244,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 @@ -2253,18 +2253,22 @@ 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> {
unsafe { self.cast_bound_unchecked(py) }
#[allow(deprecated)]
unsafe {
self.bind(py).downcast_unchecked()
}
}
}

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