Improve docs for Py::as_ref() and Py::into_ref()

Co-authored-by: Georg Brandl <georg@python.org>
This commit is contained in:
David Hewitt 2020-08-10 20:08:48 +01:00
parent 7d0b3b386a
commit 6b3c6fdeee
3 changed files with 29 additions and 31 deletions

View file

@ -60,9 +60,12 @@ This should change very little from a usage perspective. If you implemented trai
`PyObject` and `Py<T>`, you may find you can just remove the `PyObject` implementation. `PyObject` and `Py<T>`, you may find you can just remove the `PyObject` implementation.
### `AsPyRef` has been removed ### `AsPyRef` has been removed
The only implementor of `AsPyRef` was `Py<T>`, so the `AsPyRef::as_ref` method has been moved to As `PyObject` has been changed to be just a type alias, the only remaining implementor of `AsPyRef`
`Py::as_ref`. This should require no code changes except removing the old `use` for code which was `Py<T>`. This removed the need for a trait, so the `AsPyRef::as_ref` method has been moved to
did not use `pyo3::prelude`. `Py::as_ref`.
This should require no code changes except removing `use pyo3::AsPyRef` for code which did not use
`pyo3::prelude::*`.
Before: Before:
```rust,ignore ```rust,ignore

View file

@ -140,11 +140,18 @@ Can be cloned using Python reference counts with `.clone()`.
# let py = gil.python(); # let py = gil.python();
let list: Py<PyList> = PyList::empty(py).into(); let list: Py<PyList> = PyList::empty(py).into();
// Access the native type using Py::as_ref(py) or Py::into_ref(py) // Access to the native type using Py::as_ref(py) or Py::into_ref(py)
// (For #[pyclass] types, these will return &PyCell<T>) // (For #[pyclass] types T, these will return &PyCell<T>)
let _: &PyList = list.as_ref(py);
let _: &PyList = list.clone().into_ref(py);
// Py::as_ref() borrows the object
let _: &PyList = list.as_ref(py);
# let list_clone = list.clone(); // Just so that the .into() example for PyObject compiles.
// Py::into_ref() moves the reference into pyo3's "object storage"; useful for making APIs
// which return gil-bound references.
let _: &PyList = list.into_ref(py);
# let list = list_clone;
// Convert to PyObject with .into() // Convert to PyObject with .into()
let _: PyObject = list.into(); let _: PyObject = list.into();
``` ```

View file

@ -37,7 +37,7 @@ pub unsafe trait PyNativeType: Sized {
/// ///
/// Accessing this object is thread-safe, since any access to its API requires a `Python<'py>` GIL /// Accessing this object is thread-safe, since any access to its API requires a `Python<'py>` GIL
/// token. There are a few different ways to use the Python object contained: /// token. There are a few different ways to use the Python object contained:
/// - [`Py::as_ref`](#method.as_ref) to borrow a GIL-bound reference to the contained object, /// - [`Py::as_ref`](#method.as_ref) to borrow a GIL-bound reference to the contained object.
/// - [`Py::borrow`](#method.borrow), [`Py::try_borrow`](#method.try_borrow), /// - [`Py::borrow`](#method.borrow), [`Py::try_borrow`](#method.try_borrow),
/// [`Py::borrow_mut`](#method.borrow_mut), or [`Py::try_borrow_mut`](#method.try_borrow_mut), /// [`Py::borrow_mut`](#method.borrow_mut), or [`Py::try_borrow_mut`](#method.try_borrow_mut),
/// to directly access a `#[pyclass]` value (which has RefCell-like behavior, see /// to directly access a `#[pyclass]` value (which has RefCell-like behavior, see
@ -48,9 +48,6 @@ pub unsafe trait PyNativeType: Sized {
/// ///
/// See [the guide](https://pyo3.rs/master/types.html) for an explanation /// See [the guide](https://pyo3.rs/master/types.html) for an explanation
/// of the different Python object types. /// of the different Python object types.
///
/// `Py<T>` is implemented as a safe wrapper around `NonNull<ffi::PyObject>` with
/// specified type information.
#[repr(transparent)] #[repr(transparent)]
pub struct Py<T>(NonNull<ffi::PyObject>, PhantomData<T>); pub struct Py<T>(NonNull<ffi::PyObject>, PhantomData<T>);
@ -112,32 +109,23 @@ where
unsafe { PyNativeType::unchecked_downcast(&*any) } unsafe { PyNativeType::unchecked_downcast(&*any) }
} }
/// Similar to [`as_ref`](#method.as_ref), but instead consumes this `Py` and registers the /// Similar to [`as_ref`](#method.as_ref), and also consumes this `Py` and registers the
/// Python object reference in PyO3's object storage. The reference count for the Python /// Python object reference in PyO3's object storage. The reference count for the Python
/// object will not be decreased until the GIL lifetime ends. /// object will not be decreased until the GIL lifetime ends.
/// ///
/// # Examples /// # Example
/// Create `&PyList` from `Py<PyList>`:
/// ```
/// # use pyo3::prelude::*;
/// # use pyo3::types::PyList;
/// # Python::with_gil(|py| {
/// let list: Py<PyList> = PyList::empty(py).into();
/// let list: &PyList = list.into_ref(py);
/// assert_eq!(list.len(), 0);
/// # });
/// ```
/// ///
/// Create `&PyCell<MyClass>` from `Py<MyClass>`: /// Useful when returning GIL-bound references from functions. In the snippet below, note that
/// the `'py` lifetime of the input GIL lifetime is also given to the returned reference:
/// ``` /// ```
/// # use pyo3::prelude::*; /// # use pyo3::prelude::*;
/// #[pyclass] /// fn new_py_any<'py>(py: Python<'py>, value: impl IntoPy<PyObject>) -> &'py PyAny {
/// struct MyClass { } /// let obj: PyObject = value.into_py(py);
/// # Python::with_gil(|py| { ///
/// let my_class: Py<MyClass> = Py::new(py, MyClass { }).unwrap(); /// // .as_ref(py) would not be suitable here, because a reference to `obj` may not be
/// let my_class_cell: &PyCell<MyClass> = my_class.into_ref(py); /// // returned from the function.
/// assert!(my_class_cell.try_borrow().is_ok()); /// obj.into_ref(py)
/// # }); /// }
/// ``` /// ```
pub fn into_ref(self, py: Python) -> &T::AsRefTarget { pub fn into_ref(self, py: Python) -> &T::AsRefTarget {
unsafe { py.from_owned_ptr(self.into_ptr()) } unsafe { py.from_owned_ptr(self.into_ptr()) }