Skip to content

Commit 93aef75

Browse files
committed
feature gate PyCell
1 parent c5f9001 commit 93aef75

27 files changed

+140
-83
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ generate-import-lib = ["pyo3-ffi/generate-import-lib"]
106106
auto-initialize = []
107107

108108
# Allows use of the deprecated "GIL Refs" APIs.
109-
gil-refs = []
109+
gil-refs = ["pyo3-macros/gil-refs"]
110110

111111
# Enables `Clone`ing references to Python objects `Py<T>` which panics if the GIL is not held.
112112
py-clone = []

guide/src/class.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,7 @@ struct MyClass {
13071307
impl pyo3::types::DerefToPyAny for MyClass {}
13081308

13091309
# #[allow(deprecated)]
1310+
# #[cfg(feature = "gil-refs")]
13101311
unsafe impl pyo3::type_object::HasPyGilRef for MyClass {
13111312
type AsRefTarget = pyo3::PyCell<Self>;
13121313
}

guide/src/migration.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,7 +1609,7 @@ For more, see [the constructor section](class.md#constructor) of this guide.
16091609
<details>
16101610
<summary><small>Click to expand</small></summary>
16111611

1612-
PyO3 0.9 introduces [`PyCell`], which is a [`RefCell`]-like object wrapper
1612+
PyO3 0.9 introduces `PyCell`, which is a [`RefCell`]-like object wrapper
16131613
for ensuring Rust's rules regarding aliasing of references are upheld.
16141614
For more detail, see the
16151615
[Rust Book's section on Rust's rules of references](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#the-rules-of-references)
@@ -1788,7 +1788,6 @@ impl PySequenceProtocol for ByteSequence {
17881788

17891789
[`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html
17901790
[`PyAny`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html
1791-
[`PyCell`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyCell.html
17921791
[`PyBorrowMutError`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyBorrowMutError.html
17931792
[`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html
17941793
[`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html

pyo3-macros-backend/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ workspace = true
2929

3030
[features]
3131
experimental-async = []
32+
gil-refs = []

pyo3-macros-backend/src/module.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,11 @@ fn process_functions_in_module(options: &PyModuleOptions, func: &mut syn::ItemFn
384384
let Ctx { pyo3_path } = ctx;
385385
let mut stmts: Vec<syn::Stmt> = Vec::new();
386386

387+
#[cfg(feature = "gil-refs")]
388+
let imports = quote!(use #pyo3_path::{PyNativeType, types::PyModuleMethods};);
389+
#[cfg(not(feature = "gil-refs"))]
390+
let imports = quote!(use #pyo3_path::types::PyModuleMethods;);
391+
387392
for mut stmt in func.block.stmts.drain(..) {
388393
if let syn::Stmt::Item(Item::Fn(func)) = &mut stmt {
389394
if let Some(pyfn_args) = get_pyfn_attr(&mut func.attrs)? {
@@ -394,7 +399,7 @@ fn process_functions_in_module(options: &PyModuleOptions, func: &mut syn::ItemFn
394399
#wrapped_function
395400
{
396401
#[allow(unknown_lints, unused_imports, redundant_imports)]
397-
use #pyo3_path::{PyNativeType, types::PyModuleMethods};
402+
#imports
398403
#module_name.as_borrowed().add_function(#pyo3_path::wrap_pyfunction!(#name, #module_name.as_borrowed())?)?;
399404
}
400405
};

pyo3-macros-backend/src/pyclass.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1307,11 +1307,19 @@ fn impl_pytypeinfo(
13071307
quote! { ::core::option::Option::None }
13081308
};
13091309

1310-
quote! {
1310+
#[cfg(feature = "gil-refs")]
1311+
let has_py_gil_ref = quote! {
13111312
#[allow(deprecated)]
13121313
unsafe impl #pyo3_path::type_object::HasPyGilRef for #cls {
13131314
type AsRefTarget = #pyo3_path::PyCell<Self>;
13141315
}
1316+
};
1317+
1318+
#[cfg(not(feature = "gil-refs"))]
1319+
let has_py_gil_ref = TokenStream::new();
1320+
1321+
quote! {
1322+
#has_py_gil_ref
13151323

13161324
unsafe impl #pyo3_path::type_object::PyTypeInfo for #cls {
13171325
const NAME: &'static str = #cls_name;

pyo3-macros/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ proc-macro = true
1717
multiple-pymethods = []
1818
experimental-async = ["pyo3-macros-backend/experimental-async"]
1919
experimental-declarative-modules = []
20+
gil-refs = ["pyo3-macros-backend/gil-refs"]
2021

2122
[dependencies]
2223
proc-macro2 = { version = "1", default-features = false }

src/conversion.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@ use crate::inspect::types::TypeInfo;
55
use crate::pyclass::boolean_struct::False;
66
use crate::types::any::PyAnyMethods;
77
use crate::types::PyTuple;
8-
use crate::{
9-
ffi, Borrowed, Bound, Py, PyAny, PyClass, PyNativeType, PyObject, PyRef, PyRefMut, Python,
10-
};
8+
use crate::{ffi, Borrowed, Bound, Py, PyAny, PyClass, PyObject, PyRef, PyRefMut, Python};
119
#[cfg(feature = "gil-refs")]
1210
use {
1311
crate::{
1412
err::{self, PyDowncastError},
15-
gil,
13+
gil, PyNativeType,
1614
},
1715
std::ptr::NonNull,
1816
};
@@ -221,6 +219,7 @@ pub trait FromPyObject<'py>: Sized {
221219
///
222220
/// Implementors are encouraged to implement `extract_bound` and leave this method as the
223221
/// default implementation, which will forward calls to `extract_bound`.
222+
#[cfg(feature = "gil-refs")]
224223
fn extract(ob: &'py PyAny) -> PyResult<Self> {
225224
Self::extract_bound(&ob.as_borrowed())
226225
}

src/err/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ use crate::panic::PanicException;
33
use crate::type_object::PyTypeInfo;
44
use crate::types::any::PyAnyMethods;
55
use crate::types::{string::PyStringMethods, typeobject::PyTypeMethods, PyTraceback, PyType};
6+
#[cfg(feature = "gil-refs")]
7+
use crate::PyNativeType;
68
use crate::{
79
exceptions::{self, PyBaseException},
810
ffi,
911
};
10-
use crate::{Borrowed, IntoPy, Py, PyAny, PyNativeType, PyObject, Python, ToPyObject};
12+
use crate::{Borrowed, IntoPy, Py, PyAny, PyObject, Python, ToPyObject};
1113
use std::borrow::Cow;
1214
use std::cell::UnsafeCell;
1315
use std::ffi::CString;
@@ -47,11 +49,13 @@ pub type PyResult<T> = Result<T, PyErr>;
4749

4850
/// Error that indicates a failure to convert a PyAny to a more specific Python type.
4951
#[derive(Debug)]
52+
#[cfg(feature = "gil-refs")]
5053
pub struct PyDowncastError<'a> {
5154
from: &'a PyAny,
5255
to: Cow<'static, str>,
5356
}
5457

58+
#[cfg(feature = "gil-refs")]
5559
impl<'a> PyDowncastError<'a> {
5660
/// Create a new `PyDowncastError` representing a failure to convert the object
5761
/// `from` into the type named in `to`.
@@ -64,7 +68,6 @@ impl<'a> PyDowncastError<'a> {
6468

6569
/// Compatibility API to convert the Bound variant `DowncastError` into the
6670
/// gil-ref variant
67-
#[cfg(feature = "gil-refs")]
6871
pub(crate) fn from_downcast_err(DowncastError { from, to }: DowncastError<'a, 'a>) -> Self {
6972
#[allow(deprecated)]
7073
let from = unsafe { from.py().from_borrowed_ptr(from.as_ptr()) };
@@ -1012,8 +1015,10 @@ impl<'a> std::convert::From<PyDowncastError<'a>> for PyErr {
10121015
}
10131016
}
10141017

1018+
#[cfg(feature = "gil-refs")]
10151019
impl<'a> std::error::Error for PyDowncastError<'a> {}
10161020

1021+
#[cfg(feature = "gil-refs")]
10171022
impl<'a> std::fmt::Display for PyDowncastError<'a> {
10181023
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
10191024
display_downcast_error(f, &self.from.as_borrowed(), &self.to)

src/exceptions.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ macro_rules! import_exception_bound {
146146

147147
// FIXME remove this: was necessary while `PyTypeInfo` requires `HasPyGilRef`,
148148
// should change in 0.22.
149+
#[cfg(feature = "gil-refs")]
149150
unsafe impl $crate::type_object::HasPyGilRef for $name {
150151
type AsRefTarget = $crate::PyAny;
151152
}

0 commit comments

Comments
 (0)