From 8ffeecc54c082975b9dbdab183445d5391e258ab Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Sun, 15 Jan 2023 10:06:45 +0000 Subject: [PATCH] refactor PyAny::is_instance_of --- newsfragments/2881.added.md | 1 + newsfragments/2881.changed.md | 1 + src/type_object.rs | 3 +++ src/types/any.rs | 24 +++++++++++++++++++++++- src/types/mod.rs | 1 + 5 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 newsfragments/2881.added.md create mode 100644 newsfragments/2881.changed.md diff --git a/newsfragments/2881.added.md b/newsfragments/2881.added.md new file mode 100644 index 00000000000..60a2d5f84bc --- /dev/null +++ b/newsfragments/2881.added.md @@ -0,0 +1 @@ +Add `PyAny::is_exact_instance` and `PyAny::is_exact_instance_of`. diff --git a/newsfragments/2881.changed.md b/newsfragments/2881.changed.md new file mode 100644 index 00000000000..87c33011093 --- /dev/null +++ b/newsfragments/2881.changed.md @@ -0,0 +1 @@ +`PyAny::is_instance_of::(obj)` is now equivalent to `T::is_type_of(obj)`. diff --git a/src/type_object.rs b/src/type_object.rs index 53082dbd62c..8a591ecbc1b 100644 --- a/src/type_object.rs +++ b/src/type_object.rs @@ -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()) } } diff --git a/src/types/any.rs b/src/types/any.rs index 5abe97854b3..ef50487381b 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -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() } } @@ -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 { 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 { + 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(&self) -> PyResult { - 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(&self) -> PyResult { + Ok(T::is_exact_type_of(self)) } /// Determines if self contains `value`. diff --git a/src/types/mod.rs b/src/types/mod.rs index 923dfcc096d..e0389ad8c09 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -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)]