Skip to content

Commit

Permalink
Use the new bound API instead of .as_ref(py) (#3853)
Browse files Browse the repository at this point in the history
* Use the new bound API instead of .as_ref(py)

* Move import into a nested scope

* Use to_cow instead of to_str for compatibility

`to_str` is not available before Python 3.10 on the limited api.

* Relax &self lifetimes

* Use Bound<'py, PyAny> in test Mapping signatures

* Use .as_bytes(py)

* Simplify ThrowCallback::throw signature

* Avoid .as_any call with Py api instead of Bound
  • Loading branch information
LilyFoote authored Feb 18, 2024
1 parent 5f42c02 commit 0dd568d
Show file tree
Hide file tree
Showing 20 changed files with 71 additions and 62 deletions.
3 changes: 2 additions & 1 deletion src/conversions/std/ipaddr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ mod test_ipaddr {
};

let pyobj = ip.into_py(py);
let repr = pyobj.as_ref(py).repr().unwrap().to_string_lossy();
let repr = pyobj.bind(py).repr().unwrap();
let repr = repr.to_string_lossy();
assert_eq!(repr, format!("{}('{}')", py_cls, ip));

let ip2: IpAddr = pyobj.extract(py).unwrap();
Expand Down
10 changes: 4 additions & 6 deletions src/conversions/std/osstr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,11 @@ impl FromPyObject<'_> for OsString {

// Create an OsStr view into the raw bytes from Python
#[cfg(target_os = "wasi")]
let os_str: &OsStr = std::os::wasi::ffi::OsStrExt::from_bytes(
fs_encoded_bytes.as_ref(ob.py()).as_bytes(),
);
let os_str: &OsStr =
std::os::wasi::ffi::OsStrExt::from_bytes(fs_encoded_bytes.as_bytes(ob.py()));
#[cfg(not(target_os = "wasi"))]
let os_str: &OsStr = std::os::unix::ffi::OsStrExt::from_bytes(
fs_encoded_bytes.as_ref(ob.py()).as_bytes(),
);
let os_str: &OsStr =
std::os::unix::ffi::OsStrExt::from_bytes(fs_encoded_bytes.as_bytes(ob.py()));

Ok(os_str.to_os_string())
}
Expand Down
4 changes: 2 additions & 2 deletions src/conversions/std/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ mod tests {
.unwrap_err();

let cow = Cow::<[u8]>::Borrowed(b"foobar").to_object(py);
assert!(cow.as_ref(py).is_instance_of::<PyBytes>());
assert!(cow.bind(py).is_instance_of::<PyBytes>());

let cow = Cow::<[u8]>::Owned(b"foobar".to_vec()).to_object(py);
assert!(cow.as_ref(py).is_instance_of::<PyBytes>());
assert!(cow.bind(py).is_instance_of::<PyBytes>());
});
}
}
7 changes: 4 additions & 3 deletions src/conversions/std/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ impl FromPyObject<'_> for char {

#[cfg(test)]
mod tests {
use crate::types::any::PyAnyMethods;
use crate::Python;
use crate::{IntoPy, PyObject, ToPyObject};
use std::borrow::Cow;
Expand Down Expand Up @@ -200,7 +201,7 @@ mod tests {
let s = "Hello Python";
let py_string = s.to_object(py);

let s2: &str = py_string.as_ref(py).extract().unwrap();
let s2: &str = py_string.bind(py).extract().unwrap();
assert_eq!(s, s2);
})
}
Expand All @@ -210,7 +211,7 @@ mod tests {
Python::with_gil(|py| {
let ch = '😃';
let py_string = ch.to_object(py);
let ch2: char = py_string.as_ref(py).extract().unwrap();
let ch2: char = py_string.bind(py).extract().unwrap();
assert_eq!(ch, ch2);
})
}
Expand All @@ -220,7 +221,7 @@ mod tests {
Python::with_gil(|py| {
let s = "Hello Python";
let py_string = s.to_object(py);
let err: crate::PyResult<char> = py_string.as_ref(py).extract();
let err: crate::PyResult<char> = py_string.bind(py).extract();
assert!(err
.unwrap_err()
.to_string()
Expand Down
8 changes: 4 additions & 4 deletions src/coroutine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use crate::{
coroutine::{cancel::ThrowCallback, waker::AsyncioWaker},
exceptions::{PyAttributeError, PyRuntimeError, PyStopIteration},
panic::PanicException,
types::{PyIterator, PyString},
IntoPy, Py, PyAny, PyErr, PyNativeType, PyObject, PyResult, Python,
types::{string::PyStringMethods, PyIterator, PyString},
IntoPy, Py, PyAny, PyErr, PyObject, PyResult, Python,
};

pub(crate) mod cancel;
Expand Down Expand Up @@ -75,7 +75,7 @@ impl Coroutine {
};
// reraise thrown exception it
match (throw, &self.throw_callback) {
(Some(exc), Some(cb)) => cb.throw(exc.as_ref(py)),
(Some(exc), Some(cb)) => cb.throw(exc),
(Some(exc), None) => {
self.close();
return Err(PyErr::from_value_bound(exc.into_bound(py)));
Expand Down Expand Up @@ -135,7 +135,7 @@ impl Coroutine {
#[getter]
fn __qualname__(&self, py: Python<'_>) -> PyResult<Py<PyString>> {
match (&self.name, &self.qualname_prefix) {
(Some(name), Some(prefix)) => Ok(format!("{}.{}", prefix, name.as_ref(py).to_str()?)
(Some(name), Some(prefix)) => Ok(format!("{}.{}", prefix, name.bind(py).to_cow()?)
.as_str()
.into_py(py)),
(Some(name), None) => Ok(name.clone_ref(py)),
Expand Down
6 changes: 3 additions & 3 deletions src/coroutine/cancel.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{PyAny, PyObject};
use crate::{Py, PyAny, PyObject};
use parking_lot::Mutex;
use std::future::Future;
use std::pin::Pin;
Expand Down Expand Up @@ -68,9 +68,9 @@ impl Future for Cancelled<'_> {
pub struct ThrowCallback(Arc<Mutex<Inner>>);

impl ThrowCallback {
pub(super) fn throw(&self, exc: &PyAny) {
pub(super) fn throw(&self, exc: Py<PyAny>) {
let mut inner = self.0.lock();
inner.exception = Some(exc.into());
inner.exception = Some(exc);
if let Some(waker) = inner.waker.take() {
waker.wake();
}
Expand Down
11 changes: 7 additions & 4 deletions src/coroutine/waker.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::sync::GILOnceCell;
use crate::types::any::PyAnyMethods;
use crate::types::PyCFunction;
use crate::{intern, wrap_pyfunction, Py, PyAny, PyObject, PyResult, Python};
use crate::{intern, wrap_pyfunction, Bound, Py, PyAny, PyObject, PyResult, Python};
use pyo3_macros::pyfunction;
use std::sync::Arc;
use std::task::Wake;
Expand All @@ -25,10 +25,13 @@ impl AsyncioWaker {
self.0.take();
}

pub(super) fn initialize_future<'a>(&'a self, py: Python<'a>) -> PyResult<Option<&'a PyAny>> {
pub(super) fn initialize_future<'py>(
&self,
py: Python<'py>,
) -> PyResult<Option<&Bound<'py, PyAny>>> {
let init = || LoopAndFuture::new(py).map(Some);
let loop_and_future = self.0.get_or_try_init(py, init)?.as_ref();
Ok(loop_and_future.map(|LoopAndFuture { future, .. }| future.as_ref(py)))
Ok(loop_and_future.map(|LoopAndFuture { future, .. }| future.bind(py)))
}
}

Expand Down Expand Up @@ -74,7 +77,7 @@ impl LoopAndFuture {
let call_soon_threadsafe = self.event_loop.call_method1(
py,
intern!(py, "call_soon_threadsafe"),
(release_waiter, self.future.as_ref(py)),
(release_waiter, self.future.bind(py)),
);
if let Err(err) = call_soon_threadsafe {
// `call_soon_threadsafe` will raise if the event loop is closed;
Expand Down
6 changes: 3 additions & 3 deletions src/err/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::instance::Bound;
use crate::panic::PanicException;
use crate::type_object::PyTypeInfo;
use crate::types::any::PyAnyMethods;
use crate::types::string::PyStringMethods;
use crate::types::{PyTraceback, PyType};
use crate::{
exceptions::{self, PyBaseException},
Expand Down Expand Up @@ -403,7 +404,7 @@ impl PyErr {
if ptype.as_ptr() == PanicException::type_object_raw(py).cast() {
let msg = pvalue
.as_ref()
.and_then(|obj| obj.as_ref(py).str().ok())
.and_then(|obj| obj.bind(py).str().ok())
.map(|py_str| py_str.to_string_lossy().into())
.unwrap_or_else(|| String::from("Unwrapped panic from Python code"));

Expand All @@ -425,7 +426,7 @@ impl PyErr {
#[cfg(Py_3_12)]
fn _take(py: Python<'_>) -> Option<PyErr> {
let state = PyErrStateNormalized::take(py)?;
let pvalue = state.pvalue.as_ref(py);
let pvalue = state.pvalue.bind(py);
if pvalue.get_type().as_ptr() == PanicException::type_object_raw(py).cast() {
let msg: String = pvalue
.str()
Expand Down Expand Up @@ -905,7 +906,6 @@ impl std::fmt::Debug for PyErr {

impl std::fmt::Display for PyErr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use crate::types::string::PyStringMethods;
Python::with_gil(|py| {
let value = self.value_bound(py);
let type_name = value.get_type().qualname().map_err(|_| std::fmt::Error)?;
Expand Down
10 changes: 5 additions & 5 deletions src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -989,7 +989,7 @@ where
/// Panics if the value is currently mutably borrowed. For a non-panicking variant, use
/// [`try_borrow`](#method.try_borrow).
pub fn borrow<'py>(&'py self, py: Python<'py>) -> PyRef<'py, T> {
self.as_ref(py).borrow()
self.bind(py).borrow()
}

/// Mutably borrows the value `T`.
Expand Down Expand Up @@ -1028,7 +1028,7 @@ where
where
T: PyClass<Frozen = False>,
{
self.as_ref(py).borrow_mut()
self.bind(py).borrow_mut()
}

/// Attempts to immutably borrow the value `T`, returning an error if the value is currently mutably borrowed.
Expand All @@ -1042,7 +1042,7 @@ where
/// Equivalent to `self.as_ref(py).borrow_mut()` -
/// see [`PyCell::try_borrow`](crate::pycell::PyCell::try_borrow).
pub fn try_borrow<'py>(&'py self, py: Python<'py>) -> Result<PyRef<'py, T>, PyBorrowError> {
self.as_ref(py).try_borrow()
self.bind(py).try_borrow()
}

/// Attempts to mutably borrow the value `T`, returning an error if the value is currently borrowed.
Expand All @@ -1060,7 +1060,7 @@ where
where
T: PyClass<Frozen = False>,
{
self.as_ref(py).try_borrow_mut()
self.bind(py).try_borrow_mut()
}

/// Provide an immutable borrow of the value `T` without acquiring the GIL.
Expand Down Expand Up @@ -1667,7 +1667,7 @@ where
T::AsRefTarget: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Python::with_gil(|py| std::fmt::Display::fmt(self.as_ref(py), f))
Python::with_gil(|py| std::fmt::Display::fmt(self.bind(py), f))
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/pycell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
//!
//! // We borrow the guard and then dereference
//! // it to get a mutable reference to Number
//! let mut guard: PyRefMut<'_, Number> = n.as_ref(py).borrow_mut();
//! let mut guard: PyRefMut<'_, Number> = n.bind(py).borrow_mut();
//! let n_mutable: &mut Number = &mut *guard;
//!
//! n_mutable.increment();
Expand All @@ -105,7 +105,7 @@
//! // `PyRefMut` before borrowing again.
//! drop(guard);
//!
//! let n_immutable: &Number = &n.as_ref(py).borrow();
//! let n_immutable: &Number = &n.bind(py).borrow();
//! assert_eq!(n_immutable.inner, 1);
//!
//! Ok(())
Expand Down
6 changes: 3 additions & 3 deletions src/types/capsule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ mod tests {
});

Python::with_gil(|py| {
let f = unsafe { cap.as_ref(py).reference::<fn(u32) -> u32>() };
let f = unsafe { cap.bind(py).reference::<fn(u32) -> u32>() };
assert_eq!(f(123), 123);
});
}
Expand Down Expand Up @@ -555,7 +555,7 @@ mod tests {
});

Python::with_gil(|py| {
let ctx: &Vec<u8> = unsafe { cap.as_ref(py).reference() };
let ctx: &Vec<u8> = unsafe { cap.bind(py).reference() };
assert_eq!(ctx, &[1, 2, 3, 4]);
})
}
Expand All @@ -574,7 +574,7 @@ mod tests {
});

Python::with_gil(|py| {
let ctx_ptr: *mut c_void = cap.as_ref(py).context().unwrap();
let ctx_ptr: *mut c_void = cap.bind(py).context().unwrap();
let ctx = unsafe { *Box::from_raw(ctx_ptr.cast::<&Vec<u8>>()) };
assert_eq!(ctx, &vec![1_u8, 2, 3, 4]);
})
Expand Down
2 changes: 1 addition & 1 deletion tests/test_class_basics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ fn test_unsendable<T: PyClass + 'static>() -> PyResult<()> {
// Accessing the value inside this thread should not panic
let caught_panic =
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| -> PyResult<_> {
assert_eq!(obj.as_ref(py).getattr("value")?.extract::<usize>()?, 5);
assert_eq!(obj.getattr(py, "value")?.extract::<usize>(py)?, 5);
Ok(())
}))
.is_err();
Expand Down
4 changes: 2 additions & 2 deletions tests/test_class_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ fn test_polymorphic_container_stores_sub_class() {
.unwrap()
.to_object(py);

p.as_ref(py)
p.bind(py)
.setattr(
"inner",
PyCell::new(
Expand All @@ -116,7 +116,7 @@ fn test_polymorphic_container_does_not_accept_other_types() {
.unwrap()
.to_object(py);

let setattr = |value: PyObject| p.as_ref(py).setattr("inner", value);
let setattr = |value: PyObject| p.bind(py).setattr("inner", value);

assert!(setattr(1i32.into_py(py)).is_err());
assert!(setattr(py.None()).is_err());
Expand Down
10 changes: 8 additions & 2 deletions tests/test_field_cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@ fn test_cfg() {
Python::with_gil(|py| {
let cfg = CfgClass { b: 3 };
let py_cfg = Py::new(py, cfg).unwrap();
assert!(py_cfg.as_ref(py).getattr("a").is_err());
let b: u32 = py_cfg.as_ref(py).getattr("b").unwrap().extract().unwrap();
assert!(py_cfg.bind(py).as_any().getattr("a").is_err());
let b: u32 = py_cfg
.bind(py)
.as_any()
.getattr("b")
.unwrap()
.extract()
.unwrap();
assert_eq!(b, 3);
});
}
2 changes: 1 addition & 1 deletion tests/test_inheritance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ mod inheriting_native_type {
let item = &py.eval_bound("object()", None, None).unwrap();
assert_eq!(item.get_refcnt(), 1);

dict_sub.as_ref(py).set_item("foo", item).unwrap();
dict_sub.bind(py).as_any().set_item("foo", item).unwrap();
assert_eq!(item.get_refcnt(), 2);

drop(dict_sub);
Expand Down
4 changes: 2 additions & 2 deletions tests/test_mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ fn mapping_is_not_sequence() {

PyMapping::register::<Mapping>(py).unwrap();

assert!(m.as_ref(py).downcast::<PyMapping>().is_ok());
assert!(m.as_ref(py).downcast::<PySequence>().is_err());
assert!(m.bind(py).as_any().downcast::<PyMapping>().is_ok());
assert!(m.bind(py).as_any().downcast::<PySequence>().is_err());
});
}
Loading

0 comments on commit 0dd568d

Please sign in to comment.