#[repr(transparent)]pub struct PyClassGuardMut<'a, T: PyClass<Frozen = False>> {
ptr: NonNull<PyObject>,
marker: PhantomData<&'a Py<T>>,
}Expand description
A wrapper type for a mutably borrowed value from a PyClass
§When not to use PyClassGuardMut
Usually you can use &mut references as method and function receivers and
arguments, and you won’t need to use PyClassGuardMut directly:
use pyo3::prelude::*;
#[pyclass]
struct Number {
inner: u32,
}
#[pymethods]
impl Number {
fn increment(&mut self) {
self.inner += 1;
}
}The #[pymethods] proc macro will generate this wrapper
function (and more), using PyClassGuardMut under the hood:
// The function which is exported to Python looks roughly like the following
unsafe extern "C" fn __pymethod_increment__(
_slf: *mut ::pyo3::ffi::PyObject,
_args: *mut ::pyo3::ffi::PyObject,
) -> *mut ::pyo3::ffi::PyObject {
unsafe fn inner<'py>(
py: ::pyo3::Python<'py>,
_slf: *mut ::pyo3::ffi::PyObject,
) -> ::pyo3::PyResult<*mut ::pyo3::ffi::PyObject> {
let function = Number::increment;
let mut holder_0 = ::pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT;
let result = {
let ret = function(::pyo3::impl_::extract_argument::extract_pyclass_ref_mut::<Number>(
unsafe { ::pyo3::impl_::extract_argument::cast_function_argument(py, _slf) },
&mut holder_0,
)?);
{
let result = {
let obj = ret;
::pyo3::impl_::wrap::converter(&obj)
.wrap(obj)
.map_err(::core::convert::Into::<::pyo3::PyErr>::into)
};
::pyo3::impl_::wrap::converter(&result).map_into_ptr(py, result)
}
};
result
}
unsafe {
::pyo3::impl_::trampoline::get_trampoline_function!(noargs, inner)(
_slf,
_args,
)
}
}§When to use PyClassGuardMut
§Using PyClasses from Rust
However, we do need PyClassGuardMut if we want to call its methods
from Rust:
Python::attach(|py| {
let n = Py::new(py, Number { inner: 0 })?;
// We borrow the guard and then dereference
// it to get a mutable reference to Number
let mut guard: PyClassGuardMut<'_, Number> = n.extract(py)?;
let n_mutable: &mut Number = &mut *guard;
n_mutable.increment();
// To avoid panics we must dispose of the
// `PyClassGuardMut` before borrowing again.
drop(guard);
let n_immutable: &Number = &*n.extract::<PyClassGuard<'_, Number>>(py)?;
assert_eq!(n_immutable.inner, 1);
Ok(())
})§Dealing with possibly overlapping mutable references
It is also necessary to use PyClassGuardMut if you can receive mutable
arguments that may overlap. Suppose the following function that swaps the
values of two Numbers:
#[pyfunction]
fn swap_numbers(a: &mut Number, b: &mut Number) {
std::mem::swap(&mut a.inner, &mut b.inner);
}When users pass in the same Number as both arguments, one of the mutable
borrows will fail and raise a RuntimeError:
>>> a = Number()
>>> swap_numbers(a, a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: Already borrowedIt is better to write that function like this:
#[pyfunction]
fn swap_numbers(a: &Bound<'_, Number>, b: &Bound<'_, Number>) -> PyResult<()> {
// Check that the pointers are unequal
if !a.is(b) {
let mut a: PyClassGuardMut<'_, Number> = a.extract()?;
let mut b: PyClassGuardMut<'_, Number> = b.extract()?;
std::mem::swap(&mut a.inner, &mut b.inner);
} else {
// Do nothing - they are the same object, so don't need swapping.
}
Ok(())
}See PyClassGuard and the guide for more information.
Fields§
§ptr: NonNull<PyObject>§marker: PhantomData<&'a Py<T>>Implementations§
Source§impl<'a, T: PyClass<Frozen = False>> PyClassGuardMut<'a, T>
impl<'a, T: PyClass<Frozen = False>> PyClassGuardMut<'a, T>
pub(crate) fn try_borrow_mut(obj: &'a Py<T>) -> Result<Self, PyBorrowMutError>
pub(crate) fn try_borrow_mut_from_borrowed( obj: Borrowed<'a, '_, T>, ) -> Result<Self, PyBorrowMutError>
fn try_from_class_object( obj: &'a <T as PyClassImpl>::Layout, ) -> Result<Self, PyBorrowMutError>
pub(crate) fn as_class_object(&self) -> &'a <T as PyClassImpl>::Layout
Sourcepub fn map<F, U: ?Sized>(self, f: F) -> PyClassGuardMap<'a, U, true>
pub fn map<F, U: ?Sized>(self, f: F) -> PyClassGuardMap<'a, U, true>
Consumes the PyClassGuardMut and returns a PyClassGuardMap for a component of the
borrowed data
§Examples
#[pyclass]
pub struct MyClass {
data: [i32; 100],
}
let obj = Bound::new(py, MyClass { data: [0; 100] })?;
let mut data = obj.extract::<PyClassGuardMut<'_, MyClass>>()?.map(|c| c.data.as_mut_slice());
data[0] = 42;Source§impl<'a, T> PyClassGuardMut<'a, T>
impl<'a, T> PyClassGuardMut<'a, T>
Sourcepub fn as_super(&mut self) -> &mut PyClassGuardMut<'a, T::BaseType>
pub fn as_super(&mut self) -> &mut PyClassGuardMut<'a, T::BaseType>
Borrows a mutable reference to PyClassGuardMut<T::BaseType>.
With the help of this method, you can mutate attributes and call
mutating methods on the superclass without consuming the
PyClassGuardMut<T>. This method can also be chained to access the
super-superclass (and so on).
See PyClassGuard::as_super for more.
Sourcepub fn into_super(self) -> PyClassGuardMut<'a, T::BaseType>
pub fn into_super(self) -> PyClassGuardMut<'a, T::BaseType>
Gets a PyClassGuardMut<T::BaseType>.
See PyClassGuard::into_super for more.
Trait Implementations§
Source§impl<'a, 'py, T: PyClass<Frozen = False>> FromPyObject<'a, 'py> for PyClassGuardMut<'a, T>
impl<'a, 'py, T: PyClass<Frozen = False>> FromPyObject<'a, 'py> for PyClassGuardMut<'a, T>
Source§const INPUT_TYPE: PyStaticExpr = T::TYPE_HINT
const INPUT_TYPE: PyStaticExpr = T::TYPE_HINT
experimental-inspect only.Source§type Error = PyClassGuardMutError<'a, 'py>
type Error = PyClassGuardMutError<'a, 'py>
Source§#[doc(hidden)]fn sequence_extractor(
_obj: Borrowed<'_, 'py, PyAny>,
_: Token,
) -> Option<impl FromPyObjectSequence<Target = Self>>
#[doc(hidden)]fn sequence_extractor(
_obj: Borrowed<'_, 'py, PyAny>,
_: Token,
) -> Option<impl FromPyObjectSequence<Target = Self>>
Vec<u8> and [u8; N],
where the bytes can be directly copied from some python objects without going through
iteration.Source§fn as_local_tz(_: Token) -> Option<Self>
fn as_local_tz(_: Token) -> Option<Self>
chrono-local only.DateTime<Tz> where Tz is
chrono::Local, which will accept “naive” datetime objects as being in the local timezone.Source§impl<'a, 'py, T: PyClass<Frozen = False>> IntoPyObject<'py> for &PyClassGuardMut<'a, T>
impl<'a, 'py, T: PyClass<Frozen = False>> IntoPyObject<'py> for &PyClassGuardMut<'a, T>
Source§const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT
const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT
experimental-inspect only.Source§type Error = Infallible
type Error = Infallible
Source§fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error>
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error>
Source§#[doc(hidden)]fn owned_sequence_into_pyobject<I>(
iter: I,
py: Python<'py>,
_: Token,
) -> Result<Bound<'py, PyAny>, PyErr>
#[doc(hidden)]fn owned_sequence_into_pyobject<I>(
iter: I,
py: Python<'py>,
_: Token,
) -> Result<Bound<'py, PyAny>, PyErr>
Vec<u8>, [u8; N]
and SmallVec<[u8; N]> as a sequence of bytes into a bytes object.Source§#[doc(hidden)]fn borrowed_sequence_into_pyobject<I>(
iter: I,
py: Python<'py>,
_: Token,
) -> Result<Bound<'py, PyAny>, PyErr>where
Self: Reference,
I: IntoIterator<Item = Self> + AsRef<[<Self as Reference>::BaseType]>,
I::IntoIter: ExactSizeIterator<Item = Self>,
#[doc(hidden)]fn borrowed_sequence_into_pyobject<I>(
iter: I,
py: Python<'py>,
_: Token,
) -> Result<Bound<'py, PyAny>, PyErr>where
Self: Reference,
I: IntoIterator<Item = Self> + AsRef<[<Self as Reference>::BaseType]>,
I::IntoIter: ExactSizeIterator<Item = Self>,
&[u8] and Cow<[u8]>
as a sequence of bytes into a bytes object.Source§#[doc(hidden)]const SEQUENCE_OUTPUT_TYPE: PyStaticExpr = _
#[doc(hidden)]const SEQUENCE_OUTPUT_TYPE: PyStaticExpr = _
experimental-inspect only.IntoPyObject::owned_sequence_into_pyobject and IntoPyObject::borrowed_sequence_into_pyobjectSource§impl<'a, 'py, T: PyClass<Frozen = False>> IntoPyObject<'py> for PyClassGuardMut<'a, T>
impl<'a, 'py, T: PyClass<Frozen = False>> IntoPyObject<'py> for PyClassGuardMut<'a, T>
Source§const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT
const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT
experimental-inspect only.Source§type Error = Infallible
type Error = Infallible
Source§fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error>
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error>
Source§#[doc(hidden)]fn owned_sequence_into_pyobject<I>(
iter: I,
py: Python<'py>,
_: Token,
) -> Result<Bound<'py, PyAny>, PyErr>
#[doc(hidden)]fn owned_sequence_into_pyobject<I>(
iter: I,
py: Python<'py>,
_: Token,
) -> Result<Bound<'py, PyAny>, PyErr>
Vec<u8>, [u8; N]
and SmallVec<[u8; N]> as a sequence of bytes into a bytes object.Source§#[doc(hidden)]const SEQUENCE_OUTPUT_TYPE: PyStaticExpr = _
#[doc(hidden)]const SEQUENCE_OUTPUT_TYPE: PyStaticExpr = _
experimental-inspect only.IntoPyObject::owned_sequence_into_pyobject and IntoPyObject::borrowed_sequence_into_pyobjectSource§impl<'a, 'py, T: PyClass<Frozen = False>> TryFrom<&'a Bound<'py, T>> for PyClassGuardMut<'a, T>
impl<'a, 'py, T: PyClass<Frozen = False>> TryFrom<&'a Bound<'py, T>> for PyClassGuardMut<'a, T>
impl<T: PyClass<Frozen = False> + Send + Sync> Send for PyClassGuardMut<'_, T>
impl<T: PyClass<Frozen = False> + Sync> Sync for PyClassGuardMut<'_, T>
Auto Trait Implementations§
impl<'a, T> Freeze for PyClassGuardMut<'a, T>
impl<'a, T> RefUnwindSafe for PyClassGuardMut<'a, T>where
T: RefUnwindSafe,
impl<'a, T> Unpin for PyClassGuardMut<'a, T>
impl<'a, T> UnsafeUnpin for PyClassGuardMut<'a, T>
impl<'a, T> UnwindSafe for PyClassGuardMut<'a, T>where
T: RefUnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<'py, T> IntoPyCallbackOutput<'py, *mut PyObject> for Twhere
T: IntoPyObject<'py>,
impl<'py, T> IntoPyCallbackOutput<'py, *mut PyObject> for Twhere
T: IntoPyObject<'py>,
Source§impl<'py, T> IntoPyCallbackOutput<'py, Py<PyAny>> for Twhere
T: IntoPyObject<'py>,
impl<'py, T> IntoPyCallbackOutput<'py, Py<PyAny>> for Twhere
T: IntoPyObject<'py>,
Source§impl<'py, T> IntoPyObjectExt<'py> for Twhere
T: IntoPyObject<'py>,
impl<'py, T> IntoPyObjectExt<'py> for Twhere
T: IntoPyObject<'py>,
Source§fn into_bound_py_any(self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>>
fn into_bound_py_any(self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>>
self into an owned Python object, dropping type information.Source§impl<'py, T> PyClassInit<'py, false, false> for Twhere
T: IntoPyObject<'py>,
impl<'py, T> PyClassInit<'py, false, false> for Twhere
T: IntoPyObject<'py>,
Source§impl<T> PyErrArguments for T
impl<T> PyErrArguments for T
Source§impl<'a, 'py, T> PyFunctionArgument<'a, '_, 'py, true> for Twhere
T: FromPyObject<'a, 'py>,
impl<'a, 'py, T> PyFunctionArgument<'a, '_, 'py, true> for Twhere
T: FromPyObject<'a, 'py>,
Source§const INPUT_TYPE: PyStaticExpr = const INPUT_TYPE: PyStaticExpr = T::INPUT_TYPE;
const INPUT_TYPE: PyStaticExpr = const INPUT_TYPE: PyStaticExpr = T::INPUT_TYPE;
experimental-inspect only.type Holder = ()
type Error = <T as FromPyObject<'a, 'py>>::Error
fn extract( obj: Borrowed<'a, 'py, PyAny>, _: &mut (), ) -> Result<T, <T as PyFunctionArgument<'a, '_, 'py, true>>::Error>
Source§impl<'a, T> PyReturnType for Twhere
T: IntoPyObject<'a>,
impl<'a, T> PyReturnType for Twhere
T: IntoPyObject<'a>,
Source§const OUTPUT_TYPE: PyStaticExpr = const OUTPUT_TYPE: PyStaticExpr = T::OUTPUT_TYPE;
const OUTPUT_TYPE: PyStaticExpr = const OUTPUT_TYPE: PyStaticExpr = T::OUTPUT_TYPE;
experimental-inspect only.Source§impl<T> SizedTypeProperties for T
impl<T> SizedTypeProperties for T
Source§#[doc(hidden)]const SIZE: usize = _
#[doc(hidden)]const SIZE: usize = _
sized_type_properties)Source§#[doc(hidden)]const ALIGN: usize = _
#[doc(hidden)]const ALIGN: usize = _
sized_type_properties)Source§#[doc(hidden)]const ALIGNMENT: Alignment = _
#[doc(hidden)]const ALIGNMENT: Alignment = _
ptr_alignment_type)Source§#[doc(hidden)]const IS_ZST: bool = _
#[doc(hidden)]const IS_ZST: bool = _
sized_type_properties)Source§#[doc(hidden)]const LAYOUT: Layout = _
#[doc(hidden)]const LAYOUT: Layout = _
sized_type_properties)Source§#[doc(hidden)]const MAX_SLICE_LEN: usize = _
#[doc(hidden)]const MAX_SLICE_LEN: usize = _
sized_type_properties)[Self]. Read more