Skip to content

Commit

Permalink
refactor PyAny::is_instance_of
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Jan 15, 2023
1 parent b24628c commit 8ffeecc
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 1 deletion.
1 change: 1 addition & 0 deletions newsfragments/2881.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`.
1 change: 1 addition & 0 deletions newsfragments/2881.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`PyAny::is_instance_of::<T>(obj)` is now equivalent to `T::is_type_of(obj)`.
3 changes: 3 additions & 0 deletions src/type_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,19 @@ pub unsafe trait PyTypeInfo: Sized {
fn type_object_raw(py: Python<'_>) -> *mut ffi::PyTypeObject;

/// Returns the safe abstraction over the type object.
#[inline]
fn type_object(py: Python<'_>) -> &PyType {
unsafe { py.from_borrowed_ptr(Self::type_object_raw(py) as _) }
}

/// Checks if `object` is an instance of this type or a subclass of this type.
#[inline]
fn is_type_of(object: &PyAny) -> bool {
unsafe { ffi::PyObject_TypeCheck(object.as_ptr(), Self::type_object_raw(object.py())) != 0 }
}

/// Checks if `object` is an instance of this type.
#[inline]
fn is_exact_type_of(object: &PyAny) -> bool {
unsafe { ffi::Py_TYPE(object.as_ptr()) == Self::type_object_raw(object.py()) }
}
Expand Down
24 changes: 23 additions & 1 deletion src/types/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,7 @@ impl PyAny {
/// Returns whether the object is considered to be None.
///
/// This is equivalent to the Python expression `self is None`.
#[inline]
pub fn is_none(&self) -> bool {
unsafe { ffi::Py_None() == self.as_ptr() }
}
Expand Down Expand Up @@ -863,18 +864,39 @@ impl PyAny {
/// Checks whether this object is an instance of type `ty`.
///
/// This is equivalent to the Python expression `isinstance(self, ty)`.
#[inline]
pub fn is_instance(&self, ty: &PyAny) -> PyResult<bool> {
let result = unsafe { ffi::PyObject_IsInstance(self.as_ptr(), ty.as_ptr()) };
err::error_on_minusone(self.py(), result)?;
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: &PyAny) -> PyResult<bool> {
let result = unsafe { ffi::PyObject_IsInstance(self.as_ptr(), ty.as_ptr()) };
err::error_on_minusone(self.py(), result)?;
Ok(result == 1)
}

/// Checks whether this object is an instance of type `T`.
///
/// This is equivalent to the Python expression `isinstance(self, T)`,
/// if the type `T` is known at compile time.
#[inline]
pub fn is_instance_of<T: PyTypeInfo>(&self) -> PyResult<bool> {
self.is_instance(T::type_object(self.py()))
Ok(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) -> PyResult<bool> {
Ok(T::is_exact_type_of(self))
}

/// Determines if self contains `value`.
Expand Down
1 change: 1 addition & 0 deletions src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ macro_rules! pyobject_native_type_info(
}

$(
#[inline]
fn is_type_of(ptr: &$crate::PyAny) -> bool {
use $crate::AsPyPointer;
#[allow(unused_unsafe)]
Expand Down

0 comments on commit 8ffeecc

Please sign in to comment.