Improve docs for Py::as_ref() and Py::into_ref()
Co-authored-by: Georg Brandl <georg@python.org>
This commit is contained in:
parent
7d0b3b386a
commit
6b3c6fdeee
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
```
|
```
|
||||||
|
|
|
@ -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()) }
|
||||||
|
|
Loading…
Reference in a new issue