Update downcast documentation

This commit is contained in:
mejrs 2023-01-24 19:15:32 +01:00
parent 18081ba14e
commit fe7b1eed04
2 changed files with 78 additions and 9 deletions

View file

@ -991,10 +991,52 @@ impl<T> std::fmt::Debug for Py<T> {
pub type PyObject = Py<PyAny>; pub type PyObject = Py<PyAny>;
impl PyObject { impl PyObject {
/// Casts the PyObject to a concrete Python object type. /// Downcast this `PyObject` to a concrete Python type or pyclass.
/// ///
/// This can cast only to native Python types, not types implemented in Rust. For a more /// Note that you can often avoid downcasting yourself by just specifying
/// flexible alternative, see [`Py::extract`](struct.Py.html#method.extract). /// the desired type in function or method signatures.
/// However, manual downcasting is sometimes necessary.
///
/// For extracting a Rust-only type, see [`Py::extract`](struct.Py.html#method.extract).
///
/// # Example: Downcasting to a specific Python object
///
/// ```rust
/// use pyo3::prelude::*;
/// use pyo3::types::{PyDict, PyList};
///
/// Python::with_gil(|py| {
/// let any: PyObject = PyDict::new(py).into();
///
/// assert!(any.downcast::<PyDict>(py).is_ok());
/// assert!(any.downcast::<PyList>(py).is_err());
/// });
/// ```
///
/// # Example: Getting a reference to a pyclass
///
/// This is useful if you want to mutate a `PyObject` that
/// might actually be a pyclass.
///
/// ```
/// # fn main() -> Result<(), pyo3::PyErr> {
/// use pyo3::prelude::*;
///
/// #[pyclass]
/// struct Class {
/// i: i32,
/// }
///
/// Python::with_gil(|py| {
/// let class: PyObject = Py::new(py, Class { i: 0 }).unwrap().into_py(py);
///
/// let class_cell: &PyCell<Class> = class.downcast(py)?;
///
/// class_cell.borrow_mut().i += 1;
/// Ok(())
/// })
/// # }
/// ```
#[inline] #[inline]
pub fn downcast<'p, T>(&'p self, py: Python<'p>) -> Result<&T, PyDowncastError<'_>> pub fn downcast<'p, T>(&'p self, py: Python<'p>) -> Result<&T, PyDowncastError<'_>>
where where
@ -1005,9 +1047,6 @@ impl PyObject {
/// Casts the PyObject to a concrete Python object type without checking validity. /// Casts the PyObject to a concrete Python object type without checking validity.
/// ///
/// This can cast only to native Python types, not types implemented in Rust. For a more
/// flexible alternative, see [`Py::extract`](struct.Py.html#method.extract).
///
/// # 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.

View file

@ -755,11 +755,15 @@ impl PyAny {
self.downcast() self.downcast()
} }
/// Converts this `PyAny` to a concrete Python type. /// Downcast this `PyAny` to a concrete Python type or pyclass.
/// ///
/// This can cast only to native Python types, not types implemented in Rust. /// Note that you can often avoid downcasting yourself by just specifying
/// the desired type in function or method signatures.
/// However, manual downcasting is sometimes necessary.
/// ///
/// # Examples /// For extracting a Rust-only type, see [`PyAny::extract`](struct.PyAny.html#method.extract).
///
/// # Example: Downcasting to a specific Python object
/// ///
/// ```rust /// ```rust
/// use pyo3::prelude::*; /// use pyo3::prelude::*;
@ -769,10 +773,36 @@ impl PyAny {
/// let dict = PyDict::new(py); /// let dict = PyDict::new(py);
/// assert!(dict.is_instance_of::<PyAny>().unwrap()); /// assert!(dict.is_instance_of::<PyAny>().unwrap());
/// let any: &PyAny = dict.as_ref(); /// let any: &PyAny = dict.as_ref();
///
/// assert!(any.downcast::<PyDict>().is_ok()); /// assert!(any.downcast::<PyDict>().is_ok());
/// assert!(any.downcast::<PyList>().is_err()); /// assert!(any.downcast::<PyList>().is_err());
/// }); /// });
/// ``` /// ```
///
/// # Example: Getting a reference to a pyclass
///
/// This is useful if you want to mutate a `PyObject` that
/// might actually be a pyclass.
///
/// ```
/// # fn main() -> Result<(), pyo3::PyErr> {
/// use pyo3::prelude::*;
///
/// #[pyclass]
/// struct Class {
/// i: i32,
/// }
///
/// Python::with_gil(|py| {
/// let class: &PyAny = Py::new(py, Class { i: 0 }).unwrap().into_ref(py);
///
/// let class_cell: &PyCell<Class> = class.downcast()?;
///
/// class_cell.borrow_mut().i += 1;
/// Ok(())
/// })
/// # }
/// ```
#[inline] #[inline]
pub fn downcast<'p, T>(&'p self) -> Result<&'p T, PyDowncastError<'_>> pub fn downcast<'p, T>(&'p self) -> Result<&'p T, PyDowncastError<'_>>
where where