Add `extract_bound` method to `FromPyObject`
This commit is contained in:
parent
eb8d11f42f
commit
595ca4b3c1
|
@ -241,12 +241,42 @@ To minimise breakage of code using the GIL-Refs API, the `Bound<T>` smart pointe
|
|||
|
||||
For example, the following APIs have gained updated variants:
|
||||
- `PyList::new`, `PyTyple::new` and similar constructors have replacements `PyList::new_bound`, `PyTuple::new_bound` etc.
|
||||
- `FromPyObject::extract` has a new `FromPyObject::extract_bound` (see the section below)
|
||||
|
||||
Because the new `Bound<T>` API brings ownership out of the PyO3 framework and into user code, there are a few places where user code is expected to need to adjust while switching to the new API:
|
||||
- Code will need to add the occasional `&` to borrow the new smart pointer as `&Bound<T>` to pass these types around (or use `.clone()` at the very small cost of increasing the Python reference count)
|
||||
- `Bound<PyList>` and `Bound<PyTuple>` cannot support indexing with `list[0]`, you should use `list.get_item(0)` instead.
|
||||
- `Bound<PyTuple>::iter_borrowed` is slightly more efficient than `Bound<PyTuple>::iter`. The default iteration of `Bound<PyTuple>` cannot return borrowed references because Rust does not (yet) have "lending iterators". Similarly `Bound<PyTuple>::get_borrowed_item` is more efficient than `Bound<PyTuple>::get_item` for the same reason.
|
||||
|
||||
#### Migrating `FromPyObject` implementations
|
||||
|
||||
`FromPyObject` has had a new method `extract_bound` which takes `&Bound<'py, PyAny>` as an argument instead of `&PyAny`. Both `extract` and `extract_bound` have been given default implementations in terms of the other, to avoid breaking code immediately on update to 0.21.
|
||||
|
||||
All implementations of `FromPyObject` should be switched from `extract` to `extract_bound`.
|
||||
|
||||
Before:
|
||||
|
||||
```rust,ignore
|
||||
impl<'py> FromPyObject<'py> for MyType {
|
||||
fn extract(obj: &'py PyAny) -> PyResult<Self> {
|
||||
/* ... */
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```rust,ignore
|
||||
impl<'py> FromPyObject<'py> for MyType {
|
||||
fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {
|
||||
/* ... */
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
The expectation is that in 0.22 `extract_bound` will have the default implementation removed and in 0.23 `extract` will be removed.
|
||||
|
||||
## from 0.19.* to 0.20
|
||||
|
||||
### Drop support for older technologies
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Add `FromPyObject::extract_bound` method, which can be implemented to avoid using the GIL Ref API in `FromPyObject` implementations.
|
|
@ -6,7 +6,7 @@ use crate::pyclass::boolean_struct::False;
|
|||
use crate::type_object::PyTypeInfo;
|
||||
use crate::types::PyTuple;
|
||||
use crate::{
|
||||
ffi, gil, Py, PyAny, PyCell, PyClass, PyNativeType, PyObject, PyRef, PyRefMut, Python,
|
||||
ffi, gil, Bound, Py, PyAny, PyCell, PyClass, PyNativeType, PyObject, PyRef, PyRefMut, Python,
|
||||
};
|
||||
use std::cell::Cell;
|
||||
use std::ptr::NonNull;
|
||||
|
@ -215,11 +215,26 @@ pub trait IntoPy<T>: Sized {
|
|||
/// Since which case applies depends on the runtime type of the Python object,
|
||||
/// both the `obj` and `prepared` variables must outlive the resulting string slice.
|
||||
///
|
||||
/// The trait's conversion method takes a `&PyAny` argument but is called
|
||||
/// `FromPyObject` for historical reasons.
|
||||
/// During the migration of PyO3 from the "GIL Refs" API to the `Bound<T>` smart pointer, this trait
|
||||
/// has two methods `extract` and `extract_bound` which are defaulted to call each other. To avoid
|
||||
/// infinite recursion, implementors must implement at least one of these methods. The recommendation
|
||||
/// is to implement `extract_bound` and leave `extract` as the default implementation.
|
||||
pub trait FromPyObject<'source>: Sized {
|
||||
/// Extracts `Self` from the source `PyObject`.
|
||||
fn extract(ob: &'source PyAny) -> PyResult<Self>;
|
||||
/// Extracts `Self` from the source GIL Ref `obj`.
|
||||
///
|
||||
/// Implementors are encouraged to implement `extract_bound` and leave this method as the
|
||||
/// default implementation, which will forward calls to `extract_bound`.
|
||||
fn extract(ob: &'source PyAny) -> PyResult<Self> {
|
||||
Self::extract_bound(&ob.as_borrowed())
|
||||
}
|
||||
|
||||
/// Extracts `Self` from the bound smart pointer `obj`.
|
||||
///
|
||||
/// Implementors are encouraged to implement this method and leave `extract` defaulted, as
|
||||
/// this will be most compatible with PyO3's future API.
|
||||
fn extract_bound(ob: &Bound<'source, PyAny>) -> PyResult<Self> {
|
||||
Self::extract(ob.clone().into_gil_ref())
|
||||
}
|
||||
|
||||
/// Extracts the type hint information for this type when it appears as an argument.
|
||||
///
|
||||
|
|
Loading…
Reference in New Issue