PyClassGuard

Struct PyClassGuard 

Source
pub struct PyClassGuard<'a, T: PyClass> { /* private fields */ }
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.

Implementations§

Source§

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

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, U> PyClassGuard<'a, T>
where T: PyClass<BaseType = U>, U: PyClass,

Source

pub fn as_super(&self) -> &PyClassGuard<'a, U>

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, U>

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> FromPyObjectBound<'a, 'py> for PyClassGuard<'a, T>

Source§

fn from_py_object_bound(obj: Borrowed<'a, 'py, PyAny>) -> PyResult<Self>

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

const INPUT_TYPE: &'static str = "typing.Any"

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

fn type_input() -> TypeInfo

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

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

Source§

const OUTPUT_TYPE: &'static str = T::PYTHON_TYPE

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§

fn type_output() -> TypeInfo

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§

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

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§

const OUTPUT_TYPE: &'static str = "typing.Any"

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§

fn type_output() -> TypeInfo

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§

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> 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> 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<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<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, 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<T> Ungil for T
where T: Send,