Add PyBool and PyTuple impls
This commit is contained in:
parent
038dfc7474
commit
1c7eb2340d
|
@ -2,7 +2,7 @@ use libc::c_char;
|
|||
use std;
|
||||
use ffi;
|
||||
use python::{Python, PythonObject, PythonObjectWithCheckedDowncast};
|
||||
use objects::PyObject;
|
||||
use objects::{PyObject, PyBool};
|
||||
use err::{self, PyErr, PyResult};
|
||||
use pyptr::{PyPtr, PythonPointer};
|
||||
|
||||
|
@ -111,30 +111,25 @@ impl <'p, 's, T> FromPyObject<'p, 's> for PyPtr<'p, T> where T: PythonObjectWith
|
|||
|
||||
|
||||
impl <'p> ToPyObject<'p> for bool {
|
||||
type ObjectType = PyObject<'p>;
|
||||
type ObjectType = PyBool<'p>;
|
||||
|
||||
#[inline]
|
||||
fn to_py_object(self, py: Python<'p>) -> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
|
||||
Ok(PyPtr::new(if self { py.True() } else { py.False() }))
|
||||
fn to_py_object(self, py: Python<'p>) -> PyResult<'p, PyPtr<'p, PyBool<'p>>> {
|
||||
Ok(PyPtr::new(PyBool::get(py, self)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn with_py_object<F, R>(self, py: Python<'p>, f: F) -> PyResult<'p, R> where F: FnOnce(&PyObject) -> PyResult<'p, R> {
|
||||
fn with_py_object<F, R>(self, py: Python<'p>, f: F) -> PyResult<'p, R>
|
||||
where F: FnOnce(&PyBool) -> PyResult<'p, R>
|
||||
{
|
||||
// Avoid unnecessary Py_INCREF/Py_DECREF pair
|
||||
f(if self { py.True() } else { py.False() })
|
||||
f(PyBool::get(py, self))
|
||||
}
|
||||
}
|
||||
|
||||
impl <'p, 'a> FromPyObject<'p, 'a> for bool {
|
||||
fn from_py_object(s: &'a PyObject<'p>) -> PyResult<'p, bool> {
|
||||
let py = s.python();
|
||||
if s == py.True() {
|
||||
Ok(true)
|
||||
} else if s == py.False() {
|
||||
Ok(false)
|
||||
} else {
|
||||
unimplemented!()
|
||||
}
|
||||
Ok(try!(s.downcast::<PyBool>()).is_true())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
24
src/err.rs
24
src/err.rs
|
@ -82,16 +82,10 @@ impl <'p> PyErr<'p> {
|
|||
unsafe { ffi::PyErr_PrintEx(1) }
|
||||
}
|
||||
|
||||
/// Print a warning message to sys.stderr when an exception has been set but it is impossible for the interpreter to actually raise the exception.
|
||||
/// It is used, for example, when an exception occurs in an __del__() method..
|
||||
pub fn write_unraisable(self, context: &PyObject<'p>) {
|
||||
self.restore();
|
||||
unsafe { ffi::PyErr_WriteUnraisable(context.as_ptr()) }
|
||||
}
|
||||
|
||||
/// Return true if the current exception matches the exception in `exc`.
|
||||
/// If `exc` is a class object, this also returns `true` when `self` is an instance of a subclass.
|
||||
/// If `exc` is a tuple, all exceptions in the tuple (and recursively in subtuples) are searched for a match.
|
||||
#[inline]
|
||||
pub fn matches(&self, exc: &PyObject) -> bool {
|
||||
unsafe { ffi::PyErr_GivenExceptionMatches(self.ptype.as_ptr(), exc.as_ptr()) != 0 }
|
||||
}
|
||||
|
@ -120,8 +114,22 @@ impl <'p> PyErr<'p> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Retrieves the exception type.
|
||||
/// If the exception type is an old-style class, returns oldstyle::PyClass.
|
||||
pub fn get_type(&self) -> &PyType<'p> {
|
||||
match self.ptype.downcast::<PyType>() {
|
||||
Ok(t) => t,
|
||||
Err(_) => unimplemented!()
|
||||
/* match self.ptype.downcast::<PyClass>() {
|
||||
Ok(_) => py.get_type::<PyClass>(),
|
||||
Err(_) => py.get_type::<PyNone>()
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the exception instance for this error.
|
||||
/// This method takes &mut self because the error might need to be normalized in order to create the exception instance.
|
||||
/// This method takes &mut self because the error might need
|
||||
/// to be normalized in order to create the exception instance.
|
||||
pub fn instance(&mut self) -> &PyObject<'p> {
|
||||
self.normalize();
|
||||
match self.pvalue {
|
||||
|
|
|
@ -3,6 +3,10 @@ pub use self::typeobject::PyType;
|
|||
pub use self::module::PyModule;
|
||||
pub use self::string::{PyBytes, PyUnicode};
|
||||
pub use self::iterator::PyIterator;
|
||||
use python::{Python, PythonObject};
|
||||
use pyptr::{PyPtr, PythonPointer};
|
||||
use err::{PyErr, PyResult};
|
||||
use ffi::{Py_ssize_t};
|
||||
|
||||
macro_rules! pythonobject_newtype_only_pythonobject(
|
||||
($name: ident) => (
|
||||
|
@ -55,7 +59,67 @@ mod string;
|
|||
mod dict;
|
||||
mod iterator;
|
||||
|
||||
pyobject_newtype!(PyTuple, PyTuple_Check, PyTuple_Type);
|
||||
pyobject_newtype!(PyList, PyList_Check, PyList_Type);
|
||||
|
||||
|
||||
pyobject_newtype!(PyBool, PyBool_Check, PyBool_Type);
|
||||
|
||||
impl <'p> PyBool<'p> {
|
||||
#[inline]
|
||||
pub fn get(py: Python<'p>, val: bool) -> &'p PyBool<'p> {
|
||||
if val { py.True() } else { py.False() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_true(&self) -> bool {
|
||||
self.as_ptr() == unsafe { ::ffi::Py_True() }
|
||||
}
|
||||
}
|
||||
|
||||
pyobject_newtype!(PyTuple, PyTuple_Check, PyTuple_Type);
|
||||
|
||||
impl <'p> PyTuple<'p> {
|
||||
pub fn new(py: Python<'p>, elements: &[&PyObject<'p>]) -> PyResult<'p, PyPtr<'p, PyTuple<'p>>> {
|
||||
unsafe {
|
||||
let len = elements.len();
|
||||
let ptr = ::ffi::PyTuple_New(len as Py_ssize_t);
|
||||
let t = try!(::err::result_from_owned_ptr(py, ptr)).unchecked_downcast_into::<PyTuple>();
|
||||
for (i, e) in elements.iter().enumerate() {
|
||||
::ffi::PyTuple_SET_ITEM(ptr, i as Py_ssize_t, e.steal_ptr());
|
||||
}
|
||||
Ok(t)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> uint {
|
||||
// non-negative Py_ssize_t should always fit into Rust uint
|
||||
unsafe {
|
||||
::ffi::PyTuple_GET_SIZE(self.as_ptr()) as uint
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_slice<'a>(&'a self) -> &'a [&'a PyObject<'p>] {
|
||||
// This is safe because &PyObject has the same memory layout as *mut ffi::PyObject,
|
||||
// and because tuples are immutable.
|
||||
unsafe {
|
||||
let ptr = self.as_ptr() as *mut ::ffi::PyTupleObject;
|
||||
::std::mem::transmute(::std::raw::Slice {
|
||||
data: (*ptr).ob_item.as_ptr(),
|
||||
len: self.len()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> ::std::ops::Index<uint> for PyTuple<'p> {
|
||||
type Output = PyObject<'p>;
|
||||
|
||||
#[inline]
|
||||
fn index<'a>(&'a self, index: &uint) -> &'a PyObject<'p> {
|
||||
// use as_slice() to use the normal Rust bounds checking when indexing
|
||||
self.as_slice()[*index]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,3 +83,11 @@ impl <'p> PyType<'p> {
|
|||
}
|
||||
}
|
||||
|
||||
impl <'p> PartialEq for PyType<'p> {
|
||||
#[inline]
|
||||
fn eq(&self, o : &PyType<'p>) -> bool {
|
||||
self.as_type_ptr() == o.as_type_ptr()
|
||||
}
|
||||
}
|
||||
impl <'p> Eq for PyType<'p> { }
|
||||
|
||||
|
|
|
@ -176,5 +176,10 @@ impl<'p> PyPtr<'p, PyObject<'p>> {
|
|||
// TODO: avoid unnecessary IncRef/DefRef
|
||||
self.deref().downcast().map(PyPtr::new)
|
||||
}
|
||||
|
||||
pub unsafe fn unchecked_downcast_into<T>(self) -> PyPtr<'p, T> where T: PythonObject<'p> {
|
||||
// TODO: avoid unnecessary IncRef/DefRef
|
||||
PyPtr::new(PythonObject::unchecked_downcast_from(self.deref()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use std;
|
|||
use std::kinds::marker::{NoSend, InvariantLifetime};
|
||||
use std::ptr;
|
||||
use ffi;
|
||||
use objects::{PyObject, PyType};
|
||||
use objects::{PyObject, PyType, PyBool};
|
||||
use pythonrun::GILGuard;
|
||||
|
||||
/// The 'Python' struct is a zero-size marker struct that is required for most python operations.
|
||||
|
@ -89,15 +89,15 @@ impl<'p> Python<'p> {
|
|||
/// Retrieves a reference to the 'True' constant value.
|
||||
#[allow(non_snake_case)] // the python keyword starts with uppercase
|
||||
#[inline]
|
||||
pub fn True(self) -> &'p PyObject<'p> {
|
||||
unsafe { PyObject::from_ptr(self, ffi::Py_True()) }
|
||||
pub fn True(self) -> &'p PyBool<'p> {
|
||||
unsafe { PythonObject::unchecked_downcast_from(PyObject::from_ptr(self, ffi::Py_True())) }
|
||||
}
|
||||
|
||||
/// Retrieves a reference to the 'False' constant value.
|
||||
#[allow(non_snake_case)] // the python keyword starts with uppercase
|
||||
#[inline]
|
||||
pub fn False(self) -> &'p PyObject<'p> {
|
||||
unsafe { PyObject::from_ptr(self, ffi::Py_False()) }
|
||||
pub fn False(self) -> &'p PyBool<'p> {
|
||||
unsafe { PythonObject::unchecked_downcast_from(PyObject::from_ptr(self, ffi::Py_False())) }
|
||||
}
|
||||
|
||||
/// Retrieves a reference to the type object for type T.
|
||||
|
|
Loading…
Reference in New Issue