Skip to content

Commit 6719e98

Browse files
committed
introduce no-pool feature
1 parent 7cea93b commit 6719e98

File tree

7 files changed

+55
-18
lines changed

7 files changed

+55
-18
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ auto-initialize = []
9999
# Optimizes PyObject to Vec conversion and so on.
100100
nightly = []
101101

102+
# Removes the "GIL Pool" internal datastructure from PyO3.
103+
no-pool = []
104+
102105
# Activates all additional features
103106
# This is mostly intended for testing purposes - activating *all* of these isn't particularly useful.
104107
full = [
@@ -116,6 +119,7 @@ full = [
116119
"anyhow",
117120
"experimental-inspect",
118121
"rust_decimal",
122+
"no-pool",
119123
]
120124

121125
[workspace]

guide/src/features.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ See [the `#[pyclass]` implementation details](class.md#implementation-details) f
8585

8686
The `nightly` feature needs the nightly Rust compiler. This allows PyO3 to use the `auto_traits` and `negative_impls` features to fix the `Python::allow_threads` function.
8787

88+
### `no-pool`
89+
90+
This feature completes the migration of PyO3's API from the "GIL Refs" API to the `Bound<T>` smart pointer API.
91+
92+
There are two key effects to this feature:
93+
- The internal "GIL Pool" datastructure is completely removed.
94+
- Many GIL Ref APIs which have temporary `_bound` variants have their return values adjusted to their future version. For example, with this feature enabled `PyTuple::new` will return `Bound<'py, PyTuple>`.
95+
8896
### `resolve-config`
8997

9098
The `resolve-config` feature of the `pyo3-build-config` crate controls whether that crate's

pytests/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ edition = "2021"
77
publish = false
88

99
[dependencies]
10-
pyo3 = { path = "../", features = ["extension-module"] }
10+
pyo3 = { path = "../", features = ["extension-module", "no-pool"] }
1111

1212
[build-dependencies]
1313
pyo3-build-config = { path = "../pyo3-build-config" }

pytests/src/datetime.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn make_date(py: Python<'_>, year: i32, month: u8, day: u8) -> PyResult<&PyDate>
1212
}
1313

1414
#[pyfunction]
15-
fn get_date_tuple<'p>(py: Python<'p>, d: &PyDate) -> &'p PyTuple {
15+
fn get_date_tuple<'p>(py: Python<'p>, d: &PyDate) -> Bound<'p, PyTuple> {
1616
PyTuple::new(py, [d.get_year(), d.get_month() as i32, d.get_day() as i32])
1717
}
1818

@@ -48,7 +48,7 @@ fn time_with_fold<'p>(
4848
}
4949

5050
#[pyfunction]
51-
fn get_time_tuple<'p>(py: Python<'p>, dt: &PyTime) -> &'p PyTuple {
51+
fn get_time_tuple<'p>(py: Python<'p>, dt: &PyTime) -> Bound<'p, PyTuple> {
5252
PyTuple::new(
5353
py,
5454
[
@@ -61,7 +61,7 @@ fn get_time_tuple<'p>(py: Python<'p>, dt: &PyTime) -> &'p PyTuple {
6161
}
6262

6363
#[pyfunction]
64-
fn get_time_tuple_fold<'p>(py: Python<'p>, dt: &PyTime) -> &'p PyTuple {
64+
fn get_time_tuple_fold<'p>(py: Python<'p>, dt: &PyTime) -> Bound<'p, PyTuple> {
6565
PyTuple::new(
6666
py,
6767
[
@@ -80,7 +80,7 @@ fn make_delta(py: Python<'_>, days: i32, seconds: i32, microseconds: i32) -> PyR
8080
}
8181

8282
#[pyfunction]
83-
fn get_delta_tuple<'p>(py: Python<'p>, delta: &PyDelta) -> &'p PyTuple {
83+
fn get_delta_tuple<'p>(py: Python<'p>, delta: &PyDelta) -> Bound<'p, PyTuple> {
8484
PyTuple::new(
8585
py,
8686
[
@@ -118,7 +118,7 @@ fn make_datetime<'p>(
118118
}
119119

120120
#[pyfunction]
121-
fn get_datetime_tuple<'p>(py: Python<'p>, dt: &PyDateTime) -> &'p PyTuple {
121+
fn get_datetime_tuple<'p>(py: Python<'p>, dt: &PyDateTime) -> Bound<'p, PyTuple> {
122122
PyTuple::new(
123123
py,
124124
[
@@ -134,7 +134,7 @@ fn get_datetime_tuple<'p>(py: Python<'p>, dt: &PyDateTime) -> &'p PyTuple {
134134
}
135135

136136
#[pyfunction]
137-
fn get_datetime_tuple_fold<'p>(py: Python<'p>, dt: &PyDateTime) -> &'p PyTuple {
137+
fn get_datetime_tuple_fold<'p>(py: Python<'p>, dt: &PyDateTime) -> Bound<'p, PyTuple> {
138138
PyTuple::new(
139139
py,
140140
[

src/types/tuple.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pyobject_native_type_core!(PyTuple, pyobject_native_static_type_object!(ffi::PyT
6060
impl PyTuple {
6161
/// Deprecated form of `PyTuple::new_bound`.
6262
#[track_caller]
63+
#[cfg(not(feature = "no-pool"))]
6364
#[deprecated(
6465
since = "0.21.0",
6566
note = "`PyTuple::new` will be replaced by `PyTuple::new_bound` in a future PyO3 version"
@@ -75,6 +76,21 @@ impl PyTuple {
7576
Self::new_bound(py, elements).into_gil_ref()
7677
}
7778

79+
/// Future form of `PyTuple::new_bound`.
80+
#[track_caller]
81+
#[inline]
82+
#[cfg(feature = "no-pool")]
83+
pub fn new<T, U>(
84+
py: Python<'_>,
85+
elements: impl IntoIterator<Item = T, IntoIter = U>,
86+
) -> Bound<'_, PyTuple>
87+
where
88+
T: ToPyObject,
89+
U: ExactSizeIterator<Item = T>,
90+
{
91+
Self::new_bound(py, elements)
92+
}
93+
7894
/// Constructs a new tuple with the given elements.
7995
///
8096
/// If you want to create a [`PyTuple`] with elements of different or unknown types, or from an
@@ -119,10 +135,18 @@ impl PyTuple {
119135
since = "0.21.0",
120136
note = "`PyTuple::empty` will be replaced by `PyTuple::empty_bound` in a future PyO3 version"
121137
)]
138+
#[cfg(not(feature = "no-pool"))]
122139
pub fn empty(py: Python<'_>) -> &PyTuple {
123140
Self::empty_bound(py).into_gil_ref()
124141
}
125142

143+
/// Future form of `PyTuple::empty_bound`.
144+
#[inline]
145+
#[cfg(feature = "no-pool")]
146+
pub fn empty(py: Python<'_>) -> Bound<'_, PyTuple> {
147+
Self::empty_bound(py)
148+
}
149+
126150
/// Constructs an empty tuple (on the Python side, a singleton object).
127151
pub fn empty_bound(py: Python<'_>) -> Bound<'_, PyTuple> {
128152
unsafe {
@@ -798,6 +822,8 @@ tuple_conversion!(
798822

799823
#[cfg(test)]
800824
mod tests {
825+
#[cfg(feature = "no-pool")]
826+
use crate::types::{any::PyAnyMethods, tuple::PyTupleMethods};
801827
use crate::types::{PyAny, PyList, PyTuple};
802828
use crate::{Python, ToPyObject};
803829
use std::collections::HashSet;
@@ -807,7 +833,6 @@ mod tests {
807833
Python::with_gil(|py| {
808834
let ob = PyTuple::new(py, [1, 2, 3]);
809835
assert_eq!(3, ob.len());
810-
let ob: &PyAny = ob.into();
811836
assert_eq!((1, 2, 3), ob.extract().unwrap());
812837

813838
let mut map = HashSet::new();

tests/test_frompyobject.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,11 @@ pub struct Tuple(String, usize);
162162
#[test]
163163
fn test_tuple_struct() {
164164
Python::with_gil(|py| {
165-
let tup = PyTuple::new(py, &[1.into_py(py), "test".into_py(py)]);
166-
let tup = Tuple::extract(tup.as_ref());
165+
let tup = PyTuple::new_bound(py, &[1.into_py(py), "test".into_py(py)]);
166+
let tup = Tuple::extract(tup.into_gil_ref());
167167
assert!(tup.is_err());
168-
let tup = PyTuple::new(py, &["test".into_py(py), 1.into_py(py)]);
169-
let tup = Tuple::extract(tup.as_ref()).expect("Failed to extract Tuple from PyTuple");
168+
let tup = PyTuple::new_bound(py, &["test".into_py(py), 1.into_py(py)]);
169+
let tup = Tuple::extract(tup.into_gil_ref()).expect("Failed to extract Tuple from PyTuple");
170170
assert_eq!(tup.0, "test");
171171
assert_eq!(tup.1, 1);
172172
});
@@ -324,8 +324,8 @@ pub struct PyBool {
324324
#[test]
325325
fn test_enum() {
326326
Python::with_gil(|py| {
327-
let tup = PyTuple::new(py, &[1.into_py(py), "test".into_py(py)]);
328-
let f = Foo::extract(tup.as_ref()).expect("Failed to extract Foo from tuple");
327+
let tup = PyTuple::new_bound(py, &[1.into_py(py), "test".into_py(py)]);
328+
let f = Foo::extract(tup.into_gil_ref()).expect("Failed to extract Foo from tuple");
329329
match f {
330330
Foo::TupleVar(test, test2) => {
331331
assert_eq!(test, 1);
@@ -401,8 +401,8 @@ TypeError: failed to extract enum Foo ('TupleVar | StructVar | TransparentTuple
401401
- variant StructWithGetItemArg (StructWithGetItemArg): KeyError: 'foo'"
402402
);
403403

404-
let tup = PyTuple::empty(py);
405-
let err = Foo::extract(tup.as_ref()).unwrap_err();
404+
let tup = PyTuple::empty_bound(py);
405+
let err = Foo::extract(tup.into_gil_ref()).unwrap_err();
406406
assert_eq!(
407407
err.to_string(),
408408
"\

tests/test_various.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,10 @@ impl PickleSupport {
126126
pub fn __reduce__<'py>(
127127
slf: &'py PyCell<Self>,
128128
py: Python<'py>,
129-
) -> PyResult<(PyObject, &'py PyTuple, PyObject)> {
129+
) -> PyResult<(PyObject, Bound<'py, PyTuple>, PyObject)> {
130130
let cls = slf.to_object(py).getattr(py, "__class__")?;
131131
let dict = slf.to_object(py).getattr(py, "__dict__")?;
132-
Ok((cls, PyTuple::empty(py), dict))
132+
Ok((cls, PyTuple::empty_bound(py), dict))
133133
}
134134
}
135135

0 commit comments

Comments
 (0)