Skip to content

Commit 1e8e09d

Browse files
authored
feature gate as/into_gil_ref APIs (Part 3) (#4172)
1 parent aef0a05 commit 1e8e09d

File tree

14 files changed

+196
-152
lines changed

14 files changed

+196
-152
lines changed

guide/src/migration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1649,7 +1649,7 @@ However, for `#[pyproto]` and some functions, you need to manually fix the code.
16491649
In 0.8 object creation was done with `PyRef::new` and `PyRefMut::new`.
16501650
In 0.9 these have both been removed.
16511651
To upgrade code, please use
1652-
[`PyCell::new`]({{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyCell.html#method.new) instead.
1652+
`PyCell::new` instead.
16531653
If you need [`PyRef`] or [`PyRefMut`], just call `.borrow()` or `.borrow_mut()`
16541654
on the newly-created `PyCell`.
16551655

guide/src/types.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,8 +446,10 @@ Like PyO3's Python native types, the GIL Ref `&PyCell<T>` implements `Deref<Targ
446446
`PyCell<T>` was used to access `&T` and `&mut T` via `PyRef<T>` and `PyRefMut<T>` respectively.
447447

448448
```rust
449+
#![allow(unused_imports)]
449450
# use pyo3::prelude::*;
450451
# #[pyclass] struct MyClass { }
452+
# #[cfg(feature = "gil-refs")]
451453
# Python::with_gil(|py| -> PyResult<()> {
452454
#[allow(deprecated)] // &PyCell is part of the deprecated GIL Refs API
453455
let cell: &PyCell<MyClass> = PyCell::new(py, MyClass {})?;

src/conversion.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,7 @@ pub trait FromPyObject<'py>: Sized {
222222
///
223223
/// Implementors are encouraged to implement this method and leave `extract` defaulted, as
224224
/// this will be most compatible with PyO3's future API.
225-
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
226-
Self::extract(ob.clone().into_gil_ref())
227-
}
225+
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self>;
228226

229227
/// Extracts the type hint information for this type when it appears as an argument.
230228
///
@@ -350,8 +348,8 @@ impl<'py, T> FromPyObject<'py> for &'py crate::PyCell<T>
350348
where
351349
T: PyClass,
352350
{
353-
fn extract(obj: &'py PyAny) -> PyResult<Self> {
354-
obj.downcast().map_err(Into::into)
351+
fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {
352+
obj.clone().into_gil_ref().downcast().map_err(Into::into)
355353
}
356354
}
357355

src/conversions/std/slice.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ impl<'a> IntoPy<PyObject> for &'a [u8] {
2020

2121
#[cfg(feature = "gil-refs")]
2222
impl<'py> crate::FromPyObject<'py> for &'py [u8] {
23-
fn extract(obj: &'py PyAny) -> PyResult<Self> {
24-
Ok(obj.downcast::<PyBytes>()?.as_bytes())
23+
fn extract_bound(obj: &crate::Bound<'py, PyAny>) -> PyResult<Self> {
24+
Ok(obj.clone().into_gil_ref().downcast::<PyBytes>()?.as_bytes())
2525
}
2626

2727
#[cfg(feature = "experimental-inspect")]

src/conversions/std/string.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ impl<'a> IntoPy<PyObject> for &'a String {
116116
/// Accepts Python `str` objects.
117117
#[cfg(feature = "gil-refs")]
118118
impl<'py> FromPyObject<'py> for &'py str {
119-
fn extract(ob: &'py PyAny) -> PyResult<Self> {
120-
ob.downcast::<PyString>()?.to_str()
119+
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
120+
ob.clone().into_gil_ref().downcast::<PyString>()?.to_str()
121121
}
122122

123123
#[cfg(feature = "experimental-inspect")]

src/impl_/frompyobject.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::{exceptions::PyTypeError, FromPyObject, PyAny, PyErr, PyResult, Pytho
44

55
pub enum Extractor<'a, 'py, T> {
66
Bound(fn(&'a Bound<'py, PyAny>) -> PyResult<T>),
7+
#[cfg(feature = "gil-refs")]
78
GilRef(fn(&'a PyAny) -> PyResult<T>),
89
}
910

@@ -13,6 +14,7 @@ impl<'a, 'py, T> From<fn(&'a Bound<'py, PyAny>) -> PyResult<T>> for Extractor<'a
1314
}
1415
}
1516

17+
#[cfg(feature = "gil-refs")]
1618
impl<'a, T> From<fn(&'a PyAny) -> PyResult<T>> for Extractor<'a, '_, T> {
1719
fn from(value: fn(&'a PyAny) -> PyResult<T>) -> Self {
1820
Self::GilRef(value)
@@ -23,6 +25,7 @@ impl<'a, 'py, T> Extractor<'a, 'py, T> {
2325
pub(crate) fn call(self, obj: &'a Bound<'py, PyAny>) -> PyResult<T> {
2426
match self {
2527
Extractor::Bound(f) => f(obj),
28+
#[cfg(feature = "gil-refs")]
2629
Extractor::GilRef(f) => f(obj.as_gil_ref()),
2730
}
2831
}

src/impl_/pyfunction.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
types::{PyCFunction, PyModule},
3-
Borrowed, Bound, PyNativeType, PyResult, Python,
3+
Borrowed, Bound, PyResult, Python,
44
};
55

66
pub use crate::impl_::pymethods::PyMethodDef;
@@ -37,14 +37,24 @@ impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for &'_ Borrowed<'_, '
3737

3838
// For Python<'py>, only the GIL Ref form exists to avoid causing type inference to kick in.
3939
// The `wrap_pyfunction_bound!` macro is needed for the Bound form.
40+
#[cfg(feature = "gil-refs")]
4041
impl<'py> WrapPyFunctionArg<'py, &'py PyCFunction> for Python<'py> {
4142
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<&'py PyCFunction> {
4243
PyCFunction::internal_new(self, method_def, None).map(Bound::into_gil_ref)
4344
}
4445
}
4546

47+
#[cfg(not(feature = "gil-refs"))]
48+
impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Python<'py> {
49+
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> {
50+
PyCFunction::internal_new(self, method_def, None)
51+
}
52+
}
53+
54+
#[cfg(feature = "gil-refs")]
4655
impl<'py> WrapPyFunctionArg<'py, &'py PyCFunction> for &'py PyModule {
4756
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<&'py PyCFunction> {
57+
use crate::PyNativeType;
4858
PyCFunction::internal_new(self.py(), method_def, Some(&self.as_borrowed()))
4959
.map(Bound::into_gil_ref)
5060
}
@@ -62,6 +72,7 @@ where
6272
}
6373
}
6474

75+
#[cfg(feature = "gil-refs")]
6576
impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for OnlyBound<Python<'py>> {
6677
fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<Bound<'py, PyCFunction>> {
6778
PyCFunction::internal_new(self.0, method_def, None)

src/impl_/pymethods.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ use crate::impl_::panic::PanicTrap;
55
use crate::internal_tricks::extract_c_string;
66
use crate::pycell::{PyBorrowError, PyBorrowMutError};
77
use crate::pyclass::boolean_struct::False;
8-
use crate::types::{any::PyAnyMethods, PyModule, PyType};
8+
use crate::types::any::PyAnyMethods;
9+
#[cfg(feature = "gil-refs")]
10+
use crate::types::{PyModule, PyType};
911
use crate::{
1012
ffi, Borrowed, Bound, DowncastError, Py, PyAny, PyClass, PyClassInitializer, PyErr, PyObject,
1113
PyRef, PyRefMut, PyResult, PyTraverseError, PyTypeCheck, PyVisit, Python,
@@ -492,13 +494,15 @@ impl<'a, 'py> BoundRef<'a, 'py, PyAny> {
492494

493495
// GIL Ref implementations for &'a T ran into trouble with orphan rules,
494496
// so explicit implementations are used instead for the two relevant types.
497+
#[cfg(feature = "gil-refs")]
495498
impl<'a> From<BoundRef<'a, 'a, PyType>> for &'a PyType {
496499
#[inline]
497500
fn from(bound: BoundRef<'a, 'a, PyType>) -> Self {
498501
bound.0.as_gil_ref()
499502
}
500503
}
501504

505+
#[cfg(feature = "gil-refs")]
502506
impl<'a> From<BoundRef<'a, 'a, PyModule>> for &'a PyModule {
503507
#[inline]
504508
fn from(bound: BoundRef<'a, 'a, PyModule>) -> Self {
@@ -507,6 +511,7 @@ impl<'a> From<BoundRef<'a, 'a, PyModule>> for &'a PyModule {
507511
}
508512

509513
#[allow(deprecated)]
514+
#[cfg(feature = "gil-refs")]
510515
impl<'a, 'py, T: PyClass> From<BoundRef<'a, 'py, T>> for &'a crate::PyCell<T> {
511516
#[inline]
512517
fn from(bound: BoundRef<'a, 'py, T>) -> Self {
@@ -518,15 +523,15 @@ impl<'a, 'py, T: PyClass> TryFrom<BoundRef<'a, 'py, T>> for PyRef<'py, T> {
518523
type Error = PyBorrowError;
519524
#[inline]
520525
fn try_from(value: BoundRef<'a, 'py, T>) -> Result<Self, Self::Error> {
521-
value.0.clone().into_gil_ref().try_into()
526+
value.0.try_borrow()
522527
}
523528
}
524529

525530
impl<'a, 'py, T: PyClass<Frozen = False>> TryFrom<BoundRef<'a, 'py, T>> for PyRefMut<'py, T> {
526531
type Error = PyBorrowMutError;
527532
#[inline]
528533
fn try_from(value: BoundRef<'a, 'py, T>) -> Result<Self, Self::Error> {
529-
value.0.clone().into_gil_ref().try_into()
534+
value.0.try_borrow_mut()
530535
}
531536
}
532537

src/instance.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,7 @@ impl<'py, T> Bound<'py, T> {
492492
///
493493
/// This is a helper to be used for migration from the deprecated "GIL Refs" API.
494494
#[inline]
495+
#[cfg(feature = "gil-refs")]
495496
pub fn as_gil_ref(&'py self) -> &'py T::AsRefTarget
496497
where
497498
T: HasPyGilRef,
@@ -507,6 +508,7 @@ impl<'py, T> Bound<'py, T> {
507508
///
508509
/// This is a helper to be used for migration from the deprecated "GIL Refs" API.
509510
#[inline]
511+
#[cfg(feature = "gil-refs")]
510512
pub fn into_gil_ref(self) -> &'py T::AsRefTarget
511513
where
512514
T: HasPyGilRef,

0 commit comments

Comments
 (0)