2021-09-13 20:58:15 +00:00
//! PyO3's interior mutability primitive.
//!
2021-09-22 01:13:26 +00:00
//! Rust has strict aliasing rules - you can either have any number of immutable (shared) references or one mutable
//! reference. Python's ownership model is the complete opposite of that - any Python object
//! can be referenced any number of times, and mutation is allowed from any reference.
//!
//! PyO3 deals with these differences by employing the [Interior Mutability]
//! pattern. This requires that PyO3 enforces the borrowing rules and it has two mechanisms for
//! doing so:
//! - Statically it can enforce threadsafe access with the [`Python<'py>`](crate::Python) token.
//! All Rust code holding that token, or anything derived from it, can assume that they have
//! safe access to the Python interpreter's state. For this reason all the native Python objects
//! can be mutated through shared references.
//! - However, methods and functions in Rust usually *do* need `&mut` references. While PyO3 can
//! use the [`Python<'py>`](crate::Python) token to guarantee thread-safe access to them, it cannot
//! statically guarantee uniqueness of `&mut` references. As such those references have to be tracked
//! dynamically at runtime, using [`PyCell`] and the other types defined in this module. This works
//! similar to std's [`RefCell`](std::cell::RefCell) type.
//!
//! # When *not* to use PyCell
//!
//! Usually you can use `&mut` references as method and function receivers and arguments, and you
//! won't need to use [`PyCell`] directly:
//!
//! ```rust
//! use pyo3::prelude::*;
//!
2021-11-20 13:58:56 +00:00
//! #[pyclass]
2021-09-22 01:13:26 +00:00
//! struct Number {
//! inner: u32,
//! }
//!
//! #[pymethods]
//! impl Number {
//! fn increment(&mut self) {
//! self.inner += 1;
//! }
//! }
//! ```
//!
//! The [`#[pymethods]`](crate::pymethods) proc macro will generate this wrapper function (and more),
//! using [`PyCell`] under the hood:
//!
2024-05-09 22:21:48 +00:00
//! ```rust,ignore
2022-05-02 22:47:09 +00:00
//! # use pyo3::prelude::*;
//! # #[pyclass]
//! # struct Number {
//! # inner: u32,
//! # }
//! #
//! # #[pymethods]
//! # impl Number {
//! # fn increment(&mut self) {
//! # self.inner += 1;
//! # }
//! # }
//! #
2022-10-25 06:22:36 +00:00
//! // The function which is exported to Python looks roughly like the following
2022-05-24 18:36:24 +00:00
//! unsafe extern "C" fn __pymethod_increment__(
2022-08-21 12:27:04 +00:00
//! _slf: *mut pyo3::ffi::PyObject,
//! _args: *mut pyo3::ffi::PyObject,
//! ) -> *mut pyo3::ffi::PyObject {
2022-05-02 22:47:09 +00:00
//! use :: pyo3 as _pyo3;
2022-10-25 06:22:36 +00:00
//! _pyo3::impl_::trampoline::noargs(_slf, _args, |py, _slf| {
2024-03-03 14:47:25 +00:00
//! # #[allow(deprecated)]
2022-10-25 06:22:36 +00:00
//! let _cell = py
//! .from_borrowed_ptr::<_pyo3::PyAny>(_slf)
//! .downcast::<_pyo3::PyCell<Number>>()?;
//! let mut _ref = _cell.try_borrow_mut()?;
//! let _slf: &mut Number = &mut *_ref;
//! _pyo3::callback::convert(py, Number::increment(_slf))
//! })
2021-09-22 01:13:26 +00:00
//! }
2022-05-24 18:36:24 +00:00
//! ```
2021-09-22 01:13:26 +00:00
//!
//! # When to use PyCell
//! ## Using pyclasses from Rust
//!
//! However, we *do* need [`PyCell`] if we want to call its methods from Rust:
//! ```rust
//! # use pyo3::prelude::*;
//! #
2021-11-20 13:58:56 +00:00
//! # #[pyclass]
2021-09-22 01:13:26 +00:00
//! # struct Number {
//! # inner: u32,
//! # }
//! #
//! # #[pymethods]
//! # impl Number {
//! # fn increment(&mut self) {
//! # self.inner += 1;
//! # }
//! # }
//! # fn main() -> PyResult<()> {
//! Python::with_gil(|py| {
2021-09-22 13:02:49 +00:00
//! let n = Py::new(py, Number { inner: 0 })?;
2021-09-22 01:13:26 +00:00
//!
//! // We borrow the guard and then dereference
//! // it to get a mutable reference to Number
2024-02-18 00:09:56 +00:00
//! let mut guard: PyRefMut<'_, Number> = n.bind(py).borrow_mut();
2021-09-22 01:13:26 +00:00
//! let n_mutable: &mut Number = &mut *guard;
//!
//! n_mutable.increment();
//!
//! // To avoid panics we must dispose of the
//! // `PyRefMut` before borrowing again.
//! drop(guard);
//!
2024-02-18 00:09:56 +00:00
//! let n_immutable: &Number = &n.bind(py).borrow();
2021-09-22 01:13:26 +00:00
//! assert_eq!(n_immutable.inner, 1);
//!
//! Ok(())
//! })
//! # }
//! ```
//! ## Dealing with possibly overlapping mutable references
//!
//! It is also necessary to use [`PyCell`] if you can receive mutable arguments that may overlap.
//! Suppose the following function that swaps the values of two `Number`s:
//! ```
//! # use pyo3::prelude::*;
2021-11-20 13:58:56 +00:00
//! # #[pyclass]
2021-09-22 01:13:26 +00:00
//! # pub struct Number {
//! # inner: u32,
//! # }
//! #[pyfunction]
2021-09-22 11:26:37 +00:00
//! fn swap_numbers(a: &mut Number, b: &mut Number) {
2021-09-22 01:13:26 +00:00
//! std::mem::swap(&mut a.inner, &mut b.inner);
//! }
2021-10-14 21:15:25 +00:00
//! # fn main() {
2022-11-20 12:47:06 +00:00
//! # Python::with_gil(|py| {
2021-10-14 21:15:25 +00:00
//! # let n = Py::new(py, Number{inner: 35}).unwrap();
//! # let n2 = n.clone_ref(py);
2022-03-30 10:56:14 +00:00
//! # assert!(n.is(&n2));
2024-03-12 22:57:03 +00:00
//! # let fun = pyo3::wrap_pyfunction_bound!(swap_numbers, py).unwrap();
2021-10-14 21:15:25 +00:00
//! # fun.call1((n, n2)).expect_err("Managed to create overlapping mutable references. Note: this is undefined behaviour.");
//! # });
//! # }
2021-09-22 01:13:26 +00:00
//! ```
//! When users pass in the same `Number` as both arguments, one of the mutable borrows will
//! fail and raise a `RuntimeError`:
//! ```text
//! >>> a = Number()
2021-09-22 11:26:37 +00:00
//! >>> swap_numbers(a, a)
2021-09-22 01:13:26 +00:00
//! Traceback (most recent call last):
//! File "<stdin>", line 1, in <module>
//! RuntimeError: Already borrowed
//! ```
//!
//! It is better to write that function like this:
2024-05-09 22:21:48 +00:00
//! ```rust,ignore
2024-03-20 22:35:08 +00:00
//! # #![allow(deprecated)]
2021-09-22 01:13:26 +00:00
//! # use pyo3::prelude::*;
2021-11-20 13:58:56 +00:00
//! # #[pyclass]
2021-09-22 01:13:26 +00:00
//! # pub struct Number {
//! # inner: u32,
//! # }
//! #[pyfunction]
//! fn swap_numbers(a: &PyCell<Number>, b: &PyCell<Number>) {
//! // Check that the pointers are unequal
2022-03-30 10:56:14 +00:00
//! if !a.is(b) {
2021-09-22 01:13:26 +00:00
//! std::mem::swap(&mut a.borrow_mut().inner, &mut b.borrow_mut().inner);
//! } else {
//! // Do nothing - they are the same object, so don't need swapping.
//! }
//! }
2021-10-14 21:15:25 +00:00
//! # fn main() {
//! # // With duplicate numbers
2022-11-20 12:47:06 +00:00
//! # Python::with_gil(|py| {
2021-10-14 21:15:25 +00:00
//! # let n = Py::new(py, Number{inner: 35}).unwrap();
//! # let n2 = n.clone_ref(py);
2022-03-30 10:56:14 +00:00
//! # assert!(n.is(&n2));
2024-03-12 22:57:03 +00:00
//! # let fun = pyo3::wrap_pyfunction_bound!(swap_numbers, py).unwrap();
2021-10-14 21:15:25 +00:00
//! # fun.call1((n, n2)).unwrap();
//! # });
//! #
//! # // With two different numbers
2022-11-20 12:47:06 +00:00
//! # Python::with_gil(|py| {
2021-10-14 21:15:25 +00:00
//! # let n = Py::new(py, Number{inner: 35}).unwrap();
//! # let n2 = Py::new(py, Number{inner: 42}).unwrap();
2022-03-30 10:56:14 +00:00
//! # assert!(!n.is(&n2));
2024-03-12 22:57:03 +00:00
//! # let fun = pyo3::wrap_pyfunction_bound!(swap_numbers, py).unwrap();
2021-10-14 21:15:25 +00:00
//! # fun.call1((&n, &n2)).unwrap();
//! # let n: u32 = n.borrow(py).inner;
//! # let n2: u32 = n2.borrow(py).inner;
//! # assert_eq!(n, 42);
//! # assert_eq!(n2, 35);
//! # });
//! # }
2021-09-22 01:13:26 +00:00
//! ```
//! See the [guide] for more information.
//!
//! [guide]: https://pyo3.rs/latest/class.html#pycell-and-interior-mutability "PyCell and interior mutability"
//! [Interior Mutability]: https://doc.rust-lang.org/book/ch15-05-interior-mutability.html "RefCell<T> and the Interior Mutability Pattern - The Rust Programming Language"
2021-09-13 20:58:15 +00:00
2024-03-03 07:00:59 +00:00
use crate ::conversion ::{ AsPyPointer , ToPyObject } ;
2020-07-04 15:55:26 +00:00
use crate ::exceptions ::PyRuntimeError ;
2024-02-27 18:56:22 +00:00
use crate ::ffi_ptr_ext ::FfiPtrExt ;
2024-03-03 07:00:59 +00:00
use crate ::impl_ ::pyclass ::PyClassImpl ;
2023-05-16 19:48:59 +00:00
use crate ::pyclass ::{
boolean_struct ::{ False , True } ,
PyClass ,
} ;
2020-02-03 13:25:16 +00:00
use crate ::pyclass_init ::PyClassInitializer ;
2021-05-04 20:10:03 +00:00
use crate ::type_object ::{ PyLayout , PySizedLayout } ;
2024-02-27 18:56:22 +00:00
use crate ::types ::any ::PyAnyMethods ;
2020-05-03 12:12:51 +00:00
use crate ::types ::PyAny ;
2024-01-30 10:31:34 +00:00
use crate ::{ ffi , Bound , IntoPy , PyErr , PyNativeType , PyObject , PyResult , PyTypeCheck , Python } ;
2020-09-15 11:50:24 +00:00
use std ::fmt ;
2020-02-03 13:25:16 +00:00
use std ::mem ::ManuallyDrop ;
2020-02-09 07:36:32 +00:00
use std ::ops ::{ Deref , DerefMut } ;
2021-11-26 16:16:05 +00:00
2022-08-20 09:03:13 +00:00
pub ( crate ) mod impl_ ;
2024-03-03 07:00:59 +00:00
use impl_ ::PyClassBorrowChecker ;
2020-02-15 04:42:25 +00:00
2024-03-03 07:00:59 +00:00
use self ::impl_ ::{ PyClassObject , PyClassObjectLayout } ;
2020-02-15 04:42:25 +00:00
2021-09-22 01:13:26 +00:00
/// A container type for (mutably) accessing [`PyClass`] values
2020-02-03 13:25:16 +00:00
///
2021-09-22 01:13:26 +00:00
/// `PyCell` autodereferences to [`PyAny`], so you can call `PyAny`'s methods on a `PyCell<T>`.
2020-05-03 12:12:51 +00:00
///
2020-02-22 14:38:01 +00:00
/// # Examples
///
2021-09-22 01:13:26 +00:00
/// This example demonstrates getting a mutable reference of the contained `PyClass`.
/// ```rust
/// use pyo3::prelude::*;
2020-02-22 14:38:01 +00:00
///
2021-11-20 13:58:56 +00:00
/// #[pyclass]
2021-09-22 01:13:26 +00:00
/// struct Number {
/// inner: u32,
2020-02-21 12:12:32 +00:00
/// }
2021-09-22 01:13:26 +00:00
///
2020-02-21 12:12:32 +00:00
/// #[pymethods]
2021-09-22 01:13:26 +00:00
/// impl Number {
/// fn increment(&mut self) {
/// self.inner += 1;
2020-02-21 12:12:32 +00:00
/// }
/// }
2021-09-22 01:13:26 +00:00
///
/// # fn main() -> PyResult<()> {
/// Python::with_gil(|py| {
2024-02-20 07:45:47 +00:00
/// # #[allow(deprecated)]
2021-09-22 01:13:26 +00:00
/// let n = PyCell::new(py, Number { inner: 0 })?;
///
/// let n_mutable: &mut Number = &mut n.borrow_mut();
/// n_mutable.increment();
///
/// Ok(())
/// })
/// # }
2020-02-03 13:25:16 +00:00
/// ```
2021-09-22 01:13:26 +00:00
/// For more information on how, when and why (not) to use `PyCell` please see the
/// [module-level documentation](self).
2024-03-03 14:47:25 +00:00
#[ cfg_attr(
not ( feature = " gil-refs " ) ,
deprecated (
since = " 0.21.0 " ,
note = " `PyCell` was merged into `Bound`, use that instead; see the migration guide for more info "
)
) ]
2024-03-03 07:00:59 +00:00
#[ repr(transparent) ]
pub struct PyCell < T : PyClassImpl > ( PyClassObject < T > ) ;
2020-02-03 13:25:16 +00:00
2024-03-03 14:47:25 +00:00
#[ allow(deprecated) ]
2023-12-14 18:35:06 +00:00
unsafe impl < T : PyClass > PyNativeType for PyCell < T > {
type AsRefSource = T ;
}
2020-05-01 16:09:10 +00:00
2024-03-03 14:47:25 +00:00
#[ allow(deprecated) ]
2020-02-03 13:25:16 +00:00
impl < T : PyClass > PyCell < T > {
2021-07-31 22:23:59 +00:00
/// Makes a new `PyCell` on the Python heap and return the reference to it.
2020-02-22 14:38:01 +00:00
///
2020-06-14 21:36:07 +00:00
/// In cases where the value in the cell does not need to be accessed immediately after
2021-09-22 01:13:26 +00:00
/// creation, consider [`Py::new`](crate::Py::new) as a more efficient alternative.
2024-02-20 07:45:47 +00:00
#[ cfg_attr(
not ( feature = " gil-refs " ) ,
deprecated (
since = " 0.21.0 " ,
2024-02-24 13:25:06 +00:00
note = " use `Bound::new(py, value)` or `Py::new(py, value)` instead of `PyCell::new(py, value)` "
2024-02-20 07:45:47 +00:00
)
) ]
2022-03-23 07:07:28 +00:00
pub fn new ( py : Python < '_ > , value : impl Into < PyClassInitializer < T > > ) -> PyResult < & Self > {
2024-03-03 07:00:59 +00:00
Bound ::new ( py , value ) . map ( Bound ::into_gil_ref )
2020-02-03 13:25:16 +00:00
}
2021-07-31 22:23:59 +00:00
/// Immutably borrows the value `T`. This borrow lasts as long as the returned `PyRef` exists.
2020-02-22 14:38:01 +00:00
///
2023-05-16 19:48:59 +00:00
/// For frozen classes, the simpler [`get`][Self::get] is available.
///
2020-02-22 14:38:01 +00:00
/// # Panics
///
/// Panics if the value is currently mutably borrowed. For a non-panicking variant, use
/// [`try_borrow`](#method.try_borrow).
2020-02-09 07:36:32 +00:00
pub fn borrow ( & self ) -> PyRef < '_ , T > {
2024-02-27 18:56:22 +00:00
PyRef ::borrow ( & self . as_borrowed ( ) )
2020-02-03 13:25:16 +00:00
}
2021-11-20 13:58:56 +00:00
/// Mutably borrows the value `T`. This borrow lasts as long as the returned `PyRefMut` exists.
///
/// # Panics
///
/// Panics if the value is currently borrowed. For a non-panicking variant, use
/// [`try_borrow_mut`](#method.try_borrow_mut).
2021-11-22 08:26:34 +00:00
pub fn borrow_mut ( & self ) -> PyRefMut < '_ , T >
where
2022-06-11 11:20:43 +00:00
T : PyClass < Frozen = False > ,
2021-11-22 08:26:34 +00:00
{
2024-02-27 18:56:22 +00:00
PyRefMut ::borrow ( & self . as_borrowed ( ) )
2020-02-10 08:30:48 +00:00
}
2020-02-22 14:38:01 +00:00
/// Immutably borrows the value `T`, returning an error if the value is currently
2021-07-31 22:23:59 +00:00
/// mutably borrowed. This borrow lasts as long as the returned `PyRef` exists.
2020-02-22 14:38:01 +00:00
///
/// This is the non-panicking variant of [`borrow`](#method.borrow).
///
2023-05-16 19:48:59 +00:00
/// For frozen classes, the simpler [`get`][Self::get] is available.
///
2020-02-22 14:38:01 +00:00
/// # Examples
///
/// ```
/// # use pyo3::prelude::*;
2021-11-20 13:58:56 +00:00
/// #[pyclass]
2020-02-22 14:38:01 +00:00
/// struct Class {}
2021-09-22 01:13:26 +00:00
///
2021-03-20 07:44:28 +00:00
/// Python::with_gil(|py| {
2024-02-20 07:45:47 +00:00
/// # #[allow(deprecated)]
2021-03-20 07:44:28 +00:00
/// let c = PyCell::new(py, Class {}).unwrap();
/// {
/// let m = c.borrow_mut();
/// assert!(c.try_borrow().is_err());
/// }
2020-02-22 14:38:01 +00:00
///
2021-03-20 07:44:28 +00:00
/// {
/// let m = c.borrow();
/// assert!(c.try_borrow().is_ok());
/// }
/// });
2020-02-22 14:38:01 +00:00
/// ```
2020-02-10 08:30:48 +00:00
pub fn try_borrow ( & self ) -> Result < PyRef < '_ , T > , PyBorrowError > {
2024-02-27 18:56:22 +00:00
PyRef ::try_borrow ( & self . as_borrowed ( ) )
2023-12-22 11:01:40 +00:00
}
2021-11-20 13:58:56 +00:00
/// Mutably borrows the value `T`, returning an error if the value is currently borrowed.
/// This borrow lasts as long as the returned `PyRefMut` exists.
2020-02-22 14:38:01 +00:00
///
2021-11-20 13:58:56 +00:00
/// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut).
2020-02-22 14:38:01 +00:00
///
/// # Examples
///
/// ```
/// # use pyo3::prelude::*;
2021-11-20 13:58:56 +00:00
/// #[pyclass]
2020-02-22 14:38:01 +00:00
/// struct Class {}
2021-03-20 07:44:28 +00:00
/// Python::with_gil(|py| {
2024-02-20 07:45:47 +00:00
/// # #[allow(deprecated)]
2021-03-20 07:44:28 +00:00
/// let c = PyCell::new(py, Class {}).unwrap();
/// {
/// let m = c.borrow();
2021-11-20 13:58:56 +00:00
/// assert!(c.try_borrow_mut().is_err());
2021-03-20 07:44:28 +00:00
/// }
2021-11-20 13:58:56 +00:00
///
/// assert!(c.try_borrow_mut().is_ok());
2021-03-20 07:44:28 +00:00
/// });
2020-02-22 14:38:01 +00:00
/// ```
2021-11-22 08:26:34 +00:00
pub fn try_borrow_mut ( & self ) -> Result < PyRefMut < '_ , T > , PyBorrowMutError >
where
2022-06-11 11:20:43 +00:00
T : PyClass < Frozen = False > ,
2021-11-22 08:26:34 +00:00
{
2024-02-27 18:56:22 +00:00
PyRefMut ::try_borrow ( & self . as_borrowed ( ) )
2020-02-09 07:36:32 +00:00
}
2021-11-20 13:58:56 +00:00
/// Immutably borrows the value `T`, returning an error if the value is
/// currently mutably borrowed.
2021-11-10 14:28:19 +00:00
///
2021-11-20 13:58:56 +00:00
/// # Safety
2021-11-10 14:28:19 +00:00
///
2021-11-20 13:58:56 +00:00
/// This method is unsafe because it does not return a `PyRef`,
/// thus leaving the borrow flag untouched. Mutably borrowing the `PyCell`
/// while the reference returned by this method is alive is undefined behaviour.
2021-11-10 14:28:19 +00:00
///
/// # Examples
///
/// ```
/// # use pyo3::prelude::*;
2021-11-20 13:58:56 +00:00
/// #[pyclass]
2021-11-10 14:28:19 +00:00
/// struct Class {}
/// Python::with_gil(|py| {
2024-02-20 07:45:47 +00:00
/// # #[allow(deprecated)]
2021-11-10 14:28:19 +00:00
/// let c = PyCell::new(py, Class {}).unwrap();
2021-11-20 13:58:56 +00:00
///
2021-11-10 14:28:19 +00:00
/// {
2021-11-20 13:58:56 +00:00
/// let m = c.borrow_mut();
/// assert!(unsafe { c.try_borrow_unguarded() }.is_err());
2021-11-10 14:28:19 +00:00
/// }
///
2021-11-20 13:58:56 +00:00
/// {
/// let m = c.borrow();
/// assert!(unsafe { c.try_borrow_unguarded() }.is_ok());
/// }
2021-11-10 14:28:19 +00:00
/// });
/// ```
2021-11-20 13:58:56 +00:00
pub unsafe fn try_borrow_unguarded ( & self ) -> Result < & T , PyBorrowError > {
2024-03-03 07:00:59 +00:00
self . 0. ensure_threadsafe ( ) ;
self . 0
. borrow_checker ( )
2022-04-23 05:27:30 +00:00
. try_borrow_unguarded ( )
2024-03-03 07:00:59 +00:00
. map ( | _ : ( ) | & * self . 0. get_ptr ( ) )
2021-11-10 14:28:19 +00:00
}
2021-11-20 13:58:56 +00:00
2023-05-16 19:48:59 +00:00
/// Provide an immutable borrow of the value `T` without acquiring the GIL.
///
/// This is available if the class is [`frozen`][macro@crate::pyclass] and [`Sync`].
///
/// While the GIL is usually required to get access to `&PyCell<T>`,
/// compared to [`borrow`][Self::borrow] or [`try_borrow`][Self::try_borrow]
/// this avoids any thread or borrow checking overhead at runtime.
///
/// # Examples
///
/// ```
/// use std::sync::atomic::{AtomicUsize, Ordering};
/// # use pyo3::prelude::*;
///
/// #[pyclass(frozen)]
/// struct FrozenCounter {
/// value: AtomicUsize,
/// }
///
/// Python::with_gil(|py| {
/// let counter = FrozenCounter { value: AtomicUsize::new(0) };
///
2024-02-20 07:45:47 +00:00
/// # #[allow(deprecated)]
2023-05-16 19:48:59 +00:00
/// let cell = PyCell::new(py, counter).unwrap();
///
/// cell.get().value.fetch_add(1, Ordering::Relaxed);
/// });
/// ```
pub fn get ( & self ) -> & T
where
T : PyClass < Frozen = True > + Sync ,
{
// SAFETY: The class itself is frozen and `Sync` and we do not access anything but `self.contents.value`.
unsafe { & * self . get_ptr ( ) }
}
2021-07-31 22:23:59 +00:00
/// Replaces the wrapped value with a new one, returning the old value.
2020-02-22 14:38:01 +00:00
///
/// # Panics
///
/// Panics if the value is currently borrowed.
#[ inline ]
2021-11-22 08:26:34 +00:00
pub fn replace ( & self , t : T ) -> T
where
2022-06-11 11:20:43 +00:00
T : PyClass < Frozen = False > ,
2021-11-22 08:26:34 +00:00
{
2020-02-22 14:38:01 +00:00
std ::mem ::replace ( & mut * self . borrow_mut ( ) , t )
}
/// Replaces the wrapped value with a new one computed from `f`, returning the old value.
///
/// # Panics
///
/// Panics if the value is currently borrowed.
2021-11-22 08:26:34 +00:00
pub fn replace_with < F : FnOnce ( & mut T ) -> T > ( & self , f : F ) -> T
where
2022-06-11 11:20:43 +00:00
T : PyClass < Frozen = False > ,
2021-11-22 08:26:34 +00:00
{
2020-02-22 14:38:01 +00:00
let mut_borrow = & mut * self . borrow_mut ( ) ;
let replacement = f ( mut_borrow ) ;
std ::mem ::replace ( mut_borrow , replacement )
}
/// Swaps the wrapped value of `self` with the wrapped value of `other`.
///
/// # Panics
///
/// Panics if the value in either `PyCell` is currently borrowed.
#[ inline ]
2021-11-22 08:26:34 +00:00
pub fn swap ( & self , other : & Self )
where
2022-06-11 11:20:43 +00:00
T : PyClass < Frozen = False > ,
2021-11-22 08:26:34 +00:00
{
2020-02-22 14:38:01 +00:00
std ::mem ::swap ( & mut * self . borrow_mut ( ) , & mut * other . borrow_mut ( ) )
2020-02-03 13:25:16 +00:00
}
2021-11-20 13:58:56 +00:00
2023-05-16 19:48:59 +00:00
pub ( crate ) fn get_ptr ( & self ) -> * mut T {
2024-03-03 07:00:59 +00:00
self . 0. get_ptr ( )
2022-04-21 07:03:45 +00:00
}
}
2024-03-03 14:47:25 +00:00
#[ allow(deprecated) ]
2022-04-21 07:03:45 +00:00
unsafe impl < T : PyClassImpl > PyLayout < T > for PyCell < T > { }
2024-03-03 14:47:25 +00:00
#[ allow(deprecated) ]
2021-05-16 23:31:05 +00:00
impl < T : PyClass > PySizedLayout < T > for PyCell < T > { }
2020-02-03 13:25:16 +00:00
2024-03-03 14:47:25 +00:00
#[ allow(deprecated) ]
2023-11-27 20:19:44 +00:00
impl < T > PyTypeCheck for PyCell < T >
where
T : PyClass ,
{
const NAME : & 'static str = < T as PyTypeCheck > ::NAME ;
2024-01-30 10:31:34 +00:00
fn type_check ( object : & Bound < '_ , PyAny > ) -> bool {
2023-11-27 20:19:44 +00:00
< T as PyTypeCheck > ::type_check ( object )
}
}
2024-03-03 14:47:25 +00:00
#[ allow(deprecated) ]
2023-07-30 18:40:52 +00:00
unsafe impl < T : PyClass > AsPyPointer for PyCell < T > {
2020-02-03 13:25:16 +00:00
fn as_ptr ( & self ) -> * mut ffi ::PyObject {
2021-05-16 23:31:05 +00:00
( self as * const _ ) as * mut _
2020-02-03 13:25:16 +00:00
}
}
2024-03-03 14:47:25 +00:00
#[ allow(deprecated) ]
2020-02-03 13:25:16 +00:00
impl < T : PyClass > ToPyObject for & PyCell < T > {
fn to_object ( & self , py : Python < '_ > ) -> PyObject {
unsafe { PyObject ::from_borrowed_ptr ( py , self . as_ptr ( ) ) }
}
}
2024-03-03 14:47:25 +00:00
#[ allow(deprecated) ]
2020-05-03 12:12:51 +00:00
impl < T : PyClass > AsRef < PyAny > for PyCell < T > {
fn as_ref ( & self ) -> & PyAny {
2024-03-01 20:51:53 +00:00
#[ allow(deprecated) ]
unsafe {
self . py ( ) . from_borrowed_ptr ( self . as_ptr ( ) )
}
2020-05-03 12:12:51 +00:00
}
}
2024-03-03 14:47:25 +00:00
#[ allow(deprecated) ]
2020-05-03 12:12:51 +00:00
impl < T : PyClass > Deref for PyCell < T > {
type Target = PyAny ;
fn deref ( & self ) -> & PyAny {
2024-03-01 20:51:53 +00:00
#[ allow(deprecated) ]
unsafe {
self . py ( ) . from_borrowed_ptr ( self . as_ptr ( ) )
}
2020-05-03 12:12:51 +00:00
}
}
2024-03-03 14:47:25 +00:00
#[ allow(deprecated) ]
2020-02-15 15:24:38 +00:00
impl < T : PyClass + fmt ::Debug > fmt ::Debug for PyCell < T > {
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
match self . try_borrow ( ) {
Ok ( borrow ) = > f . debug_struct ( " RefCell " ) . field ( " value " , & borrow ) . finish ( ) ,
Err ( _ ) = > {
struct BorrowedPlaceholder ;
impl fmt ::Debug for BorrowedPlaceholder {
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
f . write_str ( " <borrowed> " )
}
}
f . debug_struct ( " RefCell " )
. field ( " value " , & BorrowedPlaceholder )
. finish ( )
}
}
}
}
2021-09-22 01:13:26 +00:00
/// A wrapper type for an immutably borrowed value from a [`PyCell`]`<T>`.
2020-02-21 12:12:32 +00:00
///
2021-09-22 01:13:26 +00:00
/// See the [`PyCell`] documentation for more information.
2021-07-31 22:23:59 +00:00
///
2021-03-20 07:45:56 +00:00
/// # Examples
2021-07-31 22:23:59 +00:00
///
/// You can use `PyRef` as an alternative to a `&self` receiver when
/// - you need to access the pointer of the `PyCell`, or
/// - you want to get a super class.
2020-02-21 12:12:32 +00:00
/// ```
/// # use pyo3::prelude::*;
2020-09-01 00:36:26 +00:00
/// #[pyclass(subclass)]
2020-02-21 12:12:32 +00:00
/// struct Parent {
/// basename: &'static str,
/// }
2021-09-22 01:13:26 +00:00
///
2020-02-21 12:12:32 +00:00
/// #[pyclass(extends=Parent)]
/// struct Child {
/// name: &'static str,
/// }
2021-09-22 01:13:26 +00:00
///
2020-02-21 12:12:32 +00:00
/// #[pymethods]
/// impl Child {
/// #[new]
/// fn new() -> (Self, Parent) {
/// (Child { name: "Caterpillar" }, Parent { basename: "Butterfly" })
/// }
2021-09-22 01:13:26 +00:00
///
2022-03-23 07:07:28 +00:00
/// fn format(slf: PyRef<'_, Self>) -> String {
2020-02-21 12:12:32 +00:00
/// // We can get *mut ffi::PyObject from PyRef
/// let refcnt = unsafe { pyo3::ffi::Py_REFCNT(slf.as_ptr()) };
/// // We can get &Self::BaseType by as_ref
/// let basename = slf.as_ref().basename;
/// format!("{}(base: {}, cnt: {})", slf.name, basename, refcnt)
/// }
/// }
2021-03-20 07:44:28 +00:00
/// # Python::with_gil(|py| {
2024-02-20 07:45:47 +00:00
/// # let sub = Py::new(py, Child::new()).unwrap();
2024-02-27 18:56:22 +00:00
/// # pyo3::py_run!(py, sub, "assert sub.format() == 'Caterpillar(base: Butterfly, cnt: 5)', sub.format()");
2021-03-20 07:44:28 +00:00
/// # });
2020-02-21 12:12:32 +00:00
/// ```
2021-09-22 01:13:26 +00:00
///
/// See the [module-level documentation](self) for more information.
2020-02-09 07:36:32 +00:00
pub struct PyRef < ' p , T : PyClass > {
2024-02-27 18:56:22 +00:00
// TODO: once the GIL Ref API is removed, consider adding a lifetime parameter to `PyRef` to
// store `Borrowed` here instead, avoiding reference counting overhead.
inner : Bound < ' p , T > ,
2020-02-09 07:36:32 +00:00
}
2020-03-09 09:31:43 +00:00
impl < ' p , T : PyClass > PyRef < ' p , T > {
2021-09-22 01:13:26 +00:00
/// Returns a `Python` token that is bound to the lifetime of the `PyRef`.
2023-05-01 18:55:48 +00:00
pub fn py ( & self ) -> Python < ' p > {
self . inner . py ( )
2020-03-09 09:31:43 +00:00
}
}
2020-03-02 11:04:52 +00:00
2020-03-02 09:42:04 +00:00
impl < ' p , T , U > AsRef < U > for PyRef < ' p , T >
where
2022-06-11 11:20:43 +00:00
T : PyClass < BaseType = U > ,
U : PyClass ,
2020-03-02 09:42:04 +00:00
{
2020-02-21 11:37:35 +00:00
fn as_ref ( & self ) -> & T ::BaseType {
2024-03-03 07:00:59 +00:00
unsafe { & * self . inner . get_class_object ( ) . ob_base . get_ptr ( ) }
2020-02-09 07:36:32 +00:00
}
}
2024-02-27 18:56:22 +00:00
impl < ' py , T : PyClass > PyRef < ' py , T > {
2023-07-30 20:58:21 +00:00
/// Returns the raw FFI pointer represented by self.
///
/// # Safety
///
/// Callers are responsible for ensuring that the pointer does not outlive self.
///
/// The reference is borrowed; callers should not decrease the reference count
/// when they are finished with the pointer.
#[ inline ]
pub fn as_ptr ( & self ) -> * mut ffi ::PyObject {
self . inner . as_ptr ( )
}
/// Returns an owned raw FFI pointer represented by self.
///
/// # Safety
///
/// The reference is owned; when finished the caller should either transfer ownership
/// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)).
#[ inline ]
pub fn into_ptr ( self ) -> * mut ffi ::PyObject {
2024-02-27 18:56:22 +00:00
self . inner . clone ( ) . into_ptr ( )
}
2024-04-19 11:44:36 +00:00
#[ track_caller ]
2024-02-27 18:56:22 +00:00
pub ( crate ) fn borrow ( obj : & Bound < ' py , T > ) -> Self {
Self ::try_borrow ( obj ) . expect ( " Already mutably borrowed " )
}
pub ( crate ) fn try_borrow ( obj : & Bound < ' py , T > ) -> Result < Self , PyBorrowError > {
2024-03-03 07:00:59 +00:00
let cell = obj . get_class_object ( ) ;
2024-02-27 18:56:22 +00:00
cell . ensure_threadsafe ( ) ;
cell . borrow_checker ( )
. try_borrow ( )
. map ( | _ | Self { inner : obj . clone ( ) } )
}
pub ( crate ) fn try_borrow_threadsafe ( obj : & Bound < ' py , T > ) -> Result < Self , PyBorrowError > {
2024-03-03 07:00:59 +00:00
let cell = obj . get_class_object ( ) ;
2024-02-27 18:56:22 +00:00
cell . check_threadsafe ( ) ? ;
cell . borrow_checker ( )
. try_borrow ( )
. map ( | _ | Self { inner : obj . clone ( ) } )
2023-07-30 20:58:21 +00:00
}
}
2020-02-17 15:16:11 +00:00
impl < ' p , T , U > PyRef < ' p , T >
where
2022-06-11 11:20:43 +00:00
T : PyClass < BaseType = U > ,
U : PyClass ,
2020-02-17 15:16:11 +00:00
{
2021-07-31 22:23:59 +00:00
/// Gets a `PyRef<T::BaseType>`.
///
/// While `as_ref()` returns a reference of type `&T::BaseType`, this cannot be
/// used to get the base of `T::BaseType`.
///
/// But with the help of this method, you can get hold of instances of the
/// super-superclass when needed.
2020-02-25 10:56:58 +00:00
///
/// # Examples
/// ```
/// # use pyo3::prelude::*;
2020-09-01 00:36:26 +00:00
/// #[pyclass(subclass)]
2020-02-25 10:56:58 +00:00
/// struct Base1 {
/// name1: &'static str,
/// }
2021-09-22 01:13:26 +00:00
///
2020-09-01 00:36:26 +00:00
/// #[pyclass(extends=Base1, subclass)]
2020-02-25 10:56:58 +00:00
/// struct Base2 {
/// name2: &'static str,
2021-10-14 21:15:25 +00:00
/// }
2021-09-22 01:13:26 +00:00
///
2020-02-25 10:56:58 +00:00
/// #[pyclass(extends=Base2)]
/// struct Sub {
/// name3: &'static str,
2021-10-14 21:15:25 +00:00
/// }
2021-09-22 01:13:26 +00:00
///
2020-02-25 10:56:58 +00:00
/// #[pymethods]
/// impl Sub {
/// #[new]
/// fn new() -> PyClassInitializer<Self> {
2021-10-14 21:15:25 +00:00
/// PyClassInitializer::from(Base1 { name1: "base1" })
2020-02-25 10:56:58 +00:00
/// .add_subclass(Base2 { name2: "base2" })
/// .add_subclass(Self { name3: "sub" })
/// }
2022-03-23 07:07:28 +00:00
/// fn name(slf: PyRef<'_, Self>) -> String {
2020-02-25 10:56:58 +00:00
/// let subname = slf.name3;
/// let super_ = slf.into_super();
/// format!("{} {} {}", super_.as_ref().name1, super_.name2, subname)
/// }
/// }
2021-03-20 07:44:28 +00:00
/// # Python::with_gil(|py| {
2024-02-20 07:45:47 +00:00
/// # let sub = Py::new(py, Sub::new()).unwrap();
2021-03-20 07:44:28 +00:00
/// # pyo3::py_run!(py, sub, "assert sub.name() == 'base1 base2 sub'")
/// # });
2020-02-25 10:56:58 +00:00
/// ```
2020-02-17 15:16:11 +00:00
pub fn into_super ( self ) -> PyRef < ' p , U > {
2024-02-27 18:56:22 +00:00
let py = self . py ( ) ;
2020-02-18 03:52:41 +00:00
PyRef {
2024-02-27 18:56:22 +00:00
inner : unsafe {
ManuallyDrop ::new ( self )
. as_ptr ( )
. assume_owned ( py )
. downcast_into_unchecked ( )
} ,
2020-02-18 03:52:41 +00:00
}
2020-02-17 15:16:11 +00:00
}
}
2020-02-09 07:36:32 +00:00
impl < ' p , T : PyClass > Deref for PyRef < ' p , T > {
type Target = T ;
#[ inline ]
fn deref ( & self ) -> & T {
2024-03-03 07:00:59 +00:00
unsafe { & * self . inner . get_class_object ( ) . get_ptr ( ) }
2020-02-09 07:36:32 +00:00
}
}
impl < ' p , T : PyClass > Drop for PyRef < ' p , T > {
fn drop ( & mut self ) {
2024-03-03 07:00:59 +00:00
self . inner
. get_class_object ( )
. borrow_checker ( )
. release_borrow ( )
2020-02-09 07:36:32 +00:00
}
}
2020-07-21 23:02:11 +00:00
impl < T : PyClass > IntoPy < PyObject > for PyRef < '_ , T > {
fn into_py ( self , py : Python < '_ > ) -> PyObject {
unsafe { PyObject ::from_borrowed_ptr ( py , self . inner . as_ptr ( ) ) }
2020-02-15 15:24:38 +00:00
}
}
2023-08-16 11:33:40 +00:00
impl < T : PyClass > IntoPy < PyObject > for & '_ PyRef < '_ , T > {
fn into_py ( self , py : Python < '_ > ) -> PyObject {
2024-02-27 18:56:22 +00:00
unsafe { PyObject ::from_borrowed_ptr ( py , self . inner . as_ptr ( ) ) }
2023-08-16 11:33:40 +00:00
}
}
2024-03-03 14:47:25 +00:00
#[ allow(deprecated) ]
2020-02-15 15:24:38 +00:00
impl < ' a , T : PyClass > std ::convert ::TryFrom < & ' a PyCell < T > > for crate ::PyRef < ' a , T > {
type Error = PyBorrowError ;
fn try_from ( cell : & ' a crate ::PyCell < T > ) -> Result < Self , Self ::Error > {
cell . try_borrow ( )
}
}
2023-07-30 18:40:52 +00:00
unsafe impl < ' a , T : PyClass > AsPyPointer for PyRef < ' a , T > {
2020-02-15 15:24:38 +00:00
fn as_ptr ( & self ) -> * mut ffi ::PyObject {
self . inner . as_ptr ( )
}
}
impl < T : PyClass + fmt ::Debug > fmt ::Debug for PyRef < '_ , T > {
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
fmt ::Debug ::fmt ( & * * self , f )
}
}
2021-09-22 01:13:26 +00:00
/// A wrapper type for a mutably borrowed value from a[`PyCell`]`<T>`.
2020-02-21 12:12:32 +00:00
///
2021-09-22 01:13:26 +00:00
/// See the [module-level documentation](self) for more information.
2022-06-11 11:20:43 +00:00
pub struct PyRefMut < ' p , T : PyClass < Frozen = False > > {
2024-02-27 18:56:22 +00:00
// TODO: once the GIL Ref API is removed, consider adding a lifetime parameter to `PyRef` to
// store `Borrowed` here instead, avoiding reference counting overhead.
inner : Bound < ' p , T > ,
2020-02-09 07:36:32 +00:00
}
2022-06-11 11:20:43 +00:00
impl < ' p , T : PyClass < Frozen = False > > PyRefMut < ' p , T > {
2021-09-22 01:13:26 +00:00
/// Returns a `Python` token that is bound to the lifetime of the `PyRefMut`.
2023-05-01 18:55:48 +00:00
pub fn py ( & self ) -> Python < ' p > {
self . inner . py ( )
2020-03-09 09:31:43 +00:00
}
}
2020-03-02 11:04:52 +00:00
2020-03-02 09:42:04 +00:00
impl < ' p , T , U > AsRef < U > for PyRefMut < ' p , T >
where
2022-06-11 11:20:43 +00:00
T : PyClass < BaseType = U , Frozen = False > ,
U : PyClass < Frozen = False > ,
2020-03-02 09:42:04 +00:00
{
2020-02-21 11:37:35 +00:00
fn as_ref ( & self ) -> & T ::BaseType {
2024-03-03 07:00:59 +00:00
unsafe { & * self . inner . get_class_object ( ) . ob_base . get_ptr ( ) }
2020-02-10 08:30:48 +00:00
}
2020-02-21 11:37:35 +00:00
}
2020-03-02 09:42:04 +00:00
impl < ' p , T , U > AsMut < U > for PyRefMut < ' p , T >
where
2022-06-11 11:20:43 +00:00
T : PyClass < BaseType = U , Frozen = False > ,
U : PyClass < Frozen = False > ,
2020-03-02 09:42:04 +00:00
{
2020-02-21 11:37:35 +00:00
fn as_mut ( & mut self ) -> & mut T ::BaseType {
2024-03-03 07:00:59 +00:00
unsafe { & mut * self . inner . get_class_object ( ) . ob_base . get_ptr ( ) }
2020-02-10 08:30:48 +00:00
}
}
2024-02-27 18:56:22 +00:00
impl < ' py , T : PyClass < Frozen = False > > PyRefMut < ' py , T > {
2023-07-30 20:58:21 +00:00
/// Returns the raw FFI pointer represented by self.
///
/// # Safety
///
/// Callers are responsible for ensuring that the pointer does not outlive self.
///
/// The reference is borrowed; callers should not decrease the reference count
/// when they are finished with the pointer.
#[ inline ]
pub fn as_ptr ( & self ) -> * mut ffi ::PyObject {
self . inner . as_ptr ( )
}
/// Returns an owned raw FFI pointer represented by self.
///
/// # Safety
///
/// The reference is owned; when finished the caller should either transfer ownership
/// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)).
#[ inline ]
pub fn into_ptr ( self ) -> * mut ffi ::PyObject {
2024-02-27 18:56:22 +00:00
self . inner . clone ( ) . into_ptr ( )
}
2024-03-30 22:10:21 +00:00
#[ inline ]
2024-04-19 11:44:36 +00:00
#[ track_caller ]
2024-02-27 18:56:22 +00:00
pub ( crate ) fn borrow ( obj : & Bound < ' py , T > ) -> Self {
Self ::try_borrow ( obj ) . expect ( " Already borrowed " )
}
pub ( crate ) fn try_borrow ( obj : & Bound < ' py , T > ) -> Result < Self , PyBorrowMutError > {
2024-03-03 07:00:59 +00:00
let cell = obj . get_class_object ( ) ;
2024-02-27 18:56:22 +00:00
cell . ensure_threadsafe ( ) ;
cell . borrow_checker ( )
. try_borrow_mut ( )
. map ( | _ | Self { inner : obj . clone ( ) } )
2023-07-30 20:58:21 +00:00
}
}
2020-02-17 15:16:11 +00:00
impl < ' p , T , U > PyRefMut < ' p , T >
where
2022-06-11 11:20:43 +00:00
T : PyClass < BaseType = U , Frozen = False > ,
U : PyClass < Frozen = False > ,
2020-02-17 15:16:11 +00:00
{
2021-07-31 22:23:59 +00:00
/// Gets a `PyRef<T::BaseType>`.
2021-09-22 01:13:26 +00:00
///
/// See [`PyRef::into_super`] for more.
2020-02-17 15:16:11 +00:00
pub fn into_super ( self ) -> PyRefMut < ' p , U > {
2024-02-27 18:56:22 +00:00
let py = self . py ( ) ;
2020-02-18 03:52:41 +00:00
PyRefMut {
2024-02-27 18:56:22 +00:00
inner : unsafe {
ManuallyDrop ::new ( self )
. as_ptr ( )
. assume_owned ( py )
. downcast_into_unchecked ( )
} ,
2020-02-18 03:52:41 +00:00
}
2020-02-17 15:16:11 +00:00
}
}
2022-06-11 11:20:43 +00:00
impl < ' p , T : PyClass < Frozen = False > > Deref for PyRefMut < ' p , T > {
2020-02-09 07:36:32 +00:00
type Target = T ;
#[ inline ]
fn deref ( & self ) -> & T {
2024-03-03 07:00:59 +00:00
unsafe { & * self . inner . get_class_object ( ) . get_ptr ( ) }
2020-02-09 07:36:32 +00:00
}
}
2022-06-11 11:20:43 +00:00
impl < ' p , T : PyClass < Frozen = False > > DerefMut for PyRefMut < ' p , T > {
2020-02-09 07:36:32 +00:00
#[ inline ]
fn deref_mut ( & mut self ) -> & mut T {
2024-03-03 07:00:59 +00:00
unsafe { & mut * self . inner . get_class_object ( ) . get_ptr ( ) }
2020-02-09 07:36:32 +00:00
}
}
2022-06-11 11:20:43 +00:00
impl < ' p , T : PyClass < Frozen = False > > Drop for PyRefMut < ' p , T > {
2020-02-09 07:36:32 +00:00
fn drop ( & mut self ) {
2024-03-03 07:00:59 +00:00
self . inner
. get_class_object ( )
. borrow_checker ( )
. release_borrow_mut ( )
2020-02-09 07:36:32 +00:00
}
}
2022-06-11 11:20:43 +00:00
impl < T : PyClass < Frozen = False > > IntoPy < PyObject > for PyRefMut < '_ , T > {
2022-03-23 07:07:28 +00:00
fn into_py ( self , py : Python < '_ > ) -> PyObject {
2020-07-21 23:02:11 +00:00
unsafe { PyObject ::from_borrowed_ptr ( py , self . inner . as_ptr ( ) ) }
2020-02-15 15:24:38 +00:00
}
}
2023-08-16 11:33:40 +00:00
impl < T : PyClass < Frozen = False > > IntoPy < PyObject > for & '_ PyRefMut < '_ , T > {
fn into_py ( self , py : Python < '_ > ) -> PyObject {
2024-02-27 18:56:22 +00:00
self . inner . clone ( ) . into_py ( py )
2023-08-16 11:33:40 +00:00
}
}
2023-07-30 18:40:52 +00:00
unsafe impl < ' a , T : PyClass < Frozen = False > > AsPyPointer for PyRefMut < ' a , T > {
2020-02-15 15:24:38 +00:00
fn as_ptr ( & self ) -> * mut ffi ::PyObject {
self . inner . as_ptr ( )
}
}
2024-03-03 14:47:25 +00:00
#[ allow(deprecated) ]
2022-06-11 11:20:43 +00:00
impl < ' a , T : PyClass < Frozen = False > > std ::convert ::TryFrom < & ' a PyCell < T > >
for crate ::PyRefMut < ' a , T >
{
2020-02-15 15:24:38 +00:00
type Error = PyBorrowMutError ;
fn try_from ( cell : & ' a crate ::PyCell < T > ) -> Result < Self , Self ::Error > {
cell . try_borrow_mut ( )
}
}
2022-06-11 11:20:43 +00:00
impl < T : PyClass < Frozen = False > + fmt ::Debug > fmt ::Debug for PyRefMut < '_ , T > {
2020-02-15 15:24:38 +00:00
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
2022-07-12 22:01:38 +00:00
fmt ::Debug ::fmt ( self . deref ( ) , f )
2020-02-15 15:24:38 +00:00
}
}
2021-09-22 01:13:26 +00:00
/// An error type returned by [`PyCell::try_borrow`].
2020-03-18 09:12:50 +00:00
///
2021-09-22 01:13:26 +00:00
/// If this error is allowed to bubble up into Python code it will raise a `RuntimeError`.
2020-02-09 07:36:32 +00:00
pub struct PyBorrowError {
_private : ( ) ,
}
impl fmt ::Debug for PyBorrowError {
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
f . debug_struct ( " PyBorrowError " ) . finish ( )
}
}
impl fmt ::Display for PyBorrowError {
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
fmt ::Display ::fmt ( " Already mutably borrowed " , f )
}
}
2020-05-24 12:38:27 +00:00
impl From < PyBorrowError > for PyErr {
fn from ( other : PyBorrowError ) -> Self {
2020-08-25 19:33:36 +00:00
PyRuntimeError ::new_err ( other . to_string ( ) )
2020-05-24 12:38:27 +00:00
}
}
2021-09-22 01:13:26 +00:00
/// An error type returned by [`PyCell::try_borrow_mut`].
2020-03-18 09:12:50 +00:00
///
2021-09-22 01:13:26 +00:00
/// If this error is allowed to bubble up into Python code it will raise a `RuntimeError`.
2020-02-09 07:36:32 +00:00
pub struct PyBorrowMutError {
_private : ( ) ,
}
impl fmt ::Debug for PyBorrowMutError {
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
f . debug_struct ( " PyBorrowMutError " ) . finish ( )
}
}
impl fmt ::Display for PyBorrowMutError {
fn fmt ( & self , f : & mut fmt ::Formatter < '_ > ) -> fmt ::Result {
fmt ::Display ::fmt ( " Already borrowed " , f )
}
}
2020-05-24 12:38:27 +00:00
impl From < PyBorrowMutError > for PyErr {
fn from ( other : PyBorrowMutError ) -> Self {
2020-08-25 19:33:36 +00:00
PyRuntimeError ::new_err ( other . to_string ( ) )
2020-05-24 12:38:27 +00:00
}
}
2021-05-04 20:10:03 +00:00
2022-06-12 07:51:47 +00:00
#[ cfg(test) ]
#[ cfg(feature = " macros " ) ]
mod tests {
use super ::* ;
#[ crate::pyclass ]
#[ pyo3(crate = " crate " ) ]
#[ derive(Copy, Clone, PartialEq, Eq, Debug) ]
struct SomeClass ( i32 ) ;
#[ test ]
fn pycell_replace ( ) {
Python ::with_gil ( | py | {
2024-02-20 07:45:47 +00:00
#[ allow(deprecated) ]
2022-06-12 07:51:47 +00:00
let cell = PyCell ::new ( py , SomeClass ( 0 ) ) . unwrap ( ) ;
assert_eq! ( * cell . borrow ( ) , SomeClass ( 0 ) ) ;
let previous = cell . replace ( SomeClass ( 123 ) ) ;
assert_eq! ( previous , SomeClass ( 0 ) ) ;
assert_eq! ( * cell . borrow ( ) , SomeClass ( 123 ) ) ;
} )
}
#[ test ]
#[ should_panic(expected = " Already borrowed: PyBorrowMutError " ) ]
fn pycell_replace_panic ( ) {
Python ::with_gil ( | py | {
2024-02-20 07:45:47 +00:00
#[ allow(deprecated) ]
2022-06-12 07:51:47 +00:00
let cell = PyCell ::new ( py , SomeClass ( 0 ) ) . unwrap ( ) ;
let _guard = cell . borrow ( ) ;
cell . replace ( SomeClass ( 123 ) ) ;
} )
}
#[ test ]
fn pycell_replace_with ( ) {
Python ::with_gil ( | py | {
2024-02-20 07:45:47 +00:00
#[ allow(deprecated) ]
2022-06-12 07:51:47 +00:00
let cell = PyCell ::new ( py , SomeClass ( 0 ) ) . unwrap ( ) ;
assert_eq! ( * cell . borrow ( ) , SomeClass ( 0 ) ) ;
let previous = cell . replace_with ( | value | {
* value = SomeClass ( 2 ) ;
SomeClass ( 123 )
} ) ;
assert_eq! ( previous , SomeClass ( 2 ) ) ;
assert_eq! ( * cell . borrow ( ) , SomeClass ( 123 ) ) ;
} )
}
#[ test ]
#[ should_panic(expected = " Already borrowed: PyBorrowMutError " ) ]
fn pycell_replace_with_panic ( ) {
Python ::with_gil ( | py | {
2024-02-20 07:45:47 +00:00
#[ allow(deprecated) ]
2022-06-12 07:51:47 +00:00
let cell = PyCell ::new ( py , SomeClass ( 0 ) ) . unwrap ( ) ;
let _guard = cell . borrow ( ) ;
cell . replace_with ( | _ | SomeClass ( 123 ) ) ;
} )
}
#[ test ]
fn pycell_swap ( ) {
Python ::with_gil ( | py | {
2024-02-20 07:45:47 +00:00
#[ allow(deprecated) ]
2022-06-12 07:51:47 +00:00
let cell = PyCell ::new ( py , SomeClass ( 0 ) ) . unwrap ( ) ;
2024-02-20 07:45:47 +00:00
#[ allow(deprecated) ]
2022-06-12 07:51:47 +00:00
let cell2 = PyCell ::new ( py , SomeClass ( 123 ) ) . unwrap ( ) ;
assert_eq! ( * cell . borrow ( ) , SomeClass ( 0 ) ) ;
assert_eq! ( * cell2 . borrow ( ) , SomeClass ( 123 ) ) ;
cell . swap ( cell2 ) ;
assert_eq! ( * cell . borrow ( ) , SomeClass ( 123 ) ) ;
assert_eq! ( * cell2 . borrow ( ) , SomeClass ( 0 ) ) ;
} )
}
#[ test ]
#[ should_panic(expected = " Already borrowed: PyBorrowMutError " ) ]
fn pycell_swap_panic ( ) {
Python ::with_gil ( | py | {
2024-02-20 07:45:47 +00:00
#[ allow(deprecated) ]
2022-06-12 07:51:47 +00:00
let cell = PyCell ::new ( py , SomeClass ( 0 ) ) . unwrap ( ) ;
2024-02-20 07:45:47 +00:00
#[ allow(deprecated) ]
2022-06-12 07:51:47 +00:00
let cell2 = PyCell ::new ( py , SomeClass ( 123 ) ) . unwrap ( ) ;
let _guard = cell . borrow ( ) ;
cell . swap ( cell2 ) ;
} )
}
#[ test ]
#[ should_panic(expected = " Already borrowed: PyBorrowMutError " ) ]
fn pycell_swap_panic_other_borrowed ( ) {
Python ::with_gil ( | py | {
2024-02-20 07:45:47 +00:00
#[ allow(deprecated) ]
2022-06-12 07:51:47 +00:00
let cell = PyCell ::new ( py , SomeClass ( 0 ) ) . unwrap ( ) ;
2024-02-20 07:45:47 +00:00
#[ allow(deprecated) ]
2022-06-12 07:51:47 +00:00
let cell2 = PyCell ::new ( py , SomeClass ( 123 ) ) . unwrap ( ) ;
let _guard = cell2 . borrow ( ) ;
cell . swap ( cell2 ) ;
} )
}
2023-07-30 20:58:21 +00:00
#[ test ]
fn test_as_ptr ( ) {
Python ::with_gil ( | py | {
2024-02-20 07:45:47 +00:00
let cell = Bound ::new ( py , SomeClass ( 0 ) ) . unwrap ( ) ;
2023-07-30 20:58:21 +00:00
let ptr = cell . as_ptr ( ) ;
assert_eq! ( cell . borrow ( ) . as_ptr ( ) , ptr ) ;
assert_eq! ( cell . borrow_mut ( ) . as_ptr ( ) , ptr ) ;
} )
}
#[ test ]
fn test_into_ptr ( ) {
Python ::with_gil ( | py | {
2024-02-20 07:45:47 +00:00
let cell = Bound ::new ( py , SomeClass ( 0 ) ) . unwrap ( ) ;
2023-07-30 20:58:21 +00:00
let ptr = cell . as_ptr ( ) ;
assert_eq! ( cell . borrow ( ) . into_ptr ( ) , ptr ) ;
unsafe { ffi ::Py_DECREF ( ptr ) } ;
assert_eq! ( cell . borrow_mut ( ) . into_ptr ( ) , ptr ) ;
unsafe { ffi ::Py_DECREF ( ptr ) } ;
} )
}
2022-06-12 07:51:47 +00:00
}