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.
### `AsPyRef` has been removed
The only implementor of `AsPyRef` was `Py<T>`, so the `AsPyRef::as_ref` method has been moved to
`Py::as_ref`. This should require no code changes except removing the old `use` for code which
did not use `pyo3::prelude`.
As `PyObject` has been changed to be just a type alias, the only remaining implementor of `AsPyRef`
was `Py<T>`. This removed the need for a trait, so the `AsPyRef::as_ref` method has been moved to
`Py::as_ref`.
This should require no code changes except removing `use pyo3::AsPyRef` for code which did not use
`pyo3::prelude::*`.
Before:
```rust,ignore

View file

@ -140,11 +140,18 @@ Can be cloned using Python reference counts with `.clone()`.
# let py = gil.python();
let list: Py<PyList> = PyList::empty(py).into();
// Access the native type using Py::as_ref(py) or Py::into_ref(py)
// (For #[pyclass] types, these will return &PyCell<T>)
let _: &PyList = list.as_ref(py);
let _: &PyList = list.clone().into_ref(py);
// Access to the native type using Py::as_ref(py) or Py::into_ref(py)
// (For #[pyclass] types T, these will return &PyCell<T>)
// 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()
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
/// 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_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
@ -48,9 +48,6 @@ pub unsafe trait PyNativeType: Sized {
///
/// See [the guide](https://pyo3.rs/master/types.html) for an explanation
/// of the different Python object types.
///
/// `Py<T>` is implemented as a safe wrapper around `NonNull<ffi::PyObject>` with
/// specified type information.
#[repr(transparent)]
pub struct Py<T>(NonNull<ffi::PyObject>, PhantomData<T>);
@ -112,32 +109,23 @@ where
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
/// object will not be decreased until the GIL lifetime ends.
///
/// # Examples
/// 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);
/// # });
/// ```
/// # Example
///
/// 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::*;
/// #[pyclass]
/// struct MyClass { }
/// # Python::with_gil(|py| {
/// let my_class: Py<MyClass> = Py::new(py, MyClass { }).unwrap();
/// let my_class_cell: &PyCell<MyClass> = my_class.into_ref(py);
/// assert!(my_class_cell.try_borrow().is_ok());
/// # });
/// fn new_py_any<'py>(py: Python<'py>, value: impl IntoPy<PyObject>) -> &'py PyAny {
/// let obj: PyObject = value.into_py(py);
///
/// // .as_ref(py) would not be suitable here, because a reference to `obj` may not be
/// // returned from the function.
/// obj.into_ref(py)
/// }
/// ```
pub fn into_ref(self, py: Python) -> &T::AsRefTarget {
unsafe { py.from_owned_ptr(self.into_ptr()) }