documentation updates for `PyList::new_bound`
This commit is contained in:
parent
57a49a2b12
commit
1657109ae0
|
@ -13,7 +13,7 @@ fails, so usually you will use something like
|
||||||
# use pyo3::types::PyList;
|
# use pyo3::types::PyList;
|
||||||
# fn main() -> PyResult<()> {
|
# fn main() -> PyResult<()> {
|
||||||
# Python::with_gil(|py| {
|
# Python::with_gil(|py| {
|
||||||
# let list = PyList::new(py, b"foo");
|
# let list = PyList::new_bound(py, b"foo");
|
||||||
let v: Vec<i32> = list.extract()?;
|
let v: Vec<i32> = list.extract()?;
|
||||||
# assert_eq!(&v, &[102, 111, 111]);
|
# assert_eq!(&v, &[102, 111, 111]);
|
||||||
# Ok(())
|
# Ok(())
|
||||||
|
|
|
@ -75,12 +75,12 @@ Python has an [`isinstance`](https://docs.python.org/3/library/functions.html#is
|
||||||
In PyO3 every object has the [`PyAny::is_instance`] and [`PyAny::is_instance_of`] methods which do the same thing.
|
In PyO3 every object has the [`PyAny::is_instance`] and [`PyAny::is_instance_of`] methods which do the same thing.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use pyo3::Python;
|
use pyo3::prelude::*;
|
||||||
use pyo3::types::{PyBool, PyList};
|
use pyo3::types::{PyBool, PyList};
|
||||||
|
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
assert!(PyBool::new(py, true).is_instance_of::<PyBool>());
|
assert!(PyBool::new(py, true).is_instance_of::<PyBool>());
|
||||||
let list = PyList::new(py, &[1, 2, 3, 4]);
|
let list = PyList::new_bound(py, &[1, 2, 3, 4]);
|
||||||
assert!(!list.is_instance_of::<PyBool>());
|
assert!(!list.is_instance_of::<PyBool>());
|
||||||
assert!(list.is_instance_of::<PyList>());
|
assert!(list.is_instance_of::<PyList>());
|
||||||
});
|
});
|
||||||
|
|
|
@ -45,7 +45,7 @@ pyo3 = { version = "0.21", features = ["gil-refs"] }
|
||||||
|
|
||||||
The `PyTryFrom` trait has aged poorly, its [`try_from`] method now conflicts with `try_from` in the 2021 edition prelude. A lot of its functionality was also duplicated with `PyTypeInfo`.
|
The `PyTryFrom` trait has aged poorly, its [`try_from`] method now conflicts with `try_from` in the 2021 edition prelude. A lot of its functionality was also duplicated with `PyTypeInfo`.
|
||||||
|
|
||||||
To tighten up the PyO3 traits ahead of [a proposed upcoming API change](https://github.com/PyO3/pyo3/issues/3382) the `PyTypeInfo` trait has had a simpler companion `PyTypeCheck`. The methods [`PyAny::downcast`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html#method.downcast) and [`PyAny::downcast_exact`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html#method.downcast_exact) no longer use `PyTryFrom` as a bound, instead using `PyTypeCheck` and `PyTypeInfo` respectively.
|
To tighten up the PyO3 traits as part of the deprecation of the GIL Refs API the `PyTypeInfo` trait has had a simpler companion `PyTypeCheck`. The methods [`PyAny::downcast`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html#method.downcast) and [`PyAny::downcast_exact`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html#method.downcast_exact) no longer use `PyTryFrom` as a bound, instead using `PyTypeCheck` and `PyTypeInfo` respectively.
|
||||||
|
|
||||||
To migrate, switch all type casts to use `obj.downcast()` instead of `try_from(obj)` (and similar for `downcast_exact`).
|
To migrate, switch all type casts to use `obj.downcast()` instead of `try_from(obj)` (and similar for `downcast_exact`).
|
||||||
|
|
||||||
|
@ -71,6 +71,9 @@ After:
|
||||||
# use pyo3::types::{PyInt, PyList};
|
# use pyo3::types::{PyInt, PyList};
|
||||||
# fn main() -> PyResult<()> {
|
# fn main() -> PyResult<()> {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
|
// Note that PyList::new is deprecated for PyList::new_bound as part of the GIL Refs API removal,
|
||||||
|
// see the section below on migration to Bound<T>.
|
||||||
|
#[allow(deprecated)]
|
||||||
let list = PyList::new(py, 0..5);
|
let list = PyList::new(py, 0..5);
|
||||||
let b = list.get_item(0).unwrap().downcast::<PyInt>()?;
|
let b = list.get_item(0).unwrap().downcast::<PyInt>()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -234,7 +237,15 @@ impl PyClassAsyncIter {
|
||||||
|
|
||||||
### Migrating from the GIL-Refs API to `Bound<T>`
|
### Migrating from the GIL-Refs API to `Bound<T>`
|
||||||
|
|
||||||
TODO
|
To minimise breakage of code using the GIL-Refs API, the `Bound<T>` smart pointer has been introduced by adding complements to all functions which accept or return GIL Refs. This allows code to migrate by replacing the deprecated APIs with the new ones.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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".
|
||||||
|
|
||||||
## from 0.19.* to 0.20
|
## from 0.19.* to 0.20
|
||||||
|
|
||||||
|
@ -853,6 +864,7 @@ that these types can now also support Rust's indexing operators as part of a
|
||||||
consistent API:
|
consistent API:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
#![allow(deprecated)]
|
||||||
use pyo3::{Python, types::PyList};
|
use pyo3::{Python, types::PyList};
|
||||||
|
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
|
@ -1073,7 +1085,7 @@ This should require no code changes except removing `use pyo3::AsPyRef` for code
|
||||||
`pyo3::prelude::*`.
|
`pyo3::prelude::*`.
|
||||||
|
|
||||||
Before:
|
Before:
|
||||||
```rust,compile_fail
|
```rust,ignore
|
||||||
use pyo3::{AsPyRef, Py, types::PyList};
|
use pyo3::{AsPyRef, Py, types::PyList};
|
||||||
# pyo3::Python::with_gil(|py| {
|
# pyo3::Python::with_gil(|py| {
|
||||||
let list_py: Py<PyList> = PyList::empty(py).into();
|
let list_py: Py<PyList> = PyList::empty(py).into();
|
||||||
|
@ -1082,7 +1094,7 @@ let list_ref: &PyList = list_py.as_ref(py);
|
||||||
```
|
```
|
||||||
|
|
||||||
After:
|
After:
|
||||||
```rust
|
```rust,ignore
|
||||||
use pyo3::{Py, types::PyList};
|
use pyo3::{Py, types::PyList};
|
||||||
# pyo3::Python::with_gil(|py| {
|
# pyo3::Python::with_gil(|py| {
|
||||||
let list_py: Py<PyList> = PyList::empty(py).into();
|
let list_py: Py<PyList> = PyList::empty(py).into();
|
||||||
|
|
|
@ -71,6 +71,7 @@ a list:
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::types::PyList;
|
# use pyo3::types::PyList;
|
||||||
# Python::with_gil(|py| -> PyResult<()> {
|
# Python::with_gil(|py| -> PyResult<()> {
|
||||||
|
#[allow(deprecated)] // PyList::empty is part of the deprecated "GIL Refs" API.
|
||||||
let obj: &PyAny = PyList::empty(py);
|
let obj: &PyAny = PyList::empty(py);
|
||||||
|
|
||||||
// To &PyList with PyAny::downcast
|
// To &PyList with PyAny::downcast
|
||||||
|
@ -133,6 +134,7 @@ To see all Python types exposed by `PyO3` you should consult the
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::types::PyList;
|
# use pyo3::types::PyList;
|
||||||
# Python::with_gil(|py| -> PyResult<()> {
|
# Python::with_gil(|py| -> PyResult<()> {
|
||||||
|
#[allow(deprecated)] // PyList::empty is part of the deprecated "GIL Refs" API.
|
||||||
let list = PyList::empty(py);
|
let list = PyList::empty(py);
|
||||||
|
|
||||||
// Use methods from PyAny on all Python types with Deref implementation
|
// Use methods from PyAny on all Python types with Deref implementation
|
||||||
|
@ -173,7 +175,7 @@ For a `Py<PyList>`, the conversions are as below:
|
||||||
# use pyo3::prelude::*;
|
# use pyo3::prelude::*;
|
||||||
# use pyo3::types::PyList;
|
# use pyo3::types::PyList;
|
||||||
# Python::with_gil(|py| {
|
# Python::with_gil(|py| {
|
||||||
let list: Py<PyList> = PyList::empty(py).into();
|
let list: Py<PyList> = PyList::empty_bound(py).unbind();
|
||||||
|
|
||||||
// To &PyList with Py::as_ref() (borrows from the Py)
|
// To &PyList with Py::as_ref() (borrows from the Py)
|
||||||
let _: &PyList = list.as_ref(py);
|
let _: &PyList = list.as_ref(py);
|
||||||
|
|
|
@ -615,10 +615,9 @@ where
|
||||||
/// # use pyo3::types::PyList;
|
/// # use pyo3::types::PyList;
|
||||||
/// #
|
/// #
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let list: Py<PyList> = PyList::empty(py).into();
|
/// let list: Py<PyList> = PyList::empty_bound(py).into();
|
||||||
/// // FIXME as_ref() no longer makes sense with new Py API, remove this doc
|
/// let list: &PyList = list.as_ref(py);
|
||||||
/// // let list: &PyList = list.as_ref(py);
|
/// assert_eq!(list.len(), 0);
|
||||||
/// // assert_eq!(list.len(), 0);
|
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
/// use pyo3::{prelude::*, py_run, types::PyList};
|
/// use pyo3::{prelude::*, py_run, types::PyList};
|
||||||
///
|
///
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let list = PyList::new(py, &[1, 2, 3]);
|
/// let list = PyList::new_bound(py, &[1, 2, 3]);
|
||||||
/// py_run!(py, list, "assert list == [1, 2, 3]");
|
/// py_run!(py, list, "assert list == [1, 2, 3]");
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -75,10 +75,10 @@ unsafe impl<T> Sync for GILProtected<T> where T: Send {}
|
||||||
///
|
///
|
||||||
/// static LIST_CELL: GILOnceCell<Py<PyList>> = GILOnceCell::new();
|
/// static LIST_CELL: GILOnceCell<Py<PyList>> = GILOnceCell::new();
|
||||||
///
|
///
|
||||||
/// pub fn get_shared_list(py: Python<'_>) -> &PyList {
|
/// pub fn get_shared_list(py: Python<'_>) -> &Bound<'_, PyList> {
|
||||||
/// LIST_CELL
|
/// LIST_CELL
|
||||||
/// .get_or_init(py, || PyList::empty(py).into())
|
/// .get_or_init(py, || PyList::empty_bound(py).unbind())
|
||||||
/// .as_ref(py)
|
/// .bind(py)
|
||||||
/// }
|
/// }
|
||||||
/// # Python::with_gil(|py| assert_eq!(get_shared_list(py).len(), 0));
|
/// # Python::with_gil(|py| assert_eq!(get_shared_list(py).len(), 0));
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -88,7 +88,7 @@ impl PyList {
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let elements: Vec<i32> = vec![0, 1, 2, 3, 4, 5];
|
/// let elements: Vec<i32> = vec![0, 1, 2, 3, 4, 5];
|
||||||
/// let list: &PyList = PyList::new(py, elements);
|
/// let list = PyList::new_bound(py, elements);
|
||||||
/// assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5]");
|
/// assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5]");
|
||||||
/// });
|
/// });
|
||||||
/// # }
|
/// # }
|
||||||
|
@ -154,7 +154,7 @@ impl PyList {
|
||||||
/// ```
|
/// ```
|
||||||
/// use pyo3::{prelude::*, types::PyList};
|
/// use pyo3::{prelude::*, types::PyList};
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let list = PyList::new(py, [2, 3, 5, 7]);
|
/// let list = PyList::new_bound(py, [2, 3, 5, 7]);
|
||||||
/// let obj = list.get_item(0);
|
/// let obj = list.get_item(0);
|
||||||
/// assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 2);
|
/// assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 2);
|
||||||
/// });
|
/// });
|
||||||
|
@ -301,7 +301,7 @@ pub trait PyListMethods<'py> {
|
||||||
/// ```
|
/// ```
|
||||||
/// use pyo3::{prelude::*, types::PyList};
|
/// use pyo3::{prelude::*, types::PyList};
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let list = PyList::new(py, [2, 3, 5, 7]);
|
/// let list = PyList::new_bound(py, [2, 3, 5, 7]);
|
||||||
/// let obj = list.get_item(0);
|
/// let obj = list.get_item(0);
|
||||||
/// assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 2);
|
/// assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 2);
|
||||||
/// });
|
/// });
|
||||||
|
@ -414,7 +414,7 @@ impl<'py> PyListMethods<'py> for Bound<'py, PyList> {
|
||||||
/// ```
|
/// ```
|
||||||
/// use pyo3::{prelude::*, types::PyList};
|
/// use pyo3::{prelude::*, types::PyList};
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let list = PyList::new(py, [2, 3, 5, 7]);
|
/// let list = PyList::new_bound(py, [2, 3, 5, 7]);
|
||||||
/// let obj = list.get_item(0);
|
/// let obj = list.get_item(0);
|
||||||
/// assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 2);
|
/// assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 2);
|
||||||
/// });
|
/// });
|
||||||
|
|
Loading…
Reference in New Issue