adding new getter for type obj (#4197)
* adding new getter for type obj * fixing limited api build * fix formating ssues from clippy * add changelog info * Update newsfragments/4197.added.md Co-authored-by: David Hewitt <mail@davidhewitt.dev> * Update src/types/typeobject.rs Co-authored-by: David Hewitt <mail@davidhewitt.dev> * Update src/types/typeobject.rs Co-authored-by: David Hewitt <mail@davidhewitt.dev> * Update src/types/typeobject.rs Co-authored-by: David Hewitt <mail@davidhewitt.dev> * Update src/types/typeobject.rs Co-authored-by: David Hewitt <mail@davidhewitt.dev> * using uncheck downcast * fix formating * move import * Update src/types/typeobject.rs Co-authored-by: Matt Hooks <me@matthooks.com> * Update src/types/typeobject.rs Co-authored-by: Matt Hooks <me@matthooks.com> --------- Co-authored-by: David Hewitt <mail@davidhewitt.dev> Co-authored-by: Matt Hooks <me@matthooks.com>
This commit is contained in:
parent
2c654b2906
commit
d21045cbc1
|
@ -0,0 +1 @@
|
||||||
|
Add `PyTypeMethods::mro` and `PyTypeMethods::bases`.
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::err::{self, PyResult};
|
use crate::err::{self, PyResult};
|
||||||
use crate::instance::Borrowed;
|
use crate::instance::Borrowed;
|
||||||
use crate::types::any::PyAnyMethods;
|
use crate::types::any::PyAnyMethods;
|
||||||
|
use crate::types::PyTuple;
|
||||||
#[cfg(feature = "gil-refs")]
|
#[cfg(feature = "gil-refs")]
|
||||||
use crate::PyNativeType;
|
use crate::PyNativeType;
|
||||||
use crate::{ffi, Bound, PyAny, PyTypeInfo, Python};
|
use crate::{ffi, Bound, PyAny, PyTypeInfo, Python};
|
||||||
|
@ -127,6 +128,16 @@ pub trait PyTypeMethods<'py>: crate::sealed::Sealed {
|
||||||
fn is_subclass_of<T>(&self) -> PyResult<bool>
|
fn is_subclass_of<T>(&self) -> PyResult<bool>
|
||||||
where
|
where
|
||||||
T: PyTypeInfo;
|
T: PyTypeInfo;
|
||||||
|
|
||||||
|
/// Return the method resolution order for this type.
|
||||||
|
///
|
||||||
|
/// Equivalent to the Python expression `self.__mro__`.
|
||||||
|
fn mro(&self) -> Bound<'py, PyTuple>;
|
||||||
|
|
||||||
|
/// Return Python bases
|
||||||
|
///
|
||||||
|
/// Equivalent to the Python expression `self.__bases__`.
|
||||||
|
fn bases(&self) -> Bound<'py, PyTuple>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'py> PyTypeMethods<'py> for Bound<'py, PyType> {
|
impl<'py> PyTypeMethods<'py> for Bound<'py, PyType> {
|
||||||
|
@ -177,6 +188,48 @@ impl<'py> PyTypeMethods<'py> for Bound<'py, PyType> {
|
||||||
{
|
{
|
||||||
self.is_subclass(&T::type_object_bound(self.py()))
|
self.is_subclass(&T::type_object_bound(self.py()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mro(&self) -> Bound<'py, PyTuple> {
|
||||||
|
#[cfg(any(Py_LIMITED_API, PyPy))]
|
||||||
|
let mro = self
|
||||||
|
.getattr(intern!(self.py(), "__mro__"))
|
||||||
|
.expect("Cannot get `__mro__` from object.")
|
||||||
|
.extract()
|
||||||
|
.expect("Unexpected type in `__mro__` attribute.");
|
||||||
|
|
||||||
|
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
|
||||||
|
let mro = unsafe {
|
||||||
|
use crate::ffi_ptr_ext::FfiPtrExt;
|
||||||
|
(*self.as_type_ptr())
|
||||||
|
.tp_mro
|
||||||
|
.assume_borrowed(self.py())
|
||||||
|
.to_owned()
|
||||||
|
.downcast_into_unchecked()
|
||||||
|
};
|
||||||
|
|
||||||
|
mro
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bases(&self) -> Bound<'py, PyTuple> {
|
||||||
|
#[cfg(any(Py_LIMITED_API, PyPy))]
|
||||||
|
let bases = self
|
||||||
|
.getattr(intern!(self.py(), "__bases__"))
|
||||||
|
.expect("Cannot get `__bases__` from object.")
|
||||||
|
.extract()
|
||||||
|
.expect("Unexpected type in `__bases__` attribute.");
|
||||||
|
|
||||||
|
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
|
||||||
|
let bases = unsafe {
|
||||||
|
use crate::ffi_ptr_ext::FfiPtrExt;
|
||||||
|
(*self.as_type_ptr())
|
||||||
|
.tp_bases
|
||||||
|
.assume_borrowed(self.py())
|
||||||
|
.to_owned()
|
||||||
|
.downcast_into_unchecked()
|
||||||
|
};
|
||||||
|
|
||||||
|
bases
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Borrowed<'a, '_, PyType> {
|
impl<'a> Borrowed<'a, '_, PyType> {
|
||||||
|
@ -215,8 +268,8 @@ impl<'a> Borrowed<'a, '_, PyType> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::types::typeobject::PyTypeMethods;
|
use crate::types::{PyAnyMethods, PyBool, PyInt, PyLong, PyTuple, PyTypeMethods};
|
||||||
use crate::types::{PyBool, PyLong};
|
use crate::PyAny;
|
||||||
use crate::Python;
|
use crate::Python;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -237,4 +290,44 @@ mod tests {
|
||||||
.unwrap());
|
.unwrap());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mro() {
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
assert!(py
|
||||||
|
.get_type_bound::<PyBool>()
|
||||||
|
.mro()
|
||||||
|
.eq(PyTuple::new_bound(
|
||||||
|
py,
|
||||||
|
[
|
||||||
|
py.get_type_bound::<PyBool>(),
|
||||||
|
py.get_type_bound::<PyInt>(),
|
||||||
|
py.get_type_bound::<PyAny>()
|
||||||
|
]
|
||||||
|
))
|
||||||
|
.unwrap());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bases_bool() {
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
assert!(py
|
||||||
|
.get_type_bound::<PyBool>()
|
||||||
|
.bases()
|
||||||
|
.eq(PyTuple::new_bound(py, [py.get_type_bound::<PyInt>()]))
|
||||||
|
.unwrap());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bases_object() {
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
assert!(py
|
||||||
|
.get_type_bound::<PyAny>()
|
||||||
|
.bases()
|
||||||
|
.eq(PyTuple::empty_bound(py))
|
||||||
|
.unwrap());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue