Move objectprotocol to separate module

This commit is contained in:
Daniel Grunwald 2015-01-04 21:37:43 +01:00
parent 61acf98aec
commit df14c894b2
3 changed files with 241 additions and 228 deletions

View file

@ -9,11 +9,12 @@ extern crate "libpython27-sys" as ffi;
pub use ffi::Py_ssize_t;
pub use err::{PyErr, PyResult};
pub use python::Python;
pub use object::{PythonObject, PyObject, ObjectProtocol};
pub use object::{PythonObject, PyObject};
pub use typeobject::PyType;
pub use pyptr::PyPtr;
pub use module::PyModule;
pub use conversion::{FromPyObject, ToPyObject};
pub use objectprotocol::{ObjectProtocol};
// Fundamentals:
mod python;
@ -25,6 +26,7 @@ mod err;
mod typeobject;
mod module;
mod objectprotocol;
mod pythonrun;
mod conversion;

View file

@ -1,11 +1,9 @@
use std;
use std::cmp::Ordering;
use libc;
use ffi;
use {Python, Py_ssize_t, PyResult, PyErr, ToPyObject};
use typeobject::PyType;
use pyptr::{PyPtr, PythonPointer, as_ptr};
use err;
use python::Python;
use err::{PyErr, PyResult};
/// Trait implemented by all python object types.
pub trait PythonObject<'p> : 'p {
@ -69,6 +67,7 @@ impl <'p> PythonObject<'p> for PyObject<'p> {
self.py
}
#[inline]
fn type_object(py: Python<'p>, _ : Option<&Self>) -> &'p PyType<'p> {
unsafe { PyType::from_type_ptr(py, &mut ffi::PyBaseObject_Type) }
}
@ -89,7 +88,7 @@ impl <'p> PyObject<'p> {
/// Retrieves the reference count of this python object.
#[inline]
pub fn get_refcnt(&self) -> Py_ssize_t {
pub fn get_refcnt(&self) -> ffi::Py_ssize_t {
unsafe { ffi::Py_REFCNT(self.as_ptr()) }
}
@ -112,6 +111,7 @@ impl <'p> PyObject<'p> {
impl <'p> std::fmt::Show for PyObject<'p> {
fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
use objectprotocol::ObjectProtocol;
let rep = try!(self.repr().map_err(|_| std::fmt::Error));
let slice = try!(::conversion::string_as_slice(&*rep).map_err(|_| std::fmt::Error));
f.write_str(try!(std::str::from_utf8(slice).map_err(|_| std::fmt::Error)))
@ -126,225 +126,3 @@ impl <'p> PartialEq for PyObject<'p> {
}
impl <'p> Eq for PyObject<'p> { }
pub trait ObjectProtocol<'p> : PythonObject<'p> {
/// Determines whether this object has the given attribute.
/// This is equivalent to the Python expression 'hasattr(self, attr_name)'.
#[inline]
fn hasattr<'n, Sized? N: ToPyObject<'p, 'n>>(&self, attr_name: &'n N) -> PyResult<'p, bool> {
let py = self.python();
let attr_name = try!(attr_name.to_py_object(py));
unsafe {
Ok(ffi::PyObject_HasAttr(self.as_ptr(), as_ptr(&attr_name)) != 0)
}
}
/// Retrieves an attribute value.
/// This is equivalent to the Python expression 'self.attr_name'.
#[inline]
fn getattr<'n, Sized? N: ToPyObject<'p, 'n>>(&self, attr_name: &'n N)
-> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
let py = self.python();
let attr_name = try!(attr_name.to_py_object(py));
unsafe {
err::result_from_owned_ptr(py,
ffi::PyObject_GetAttr(self.as_ptr(), as_ptr(&attr_name)))
}
}
/// Sets an attribute value.
/// This is equivalent to the Python expression 'self.attr_name = value'.
#[inline]
fn setattr<'n, 'v, Sized? N: ToPyObject<'p, 'n>, Sized? V: ToPyObject<'p, 'v>>
(&self, attr_name: &'n N, value: &'v V) -> PyResult<'p, ()> {
let py = self.python();
let attr_name = try!(attr_name.to_py_object(py));
let value = try!(value.to_py_object(py));
unsafe {
err::error_on_minusone(py,
ffi::PyObject_SetAttr(self.as_ptr(), as_ptr(&attr_name), as_ptr(&value)))
}
}
/// Deletes an attribute.
/// This is equivalent to the Python expression 'del self.attr_name'.
#[inline]
fn delattr<'n, Sized? N: ToPyObject<'p, 'n>>(&self, attr_name: &'n N) -> PyResult<'p, ()> {
let py = self.python();
let attr_name = try!(attr_name.to_py_object(py));
unsafe {
err::error_on_minusone(py,
ffi::PyObject_DelAttr(self.as_ptr(), as_ptr(&attr_name)))
}
}
/// Compares two python objects.
/// This is equivalent to the python expression 'cmp(self, other)'.
#[inline]
fn compare(&self, other: &PyObject<'p>) -> PyResult<'p, Ordering> {
unsafe {
let mut result : libc::c_int = std::mem::uninitialized();
try!(err::error_on_minusone(self.python(),
ffi::PyObject_Cmp(self.as_ptr(), other.as_ptr(), &mut result)));
Ok(if result < 0 {
Ordering::Less
} else if result > 0 {
Ordering::Greater
} else {
Ordering::Equal
})
}
}
/// Compute the string representation of self.
/// This is equivalent to the python expression 'repr(self)'.
#[inline]
fn repr(&self) -> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
unsafe {
err::result_from_owned_ptr(self.python(), ffi::PyObject_Repr(self.as_ptr()))
}
}
/// Compute the string representation of self.
/// This is equivalent to the python expression 'str(self)'.
#[inline]
fn str(&self) -> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
unsafe {
err::result_from_owned_ptr(self.python(), ffi::PyObject_Str(self.as_ptr()))
}
}
/// Compute the unicode string representation of self.
/// This is equivalent to the python expression 'unistr(self)'.
#[inline]
fn unistr(&self) -> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
unsafe {
err::result_from_owned_ptr(self.python(), ffi::PyObject_Unicode(self.as_ptr()))
}
}
/// Determines whether this object is callable.
#[inline]
fn is_callable(&self) -> bool {
unsafe {
ffi::PyCallable_Check(self.as_ptr()) != 0
}
}
/// Calls the object.
/// This is equivalent to the python expression: 'self(*args, **kw)'
#[inline]
fn call(&self, args: &PyObject<'p>, kw: Option<&PyObject<'p>>) -> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
unimplemented!()
}
/// Calls a method on the object.
/// This is equivalent to the python expression: 'self.name(*args, **kw)'
#[inline]
fn call_method(&self, name: &str, args: &PyObject<'p>, kw: Option<&PyObject<'p>>)
-> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
try!(self.getattr(name)).call(args, kw)
}
/// Retrieves the hash code of the object.
/// This is equivalent to the python expression: 'hash(self)'
#[inline]
fn hash(&self) -> PyResult<'p, libc::c_long> {
let v = unsafe { ffi::PyObject_Hash(self.as_ptr()) };
if v == -1 {
Err(PyErr::fetch(self.python()))
} else {
Ok(v)
}
}
/// Returns whether the object is considered to be true.
/// This is equivalent to the python expression: 'not not self'
#[inline]
fn is_true(&self) -> PyResult<'p, bool> {
let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) };
if v == -1 {
Err(PyErr::fetch(self.python()))
} else {
Ok(v != 0)
}
}
/// Returns the length of the sequence or mapping.
/// This is equivalent to the python expression: 'len(self)'
#[inline]
fn len(&self) -> PyResult<'p, Py_ssize_t> {
let v = unsafe { ffi::PyObject_Size(self.as_ptr()) };
if v == -1 {
Err(PyErr::fetch(self.python()))
} else {
Ok(v)
}
}
/// This is equivalent to the python expression: 'self[key]'
#[inline]
fn get_item<'k, Sized? K: ToPyObject<'p, 'k>>(&self, key: &'k K) -> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
let py = self.python();
let key = try!(key.to_py_object(py));
unsafe {
err::result_from_owned_ptr(py,
ffi::PyObject_GetItem(self.as_ptr(), as_ptr(&key)))
}
}
/// Sets an item value.
/// This is equivalent to the Python expression 'self[key] = value'.
#[inline]
fn set_item<'k, 'v, Sized? K: ToPyObject<'p, 'k>, Sized? V: ToPyObject<'p, 'v>>
(&self, key: &'k K, value: &'v V) -> PyResult<'p, ()> {
let py = self.python();
let key = try!(key.to_py_object(py));
let value = try!(value.to_py_object(py));
unsafe {
err::error_on_minusone(py,
ffi::PyObject_SetItem(self.as_ptr(), as_ptr(&key), as_ptr(&value)))
}
}
/// Deletes an item.
/// This is equivalent to the Python expression 'del self[key]'.
#[inline]
fn del_item<'k, Sized? K: ToPyObject<'p, 'k>>(&self, key: &'k K) -> PyResult<'p, ()> {
let py = self.python();
let key = try!(key.to_py_object(py));
unsafe {
err::error_on_minusone(py,
ffi::PyObject_DelItem(self.as_ptr(), as_ptr(&key)))
}
}
/// Takes an object and returns an iterator for it.
/// This is typically a new iterator but if the argument
/// is an iterator, this returns itself.
#[inline]
fn iter(&self) -> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
unsafe {
err::result_from_owned_ptr(self.python(), ffi::PyObject_GetIter(self.as_ptr()))
}
}
/// Retrieves the next item from an iterator.
/// Returns None when the iterator is exhausted.
#[inline]
fn iter_next(&self) -> PyResult<'p, Option<PyPtr<'p, PyObject<'p>>>> {
let py = self.python();
let r = unsafe { ffi::PyIter_Next(self.as_ptr()) };
if r.is_null() {
if PyErr::occurred(py) {
Err(PyErr::fetch(py))
} else {
Ok(None)
}
} else {
Ok(Some(unsafe { PyPtr::from_owned_ptr(py, r) }))
}
}
}
impl <'p> ObjectProtocol<'p> for PyObject<'p> {}

233
src/objectprotocol.rs Normal file
View file

@ -0,0 +1,233 @@
use std;
use std::cmp::Ordering;
use ffi;
use libc;
use python::{Python};
use object::{PythonObject, PyObject};
use pyptr::{PyPtr, PythonPointer, as_ptr};
use conversion::ToPyObject;
use err::{PyErr, PyResult, result_from_owned_ptr, error_on_minusone};
pub trait ObjectProtocol<'p> : PythonObject<'p> {
/// Determines whether this object has the given attribute.
/// This is equivalent to the Python expression 'hasattr(self, attr_name)'.
#[inline]
fn hasattr<'n, Sized? N: ToPyObject<'p, 'n>>(&self, attr_name: &'n N) -> PyResult<'p, bool> {
let py = self.python();
let attr_name = try!(attr_name.to_py_object(py));
unsafe {
Ok(ffi::PyObject_HasAttr(self.as_ptr(), as_ptr(&attr_name)) != 0)
}
}
/// Retrieves an attribute value.
/// This is equivalent to the Python expression 'self.attr_name'.
#[inline]
fn getattr<'n, Sized? N: ToPyObject<'p, 'n>>(&self, attr_name: &'n N)
-> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
let py = self.python();
let attr_name = try!(attr_name.to_py_object(py));
unsafe {
result_from_owned_ptr(py,
ffi::PyObject_GetAttr(self.as_ptr(), as_ptr(&attr_name)))
}
}
/// Sets an attribute value.
/// This is equivalent to the Python expression 'self.attr_name = value'.
#[inline]
fn setattr<'n, 'v, Sized? N: ToPyObject<'p, 'n>, Sized? V: ToPyObject<'p, 'v>>
(&self, attr_name: &'n N, value: &'v V) -> PyResult<'p, ()> {
let py = self.python();
let attr_name = try!(attr_name.to_py_object(py));
let value = try!(value.to_py_object(py));
unsafe {
error_on_minusone(py,
ffi::PyObject_SetAttr(self.as_ptr(), as_ptr(&attr_name), as_ptr(&value)))
}
}
/// Deletes an attribute.
/// This is equivalent to the Python expression 'del self.attr_name'.
#[inline]
fn delattr<'n, Sized? N: ToPyObject<'p, 'n>>(&self, attr_name: &'n N) -> PyResult<'p, ()> {
let py = self.python();
let attr_name = try!(attr_name.to_py_object(py));
unsafe {
error_on_minusone(py,
ffi::PyObject_DelAttr(self.as_ptr(), as_ptr(&attr_name)))
}
}
/// Compares two python objects.
/// This is equivalent to the python expression 'cmp(self, other)'.
#[inline]
fn compare(&self, other: &PyObject<'p>) -> PyResult<'p, Ordering> {
unsafe {
let mut result : libc::c_int = std::mem::uninitialized();
try!(error_on_minusone(self.python(),
ffi::PyObject_Cmp(self.as_ptr(), other.as_ptr(), &mut result)));
Ok(if result < 0 {
Ordering::Less
} else if result > 0 {
Ordering::Greater
} else {
Ordering::Equal
})
}
}
/// Compute the string representation of self.
/// This is equivalent to the python expression 'repr(self)'.
#[inline]
fn repr(&self) -> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
unsafe {
result_from_owned_ptr(self.python(), ffi::PyObject_Repr(self.as_ptr()))
}
}
/// Compute the string representation of self.
/// This is equivalent to the python expression 'str(self)'.
#[inline]
fn str(&self) -> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
unsafe {
result_from_owned_ptr(self.python(), ffi::PyObject_Str(self.as_ptr()))
}
}
/// Compute the unicode string representation of self.
/// This is equivalent to the python expression 'unistr(self)'.
#[inline]
fn unistr(&self) -> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
unsafe {
result_from_owned_ptr(self.python(), ffi::PyObject_Unicode(self.as_ptr()))
}
}
/// Determines whether this object is callable.
#[inline]
fn is_callable(&self) -> bool {
unsafe {
ffi::PyCallable_Check(self.as_ptr()) != 0
}
}
/// Calls the object.
/// This is equivalent to the python expression: 'self(*args, **kw)'
#[inline]
fn call(&self, args: &PyObject<'p>, kw: Option<&PyObject<'p>>) -> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
unimplemented!()
}
/// Calls a method on the object.
/// This is equivalent to the python expression: 'self.name(*args, **kw)'
#[inline]
fn call_method(&self, name: &str, args: &PyObject<'p>, kw: Option<&PyObject<'p>>)
-> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
try!(self.getattr(name)).call(args, kw)
}
/// Retrieves the hash code of the object.
/// This is equivalent to the python expression: 'hash(self)'
#[inline]
fn hash(&self) -> PyResult<'p, libc::c_long> {
let v = unsafe { ffi::PyObject_Hash(self.as_ptr()) };
if v == -1 {
Err(PyErr::fetch(self.python()))
} else {
Ok(v)
}
}
/// Returns whether the object is considered to be true.
/// This is equivalent to the python expression: 'not not self'
#[inline]
fn is_true(&self) -> PyResult<'p, bool> {
let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) };
if v == -1 {
Err(PyErr::fetch(self.python()))
} else {
Ok(v != 0)
}
}
/// Returns the length of the sequence or mapping.
/// This is equivalent to the python expression: 'len(self)'
#[inline]
fn len(&self) -> PyResult<'p, ffi::Py_ssize_t> {
let v = unsafe { ffi::PyObject_Size(self.as_ptr()) };
if v == -1 {
Err(PyErr::fetch(self.python()))
} else {
Ok(v)
}
}
/// This is equivalent to the python expression: 'self[key]'
#[inline]
fn get_item<'k, Sized? K: ToPyObject<'p, 'k>>(&self, key: &'k K) -> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
let py = self.python();
let key = try!(key.to_py_object(py));
unsafe {
result_from_owned_ptr(py,
ffi::PyObject_GetItem(self.as_ptr(), as_ptr(&key)))
}
}
/// Sets an item value.
/// This is equivalent to the Python expression 'self[key] = value'.
#[inline]
fn set_item<'k, 'v, Sized? K: ToPyObject<'p, 'k>, Sized? V: ToPyObject<'p, 'v>>
(&self, key: &'k K, value: &'v V) -> PyResult<'p, ()> {
let py = self.python();
let key = try!(key.to_py_object(py));
let value = try!(value.to_py_object(py));
unsafe {
error_on_minusone(py,
ffi::PyObject_SetItem(self.as_ptr(), as_ptr(&key), as_ptr(&value)))
}
}
/// Deletes an item.
/// This is equivalent to the Python expression 'del self[key]'.
#[inline]
fn del_item<'k, Sized? K: ToPyObject<'p, 'k>>(&self, key: &'k K) -> PyResult<'p, ()> {
let py = self.python();
let key = try!(key.to_py_object(py));
unsafe {
error_on_minusone(py,
ffi::PyObject_DelItem(self.as_ptr(), as_ptr(&key)))
}
}
/// Takes an object and returns an iterator for it.
/// This is typically a new iterator but if the argument
/// is an iterator, this returns itself.
#[inline]
fn iter(&self) -> PyResult<'p, PyPtr<'p, PyObject<'p>>> {
unsafe {
result_from_owned_ptr(self.python(), ffi::PyObject_GetIter(self.as_ptr()))
}
}
/// Retrieves the next item from an iterator.
/// Returns None when the iterator is exhausted.
#[inline]
fn iter_next(&self) -> PyResult<'p, Option<PyPtr<'p, PyObject<'p>>>> {
let py = self.python();
let r = unsafe { ffi::PyIter_Next(self.as_ptr()) };
if r.is_null() {
if PyErr::occurred(py) {
Err(PyErr::fetch(py))
} else {
Ok(None)
}
} else {
Ok(Some(unsafe { PyPtr::from_owned_ptr(py, r) }))
}
}
}
impl <'p> ObjectProtocol<'p> for PyObject<'p> {}