diff --git a/src/objects/bytearray.rs b/src/objects/bytearray.rs index 1a453f67..ddfc7ecb 100644 --- a/src/objects/bytearray.rs +++ b/src/objects/bytearray.rs @@ -77,7 +77,6 @@ impl PyByteArray { mod test { use exc; use python::Python; - use typeob::PyTypeObject; use objects::{PyObject, PyByteArray}; #[test] @@ -100,7 +99,7 @@ mod test { let none = py.None(); if let Err(mut err) = PyByteArray::from(py, &none) { - assert!(exc::TypeError::type_object(py).is_instance(py, &err.instance(py))) + assert!(py.is_instance::(&err.instance(py)).unwrap()) } else { panic!("error"); } diff --git a/src/objects/typeobject.rs b/src/objects/typeobject.rs index d0f806ef..f6de0757 100644 --- a/src/objects/typeobject.rs +++ b/src/objects/typeobject.rs @@ -9,6 +9,8 @@ use ffi; use pointers::PyPtr; use python::{Python, ToPyPointer}; use objects::PyObject; +use err::{PyErr, PyResult}; +use typeob::PyTypeObject; /// Represents a reference to a Python type object. pub struct PyType(PyPtr); @@ -39,16 +41,34 @@ impl PyType { } } - /// Return true if `self` is a subtype of `b`. - #[inline] - pub fn is_subtype_of(&self, _py: Python, b: &PyType) -> bool { - unsafe { ffi::PyType_IsSubtype(self.as_type_ptr(), b.as_type_ptr()) != 0 } + /// Check whether `self` is subclass of type `T` like Python `issubclass` function + pub fn is_subclass(self, py: Python) -> PyResult + where T: PyTypeObject + { + let result = unsafe { + ffi::PyObject_IsSubclass(self.as_ptr(), T::type_object(py).as_ptr()) + }; + if result == -1 { + Err(PyErr::fetch(py)) + } else if result == 1 { + Ok(true) + } else { + Ok(false) + } } - /// Return true if `obj` is an instance of `self`. - #[inline] - pub fn is_instance(&self, _py: Python, obj: &T) -> bool { - unsafe { ffi::PyObject_TypeCheck(obj.as_ptr(), self.as_type_ptr()) != 0 } + // Check whether `obj` is an instance of `self` + pub fn is_instance(self, py: Python, obj: &T) -> PyResult { + let result = unsafe { + ffi::PyObject_IsInstance(obj.as_ptr(), self.as_ptr()) + }; + if result == -1 { + Err(PyErr::fetch(py)) + } else if result == 1 { + Ok(true) + } else { + Ok(false) + } } } diff --git a/src/python.rs b/src/python.rs index 10eadf78..83360ef7 100644 --- a/src/python.rs +++ b/src/python.rs @@ -255,11 +255,25 @@ impl<'p> Python<'p> { Err(e) => e.release(self) } } + + /// Check whether `obj` is an instance of type `T` like Python `isinstance` function + pub fn is_instance(self, obj: &PyObject) -> PyResult { + T::type_object(self).is_instance(self, obj) + } + + /// Check whether type `T` is subclass of type `U` like Python `issubclass` function + pub fn is_subclass(self) -> PyResult + where T: PyTypeObject, + U: PyTypeObject + { + T::type_object(self).is_subclass::(self) + } } #[cfg(test)] mod test { use {Python, PyDict}; + use objects::{PyBool, PyList, PyLong}; #[test] fn test_eval() { @@ -285,4 +299,22 @@ mod test { let v: i32 = py.eval("min(foo, 2)", None, Some(&d)).unwrap().extract(py).unwrap(); assert_eq!(v, 2); } + + #[test] + fn test_is_instance() { + let gil = Python::acquire_gil(); + let py = gil.python(); + assert!(py.is_instance::(py.True().as_ref()).unwrap()); + let list = PyList::new(py, &[1, 2, 3, 4]); + assert!(!py.is_instance::(list.as_ref()).unwrap()); + assert!(py.is_instance::(list.as_ref()).unwrap()); + } + + #[test] + fn test_is_subclass() { + let gil = Python::acquire_gil(); + let py = gil.python(); + assert!(py.is_subclass::().unwrap()); + assert!(!py.is_subclass::().unwrap()); + } }