Skip to content

Commit

Permalink
add PyAny::is_exact_instance and PyAny::is_exact_instance_of
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed May 18, 2023
1 parent eab3aba commit caaa46f
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 3 deletions.
1 change: 1 addition & 0 deletions newsfragments/3161.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add `PyAny::is_exact_instance` and `PyAny::is_exact_instance_of`.
50 changes: 47 additions & 3 deletions src/types/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,15 @@ impl PyAny {
Ok(result == 1)
}

/// Checks whether this object is an instance of exactly type `ty` (not a subclass).
///
/// This is equivalent to the Python expression `type(self) is ty`.
#[inline]
pub fn is_exact_instance(&self, ty: &PyType) -> bool {
let result = unsafe { ffi::Py_IS_TYPE(self.as_ptr(), ty.as_type_ptr()) };
result != 0
}

/// Checks whether this object is an instance of type `T`.
///
/// This is equivalent to the Python expression `isinstance(self, T)`,
Expand All @@ -921,6 +930,15 @@ impl PyAny {
T::is_type_of(self)
}

/// Checks whether this object is an instance of exactly type `T`.
///
/// This is equivalent to the Python expression `type(self) is T`,
/// if the type `T` is known at compile time.
#[inline]
pub fn is_exact_instance_of<T: PyTypeInfo>(&self) -> bool {
T::is_exact_type_of(self)
}

/// Determines if self contains `value`.
///
/// This is equivalent to the Python expression `value in self`.
Expand Down Expand Up @@ -957,7 +975,7 @@ impl PyAny {
#[cfg(test)]
mod tests {
use crate::{
types::{IntoPyDict, PyList, PyLong, PyModule},
types::{IntoPyDict, PyBool, PyList, PyLong, PyModule},
Python, ToPyObject,
};
#[test]
Expand Down Expand Up @@ -1043,7 +1061,7 @@ class SimpleClass:
}

#[test]
fn test_any_isinstance_of() {
fn test_any_is_instance_of() {
Python::with_gil(|py| {
let x = 5.to_object(py).into_ref(py);
assert!(x.is_instance_of::<PyLong>());
Expand All @@ -1054,13 +1072,39 @@ class SimpleClass:
}

#[test]
fn test_any_isinstance() {
fn test_any_is_instance() {
Python::with_gil(|py| {
let l = vec![1u8, 2].to_object(py).into_ref(py);
assert!(l.is_instance(py.get_type::<PyList>()).unwrap());
});
}

#[test]
fn test_any_is_exact_instance_of() {
Python::with_gil(|py| {
let x = 5.to_object(py).into_ref(py);
assert!(x.is_exact_instance_of::<PyLong>());

let t = PyBool::new(py, true);
assert!(t.is_instance_of::<PyLong>());
assert!(!t.is_exact_instance_of::<PyLong>());
assert!(t.is_exact_instance_of::<PyBool>());

let l = vec![x, x].to_object(py).into_ref(py);
assert!(l.is_exact_instance_of::<PyList>());
});
}

#[test]
fn test_any_is_exact_instance() {
Python::with_gil(|py| {
let t = PyBool::new(py, true);
assert!(t.is_instance(py.get_type::<PyLong>()).unwrap());
assert!(!t.is_exact_instance(py.get_type::<PyLong>()));
assert!(t.is_exact_instance(py.get_type::<PyBool>()));
});
}

#[test]
fn test_any_contains() {
Python::with_gil(|py| {
Expand Down

0 comments on commit caaa46f

Please sign in to comment.