2017-05-27 17:49:38 +00:00
|
|
|
// Copyright (c) 2017-present PyO3 Project and Contributors
|
2015-04-19 03:22:03 +00:00
|
|
|
//
|
2017-05-27 17:49:38 +00:00
|
|
|
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
2015-04-19 03:22:03 +00:00
|
|
|
|
2015-06-27 21:49:53 +00:00
|
|
|
use std::fmt;
|
2015-01-04 20:37:43 +00:00
|
|
|
use std::cmp::Ordering;
|
|
|
|
use ffi;
|
|
|
|
use libc;
|
2017-05-25 03:31:51 +00:00
|
|
|
use pyptr::{Py, PyPtr};
|
2017-05-29 20:30:38 +00:00
|
|
|
use python::{Python, PyDowncastInto, ToPythonPointer};
|
2017-05-16 21:18:31 +00:00
|
|
|
use objects::{PyObject, PyDict, PyString};
|
2017-05-29 20:30:38 +00:00
|
|
|
use token::PythonObjectWithGilToken;
|
2017-05-14 21:42:56 +00:00
|
|
|
use conversion::{ToPyObject, ToPyTuple};
|
2017-05-28 15:57:34 +00:00
|
|
|
use typeob::PyTypeInfo;
|
2015-09-20 17:39:59 +00:00
|
|
|
use err::{PyErr, PyResult, self};
|
2015-01-04 20:37:43 +00:00
|
|
|
|
2017-05-25 03:31:51 +00:00
|
|
|
|
2017-05-29 20:30:38 +00:00
|
|
|
pub trait ObjectProtocol<'p> {
|
2017-05-28 15:57:34 +00:00
|
|
|
|
|
|
|
/// Determines whether this object has the given attribute.
|
|
|
|
/// This is equivalent to the Python expression 'hasattr(self, attr_name)'.
|
|
|
|
fn hasattr<N>(&self, attr_name: N) -> PyResult<bool> where N: ToPyObject;
|
|
|
|
|
|
|
|
/// Retrieves an attribute value.
|
|
|
|
/// This is equivalent to the Python expression 'self.attr_name'.
|
2017-05-29 20:30:38 +00:00
|
|
|
fn getattr<N>(&self, attr_name: N) -> PyResult<PyObject<'p>> where N: ToPyObject;
|
2017-05-28 15:57:34 +00:00
|
|
|
|
|
|
|
/// Sets an attribute value.
|
|
|
|
/// This is equivalent to the Python expression 'self.attr_name = value'.
|
|
|
|
fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()>
|
|
|
|
where N: ToPyObject, V: ToPyObject;
|
|
|
|
|
|
|
|
/// Deletes an attribute.
|
|
|
|
/// This is equivalent to the Python expression 'del self.attr_name'.
|
|
|
|
fn delattr<N>(&self, attr_name: N) -> PyResult<()> where N: ToPyObject;
|
|
|
|
|
|
|
|
/// Compares two Python objects.
|
|
|
|
///
|
|
|
|
/// On Python 2, this is equivalent to the Python expression 'cmp(self, other)'.
|
|
|
|
///
|
|
|
|
/// On Python 3, this is equivalent to:
|
|
|
|
/// ```
|
|
|
|
/// if self == other:
|
|
|
|
/// return Equal
|
|
|
|
/// elif a < b:
|
|
|
|
/// return Less
|
|
|
|
/// elif a > b:
|
|
|
|
/// return Greater
|
|
|
|
/// else:
|
|
|
|
/// raise TypeError("ObjectProtocol::compare(): All comparisons returned false")
|
|
|
|
/// ```
|
|
|
|
fn compare<O>(&self, other: O) -> PyResult<Ordering> where O: ToPyObject;
|
|
|
|
|
|
|
|
/// Compares two Python objects.
|
|
|
|
///
|
|
|
|
/// Depending on the value of `compare_op`, equivalent to one of the following Python expressions:
|
|
|
|
/// * CompareOp::Eq: `self == other`
|
|
|
|
/// * CompareOp::Ne: `self != other`
|
|
|
|
/// * CompareOp::Lt: `self < other`
|
|
|
|
/// * CompareOp::Le: `self <= other`
|
|
|
|
/// * CompareOp::Gt: `self > other`
|
|
|
|
/// * CompareOp::Ge: `self >= other`
|
|
|
|
fn rich_compare<O>(&self, other: O, compare_op: ::CompareOp)
|
2017-05-29 20:30:38 +00:00
|
|
|
-> PyResult<PyObject<'p>> where O: ToPyObject;
|
2017-05-28 15:57:34 +00:00
|
|
|
|
|
|
|
/// Compute the string representation of self.
|
|
|
|
/// This is equivalent to the Python expression 'repr(self)'.
|
2017-05-29 20:30:38 +00:00
|
|
|
fn repr(&self) -> PyResult<PyString<'p>>;
|
2017-05-28 15:57:34 +00:00
|
|
|
|
|
|
|
/// Compute the string representation of self.
|
|
|
|
/// This is equivalent to the Python expression 'str(self)'.
|
2017-05-29 20:30:38 +00:00
|
|
|
fn str(&self) -> PyResult<PyString<'p>>;
|
2017-05-28 15:57:34 +00:00
|
|
|
|
|
|
|
/// Determines whether this object is callable.
|
|
|
|
fn is_callable(&self) -> bool;
|
|
|
|
|
|
|
|
/// Calls the object.
|
|
|
|
/// This is equivalent to the Python expression: 'self(*args, **kwargs)'
|
2017-05-29 20:30:38 +00:00
|
|
|
fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject<'p>>
|
2017-05-28 15:57:34 +00:00
|
|
|
where A: ToPyTuple;
|
|
|
|
|
|
|
|
/// Calls a method on the object.
|
|
|
|
/// This is equivalent to the Python expression: 'self.name(*args, **kwargs)'
|
|
|
|
fn call_method<A>(&self,
|
|
|
|
name: &str, args: A,
|
2017-05-29 20:30:38 +00:00
|
|
|
kwargs: Option<&PyDict>) -> PyResult<PyObject<'p>>
|
2017-05-28 15:57:34 +00:00
|
|
|
where A: ToPyTuple;
|
|
|
|
|
|
|
|
/// Retrieves the hash code of the object.
|
|
|
|
/// This is equivalent to the Python expression: 'hash(self)'
|
|
|
|
fn hash(&self) -> PyResult<::Py_hash_t>;
|
|
|
|
|
|
|
|
/// Returns whether the object is considered to be true.
|
|
|
|
/// This is equivalent to the Python expression: 'not not self'
|
|
|
|
fn is_true(&self) -> PyResult<bool>;
|
|
|
|
|
2017-05-29 09:47:27 +00:00
|
|
|
/// Returns whether the object is considered to be None.
|
|
|
|
/// This is equivalent to the Python expression: 'is None'
|
|
|
|
#[inline]
|
|
|
|
fn is_none(&self) -> bool;
|
|
|
|
|
2017-05-28 15:57:34 +00:00
|
|
|
/// Returns the length of the sequence or mapping.
|
|
|
|
/// This is equivalent to the Python expression: 'len(self)'
|
|
|
|
fn len(&self) -> PyResult<usize>;
|
|
|
|
|
|
|
|
/// This is equivalent to the Python expression: 'self[key]'
|
2017-05-29 20:30:38 +00:00
|
|
|
fn get_item<K>(&self, key: K) -> PyResult<PyObject<'p>> where K: ToPyObject;
|
2017-05-28 15:57:34 +00:00
|
|
|
|
|
|
|
/// Sets an item value.
|
|
|
|
/// This is equivalent to the Python expression 'self[key] = value'.
|
|
|
|
fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
|
|
|
|
where K: ToPyObject, V: ToPyObject;
|
|
|
|
|
|
|
|
/// Deletes an item.
|
|
|
|
/// This is equivalent to the Python expression 'del self[key]'.
|
|
|
|
fn del_item<K>(&self, key: K) -> PyResult<()> where K: ToPyObject;
|
|
|
|
|
|
|
|
// /// 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.
|
|
|
|
// fn iter<'a>(&'a self) -> PyResult<Py<'p, ::objects::PyIterator<'a>>>;
|
2017-05-30 01:36:44 +00:00
|
|
|
|
|
|
|
fn get_refcnt(&self) -> isize;
|
2017-05-28 15:57:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-29 20:30:38 +00:00
|
|
|
impl<'p, T> ObjectProtocol<'p> for T where T: PythonObjectWithGilToken<'p> + ToPythonPointer {
|
2017-05-25 03:31:51 +00:00
|
|
|
|
2015-01-04 20:37:43 +00:00
|
|
|
/// Determines whether this object has the given attribute.
|
|
|
|
/// This is equivalent to the Python expression 'hasattr(self, attr_name)'.
|
|
|
|
#[inline]
|
2017-05-28 15:57:34 +00:00
|
|
|
fn hasattr<N>(&self, attr_name: N) -> PyResult<bool> where N: ToPyObject {
|
2017-05-29 20:30:38 +00:00
|
|
|
attr_name.with_borrowed_ptr(self.gil(), |attr_name| unsafe {
|
2015-01-07 00:40:48 +00:00
|
|
|
Ok(ffi::PyObject_HasAttr(self.as_ptr(), attr_name) != 0)
|
2015-01-05 20:14:01 +00:00
|
|
|
})
|
2015-01-04 20:37:43 +00:00
|
|
|
}
|
2015-09-20 17:39:59 +00:00
|
|
|
|
2015-01-04 20:37:43 +00:00
|
|
|
/// Retrieves an attribute value.
|
|
|
|
/// This is equivalent to the Python expression 'self.attr_name'.
|
|
|
|
#[inline]
|
2017-05-29 20:30:38 +00:00
|
|
|
fn getattr<N>(&self, attr_name: N) -> PyResult<PyObject<'p>> where N: ToPyObject
|
2017-05-25 03:31:51 +00:00
|
|
|
{
|
2017-05-29 20:30:38 +00:00
|
|
|
attr_name.with_borrowed_ptr(self.gil(), |attr_name| unsafe {
|
|
|
|
PyObject::from_owned_ptr_or_err(
|
|
|
|
self.gil(), ffi::PyObject_GetAttr(self.as_ptr(), attr_name))
|
2015-01-05 20:14:01 +00:00
|
|
|
})
|
2015-01-04 20:37:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets an attribute value.
|
|
|
|
/// This is equivalent to the Python expression 'self.attr_name = value'.
|
|
|
|
#[inline]
|
2017-05-28 15:57:34 +00:00
|
|
|
fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()>
|
2015-10-25 16:55:29 +00:00
|
|
|
where N: ToPyObject, V: ToPyObject
|
2015-01-05 20:14:01 +00:00
|
|
|
{
|
2017-05-25 03:31:51 +00:00
|
|
|
attr_name.with_borrowed_ptr(
|
2017-05-29 20:30:38 +00:00
|
|
|
self.gil(), move |attr_name|
|
|
|
|
value.with_borrowed_ptr(self.gil(), |value| unsafe {
|
2017-05-25 03:31:51 +00:00
|
|
|
err::error_on_minusone(
|
2017-05-29 20:30:38 +00:00
|
|
|
self.gil(), ffi::PyObject_SetAttr(self.as_ptr(), attr_name, value))
|
2015-01-05 20:14:01 +00:00
|
|
|
}))
|
2015-01-04 20:37:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Deletes an attribute.
|
|
|
|
/// This is equivalent to the Python expression 'del self.attr_name'.
|
|
|
|
#[inline]
|
2017-05-28 15:57:34 +00:00
|
|
|
fn delattr<N>(&self, attr_name: N) -> PyResult<()> where N: ToPyObject {
|
2017-05-29 20:30:38 +00:00
|
|
|
attr_name.with_borrowed_ptr(self.gil(), |attr_name| unsafe {
|
|
|
|
err::error_on_minusone(self.gil(),
|
2015-01-07 00:40:48 +00:00
|
|
|
ffi::PyObject_DelAttr(self.as_ptr(), attr_name))
|
2015-01-05 20:14:01 +00:00
|
|
|
})
|
2015-01-04 20:37:43 +00:00
|
|
|
}
|
|
|
|
|
2015-06-27 20:45:35 +00:00
|
|
|
/// Compares two Python objects.
|
2017-03-12 12:50:01 +00:00
|
|
|
///
|
|
|
|
/// On Python 2, this is equivalent to the Python expression 'cmp(self, other)'.
|
|
|
|
///
|
|
|
|
/// On Python 3, this is equivalent to:
|
|
|
|
/// ```
|
|
|
|
/// if self == other:
|
|
|
|
/// return Equal
|
|
|
|
/// elif a < b:
|
|
|
|
/// return Less
|
|
|
|
/// elif a > b:
|
|
|
|
/// return Greater
|
|
|
|
/// else:
|
|
|
|
/// raise TypeError("ObjectProtocol::compare(): All comparisons returned false")
|
|
|
|
/// ```
|
2017-05-28 15:57:34 +00:00
|
|
|
fn compare<O>(&self, other: O) -> PyResult<Ordering> where O: ToPyObject {
|
|
|
|
unsafe fn do_compare(py: Python,
|
2017-05-25 03:31:51 +00:00
|
|
|
a: *mut ffi::PyObject,
|
|
|
|
b: *mut ffi::PyObject) -> PyResult<Ordering> {
|
2017-03-12 12:50:01 +00:00
|
|
|
let result = ffi::PyObject_RichCompareBool(a, b, ffi::Py_EQ);
|
|
|
|
if result == 1 {
|
|
|
|
return Ok(Ordering::Equal);
|
|
|
|
} else if result < 0 {
|
|
|
|
return Err(PyErr::fetch(py));
|
|
|
|
}
|
|
|
|
let result = ffi::PyObject_RichCompareBool(a, b, ffi::Py_LT);
|
|
|
|
if result == 1 {
|
|
|
|
return Ok(Ordering::Less);
|
|
|
|
} else if result < 0 {
|
|
|
|
return Err(PyErr::fetch(py));
|
|
|
|
}
|
|
|
|
let result = ffi::PyObject_RichCompareBool(a, b, ffi::Py_GT);
|
|
|
|
if result == 1 {
|
|
|
|
return Ok(Ordering::Greater);
|
|
|
|
} else if result < 0 {
|
|
|
|
return Err(PyErr::fetch(py));
|
|
|
|
}
|
|
|
|
return Err(PyErr::new::<::exc::TypeError, _>(py, "ObjectProtocol::compare(): All comparisons returned false"));
|
|
|
|
}
|
|
|
|
|
2017-05-29 20:30:38 +00:00
|
|
|
other.with_borrowed_ptr(self.gil(), |other| unsafe {
|
|
|
|
do_compare(self.gil(), self.as_ptr(), other)
|
2017-03-12 12:50:01 +00:00
|
|
|
})
|
2017-05-28 15:57:34 +00:00
|
|
|
}
|
2017-03-12 12:50:01 +00:00
|
|
|
|
|
|
|
/// Compares two Python objects.
|
|
|
|
///
|
|
|
|
/// Depending on the value of `compare_op`, equivalent to one of the following Python expressions:
|
|
|
|
/// * CompareOp::Eq: `self == other`
|
|
|
|
/// * CompareOp::Ne: `self != other`
|
|
|
|
/// * CompareOp::Lt: `self < other`
|
|
|
|
/// * CompareOp::Le: `self <= other`
|
|
|
|
/// * CompareOp::Gt: `self > other`
|
|
|
|
/// * CompareOp::Ge: `self >= other`
|
2017-05-28 15:57:34 +00:00
|
|
|
fn rich_compare<O>(&self, other: O, compare_op: ::CompareOp)
|
2017-05-29 20:30:38 +00:00
|
|
|
-> PyResult<PyObject<'p>> where O: ToPyObject {
|
2017-05-25 03:31:51 +00:00
|
|
|
unsafe {
|
2017-05-29 20:30:38 +00:00
|
|
|
other.with_borrowed_ptr(self.gil(), |other| {
|
|
|
|
PyObject::from_owned_ptr_or_err(
|
|
|
|
self.gil(), ffi::PyObject_RichCompare(
|
2017-05-25 03:31:51 +00:00
|
|
|
self.as_ptr(), other, compare_op as libc::c_int))
|
|
|
|
})
|
|
|
|
}
|
2017-05-28 15:57:34 +00:00
|
|
|
}
|
2015-01-04 20:37:43 +00:00
|
|
|
|
|
|
|
/// Compute the string representation of self.
|
2015-06-27 20:45:35 +00:00
|
|
|
/// This is equivalent to the Python expression 'repr(self)'.
|
2015-01-04 20:37:43 +00:00
|
|
|
#[inline]
|
2017-05-29 20:30:38 +00:00
|
|
|
fn repr(&self) -> PyResult<PyString<'p>> {
|
|
|
|
Ok(PyString::downcast_from_owned_ptr(
|
|
|
|
self.gil(), unsafe{ffi::PyObject_Repr(self.as_ptr())})?)
|
2015-01-04 20:37:43 +00:00
|
|
|
}
|
2015-06-27 18:53:40 +00:00
|
|
|
|
2015-01-04 20:37:43 +00:00
|
|
|
/// Compute the string representation of self.
|
2015-06-27 20:45:35 +00:00
|
|
|
/// This is equivalent to the Python expression 'str(self)'.
|
2015-01-04 20:37:43 +00:00
|
|
|
#[inline]
|
2017-05-29 20:30:38 +00:00
|
|
|
fn str(&self) -> PyResult<PyString<'p>> {
|
|
|
|
Ok(PyString::downcast_from_owned_ptr(
|
|
|
|
self.gil(), unsafe{ffi::PyObject_Str(self.as_ptr())})?)
|
2015-01-04 20:37:43 +00:00
|
|
|
}
|
2015-06-27 18:53:40 +00:00
|
|
|
|
2015-01-04 20:37:43 +00:00
|
|
|
/// Determines whether this object is callable.
|
|
|
|
#[inline]
|
2017-05-28 15:57:34 +00:00
|
|
|
fn is_callable(&self) -> bool {
|
2015-01-04 20:37:43 +00:00
|
|
|
unsafe {
|
|
|
|
ffi::PyCallable_Check(self.as_ptr()) != 0
|
|
|
|
}
|
|
|
|
}
|
2015-06-27 18:53:40 +00:00
|
|
|
|
2017-05-28 15:57:34 +00:00
|
|
|
/// Calls the object.
|
2015-06-27 20:45:35 +00:00
|
|
|
/// This is equivalent to the Python expression: 'self(*args, **kwargs)'
|
2015-01-04 20:37:43 +00:00
|
|
|
#[inline]
|
2017-05-29 20:30:38 +00:00
|
|
|
fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject<'p>>
|
2017-04-28 23:02:52 +00:00
|
|
|
where A: ToPyTuple
|
2015-10-25 16:55:29 +00:00
|
|
|
{
|
2017-05-29 20:30:38 +00:00
|
|
|
let t = args.to_py_tuple(self.gil());
|
2017-05-25 03:31:51 +00:00
|
|
|
unsafe {
|
2017-05-29 20:30:38 +00:00
|
|
|
PyObject::from_owned_ptr_or_err(
|
|
|
|
self.gil(),
|
2017-05-28 15:57:34 +00:00
|
|
|
ffi::PyObject_Call(self.as_ptr(), t.as_ptr(), kwargs.as_ptr()))
|
2017-05-25 03:31:51 +00:00
|
|
|
}
|
2015-01-04 20:37:43 +00:00
|
|
|
}
|
2015-06-27 18:53:40 +00:00
|
|
|
|
2015-01-04 20:37:43 +00:00
|
|
|
/// Calls a method on the object.
|
2015-06-27 20:45:35 +00:00
|
|
|
/// This is equivalent to the Python expression: 'self.name(*args, **kwargs)'
|
2015-01-04 20:37:43 +00:00
|
|
|
#[inline]
|
2017-05-28 15:57:34 +00:00
|
|
|
fn call_method<A>(&self,
|
|
|
|
name: &str, args: A,
|
2017-05-29 20:30:38 +00:00
|
|
|
kwargs: Option<&PyDict>) -> PyResult<PyObject<'p>>
|
2017-04-28 23:02:52 +00:00
|
|
|
where A: ToPyTuple
|
2015-10-25 16:55:29 +00:00
|
|
|
{
|
2017-05-29 20:30:38 +00:00
|
|
|
name.with_borrowed_ptr(self.gil(), |name| unsafe {
|
|
|
|
let t = args.to_py_tuple(self.gil());
|
2017-05-28 15:57:34 +00:00
|
|
|
let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name);
|
2017-05-29 20:30:38 +00:00
|
|
|
PyObject::from_owned_ptr_or_err(
|
|
|
|
self.gil(),
|
2017-05-28 15:57:34 +00:00
|
|
|
ffi::PyObject_Call(ptr, t.as_ptr(), kwargs.as_ptr()))
|
|
|
|
})
|
|
|
|
}
|
2015-06-27 18:53:40 +00:00
|
|
|
|
2015-01-04 20:37:43 +00:00
|
|
|
/// Retrieves the hash code of the object.
|
2015-06-27 20:45:35 +00:00
|
|
|
/// This is equivalent to the Python expression: 'hash(self)'
|
2015-01-04 20:37:43 +00:00
|
|
|
#[inline]
|
2017-05-28 15:57:34 +00:00
|
|
|
fn hash(&self) -> PyResult<::Py_hash_t> {
|
2015-01-04 20:37:43 +00:00
|
|
|
let v = unsafe { ffi::PyObject_Hash(self.as_ptr()) };
|
|
|
|
if v == -1 {
|
2017-05-29 20:30:38 +00:00
|
|
|
Err(PyErr::fetch(self.gil()))
|
2015-01-04 20:37:43 +00:00
|
|
|
} else {
|
|
|
|
Ok(v)
|
|
|
|
}
|
|
|
|
}
|
2015-09-20 17:39:59 +00:00
|
|
|
|
2015-01-04 20:37:43 +00:00
|
|
|
/// Returns whether the object is considered to be true.
|
2015-06-27 20:45:35 +00:00
|
|
|
/// This is equivalent to the Python expression: 'not not self'
|
2015-01-04 20:37:43 +00:00
|
|
|
#[inline]
|
2017-05-28 15:57:34 +00:00
|
|
|
fn is_true(&self) -> PyResult<bool> {
|
2015-01-04 20:37:43 +00:00
|
|
|
let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) };
|
|
|
|
if v == -1 {
|
2017-05-29 20:30:38 +00:00
|
|
|
Err(PyErr::fetch(self.gil()))
|
2015-01-04 20:37:43 +00:00
|
|
|
} else {
|
|
|
|
Ok(v != 0)
|
|
|
|
}
|
|
|
|
}
|
2015-09-20 17:39:59 +00:00
|
|
|
|
2017-05-29 09:47:27 +00:00
|
|
|
/// Returns whether the object is considered to be None.
|
|
|
|
/// This is equivalent to the Python expression: 'is None'
|
|
|
|
#[inline]
|
|
|
|
fn is_none(&self) -> bool {
|
|
|
|
unsafe { ffi::Py_None() == self.as_ptr() }
|
|
|
|
}
|
|
|
|
|
2015-01-04 20:37:43 +00:00
|
|
|
/// Returns the length of the sequence or mapping.
|
2015-06-27 20:45:35 +00:00
|
|
|
/// This is equivalent to the Python expression: 'len(self)'
|
2015-01-04 20:37:43 +00:00
|
|
|
#[inline]
|
2017-05-28 15:57:34 +00:00
|
|
|
fn len(&self) -> PyResult<usize> {
|
2015-01-04 20:37:43 +00:00
|
|
|
let v = unsafe { ffi::PyObject_Size(self.as_ptr()) };
|
|
|
|
if v == -1 {
|
2017-05-29 20:30:38 +00:00
|
|
|
Err(PyErr::fetch(self.gil()))
|
2015-01-04 20:37:43 +00:00
|
|
|
} else {
|
2015-05-24 20:45:43 +00:00
|
|
|
Ok(v as usize)
|
2015-01-04 20:37:43 +00:00
|
|
|
}
|
|
|
|
}
|
2015-09-20 17:39:59 +00:00
|
|
|
|
2015-06-27 20:45:35 +00:00
|
|
|
/// This is equivalent to the Python expression: 'self[key]'
|
2015-01-04 20:37:43 +00:00
|
|
|
#[inline]
|
2017-05-29 20:30:38 +00:00
|
|
|
fn get_item<K>(&self, key: K) -> PyResult<PyObject<'p>> where K: ToPyObject {
|
|
|
|
key.with_borrowed_ptr(self.gil(), |key| unsafe {
|
|
|
|
PyObject::from_owned_ptr_or_err(
|
|
|
|
self.gil(), ffi::PyObject_GetItem(self.as_ptr(), key))
|
2015-01-05 20:14:01 +00:00
|
|
|
})
|
2015-01-04 20:37:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets an item value.
|
|
|
|
/// This is equivalent to the Python expression 'self[key] = value'.
|
|
|
|
#[inline]
|
2017-05-28 15:57:34 +00:00
|
|
|
fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>
|
2017-05-25 03:31:51 +00:00
|
|
|
where K: ToPyObject, V: ToPyObject
|
|
|
|
{
|
|
|
|
key.with_borrowed_ptr(
|
2017-05-29 20:30:38 +00:00
|
|
|
self.gil(), move |key|
|
|
|
|
value.with_borrowed_ptr(self.gil(), |value| unsafe {
|
|
|
|
err::error_on_minusone(self.gil(),
|
2015-01-07 00:40:48 +00:00
|
|
|
ffi::PyObject_SetItem(self.as_ptr(), key, value))
|
2015-01-05 20:14:01 +00:00
|
|
|
}))
|
2015-01-04 20:37:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Deletes an item.
|
|
|
|
/// This is equivalent to the Python expression 'del self[key]'.
|
|
|
|
#[inline]
|
2017-05-28 15:57:34 +00:00
|
|
|
fn del_item<K>(&self, key: K) -> PyResult<()> where K: ToPyObject {
|
2017-05-29 20:30:38 +00:00
|
|
|
key.with_borrowed_ptr(self.gil(), |key| unsafe {
|
|
|
|
err::error_on_minusone(self.gil(),
|
2015-01-07 00:40:48 +00:00
|
|
|
ffi::PyObject_DelItem(self.as_ptr(), key))
|
2015-01-05 20:14:01 +00:00
|
|
|
})
|
2015-01-04 20:37:43 +00:00
|
|
|
}
|
2015-09-20 17:39:59 +00:00
|
|
|
|
2017-05-25 03:31:51 +00:00
|
|
|
// /// 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]
|
|
|
|
//pub fn iter<'a>(&'a self) -> PyResult<Py<'p, ::objects::PyIterator<'a>>> {
|
|
|
|
// Py::from_owned_ptr_or_err(self.py(), ffi::PyObject_GetIter(self.as_ptr()))
|
|
|
|
//}
|
2017-05-30 01:36:44 +00:00
|
|
|
|
|
|
|
fn get_refcnt(&self) -> isize {
|
|
|
|
unsafe { ffi::Py_REFCNT(self.as_ptr()) }
|
|
|
|
}
|
2015-01-05 15:34:12 +00:00
|
|
|
}
|
|
|
|
|
2015-01-04 20:37:43 +00:00
|
|
|
|
2017-05-29 20:30:38 +00:00
|
|
|
impl<'p, T> fmt::Debug for Py<'p, T> where T: ObjectProtocol<'p> + PyTypeInfo {
|
2015-01-11 17:56:59 +00:00
|
|
|
fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
2015-10-25 16:55:29 +00:00
|
|
|
// TODO: we shouldn't use fmt::Error when repr() fails
|
2017-05-25 03:31:51 +00:00
|
|
|
let repr_obj = try!(self.repr().map_err(|_| fmt::Error));
|
|
|
|
f.write_str(&repr_obj.to_string_lossy())
|
2015-01-11 17:56:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-29 20:30:38 +00:00
|
|
|
impl<'p, T> fmt::Display for Py<'p, T> where T: ObjectProtocol<'p> + PyTypeInfo {
|
2015-01-11 17:56:59 +00:00
|
|
|
fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
2015-10-25 16:55:29 +00:00
|
|
|
// TODO: we shouldn't use fmt::Error when str() fails
|
2017-05-25 03:31:51 +00:00
|
|
|
let str_obj = try!(self.str().map_err(|_| fmt::Error));
|
|
|
|
f.write_str(&str_obj.to_string_lossy())
|
2015-01-11 17:56:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-29 20:30:38 +00:00
|
|
|
impl<'p, T> fmt::Debug for PyPtr<T> where T: ObjectProtocol<'p> + PyTypeInfo {
|
2017-05-25 03:31:51 +00:00
|
|
|
default fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
|
|
|
|
|
|
|
// TODO: we shouldn't use fmt::Error when repr() fails
|
2017-05-28 15:57:34 +00:00
|
|
|
let r = self.as_ref(py);
|
2017-05-25 03:31:51 +00:00
|
|
|
let repr_obj = try!(r.repr().map_err(|_| fmt::Error));
|
|
|
|
f.write_str(&repr_obj.to_string_lossy())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-29 20:30:38 +00:00
|
|
|
impl<'p, T> fmt::Display for PyPtr<T> where T: ObjectProtocol<'p> + PyTypeInfo {
|
2017-05-25 03:31:51 +00:00
|
|
|
default fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
|
|
|
|
|
|
|
// TODO: we shouldn't use fmt::Error when repr() fails
|
2017-05-28 15:57:34 +00:00
|
|
|
let r = self.as_ref(py);
|
|
|
|
let repr_obj = try!(r.as_ref().str().map_err(|_| fmt::Error));
|
2017-05-25 03:31:51 +00:00
|
|
|
f.write_str(&repr_obj.to_string_lossy())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-20 17:39:59 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
2017-05-29 20:30:38 +00:00
|
|
|
use python::{Python};
|
2015-09-20 17:39:59 +00:00
|
|
|
use conversion::ToPyObject;
|
2017-05-29 20:30:38 +00:00
|
|
|
//use objects::{PyTuple}; //PyList,
|
2017-03-12 12:50:01 +00:00
|
|
|
use super::ObjectProtocol;
|
2015-09-20 17:39:59 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_debug_string() {
|
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
2017-05-29 20:30:38 +00:00
|
|
|
let v = "Hello\n".to_object(py);
|
2015-09-20 17:39:59 +00:00
|
|
|
assert_eq!(format!("{:?}", v), "'Hello\\n'");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_display_string() {
|
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
2017-05-29 20:30:38 +00:00
|
|
|
let v = "Hello\n".to_object(py);
|
2015-09-20 17:39:59 +00:00
|
|
|
assert_eq!(format!("{}", v), "Hello\n");
|
|
|
|
}
|
2017-03-12 12:50:01 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_compare() {
|
|
|
|
use std::cmp::Ordering;
|
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
2017-05-29 20:30:38 +00:00
|
|
|
let one = 1i32.to_object(py).into_object(py);
|
|
|
|
assert_eq!(one.compare(1).unwrap(), Ordering::Equal);
|
|
|
|
assert_eq!(one.compare(2).unwrap(), Ordering::Less);
|
|
|
|
assert_eq!(one.compare(0).unwrap(), Ordering::Greater);
|
2017-03-12 12:50:01 +00:00
|
|
|
}
|
2015-09-20 17:39:59 +00:00
|
|
|
}
|