pyo3/types/
pysuper.rs

1use crate::instance::Bound;
2use crate::types::any::PyAnyMethods;
3use crate::types::PyType;
4use crate::PyTypeInfo;
5use crate::{PyAny, PyResult};
6
7/// Represents a Python `super` object.
8///
9/// Values of this type are accessed via PyO3's smart pointers, e.g. as
10/// [`Py<PySuper>`][crate::Py] or [`Bound<'py, PySuper>`][Bound].
11#[repr(transparent)]
12pub struct PySuper(PyAny);
13
14#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]
15pyobject_native_type_core!(
16    PySuper,
17    pyobject_native_static_type_object!(crate::ffi::PySuper_Type),
18    "builtins",
19    "super"
20);
21
22#[cfg(any(Py_LIMITED_API, PyPy, GraalPy))]
23pyobject_native_type_core!(
24    PySuper,
25    |py| {
26        use crate::sync::PyOnceLock;
27        use crate::types::{PyType, PyTypeMethods};
28        use crate::Py;
29        static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();
30        TYPE.import(py, "builtins", "super").unwrap().as_type_ptr()
31    },
32    "builtins",
33    "super"
34);
35
36impl PySuper {
37    /// Constructs a new super object. More read about super object: [docs](https://docs.python.org/3/library/functions.html#super)
38    ///
39    /// # Examples
40    ///
41    /// ```rust,no_run
42    /// use pyo3::prelude::*;
43    ///
44    /// #[pyclass(subclass)]
45    /// struct BaseClass {
46    ///     val1: usize,
47    /// }
48    ///
49    /// #[pymethods]
50    /// impl BaseClass {
51    ///     #[new]
52    ///     fn new() -> Self {
53    ///         BaseClass { val1: 10 }
54    ///     }
55    ///
56    ///     pub fn method(&self) -> usize {
57    ///         self.val1
58    ///     }
59    /// }
60    ///
61    /// #[pyclass(extends=BaseClass)]
62    /// struct SubClass {}
63    ///
64    /// #[pymethods]
65    /// impl SubClass {
66    ///     #[new]
67    ///     fn new() -> (Self, BaseClass) {
68    ///         (SubClass {}, BaseClass::new())
69    ///     }
70    ///
71    ///     fn method<'py>(self_: &Bound<'py, Self>) -> PyResult<Bound<'py, PyAny>> {
72    ///         let super_ = self_.py_super()?;
73    ///         super_.call_method("method", (), None)
74    ///     }
75    /// }
76    /// ```
77    pub fn new<'py>(
78        ty: &Bound<'py, PyType>,
79        obj: &Bound<'py, PyAny>,
80    ) -> PyResult<Bound<'py, PySuper>> {
81        PySuper::type_object(ty.py()).call1((ty, obj)).map(|any| {
82            // Safety: super() always returns instance of super
83            unsafe { any.cast_into_unchecked() }
84        })
85    }
86}