Implement is_instance and is_subclass (#27)
* Implement is_instance * Implement is_subclass * Move is_instance and is_subclass to Python impl * Move implementation detail to PyType
This commit is contained in:
parent
cb68cd23a2
commit
6b18ccb50b
|
@ -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::<exc::TypeError>(&err.instance(py)).unwrap())
|
||||
} else {
|
||||
panic!("error");
|
||||
}
|
||||
|
|
|
@ -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<T>(self, py: Python) -> PyResult<bool>
|
||||
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<T: ToPyPointer>(&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<T: ToPyPointer>(self, py: Python, obj: &T) -> PyResult<bool> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<T: PyTypeObject>(self, obj: &PyObject) -> PyResult<bool> {
|
||||
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<T, U>(self) -> PyResult<bool>
|
||||
where T: PyTypeObject,
|
||||
U: PyTypeObject
|
||||
{
|
||||
T::type_object(self).is_subclass::<U>(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::<PyBool>(py.True().as_ref()).unwrap());
|
||||
let list = PyList::new(py, &[1, 2, 3, 4]);
|
||||
assert!(!py.is_instance::<PyBool>(list.as_ref()).unwrap());
|
||||
assert!(py.is_instance::<PyList>(list.as_ref()).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_subclass() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
assert!(py.is_subclass::<PyBool, PyLong>().unwrap());
|
||||
assert!(!py.is_subclass::<PyBool, PyList>().unwrap());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue