Skip to main content

PyClassGuard

Struct PyClassGuard 

Source
#[repr(transparent)]
pub struct PyClassGuard<'a, T: PyClass> { ptr: NonNull<PyObject>, marker: PhantomData<&'a Py<T>>, }
Expand description

A wrapper type for an immutably borrowed value from a PyClass.

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 thread-safe access with the Python<'py> 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> 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 PyClassGuard and PyClassGuardMut defined in this module. This works similar to std’s RefCell type. Especially when building for free-threaded Python it gets harder to track which thread borrows which object at any time. This can lead to method calls failing with PyBorrowError. In these cases consider using frozen classes together with Rust interior mutability primitives like Mutex instead of using PyClassGuardMut to get mutable access.

§Examples

You can use PyClassGuard as an alternative to a &self receiver when

  • you need to access the pointer of the PyClass, or
  • you want to get a super class.
#[pyclass(subclass)]
struct Parent {
    basename: &'static str,
}

#[pyclass(extends=Parent)]
struct Child {
    name: &'static str,
 }

#[pymethods]
impl Child {
    #[new]
    fn new() -> (Self, Parent) {
        (Child { name: "Caterpillar" }, Parent { basename: "Butterfly" })
    }

    fn format(slf: PyClassGuard<'_, Self>) -> String {
        // We can get &Self::BaseType by as_super
        let basename = slf.as_super().basename;
        format!("{}(base: {})", slf.name, basename)
    }
}

See also PyClassGuardMut and the guide for more information.

Fields§

§ptr: NonNull<PyObject>§marker: PhantomData<&'a Py<T>>

Implementations§

Source§

impl<'a, T: PyClass> PyClassGuard<'a, T>

Source

pub(crate) fn try_borrow(obj: &'a Py<T>) -> Result<Self, PyBorrowError>

Source

pub(crate) fn try_borrow_from_borrowed( obj: Borrowed<'a, '_, T>, ) -> Result<Self, PyBorrowError>

Source

fn try_from_class_object( obj: &'a <T as PyClassImpl>::Layout, ) -> Result<Self, PyBorrowError>

Source

pub(crate) fn as_class_object(&self) -> &'a <T as PyClassImpl>::Layout

Source

pub fn map<F, U: ?Sized>(self, f: F) -> PyClassGuardMap<'a, U, false>
where F: FnOnce(&T) -> &U,

Consumes the PyClassGuard and returns a PyClassGuardMap for a component of the borrowed data

§Examples

#[pyclass]
pub struct MyClass {
    msg: String,
}

let obj = Bound::new(py, MyClass { msg: String::from("hello") })?;
let msg = obj.extract::<PyClassGuard<'_, MyClass>>()?.map(|c| &c.msg);
assert_eq!(&*msg, "hello");
Source§

impl<'a, T> PyClassGuard<'a, T>
where T: PyClass, T::BaseType: PyClass,

Source

pub fn as_super(&self) -> &PyClassGuard<'a, T::BaseType>

Borrows a shared reference to PyClassGuard<T::BaseType>.

With the help of this method, you can access attributes and call methods on the superclass without consuming the PyClassGuard<T>. This method can also be chained to access the super-superclass (and so on).

§Examples
#[pyclass(subclass)]
struct Base {
    base_name: &'static str,
}
#[pymethods]
impl Base {
    fn base_name_len(&self) -> usize {
        self.base_name.len()
    }
}

#[pyclass(extends=Base)]
struct Sub {
    sub_name: &'static str,
}

#[pymethods]
impl Sub {
    #[new]
    fn new() -> (Self, Base) {
        (Self { sub_name: "sub_name" }, Base { base_name: "base_name" })
    }
    fn sub_name_len(&self) -> usize {
        self.sub_name.len()
    }
    fn format_name_lengths(slf: PyClassGuard<'_, Self>) -> String {
        format!("{} {}", slf.as_super().base_name_len(), slf.sub_name_len())
    }
}
Source

pub fn into_super(self) -> PyClassGuard<'a, T::BaseType>

Gets a PyClassGuard<T::BaseType>.

With the help of this method, you can get hold of instances of the super-superclass when needed.

§Examples
#[pyclass(subclass)]
struct Base1 {
    name1: &'static str,
}

#[pyclass(extends=Base1, subclass)]
struct Base2 {
    name2: &'static str,
}

#[pyclass(extends=Base2)]
struct Sub {
    name3: &'static str,
}

#[pymethods]
impl Sub {
    #[new]
    fn new() -> PyClassInitializer<Self> {
        PyClassInitializer::from(Base1 { name1: "base1" })
            .add_subclass(Base2 { name2: "base2" })
            .add_subclass(Self { name3: "sub" })
    }
    fn name(slf: PyClassGuard<'_, Self>) -> String {
        let subname = slf.name3;
        let super_ = slf.into_super();
        format!("{} {} {}", super_.as_super().name1, super_.name2, subname)
    }
}

Trait Implementations§

Source§

impl<T: PyClass> Deref for PyClassGuard<'_, T>

Source§

type Target = T

The resulting type after dereferencing.
Source§

fn deref(&self) -> &T

Dereferences the value.
Source§

impl<T: PyClass> Drop for PyClassGuard<'_, T>

Source§

fn drop(&mut self)

Releases the shared borrow

Source§

impl<'a, 'py, T: PyClass> FromPyObject<'a, 'py> for PyClassGuard<'a, T>

Source§

const INPUT_TYPE: PyStaticExpr = T::TYPE_HINT

Available on crate feature experimental-inspect only.
Provides the type hint information for this type when it appears as an argument. Read more
Source§

type Error = PyClassGuardError<'a, 'py>

The type returned in the event of a conversion error. Read more
Source§

fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error>

Extracts Self from the bound smart pointer obj. Read more
Source§

#[doc(hidden)]
fn sequence_extractor( _obj: Borrowed<'_, 'py, PyAny>, _: Token, ) -> Option<impl FromPyObjectSequence<Target = Self>>

Specialization hook for extracting sequences for types like 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>

Available on crate feature chrono-local only.
Helper used to make a specialized path in extracting 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> IntoPyObject<'py> for &PyClassGuard<'a, T>

Source§

const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT

Available on crate feature experimental-inspect only.
Extracts the type hint information for this type when it appears as a return value. Read more
Source§

type Target = T

The Python output type
Source§

type Output = Borrowed<'a, 'py, T>

The smart pointer type to use. Read more
Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error>

Performs the conversion.
Source§

#[doc(hidden)]
fn owned_sequence_into_pyobject<I>( iter: I, py: Python<'py>, _: Token, ) -> Result<Bound<'py, PyAny>, PyErr>
where I: IntoIterator<Item = Self> + AsRef<[Self]>, I::IntoIter: ExactSizeIterator<Item = Self>,

Converts sequence of Self into a Python object. Used to specialize 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>,

Converts sequence of Self into a Python object. Used to specialize &[u8] and Cow<[u8]> as a sequence of bytes into a bytes object.
Source§

#[doc(hidden)]
const SEQUENCE_OUTPUT_TYPE: PyStaticExpr = _

Available on crate feature experimental-inspect only.
Source§

impl<'a, 'py, T: PyClass> IntoPyObject<'py> for PyClassGuard<'a, T>

Source§

const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT

Available on crate feature experimental-inspect only.
Extracts the type hint information for this type when it appears as a return value. Read more
Source§

type Target = T

The Python output type
Source§

type Output = Borrowed<'a, 'py, T>

The smart pointer type to use. Read more
Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error>

Performs the conversion.
Source§

#[doc(hidden)]
fn owned_sequence_into_pyobject<I>( iter: I, py: Python<'py>, _: Token, ) -> Result<Bound<'py, PyAny>, PyErr>
where I: IntoIterator<Item = Self> + AsRef<[Self]>, I::IntoIter: ExactSizeIterator<Item = Self>,

Converts sequence of Self into a Python object. Used to specialize 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 = _

Available on crate feature experimental-inspect only.
Source§

impl<'a, 'py, T: PyClass> TryFrom<&'a Bound<'py, T>> for PyClassGuard<'a, T>

Source§

type Error = PyBorrowError

The type returned in the event of a conversion error.
Source§

fn try_from(value: &'a Bound<'py, T>) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl<T: PyClass + Sync> Send for PyClassGuard<'_, T>

Source§

impl<T: PyClass + Sync> Sync for PyClassGuard<'_, T>

Auto Trait Implementations§

§

impl<'a, T> Freeze for PyClassGuard<'a, T>

§

impl<'a, T> RefUnwindSafe for PyClassGuard<'a, T>
where T: RefUnwindSafe,

§

impl<'a, T> Unpin for PyClassGuard<'a, T>

§

impl<'a, T> UnsafeUnpin for PyClassGuard<'a, T>

§

impl<'a, T> UnwindSafe for PyClassGuard<'a, T>
where T: RefUnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<'py, T> IntoPyCallbackOutput<'py, *mut PyObject> for T
where T: IntoPyObject<'py>,

Source§

impl<'py, T> IntoPyCallbackOutput<'py, Py<PyAny>> for T
where T: IntoPyObject<'py>,

Source§

fn convert(self, py: Python<'py>) -> Result<Py<PyAny>, PyErr>

Source§

impl<'py, T> IntoPyObjectExt<'py> for T
where T: IntoPyObject<'py>,

Source§

fn into_bound_py_any(self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>>

Converts self into an owned Python object, dropping type information.
Source§

fn into_py_any(self, py: Python<'py>) -> PyResult<Py<PyAny>>

Converts self into an owned Python object, dropping type information and unbinding it from the 'py lifetime.
Source§

fn into_pyobject_or_pyerr(self, py: Python<'py>) -> PyResult<Self::Output>

Converts self into a Python object. Read more
Source§

impl<'py, T> PyClassInit<'py, false, false> for T
where T: IntoPyObject<'py>,

Source§

fn init( self, cls: Borrowed<'_, 'py, PyType>, ) -> Result<Bound<'py, PyAny>, PyErr>

Source§

impl<T> PyErrArguments for T
where T: for<'py> IntoPyObject<'py> + Send + Sync,

Source§

fn arguments(self, py: Python<'_>) -> Py<PyAny>

Arguments for exception
Source§

impl<'a, 'py, T> PyFunctionArgument<'a, '_, 'py, true> for T
where T: FromPyObject<'a, 'py>,

Source§

const INPUT_TYPE: PyStaticExpr = const INPUT_TYPE: PyStaticExpr = T::INPUT_TYPE;

Available on crate feature experimental-inspect only.
Provides the type hint information for which Python types are allowed.
Source§

type Holder = ()

Source§

type Error = <T as FromPyObject<'a, 'py>>::Error

Source§

fn extract( obj: Borrowed<'a, 'py, PyAny>, _: &mut (), ) -> Result<T, <T as PyFunctionArgument<'a, '_, 'py, true>>::Error>

Source§

impl<'a, T> PyReturnType for T
where T: IntoPyObject<'a>,

Source§

const OUTPUT_TYPE: PyStaticExpr = const OUTPUT_TYPE: PyStaticExpr = T::OUTPUT_TYPE;

Available on crate feature experimental-inspect only.
The function return type
Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> SizedTypeProperties for T

Source§

#[doc(hidden)]
const SIZE: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const ALIGN: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const ALIGNMENT: Alignment = _

🔬This is a nightly-only experimental API. (ptr_alignment_type)
Source§

#[doc(hidden)]
const IS_ZST: bool = _

🔬This is a nightly-only experimental API. (sized_type_properties)
true if this type requires no storage. false if its size is greater than zero. Read more
Source§

#[doc(hidden)]
const LAYOUT: Layout = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const MAX_SLICE_LEN: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
The largest safe length for a [Self]. Read more
Source§

impl<T> SomeWrap<T> for T

Source§

fn wrap(self) -> Option<T>

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<'py, T> Sealed<'py, *mut PyObject> for T
where T: IntoPyObject<'py>,

Source§

impl<'py, T> Sealed<'py, Py<PyAny>> for T
where T: IntoPyObject<'py>,

Source§

impl<'a, 'py, T> Sealed<true> for T
where T: FromPyObject<'a, 'py>,

Source§

impl<'a, T> Sealed for T
where T: IntoPyObject<'a>,

Source§

impl<'py, T> Sealed for T
where T: IntoPyObject<'py>,

Source§

impl<T> Ungil for T
where T: Send,

⚠️ Internal Docs ⚠️ Not Public API 👉 Official Docs Here