Skip to content

Commit 6776b90

Browse files
authored
Merge pull request #3707 from davidhewitt/gil-refs-feature
add `gil-refs` feature to aid migration
2 parents 54b214b + a9f867c commit 6776b90

File tree

9 files changed

+71
-12
lines changed

9 files changed

+71
-12
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ generate-import-lib = ["pyo3-ffi/generate-import-lib"]
9696
# Changes `Python::with_gil` to automatically initialize the Python interpreter if needed.
9797
auto-initialize = []
9898

99+
# Allows use of the deprecated "GIL Refs" APIs.
100+
gil-refs = []
101+
99102
# Optimizes PyObject to Vec conversion and so on.
100103
nightly = []
101104

guide/src/features.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ This feature adds the `pyo3::inspect` module, as well as `IntoPy::type_output` a
5757

5858
This is a first step towards adding first-class support for generating type annotations automatically in PyO3, however work is needed to finish this off. All feedback and offers of help welcome on [issue #2454](https://github.com/PyO3/pyo3/issues/2454).
5959

60+
### `gil-refs`
61+
62+
This feature is a backwards-compatibility feature to allow continued use of the "GIL Refs" APIs deprecated in PyO3 0.21. These APIs have performance drawbacks and soundness edge cases which the newer `Bound<T>` smart pointer and accompanying APIs resolve.
63+
64+
This feature and the APIs it enables is expected to be removed in a future PyO3 version.
65+
6066
### `macros`
6167

6268
This feature enables a dependency on the `pyo3-macros` crate, which provides the procedural macros portion of PyO3's API:

guide/src/migration.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,42 @@ For a detailed list of all changes, see the [CHANGELOG](changelog.md).
55

66
## from 0.20.* to 0.21
77

8+
PyO3 0.21 introduces a new `Bound<'py, T>` smart pointer which replaces the existing "GIL Refs" API to interact with Python objects. For example, in PyO3 0.20 the reference `&'py PyAny` would be used to interact with Python objects. In PyO3 0.21 the updated type is `Bound<'py, PyAny>`. Making this change moves Rust ownership semantics out of PyO3's internals and into user code. This change fixes [a known soundness edge case of interaction with gevent](https://github.com/PyO3/pyo3/issues/3668) as well as improves CPU and [memory performance](https://github.com/PyO3/pyo3/issues/1056). For a full history of discussion see https://github.com/PyO3/pyo3/issues/3382.
9+
10+
The "GIL Ref" `&'py PyAny` and similar types such as `&'py PyDict` continue to be available as a deprecated API. Due to the advantages of the new API it is advised that all users make the effort to upgrade as soon as possible.
11+
12+
In addition to the major API type overhaul, PyO3 has needed to make a few small breaking adjustments to other APIs to close correctness and soundness gaps.
13+
14+
The recommended steps to update to PyO3 0.21 is as follows:
15+
1. Enable the `gil-refs` feature to silence deprecations related to the API change
16+
2. Fix all other PyO3 0.21 migration steps
17+
3. Disable the `gil-refs` feature and migrate off the deprecated APIs
18+
19+
The following sections are laid out in this order.
20+
21+
### Enable the `gil-refs` feature
22+
23+
To make the transition for the PyO3 ecosystem away from the GIL Refs API as smooth as possible, in PyO3 0.21 no APIs consuming or producing GIL Refs have been altered. Instead, variants using `Bound<T>` smart pointers have been introduced, for example `PyTuple::new_bound` which returns `Bound<PyTuple>` is the replacement form of `PyTuple::new`. The GIL Ref APIs have been deprecated, but to make migration easier it is possible to disable these deprecation warnings by enabling the `gil-refs` feature.
24+
25+
It is recommended that users do this as a first step of updating to PyO3 0.21 so that the deprecation warnings do not get in the way of resolving the rest of the migration steps.
26+
27+
Before:
28+
29+
```toml
30+
# Cargo.toml
31+
[dependencies]
32+
pyo3 = "0.20"
33+
```
34+
35+
After:
36+
37+
```toml
38+
# Cargo.toml
39+
[dependencies]
40+
pyo3 = { version = "0.21", features = ["gil-refs"] }
41+
```
42+
43+
844
### `PyTypeInfo` and `PyTryFrom` have been adjusted
945

1046
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`.
@@ -196,6 +232,10 @@ impl PyClassAsyncIter {
196232

197233
`PyType::name` has been renamed to `PyType::qualname` to indicate that it does indeed return the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name), matching the `__qualname__` attribute. The newly added `PyType::name` yields the full name including the module name now which corresponds to `__module__.__name__` on the level of attributes.
198234

235+
### Migrating from the GIL-Refs API to `Bound<T>`
236+
237+
TODO
238+
199239
## from 0.19.* to 0.20
200240

201241
### Drop support for older technologies

newsfragments/3707.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add `gil-refs` feature to allow continued use of the deprecated GIL Refs APIs.

src/err/mod.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -536,9 +536,12 @@ impl PyErr {
536536
}
537537

538538
/// Deprecated form of `PyErr::write_unraisable_bound`.
539-
#[deprecated(
540-
since = "0.21.0",
541-
note = "`PyErr::write_unraisable` will be replaced by `PyErr::write_unraisable_bound` in a future PyO3 version"
539+
#[cfg_attr(
540+
not(feature = "gil-refs"),
541+
deprecated(
542+
since = "0.21.0",
543+
note = "`PyErr::write_unraisable` will be replaced by `PyErr::write_unraisable_bound` in a future PyO3 version"
544+
)
542545
)]
543546
#[inline]
544547
pub fn write_unraisable(self, py: Python<'_>, obj: Option<&PyAny>) {

src/types/datetime.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,12 @@ pub trait PyTimeAccess {
164164
/// Trait for accessing the components of a struct containing a tzinfo.
165165
pub trait PyTzInfoAccess<'py> {
166166
/// Deprecated form of `get_tzinfo_bound`.
167-
#[deprecated(
168-
since = "0.21.0",
169-
note = "`get_tzinfo` will be replaced by `get_tzinfo_bound` in a future PyO3 version"
167+
#[cfg_attr(
168+
not(feature = "gil-refs"),
169+
deprecated(
170+
since = "0.21.0",
171+
note = "`get_tzinfo` will be replaced by `get_tzinfo_bound` in a future PyO3 version"
172+
)
170173
)]
171174
fn get_tzinfo(&self) -> Option<&'py PyTzInfo> {
172175
self.get_tzinfo_bound().map(Bound::into_gil_ref)
@@ -734,7 +737,7 @@ mod tests {
734737

735738
#[test]
736739
#[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons
737-
#[allow(deprecated)]
740+
#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))]
738741
fn test_get_tzinfo() {
739742
crate::Python::with_gil(|py| {
740743
let utc = timezone_utc(py);

src/types/pysuper.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ pyobject_native_type_core!(
1717

1818
impl PySuper {
1919
/// Deprecated form of `PySuper::new_bound`.
20-
#[deprecated(
21-
since = "0.21.0",
22-
note = "`PySuper::new` will be replaced by `PySuper::new_bound` in a future PyO3 version"
20+
#[cfg_attr(
21+
not(feature = "gil-refs"),
22+
deprecated(
23+
since = "0.21.0",
24+
note = "`PySuper::new` will be replaced by `PySuper::new_bound` in a future PyO3 version"
25+
)
2326
)]
2427
pub fn new<'py>(ty: &'py PyType, obj: &'py PyAny) -> PyResult<&'py PySuper> {
2528
Self::new_bound(&ty.as_borrowed(), &obj.as_borrowed()).map(Bound::into_gil_ref)

tests/test_exceptions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ fn test_exception_nosegfault() {
100100

101101
#[test]
102102
#[cfg(Py_3_8)]
103-
#[allow(deprecated)]
103+
#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))]
104104
fn test_write_unraisable() {
105105
use common::UnraisableCapture;
106106
use pyo3::{exceptions::PyRuntimeError, ffi};

tests/test_super.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ impl SubClass {
3535
}
3636

3737
fn method_super_new(self_: &PyCell<Self>) -> PyResult<&PyAny> {
38-
#[allow(deprecated)]
38+
#[cfg_attr(not(feature = "gil-refs"), allow(deprecated))]
3939
let super_ = PySuper::new(self_.get_type(), self_)?;
4040
super_.call_method("method", (), None)
4141
}

0 commit comments

Comments
 (0)