|
3 | 3 | This guide can help you upgrade code through breaking changes from one PyO3 version to the next. |
4 | 4 | For a detailed list of all changes, see the [CHANGELOG](changelog.md). |
5 | 5 |
|
| 6 | +## from 0.20.* to 0.21 |
| 7 | + |
| 8 | +### `py.None()`, `py.NotImplemented()` and `py.Ellipsis()` now return typed singletons |
| 9 | + |
| 10 | +Previously `py.None()`, `py.NotImplemented()` and `py.Ellipsis()` would return `PyObject`. This had a few downsides: |
| 11 | + - `PyObject` does not carry static type information |
| 12 | + - `PyObject` takes ownership of a reference to the singletons, adding refcounting performance overhead |
| 13 | + - `PyObject` is not gil-bound, meaning follow up method calls might again need `py`, causing repetition |
| 14 | + |
| 15 | +To avoid these downsides, these methods now return typed gil-bound references to the singletons, e.g. `py.None()` returns `&PyNone`. These typed singletons all implement `Into<PyObject>`, so migration is straightforward. |
| 16 | + |
| 17 | +Before: |
| 18 | + |
| 19 | +```rust,compile_fail |
| 20 | +# use pyo3::prelude::*; |
| 21 | +Python::with_gil(|py| { |
| 22 | + let a: PyObject = py.None(); |
| 23 | +
|
| 24 | + let b: &PyAny = py.None().as_ref(py); // or into_ref(py) |
| 25 | +}); |
| 26 | +``` |
| 27 | + |
| 28 | +After: |
| 29 | + |
| 30 | +```rust |
| 31 | +# use pyo3::prelude::*; |
| 32 | +Python::with_gil(|py| { |
| 33 | + // For uses needing a PyObject, add `.into()` |
| 34 | + let a: PyObject = py.None().into(); |
| 35 | + |
| 36 | + // For uses needing &PyAny, remove `.as_ref(py)` |
| 37 | + let b: &PyAny = py.None(); |
| 38 | +}); |
| 39 | +``` |
| 40 | + |
| 41 | + |
6 | 42 | ## from 0.19.* to 0.20 |
7 | 43 |
|
8 | 44 | ### Drop support for older technologies |
@@ -158,7 +194,7 @@ fn raise_err() -> anyhow::Result<()> { |
158 | 194 | Err(PyValueError::new_err("original error message").into()) |
159 | 195 | } |
160 | 196 |
|
161 | | -fn main() { |
| 197 | +# fn main() { |
162 | 198 | Python::with_gil(|py| { |
163 | 199 | let rs_func = wrap_pyfunction!(raise_err, py).unwrap(); |
164 | 200 | pyo3::py_run!( |
@@ -936,14 +972,14 @@ ensure that the Python GIL was held by the current thread). Technically, this wa |
936 | 972 | To migrate, just pass a `py` argument to any calls to these methods. |
937 | 973 |
|
938 | 974 | Before: |
939 | | -```rust,compile_fail |
| 975 | +```rust,ignore |
940 | 976 | # pyo3::Python::with_gil(|py| { |
941 | 977 | py.None().get_refcnt(); |
942 | 978 | # }) |
943 | 979 | ``` |
944 | 980 |
|
945 | 981 | After: |
946 | | -```rust |
| 982 | +```rust,compile_fail |
947 | 983 | # pyo3::Python::with_gil(|py| { |
948 | 984 | py.None().get_refcnt(py); |
949 | 985 | # }) |
|
0 commit comments