restore sequence and iterator objects
This commit is contained in:
parent
61b8bd0695
commit
86a8dfec0c
|
@ -133,6 +133,16 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident, token: Option<syn::Ident>) ->
|
|||
}
|
||||
}
|
||||
|
||||
impl _pyo3::python::ToPythonPointer for #cls {
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
||||
unsafe {
|
||||
{self as *const _ as *mut u8}.offset(-offset) as *mut ffi::PyObject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl _pyo3::class::PyCustomObject for #cls {
|
||||
|
||||
}
|
||||
|
|
|
@ -33,8 +33,6 @@ pub static NO_PY_METHODS: &'static [PyMethodDefType] = &[];
|
|||
|
||||
use ffi;
|
||||
use typeob::PyTypeInfo;
|
||||
use python::ToPythonPointer;
|
||||
use token::PythonObjectWithToken;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CompareOp {
|
||||
|
@ -47,13 +45,3 @@ pub enum CompareOp {
|
|||
}
|
||||
|
||||
pub trait PyCustomObject : PyTypeInfo + Sized {}
|
||||
|
||||
impl<'p, T> ToPythonPointer for T where T: PyCustomObject + PythonObjectWithToken {
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
let offset = <T as PyTypeInfo>::offset();
|
||||
unsafe {
|
||||
{self as *const _ as *mut u8}.offset(-offset) as *mut ffi::PyObject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,9 @@
|
|||
|
||||
use pyptr::PyPtr;
|
||||
use token::PyObjectMarker;
|
||||
use typeob::PyTypeInfo;
|
||||
use objects::PyObject;
|
||||
|
||||
pub trait PyBaseObject : PyTypeInfo + Sized {}
|
||||
pub trait PyBaseObject : Sized {}
|
||||
|
||||
pub trait PyNativeObject<'p> : PyBaseObject {
|
||||
|
||||
|
|
|
@ -6,9 +6,10 @@ use std::fmt;
|
|||
use std::cmp::Ordering;
|
||||
use ffi;
|
||||
use libc;
|
||||
use ppptr::pptr;
|
||||
use pyptr::{Py, PyPtr};
|
||||
use python::{Python, PyDowncastInto, ToPythonPointer};
|
||||
use objects::{PyObject, PyDict, PyString};
|
||||
use objects::{PyObject, PyDict, PyString, PyIterator};
|
||||
use token::PythonObjectWithGilToken;
|
||||
use conversion::{ToPyObject, ToPyTuple};
|
||||
use typeob::PyTypeInfo;
|
||||
|
@ -115,10 +116,10 @@ pub trait ObjectProtocol<'p> {
|
|||
/// 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>>>;
|
||||
/// 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(&self) -> PyResult<PyIterator<'p>>;
|
||||
|
||||
fn get_refcnt(&self) -> isize;
|
||||
}
|
||||
|
@ -366,13 +367,17 @@ impl<'p, T> ObjectProtocol<'p> for T where T: PythonObjectWithGilToken<'p> + ToP
|
|||
})
|
||||
}
|
||||
|
||||
// /// 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()))
|
||||
//}
|
||||
/// 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<PyIterator<'p>> {
|
||||
unsafe {
|
||||
let ptr = pptr::from_owned_ptr_or_err(
|
||||
self.gil(), ffi::PyObject_GetIter(self.as_ptr()))?;
|
||||
PyIterator::from_object(self.gil(), ptr).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_refcnt(&self) -> isize {
|
||||
unsafe { ffi::Py_REFCNT(self.as_ptr()) }
|
||||
|
|
|
@ -78,7 +78,7 @@ impl<'p> PyByteArray<'p> {
|
|||
mod test {
|
||||
use ::ToPyObject;
|
||||
use exc;
|
||||
use python::{Python, ToPythonPointer};
|
||||
use python::Python;
|
||||
use typeob::PyTypeObject;
|
||||
use objects::PyByteArray;
|
||||
|
||||
|
@ -101,7 +101,6 @@ mod test {
|
|||
assert_eq!(20, bytearray.len());
|
||||
|
||||
let none = py.None();
|
||||
println!("NONE: {:?} {}", none.as_ptr(), none.get_refcnt());
|
||||
if let Err(mut err) = PyByteArray::from(none.as_object(py)) {
|
||||
assert!(exc::TypeError::type_object(py).is_instance(&err.instance(py)))
|
||||
} else {
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
use ::pptr;
|
||||
use ffi;
|
||||
use pyptr::PyPtr;
|
||||
use python::{Python, ToPythonPointer};
|
||||
use python::{Python, ToPythonPointer, PyDowncastInto};
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
use objects::PyObject;
|
||||
use token::{PyObjectMarker, PythonObjectWithGilToken}; //, PyList};
|
||||
use objects::{PyObject, PyList};
|
||||
use token::{PyObjectMarker, PythonObjectWithGilToken};
|
||||
use err::{self, PyResult, PyErr};
|
||||
use std::{mem, collections, hash, cmp};
|
||||
|
||||
|
@ -98,11 +98,12 @@ impl<'p> PyDict<'p> {
|
|||
|
||||
// List of dict items.
|
||||
// This is equivalent to the python expression `list(dict.items())`.
|
||||
//pub fn items_list(&self) -> Py<PyList> {
|
||||
// unsafe {
|
||||
// Py::from_owned_ptr_or_panic(self.py(), ffi::PyDict_Items(self.as_ptr()))
|
||||
// }
|
||||
//}
|
||||
pub fn items_list(&self) -> PyList<'p> {
|
||||
unsafe {
|
||||
PyList::downcast_from_owned_ptr(
|
||||
self.gil(), ffi::PyDict_Items(self.as_ptr())).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the list of (key, value) pairs in this dictionary.
|
||||
pub fn items(&self) -> Vec<(PyObject<'p>, PyObject<'p>)> {
|
||||
|
@ -153,9 +154,9 @@ impl <K, V> ToPyObject for collections::BTreeMap<K, V>
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use python::{Python};
|
||||
use python::{Python, PyDowncastInto};
|
||||
use conversion::ToPyObject;
|
||||
use objects::{PyDict}; //, PyTuple};
|
||||
use objects::{PyDict, PyTuple};
|
||||
use ::PyDowncastFrom;
|
||||
|
||||
|
||||
|
@ -251,7 +252,7 @@ mod test {
|
|||
assert_eq!(32i32, *v.get(&7i32).unwrap()); // not updated!
|
||||
}
|
||||
|
||||
/*#[test]
|
||||
#[test]
|
||||
fn test_items_list() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
@ -259,18 +260,18 @@ mod test {
|
|||
v.insert(7, 32);
|
||||
v.insert(8, 42);
|
||||
v.insert(9, 123);
|
||||
let dict = PyDict::downcast_from(py, v.to_py_object(py)).unwrap();
|
||||
let dict = PyDict::downcast_into(py, v.to_object(py)).unwrap();
|
||||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||
let mut key_sum = 0;
|
||||
let mut value_sum = 0;
|
||||
for el in dict.items_list(py).iter(py) {
|
||||
for el in dict.items_list().iter() {
|
||||
let tuple = el.cast_into::<PyTuple>(py).unwrap();
|
||||
key_sum += tuple.get_item(py, 0).extract::<i32>(py).unwrap();
|
||||
value_sum += tuple.get_item(py, 1).extract::<i32>(py).unwrap();
|
||||
key_sum += tuple.get_item(0).extract::<i32>().unwrap();
|
||||
value_sum += tuple.get_item(1).extract::<i32>().unwrap();
|
||||
}
|
||||
assert_eq!(7 + 8 + 9, key_sum);
|
||||
assert_eq!(32 + 42 + 123, value_sum);
|
||||
}*/
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_items() {
|
||||
|
|
|
@ -2,58 +2,52 @@
|
|||
//
|
||||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
use python::{Python, PythonObjectDowncastError};
|
||||
use objects::PyObject;
|
||||
use err::{PyErr, PyResult};
|
||||
use ffi;
|
||||
use ppptr::pptr;
|
||||
use python::{Python, ToPythonPointer, IntoPythonPointer};
|
||||
use objects::PyObject;
|
||||
use err::{PyErr, PyResult, PyDowncastError};
|
||||
|
||||
/// A python iterator object.
|
||||
///
|
||||
/// Unlike other python objects, this class includes a `Python<'p>` token
|
||||
/// so that PyIterator can implement the rust `Iterator` trait.
|
||||
pub struct PyIterator<'p> {
|
||||
py: Python<'p>,
|
||||
iter: PyObject,
|
||||
}
|
||||
pub struct PyIterator<'p>(pptr<'p>);
|
||||
|
||||
|
||||
impl <'p> PyIterator<'p> {
|
||||
/// Constructs a PyIterator from a Python iterator object.
|
||||
pub fn from_object(py: Python<'p>, obj: PyObject) -> Result<PyIterator<'p>, PythonObjectDowncastError<'p>> {
|
||||
if unsafe { ffi::PyIter_Check(obj.as_ptr()) != 0 } {
|
||||
Ok(PyIterator { py: py, iter: obj })
|
||||
} else {
|
||||
Err(PythonObjectDowncastError(py, None))
|
||||
pub fn from_object<T>(py: Python<'p>, obj: T)
|
||||
-> Result<PyIterator<'p>, PyDowncastError<'p>>
|
||||
where T: IntoPythonPointer
|
||||
{
|
||||
unsafe {
|
||||
let ptr = obj.into_ptr();
|
||||
if ffi::PyIter_Check(ptr) != 0 {
|
||||
Ok(PyIterator(pptr::from_borrowed_ptr(py, ptr)))
|
||||
} else {
|
||||
ffi::Py_DECREF(ptr);
|
||||
Err(PyDowncastError(py, None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the Python iterator object.
|
||||
#[inline]
|
||||
pub fn as_object(&self) -> &PyObject {
|
||||
&self.iter
|
||||
}
|
||||
|
||||
/// Gets the Python iterator object.
|
||||
#[inline]
|
||||
pub fn into_object(self) -> PyObject {
|
||||
self.iter
|
||||
}
|
||||
}
|
||||
|
||||
impl <'p> Iterator for PyIterator<'p> {
|
||||
type Item = PyResult<PyObject>;
|
||||
type Item = PyResult<PyObject<'p>>;
|
||||
|
||||
/// Retrieves the next item from an iterator.
|
||||
/// Returns `None` when the iterator is exhausted.
|
||||
/// If an exception occurs, returns `Some(Err(..))`.
|
||||
/// Further next() calls after an exception occurs are likely
|
||||
/// to repeatedly result in the same exception.
|
||||
fn next(&mut self) -> Option<PyResult<PyObject>> {
|
||||
let py = self.py;
|
||||
match unsafe { PyObject::from_owned_ptr_opt(py, ffi::PyIter_Next(self.iter.as_ptr())) } {
|
||||
fn next(&mut self) -> Option<PyResult<PyObject<'p>>> {
|
||||
match unsafe { PyObject::from_owned_ptr_or_opt(
|
||||
self.0.token(), ffi::PyIter_Next(self.0.as_ptr())) } {
|
||||
Some(obj) => Some(Ok(obj)),
|
||||
None => {
|
||||
if PyErr::occurred(py) {
|
||||
Some(Err(PyErr::fetch(py)))
|
||||
if PyErr::occurred(self.0.token()) {
|
||||
Some(Err(PyErr::fetch(self.0.token())))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -64,7 +58,7 @@ impl <'p> Iterator for PyIterator<'p> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use python::{Python, PythonObject};
|
||||
use python::{Python};
|
||||
use conversion::ToPyObject;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
|
@ -72,11 +66,10 @@ mod tests {
|
|||
fn vec_iter() {
|
||||
let gil_guard = Python::acquire_gil();
|
||||
let py = gil_guard.python();
|
||||
let obj = vec![10, 20].to_py_object(py).into_object();
|
||||
let mut it = obj.iter(py).unwrap();
|
||||
assert_eq!(10, it.next().unwrap().unwrap().extract(py).unwrap());
|
||||
assert_eq!(20, it.next().unwrap().unwrap().extract(py).unwrap());
|
||||
let obj = vec![10, 20].to_object(py).into_object(py);
|
||||
let mut it = obj.iter().unwrap();
|
||||
assert_eq!(10, it.next().unwrap().unwrap().extract().unwrap());
|
||||
assert_eq!(20, it.next().unwrap().unwrap().extract().unwrap());
|
||||
assert!(it.next().is_none());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
use ::pptr;
|
||||
use pyptr::{Py, PyPtr};
|
||||
use python::{Python, ToPythonPointer, IntoPythonPointer, PythonToken, PythonObjectWithToken};
|
||||
use objects::PyObject;
|
||||
use err::{self, PyResult};
|
||||
use ffi::{self, Py_ssize_t};
|
||||
use pyptr::PyPtr;
|
||||
use python::{Python, ToPythonPointer, IntoPythonPointer};
|
||||
use objects::PyObject;
|
||||
use token::{PyObjectMarker, PythonObjectWithGilToken};
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
|
||||
/// Represents a Python `list`.
|
||||
|
@ -38,30 +40,35 @@ impl<'p> PyList<'p> {
|
|||
/// Gets the item at the specified index.
|
||||
///
|
||||
/// Panics if the index is out of range.
|
||||
pub fn get_item(&self, index: usize) -> &PyObject {
|
||||
// TODO: do we really want to panic here?
|
||||
assert!(index < self.len());
|
||||
pub fn get_item(&self, index: isize) -> PyObject<'p> {
|
||||
unsafe {
|
||||
let ptr = ffi::PyList_GetItem(self.as_ptr(), index as Py_ssize_t);
|
||||
self.py_token().from_owned(ptr)
|
||||
PyObject::from_borrowed_ptr(
|
||||
self.gil(), ffi::PyList_GetItem(self.as_ptr(), index as Py_ssize_t))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the item at the specified index.
|
||||
///
|
||||
/// Panics if the index is out of range.
|
||||
pub fn set_item(&self, index: usize, item: Py<'p, PyObject>) {
|
||||
let r = unsafe { ffi::PyList_SetItem(
|
||||
self.as_ptr(), index as Py_ssize_t, item.into_ptr()) };
|
||||
assert!(r == 0);
|
||||
pub fn set_item<I>(&self, index: isize, item: I) -> PyResult<()>
|
||||
where I: ToPyObject
|
||||
{
|
||||
item.with_borrowed_ptr(self.gil(), |item| unsafe {
|
||||
err::error_on_minusone(
|
||||
self.gil(), ffi::PyList_SetItem(self.as_ptr(), index, item))
|
||||
})
|
||||
}
|
||||
|
||||
/// Inserts an item at the specified index.
|
||||
///
|
||||
/// Panics if the index is out of range.
|
||||
pub fn insert_item(&self, index: usize, item: Py<'p, PyObject>) {
|
||||
let r = unsafe { ffi::PyList_Insert(self.as_ptr(), index as Py_ssize_t, item.as_ptr()) };
|
||||
assert!(r == 0);
|
||||
pub fn insert_item<I>(&self, index: isize, item: I) -> PyResult<()>
|
||||
where I: ToPyObject
|
||||
{
|
||||
item.with_borrowed_ptr(self.gil(), |item| unsafe {
|
||||
err::error_on_minusone(
|
||||
self.gil(), ffi::PyList_Insert(self.as_ptr(), index, item))
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -73,15 +80,15 @@ impl<'p> PyList<'p> {
|
|||
/// Used by `PyList::iter()`.
|
||||
pub struct PyListIterator<'p> {
|
||||
list: &'p PyList<'p>,
|
||||
index: usize
|
||||
index: isize
|
||||
}
|
||||
|
||||
impl <'p> Iterator for PyListIterator<'p> {
|
||||
type Item = Py<'p, PyObject>;
|
||||
type Item = PyObject<'p>;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'p PyObject> {
|
||||
if self.index < self.list.len() {
|
||||
fn next(&mut self) -> Option<PyObject<'p>> {
|
||||
if self.index < self.list.len() as isize {
|
||||
let item = self.list.get_item(self.index);
|
||||
self.index += 1;
|
||||
Some(item)
|
||||
|
@ -96,7 +103,7 @@ impl <'p> Iterator for PyListIterator<'p> {
|
|||
|
||||
impl <T> ToPyObject for [T] where T: ToPyObject {
|
||||
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObject> {
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
unsafe {
|
||||
let ptr = ffi::PyList_New(self.len() as Py_ssize_t);
|
||||
for (i, e) in self.iter().enumerate() {
|
||||
|
@ -110,7 +117,7 @@ impl <T> ToPyObject for [T] where T: ToPyObject {
|
|||
|
||||
impl <T> ToPyObject for Vec<T> where T: ToPyObject {
|
||||
|
||||
fn to_object<'p>(&self, py: Python<'p>) -> PyPtr<PyObject> {
|
||||
fn to_object(&self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
self.as_slice().to_object(py)
|
||||
}
|
||||
|
||||
|
@ -118,7 +125,7 @@ impl <T> ToPyObject for Vec<T> where T: ToPyObject {
|
|||
|
||||
impl <T> IntoPyObject for Vec<T> where T: IntoPyObject {
|
||||
|
||||
fn into_object(self, py: Python) -> PyPtr<PyObject> {
|
||||
fn into_object(self, py: Python) -> PyPtr<PyObjectMarker> {
|
||||
unsafe {
|
||||
let ptr = ffi::PyList_New(self.len() as Py_ssize_t);
|
||||
for (i, e) in self.into_iter().enumerate() {
|
||||
|
@ -132,8 +139,8 @@ impl <T> IntoPyObject for Vec<T> where T: IntoPyObject {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use python::{Python, PythonObjectWithCheckedDowncast};
|
||||
use conversion::ToPyObject;
|
||||
use python::{Python, PyDowncastInto};
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
use objects::PyList;
|
||||
|
||||
#[test]
|
||||
|
@ -141,8 +148,8 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec![1,2,3,4];
|
||||
let list = PyList::downcast_from(py, v.to_object(py)).unwrap();
|
||||
assert_eq!(4, list.len(py));
|
||||
let list = PyList::downcast_into(py, v.to_object(py)).unwrap();
|
||||
assert_eq!(4, list.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -150,11 +157,11 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let list = PyList::downcast_from(py, v.to_py_object(py)).unwrap();
|
||||
assert_eq!(2, list.get_item(py, 0).extract::<i32>(py).unwrap());
|
||||
assert_eq!(3, list.get_item(py, 1).extract::<i32>(py).unwrap());
|
||||
assert_eq!(5, list.get_item(py, 2).extract::<i32>(py).unwrap());
|
||||
assert_eq!(7, list.get_item(py, 3).extract::<i32>(py).unwrap());
|
||||
let list = PyList::downcast_into(py, v.to_object(py)).unwrap();
|
||||
assert_eq!(2, list.get_item(0).extract::<i32>().unwrap());
|
||||
assert_eq!(3, list.get_item(1).extract::<i32>().unwrap());
|
||||
assert_eq!(5, list.get_item(2).extract::<i32>().unwrap());
|
||||
assert_eq!(7, list.get_item(3).extract::<i32>().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -162,11 +169,11 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let list = PyList::downcast_from(py, v.to_py_object(py)).unwrap();
|
||||
let val = 42i32.to_py_object(py).into_object();
|
||||
assert_eq!(2, list.get_item(py, 0).extract::<i32>(py).unwrap());
|
||||
list.set_item(py, 0, val);
|
||||
assert_eq!(42, list.get_item(py, 0).extract::<i32>(py).unwrap());
|
||||
let list = PyList::downcast_into(py, v.to_object(py)).unwrap();
|
||||
let val = 42i32.to_object(py).into_object(py);
|
||||
assert_eq!(2, list.get_item(0).extract::<i32>().unwrap());
|
||||
list.set_item(0, val).unwrap();
|
||||
assert_eq!(42, list.get_item(0).extract::<i32>().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -174,14 +181,14 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let list = PyList::downcast_from(py, v.to_py_object(py)).unwrap();
|
||||
let val = 42i32.to_py_object(py).into_object();
|
||||
assert_eq!(4, list.len(py));
|
||||
assert_eq!(2, list.get_item(py, 0).extract::<i32>(py).unwrap());
|
||||
list.insert_item(py, 0, val);
|
||||
assert_eq!(5, list.len(py));
|
||||
assert_eq!(42, list.get_item(py, 0).extract::<i32>(py).unwrap());
|
||||
assert_eq!(2, list.get_item(py, 1).extract::<i32>(py).unwrap());
|
||||
let list = PyList::downcast_into(py, v.to_object(py)).unwrap();
|
||||
let val = 42i32.to_object(py).into_object(py);
|
||||
assert_eq!(4, list.len());
|
||||
assert_eq!(2, list.get_item(0).extract::<i32>().unwrap());
|
||||
list.insert_item(0, val).unwrap();
|
||||
assert_eq!(5, list.len());
|
||||
assert_eq!(42, list.get_item(0).extract::<i32>().unwrap());
|
||||
assert_eq!(2, list.get_item(1).extract::<i32>().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -189,10 +196,10 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let list = PyList::downcast_from(py, v.to_py_object(py)).unwrap();
|
||||
let list = PyList::downcast_into(py, v.to_object(py)).unwrap();
|
||||
let mut idx = 0;
|
||||
for el in list.iter(py) {
|
||||
assert_eq!(v[idx], el.extract::<i32>(py).unwrap());
|
||||
for el in list.iter() {
|
||||
assert_eq!(v[idx], el.extract::<i32>().unwrap());
|
||||
idx += 1;
|
||||
}
|
||||
assert_eq!(idx, v.len());
|
||||
|
@ -203,8 +210,8 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let list = PyList::downcast_from(py, v.to_py_object(py)).unwrap();
|
||||
let v2 = list.into_object().extract::<Vec<i32>>(py).unwrap();
|
||||
let list = PyList::downcast_into(py, v.to_object(py)).unwrap();
|
||||
let v2 = list.into_object(py).into_object(py).extract::<Vec<i32>>().unwrap();
|
||||
assert_eq!(v, v2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,21 +4,21 @@ pub use self::object::PyObject;
|
|||
pub use self::typeobject::PyType;
|
||||
pub use self::module::PyModule;
|
||||
pub use self::string::{PyBytes, PyString, PyStringData};
|
||||
//pub use self::iterator::PyIterator;
|
||||
pub use self::iterator::PyIterator;
|
||||
pub use self::boolobject::PyBool;
|
||||
pub use self::bytearray::PyByteArray;
|
||||
pub use self::tuple::{PyTuple, NoArgs};
|
||||
pub use self::dict::PyDict;
|
||||
//pub use self::list::PyList;
|
||||
pub use self::list::PyList;
|
||||
pub use self::num::{PyLong, PyFloat};
|
||||
//pub use self::sequence::PySequence;
|
||||
pub use self::sequence::PySequence;
|
||||
pub use self::slice::PySlice;
|
||||
//pub use self::set::{PySet, PyFrozenSet};
|
||||
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pyobject_nativetype(
|
||||
($name: ident, $checkfunction: ident, $typeobject: ident) => (
|
||||
($name: ident, $checkfunction: ident, $typeobject: ident) => {
|
||||
|
||||
impl<'p> $crate::typeob::PyTypeInfo for $name<'p> {
|
||||
type Type = ();
|
||||
|
@ -43,6 +43,11 @@ macro_rules! pyobject_nativetype(
|
|||
}
|
||||
}
|
||||
|
||||
pyobject_nativetype!($name, $checkfunction);
|
||||
};
|
||||
|
||||
($name: ident, $checkfunction: ident) => (
|
||||
|
||||
impl<'p> $crate::native::PyBaseObject for $name<'p> {}
|
||||
|
||||
impl<'p> $crate::native::PyNativeObject<'p> for $name<'p> {
|
||||
|
@ -80,22 +85,32 @@ macro_rules! pyobject_nativetype(
|
|||
|
||||
impl<'p> $crate::python::PyDowncastInto<'p> for $name<'p>
|
||||
{
|
||||
fn downcast_into(py: $crate::Python<'p>, ob: $crate::PyObject)
|
||||
-> Result<$name<'p>, $crate::PyDowncastError<'p>>
|
||||
fn downcast_into<I>(py: $crate::Python<'p>, ob: I)
|
||||
-> Result<Self, $crate::PyDowncastError<'p>>
|
||||
where I: $crate::ToPythonPointer + $crate::IntoPythonPointer
|
||||
{
|
||||
match $crate::pptr::cast_from_owned_ptr::<$name>(py, ob.as_ptr()) {
|
||||
Ok(ptr) => {
|
||||
$crate::std::mem::forget(ob);
|
||||
Ok($name(ptr))
|
||||
},
|
||||
Err(e) => Err(e)
|
||||
unsafe{
|
||||
let ptr = ob.into_ptr();
|
||||
if ffi::$checkfunction(ptr) != 0 {
|
||||
Ok($name(pptr::from_owned_ptr(py, ptr)))
|
||||
} else {
|
||||
$crate::ffi::Py_DECREF(ptr);
|
||||
Err($crate::PyDowncastError(py, None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn downcast_from_owned_ptr(py: $crate::Python<'p>, ptr: *mut $crate::ffi::PyObject)
|
||||
-> Result<$name<'p>, $crate::PyDowncastError<'p>>
|
||||
{
|
||||
Ok($name($crate::pptr::cast_from_owned_ptr::<$name>(py, ptr)?))
|
||||
unsafe{
|
||||
if ffi::$checkfunction(ptr) != 0 {
|
||||
Ok($name(pptr::from_owned_ptr(py, ptr)))
|
||||
} else {
|
||||
$crate::ffi::Py_DECREF(ptr);
|
||||
Err($crate::PyDowncastError(py, None))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,8 +139,13 @@ macro_rules! pyobject_nativetype(
|
|||
{
|
||||
use $crate::token::PythonObjectWithGilToken;
|
||||
|
||||
Ok($name(
|
||||
$crate::pptr::cast_from_borrowed_ptr::<$name>(py.gil(), py.as_ptr())?))
|
||||
unsafe {
|
||||
if ffi::$checkfunction(py.as_ptr()) != 0 {
|
||||
Ok( $name($crate::pptr::from_borrowed_ptr(py.gil(), py.as_ptr())) )
|
||||
} else {
|
||||
Err(::PyDowncastError(py.gil(), None).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,13 +242,13 @@ mod typeobject;
|
|||
mod module;
|
||||
mod string;
|
||||
mod dict;
|
||||
//mod iterator;
|
||||
mod iterator;
|
||||
mod boolobject;
|
||||
mod bytearray;
|
||||
mod tuple;
|
||||
//mod list;
|
||||
mod list;
|
||||
mod num;
|
||||
//mod sequence;
|
||||
mod sequence;
|
||||
mod slice;
|
||||
// mod set;
|
||||
mod object;
|
||||
|
|
|
@ -3,26 +3,31 @@
|
|||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
use ffi;
|
||||
use python::{Python, PythonObject, ToPythonPointer, PyDrop};
|
||||
use ppptr::pptr;
|
||||
use python::{ToPythonPointer, PyDowncastFrom, PyDowncastInto};
|
||||
use conversion::{FromPyObject, ToPyObject};
|
||||
use objects::{PyObject, PyList, PyTuple, PyIterator};
|
||||
use objects::{PyObject, PyList, PyTuple};
|
||||
use ffi::Py_ssize_t;
|
||||
use err;
|
||||
use err::{PyErr, PyResult, result_from_owned_ptr, result_cast_from_owned_ptr};
|
||||
use buffer;
|
||||
use err::{PyErr, PyResult};
|
||||
// use buffer;
|
||||
use token::PythonObjectWithGilToken;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
|
||||
/// Represents a reference to a python object supporting the sequence protocol.
|
||||
pub struct PySequence(PyObject);
|
||||
pub struct PySequence<'p>(pptr<'p>);
|
||||
|
||||
pyobject_newtype!(PySequence, PySequence_Check);
|
||||
pyobject_nativetype!(PySequence, PySequence_Check);
|
||||
|
||||
impl PySequence {
|
||||
|
||||
impl<'p> PySequence<'p> {
|
||||
/// Returns the number of objects in sequence. This is equivalent to Python `len()`.
|
||||
#[inline]
|
||||
pub fn len(&self, py: Python) -> PyResult<isize> {
|
||||
pub fn len(&self) -> PyResult<isize> {
|
||||
let v = unsafe { ffi::PySequence_Size(self.0.as_ptr()) };
|
||||
if v == -1 {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.gil()))
|
||||
} else {
|
||||
Ok(v as isize)
|
||||
}
|
||||
|
@ -30,9 +35,11 @@ impl PySequence {
|
|||
|
||||
/// Return the concatenation of o1 and o2. Equivalent to python `o1 + o2`
|
||||
#[inline]
|
||||
pub fn concat(&self, py: Python, other: &PySequence) -> PyResult<PyObject> {
|
||||
pub fn concat(&self, other: &PySequence) -> PyResult<PySequence<'p>> {
|
||||
unsafe {
|
||||
err::result_from_owned_ptr(py, ffi::PySequence_Concat(self.as_ptr(), other.as_ptr()))
|
||||
Ok(PySequence(pptr::from_owned_ptr_or_err(
|
||||
self.gil(),
|
||||
ffi::PySequence_Concat(self.as_ptr(), other.as_ptr()))?))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,17 +47,21 @@ impl PySequence {
|
|||
/// Equivalent to python `o * count`
|
||||
/// NB: Python accepts negative counts; it returns an empty Sequence.
|
||||
#[inline]
|
||||
pub fn repeat(&self, py: Python, count: isize) -> PyResult<PyObject> {
|
||||
pub fn repeat(&self, count: isize) -> PyResult<PySequence<'p>> {
|
||||
unsafe {
|
||||
err::result_from_owned_ptr(py, ffi::PySequence_Repeat(self.as_ptr(), count as Py_ssize_t))
|
||||
Ok(PySequence(pptr::from_owned_ptr_or_err(
|
||||
self.gil(),
|
||||
ffi::PySequence_Repeat(self.as_ptr(), count as Py_ssize_t))?))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the concatenation of o1 and o2 on success. Equivalent to python `o1 += o2`
|
||||
#[inline]
|
||||
pub fn in_place_concat(&self, py: Python, other: &PySequence) -> PyResult<PyObject> {
|
||||
pub fn in_place_concat(&self, other: &PySequence) -> PyResult<PySequence<'p>> {
|
||||
unsafe {
|
||||
result_from_owned_ptr(py, ffi::PySequence_InPlaceConcat(self.as_ptr(), other.as_ptr()))
|
||||
Ok(PySequence(pptr::from_owned_ptr_or_err(
|
||||
self.0.token(),
|
||||
ffi::PySequence_InPlaceConcat(self.0.as_ptr(), other.as_ptr()))?))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,28 +69,30 @@ impl PySequence {
|
|||
/// Equivalent to python `o *= count`
|
||||
/// NB: Python accepts negative counts; it empties the Sequence.
|
||||
#[inline]
|
||||
pub fn in_place_repeat(&self, py: Python, count: isize) -> PyResult<PyObject> {
|
||||
pub fn in_place_repeat(&self, count: isize) -> PyResult<PySequence<'p>> {
|
||||
unsafe {
|
||||
result_from_owned_ptr(py,
|
||||
ffi::PySequence_InPlaceRepeat(self.as_ptr(), count as Py_ssize_t))
|
||||
Ok(PySequence(pptr::from_owned_ptr_or_err(
|
||||
self.0.token(),
|
||||
ffi::PySequence_InPlaceRepeat(self.as_ptr(), count as Py_ssize_t))?))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the ith element of the Sequence. Equivalent to python `o[index]`
|
||||
#[inline]
|
||||
pub fn get_item(&self, py: Python, index: isize) -> PyResult<PyObject> {
|
||||
pub fn get_item(&self, index: isize) -> PyResult<PyObject<'p>> {
|
||||
unsafe {
|
||||
result_from_owned_ptr(py,
|
||||
ffi::PySequence_GetItem(self.as_ptr(), index as Py_ssize_t))
|
||||
PyObject::from_owned_ptr_or_err(
|
||||
self.0.token(), ffi::PySequence_GetItem(self.as_ptr(), index as Py_ssize_t))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the slice of sequence object o between begin and end.
|
||||
/// This is the equivalent of the Python expression `o[begin:end]`
|
||||
#[inline]
|
||||
pub fn get_slice(&self, py: Python, begin : isize, end : isize) -> PyResult<PyObject> {
|
||||
pub fn get_slice(&self, begin: isize, end: isize) -> PyResult<PyObject> {
|
||||
unsafe {
|
||||
result_from_owned_ptr(py,
|
||||
PyObject::from_owned_ptr_or_err(
|
||||
self.0.token(),
|
||||
ffi::PySequence_GetSlice(self.as_ptr(), begin as Py_ssize_t, end as Py_ssize_t))
|
||||
}
|
||||
}
|
||||
|
@ -87,9 +100,9 @@ impl PySequence {
|
|||
/// Assign object v to the ith element of o.
|
||||
/// Equivalent to Python statement `o[i] = v`
|
||||
#[inline]
|
||||
pub fn set_item(&self, py: Python, i: isize, v: &PyObject) -> PyResult<()> {
|
||||
pub fn set_item(&self, i: isize, v: &PyObject) -> PyResult<()> {
|
||||
unsafe {
|
||||
err::error_on_minusone(py,
|
||||
err::error_on_minusone(self.0.token(),
|
||||
ffi::PySequence_SetItem(self.as_ptr(), i as Py_ssize_t, v.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
@ -97,9 +110,9 @@ impl PySequence {
|
|||
/// Delete the ith element of object o.
|
||||
/// Python statement `del o[i]`
|
||||
#[inline]
|
||||
pub fn del_item(&self, py: Python, i: isize) -> PyResult<()> {
|
||||
pub fn del_item(&self, i: isize) -> PyResult<()> {
|
||||
unsafe {
|
||||
err::error_on_minusone(py,
|
||||
err::error_on_minusone(self.0.token(),
|
||||
ffi::PySequence_DelItem(self.as_ptr(), i as Py_ssize_t))
|
||||
}
|
||||
}
|
||||
|
@ -107,19 +120,22 @@ impl PySequence {
|
|||
/// Assign the sequence object v to the slice in sequence object o from i1 to i2.
|
||||
/// This is the equivalent of the Python statement `o[i1:i2] = v`
|
||||
#[inline]
|
||||
pub fn set_slice(&self, py: Python, i1: isize, i2: isize, v: &PyObject) -> PyResult<()> {
|
||||
pub fn set_slice(&self, i1: isize, i2: isize, v: &PyObject) -> PyResult<()> {
|
||||
unsafe {
|
||||
err::error_on_minusone(py,
|
||||
ffi::PySequence_SetSlice(self.as_ptr(), i1 as Py_ssize_t, i2 as Py_ssize_t, v.as_ptr()))
|
||||
err::error_on_minusone(
|
||||
self.0.token(),
|
||||
ffi::PySequence_SetSlice(
|
||||
self.as_ptr(), i1 as Py_ssize_t, i2 as Py_ssize_t, v.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete the slice in sequence object o from i1 to i2.
|
||||
/// equivalent of the Python statement `del o[i1:i2]`
|
||||
#[inline]
|
||||
pub fn del_slice(&self, py: Python, i1: isize, i2: isize) -> PyResult<()> {
|
||||
pub fn del_slice(&self, i1: isize, i2: isize) -> PyResult<()> {
|
||||
unsafe {
|
||||
err::error_on_minusone(py,
|
||||
err::error_on_minusone(
|
||||
self.0.token(),
|
||||
ffi::PySequence_DelSlice(self.as_ptr(), i1 as Py_ssize_t, i2 as Py_ssize_t))
|
||||
}
|
||||
}
|
||||
|
@ -127,14 +143,14 @@ impl PySequence {
|
|||
/// Return the number of occurrences of value in o, that is, return the number of keys for
|
||||
/// which `o[key] == value`
|
||||
#[inline]
|
||||
pub fn count<V>(&self, py: Python, value: V) -> PyResult<usize>
|
||||
pub fn count<V>(&self, value: V) -> PyResult<usize>
|
||||
where V: ToPyObject
|
||||
{
|
||||
let r = value.with_borrowed_ptr(py, |ptr| unsafe {
|
||||
let r = value.with_borrowed_ptr(self.0.token(), |ptr| unsafe {
|
||||
ffi::PySequence_Count(self.as_ptr(), ptr)
|
||||
});
|
||||
if r == -1 {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.gil()))
|
||||
} else {
|
||||
Ok(r as usize)
|
||||
}
|
||||
|
@ -142,30 +158,30 @@ impl PySequence {
|
|||
|
||||
/// Determine if o contains value. this is equivalent to the Python expression `value in o`
|
||||
#[inline]
|
||||
pub fn contains<V>(&self, py: Python, value: V) -> PyResult<bool>
|
||||
pub fn contains<V>(&self, value: V) -> PyResult<bool>
|
||||
where V: ToPyObject
|
||||
{
|
||||
let r = value.with_borrowed_ptr(py, |ptr| unsafe {
|
||||
let r = value.with_borrowed_ptr(self.0.token(), |ptr| unsafe {
|
||||
ffi::PySequence_Contains(self.as_ptr(), ptr)
|
||||
});
|
||||
match r {
|
||||
0 => Ok(false),
|
||||
1 => Ok(true),
|
||||
_ => Err(PyErr::fetch(py))
|
||||
_ => Err(PyErr::fetch(self.gil()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the first index i for which o[i] == value.
|
||||
/// This is equivalent to the Python expression `o.index(value)`
|
||||
#[inline]
|
||||
pub fn index<V>(&self, py: Python, value: V) -> PyResult<usize>
|
||||
pub fn index<V>(&self, value: V) -> PyResult<usize>
|
||||
where V: ToPyObject
|
||||
{
|
||||
let r = value.with_borrowed_ptr(py, |ptr| unsafe {
|
||||
let r = value.with_borrowed_ptr(self.0.token(), |ptr| unsafe {
|
||||
ffi::PySequence_Index(self.as_ptr(), ptr)
|
||||
});
|
||||
if r == -1 {
|
||||
Err(PyErr::fetch(py))
|
||||
Err(PyErr::fetch(self.gil()))
|
||||
} else {
|
||||
Ok(r as usize)
|
||||
}
|
||||
|
@ -173,46 +189,33 @@ impl PySequence {
|
|||
|
||||
/// Return a fresh list based on the Sequence.
|
||||
#[inline]
|
||||
pub fn list(&self, py: Python) -> PyResult<PyList> {
|
||||
pub fn list(&self) -> PyResult<PyList<'p>> {
|
||||
unsafe {
|
||||
result_cast_from_owned_ptr(py, ffi::PySequence_List(self.as_ptr()))
|
||||
Ok(PyList::downcast_from_owned_ptr(
|
||||
self.0.token(), ffi::PySequence_List(self.as_ptr()))?)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a fresh tuple based on the Sequence.
|
||||
#[inline]
|
||||
pub fn tuple(&self, py: Python) -> PyResult<PyTuple> {
|
||||
pub fn tuple(&self) -> PyResult<PyTuple> {
|
||||
unsafe {
|
||||
result_cast_from_owned_ptr(py, ffi::PySequence_Tuple(self.as_ptr()))
|
||||
Ok(PyTuple::downcast_from_owned_ptr(
|
||||
self.0.token(), ffi::PySequence_Tuple(self.as_ptr()))?)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter<'p>(&self, py: Python<'p>) -> PyResult<PyIterator<'p>> {
|
||||
use objectprotocol::ObjectProtocol;
|
||||
self.as_object().iter(py)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature="nightly"))]
|
||||
impl <'source, T> FromPyObject<'source> for Vec<T>
|
||||
|
||||
impl<'source, T> FromPyObject<'source> for Vec<T>
|
||||
where for<'a> T: FromPyObject<'a>
|
||||
{
|
||||
fn extract(py: Python, obj: &'source PyObject) -> PyResult<Self> {
|
||||
extract_sequence(py, obj)
|
||||
default fn extract(obj: &'source PyObject<'source>) -> PyResult<Self> {
|
||||
extract_sequence(obj)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="nightly")]
|
||||
impl <'source, T> FromPyObject<'source> for Vec<T>
|
||||
where for<'a> T: FromPyObject<'a>
|
||||
{
|
||||
default fn extract(py: Python, obj: &'source PyObject) -> PyResult<Self> {
|
||||
extract_sequence(py, obj)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="nightly")]
|
||||
/*#[cfg(feature="nightly")]
|
||||
impl <'source, T> FromPyObject<'source> for Vec<T>
|
||||
where for<'a> T: FromPyObject<'a> + buffer::Element + Copy
|
||||
{
|
||||
|
@ -230,34 +233,33 @@ impl <'source, T> FromPyObject<'source> for Vec<T>
|
|||
// fall back to sequence protocol
|
||||
extract_sequence(py, obj)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
fn extract_sequence<T>(py: Python, obj: &PyObject) -> PyResult<Vec<T>>
|
||||
fn extract_sequence<T>(obj: &PyObject) -> PyResult<Vec<T>>
|
||||
where for<'a> T: FromPyObject<'a>
|
||||
{
|
||||
let seq = try!(obj.cast_as::<PySequence>(py));
|
||||
let seq = PySequence::downcast_from(obj)?;
|
||||
let mut v = Vec::new();
|
||||
for item in try!(seq.iter(py)) {
|
||||
for item in try!(seq.iter()) {
|
||||
let item = try!(item);
|
||||
v.push(try!(T::extract(py, &item)));
|
||||
item.release_ref(py);
|
||||
v.push(try!(T::extract(&item)));
|
||||
}
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std;
|
||||
use python::{Python, PythonObject};
|
||||
use python::{Python, PyDowncastInto};
|
||||
use conversion::ToPyObject;
|
||||
use objects::{PySequence, PyList, PyTuple, PyIterator};
|
||||
use objects::{PySequence};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
#[test]
|
||||
fn test_numbers_are_not_sequences() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = 42i32;
|
||||
assert!(v.to_py_object(py).into_object().cast_into::<PySequence>(py).is_err());
|
||||
assert!(v.to_object(py).into_object(py).cast_into::<PySequence>(py).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -265,18 +267,18 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = "London Calling";
|
||||
assert!(v.to_py_object(py).into_object().cast_into::<PySequence>(py).is_ok());
|
||||
assert!(v.to_object(py).into_object(py).cast_into::<PySequence>(py).is_ok());
|
||||
}
|
||||
#[test]
|
||||
fn test_seq_empty() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![];
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(0, seq.len(py).unwrap());
|
||||
let seq = v.to_object(py).into_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(0, seq.len().unwrap());
|
||||
|
||||
let needle = 7i32.to_py_object(py).into_object();
|
||||
assert_eq!(false, seq.contains(py, &needle).unwrap());
|
||||
let needle = 7i32.to_object(py).into_object(py);
|
||||
assert_eq!(false, seq.contains(&needle).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -284,17 +286,17 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(6, seq.len(py).unwrap());
|
||||
let seq = v.to_object(py).into_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(6, seq.len().unwrap());
|
||||
|
||||
let bad_needle = 7i32.to_py_object(py).into_object();
|
||||
assert_eq!(false, seq.contains(py, &bad_needle).unwrap());
|
||||
let bad_needle = 7i32.to_object(py).into_object(py);
|
||||
assert_eq!(false, seq.contains(&bad_needle).unwrap());
|
||||
|
||||
let good_needle = 8i32.to_py_object(py).into_object();
|
||||
assert_eq!(true, seq.contains(py, &good_needle).unwrap());
|
||||
let good_needle = 8i32.to_object(py).into_object(py);
|
||||
assert_eq!(true, seq.contains(&good_needle).unwrap());
|
||||
|
||||
let type_coerced_needle = 8f32.to_py_object(py).into_object();
|
||||
assert_eq!(true, seq.contains(py, &type_coerced_needle).unwrap());
|
||||
let type_coerced_needle = 8f32.to_object(py).into_object(py);
|
||||
assert_eq!(true, seq.contains(&type_coerced_needle).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -302,19 +304,19 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(1, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(1, seq.get_item(py, 1).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(2, seq.get_item(py, 2).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(3, seq.get_item(py, 3).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(5, seq.get_item(py, 4).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(8, seq.get_item(py, 5).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(8, seq.get_item(py, -1).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(5, seq.get_item(py, -2).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(3, seq.get_item(py, -3).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(2, seq.get_item(py, -4).unwrap().extract::<i32>(py).unwrap());
|
||||
assert_eq!(1, seq.get_item(py, -5).unwrap().extract::<i32>(py).unwrap());
|
||||
assert!(seq.get_item(py, 10).is_err());
|
||||
let seq = v.to_object(py).into_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(1, seq.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(1, seq.get_item(1).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(2, seq.get_item(2).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(3, seq.get_item(3).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(5, seq.get_item(4).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(8, seq.get_item(5).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(8, seq.get_item(-1).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(5, seq.get_item(-2).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(3, seq.get_item(-3).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(2, seq.get_item(-4).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(1, seq.get_item(-5).unwrap().extract::<i32>().unwrap());
|
||||
assert!(seq.get_item(10).is_err());
|
||||
}
|
||||
|
||||
// fn test_get_slice() {}
|
||||
|
@ -326,22 +328,22 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
assert!(seq.del_item(py, 10).is_err());
|
||||
assert_eq!(1, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
|
||||
assert!(seq.del_item(py, 0).is_ok());
|
||||
assert_eq!(1, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
|
||||
assert!(seq.del_item(py, 0).is_ok());
|
||||
assert_eq!(2, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
|
||||
assert!(seq.del_item(py, 0).is_ok());
|
||||
assert_eq!(3, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
|
||||
assert!(seq.del_item(py, 0).is_ok());
|
||||
assert_eq!(5, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
|
||||
assert!(seq.del_item(py, 0).is_ok());
|
||||
assert_eq!(8, seq.get_item(py, 0).unwrap().extract::<i32>(py).unwrap());
|
||||
assert!(seq.del_item(py, 0).is_ok());
|
||||
assert_eq!(0, seq.len(py).unwrap());
|
||||
assert!(seq.del_item(py, 0).is_err());
|
||||
let seq = v.to_object(py).into_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert!(seq.del_item(10).is_err());
|
||||
assert_eq!(1, seq.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert!(seq.del_item(0).is_ok());
|
||||
assert_eq!(1, seq.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert!(seq.del_item(0).is_ok());
|
||||
assert_eq!(2, seq.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert!(seq.del_item(0).is_ok());
|
||||
assert_eq!(3, seq.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert!(seq.del_item(0).is_ok());
|
||||
assert_eq!(5, seq.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert!(seq.del_item(0).is_ok());
|
||||
assert_eq!(8, seq.get_item(0).unwrap().extract::<i32>().unwrap());
|
||||
assert!(seq.del_item(0).is_ok());
|
||||
assert_eq!(0, seq.len().unwrap());
|
||||
assert!(seq.del_item(0).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -349,13 +351,13 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(0, seq.index(py, 1i32).unwrap());
|
||||
assert_eq!(2, seq.index(py, 2i32).unwrap());
|
||||
assert_eq!(3, seq.index(py, 3i32).unwrap());
|
||||
assert_eq!(4, seq.index(py, 5i32).unwrap());
|
||||
assert_eq!(5, seq.index(py, 8i32).unwrap());
|
||||
assert!(seq.index(py, 42i32).is_err());
|
||||
let seq = v.to_object(py).into_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(0, seq.index(1i32).unwrap());
|
||||
assert_eq!(2, seq.index(2i32).unwrap());
|
||||
assert_eq!(3, seq.index(3i32).unwrap());
|
||||
assert_eq!(4, seq.index(5i32).unwrap());
|
||||
assert_eq!(5, seq.index(8i32).unwrap());
|
||||
assert!(seq.index(42i32).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -363,13 +365,13 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(2, seq.count(py, 1i32).unwrap());
|
||||
assert_eq!(1, seq.count(py, 2i32).unwrap());
|
||||
assert_eq!(1, seq.count(py, 3i32).unwrap());
|
||||
assert_eq!(1, seq.count(py, 5i32).unwrap());
|
||||
assert_eq!(1, seq.count(py, 8i32).unwrap());
|
||||
assert_eq!(0, seq.count(py, 42i32).unwrap());
|
||||
let seq = v.to_object(py).into_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(2, seq.count(1i32).unwrap());
|
||||
assert_eq!(1, seq.count(2i32).unwrap());
|
||||
assert_eq!(1, seq.count(3i32).unwrap());
|
||||
assert_eq!(1, seq.count(5i32).unwrap());
|
||||
assert_eq!(1, seq.count(8i32).unwrap());
|
||||
assert_eq!(0, seq.count(42i32).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -377,10 +379,10 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![1, 1, 2, 3, 5, 8];
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
let seq = v.to_object(py).into_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
let mut idx = 0;
|
||||
for el in seq.iter(py).unwrap() {
|
||||
assert_eq!(v[idx], el.unwrap().extract::<i32>(py).unwrap());
|
||||
for el in seq.iter().unwrap() {
|
||||
assert_eq!(v[idx], el.unwrap().extract::<i32>().unwrap());
|
||||
idx += 1;
|
||||
}
|
||||
assert_eq!(idx, v.len());
|
||||
|
@ -391,13 +393,13 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec!["It", "was", "the", "worst", "of", "times"];
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
let seq = v.to_object(py).into_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
|
||||
let bad_needle = "blurst".to_py_object(py);
|
||||
assert_eq!(false, seq.contains(py, bad_needle).unwrap());
|
||||
let bad_needle = "blurst".to_object(py);
|
||||
assert_eq!(false, seq.contains(bad_needle).unwrap());
|
||||
|
||||
let good_needle = "worst".to_py_object(py);
|
||||
assert_eq!(true, seq.contains(py, good_needle).unwrap());
|
||||
let good_needle = "worst".to_object(py);
|
||||
assert_eq!(true, seq.contains(good_needle).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -405,12 +407,12 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v : Vec<i32> = vec![1, 2, 3];
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
let concat_seq = seq.concat(py, &seq).unwrap().cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(6, concat_seq.len(py).unwrap());
|
||||
let seq = v.to_object(py).into_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
let concat_seq = seq.concat(&seq).unwrap();
|
||||
assert_eq!(6, concat_seq.len().unwrap());
|
||||
let concat_v : Vec<i32> = vec![1, 2, 3, 1, 2, 3];
|
||||
for (el, cc) in seq.iter(py).unwrap().zip(concat_v) {
|
||||
assert_eq!(cc, el.unwrap().extract::<i32>(py).unwrap());
|
||||
for (el, cc) in seq.iter().unwrap().zip(concat_v) {
|
||||
assert_eq!(cc, el.unwrap().extract::<i32>().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,9 +421,9 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = "string";
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
let concat_seq = seq.concat(py, &seq).unwrap().cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(12, concat_seq.len(py).unwrap());
|
||||
let seq = v.to_object(py).into_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
let concat_seq = seq.concat(&seq).unwrap();
|
||||
assert_eq!(12, concat_seq.len().unwrap());
|
||||
/*let concat_v = "stringstring".to_owned();
|
||||
for (el, cc) in seq.iter(py).unwrap().zip(concat_v.chars()) {
|
||||
assert_eq!(cc, el.unwrap().extract::<char>(py).unwrap()); //TODO: extract::<char>() is not implemented
|
||||
|
@ -433,12 +435,12 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec!["foo", "bar"];
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
let repeat_seq = seq.repeat(py, 3).unwrap().cast_into::<PySequence>(py).unwrap();
|
||||
assert_eq!(6, repeat_seq.len(py).unwrap());
|
||||
let seq = v.to_object(py).into_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
let repeat_seq = seq.repeat(3).unwrap();
|
||||
assert_eq!(6, repeat_seq.len().unwrap());
|
||||
let repeated = vec!["foo", "bar", "foo", "bar", "foo", "bar"];
|
||||
for (el, rpt) in seq.iter(py).unwrap().zip(repeated.iter()) {
|
||||
assert_eq!(*rpt, el.unwrap().extract::<String>(py).unwrap());
|
||||
for (el, rpt) in seq.iter().unwrap().zip(repeated.iter()) {
|
||||
assert_eq!(*rpt, el.unwrap().extract::<String>().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -447,8 +449,8 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec!["foo", "bar"];
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
assert!(seq.list(py).is_ok());
|
||||
let seq = v.to_object(py).into_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert!(seq.list().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -456,8 +458,8 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = "foo";
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
assert!(seq.list(py).is_ok());
|
||||
let seq = PySequence::downcast_into(py, v.to_object(py)).unwrap();
|
||||
assert!(seq.list().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -465,8 +467,8 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = ("foo", "bar");
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
assert!(seq.tuple(py).is_ok());
|
||||
let seq = v.to_object(py).into_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert!(seq.tuple().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -474,15 +476,15 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = vec!["foo", "bar"];
|
||||
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||
assert!(seq.tuple(py).is_ok());
|
||||
let seq = v.to_object(py).into_object(py).cast_into::<PySequence>(py).unwrap();
|
||||
assert!(seq.tuple().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extract_tuple_to_vec() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v: Vec<i32> = py.eval("(1, 2)", None, None).unwrap().extract(py).unwrap();
|
||||
let v: Vec<i32> = py.eval("(1, 2)", None, None).unwrap().extract().unwrap();
|
||||
assert!(v == [1, 2]);
|
||||
}
|
||||
|
||||
|
@ -490,7 +492,7 @@ mod test {
|
|||
fn test_extract_range_to_vec() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v: Vec<i32> = py.eval("range(1, 5)", None, None).unwrap().extract(py).unwrap();
|
||||
let v: Vec<i32> = py.eval("range(1, 5)", None, None).unwrap().extract().unwrap();
|
||||
assert!(v == [1, 2, 3, 4]);
|
||||
}
|
||||
|
||||
|
@ -498,7 +500,7 @@ mod test {
|
|||
fn test_extract_bytearray_to_vec() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v: Vec<u8> = py.eval("bytearray(b'abc')", None, None).unwrap().extract(py).unwrap();
|
||||
let v: Vec<u8> = py.eval("bytearray(b'abc')", None, None).unwrap().extract().unwrap();
|
||||
assert!(v == b"abc");
|
||||
}
|
||||
}
|
||||
|
|
13
src/ppptr.rs
13
src/ppptr.rs
|
@ -4,7 +4,7 @@ use std;
|
|||
|
||||
use ffi;
|
||||
use err::{PyErr, PyResult};
|
||||
use python::{Python, PyDowncastInto, ToPythonPointer};
|
||||
use python::{Python, PyDowncastInto, ToPythonPointer, IntoPythonPointer};
|
||||
use typeob::{PyTypeInfo, PyObjectAlloc};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
|
@ -167,6 +167,17 @@ impl<'p> ToPythonPointer for pptr<'p> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'p> IntoPythonPointer for pptr<'p> {
|
||||
/// Gets the underlying FFI pointer, returns a owned pointer.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
fn into_ptr(self) -> *mut ffi::PyObject {
|
||||
let ptr = self.1;
|
||||
std::mem::forget(self);
|
||||
ptr
|
||||
}
|
||||
}
|
||||
|
||||
/// Dropping a `pptr` instance decrements the reference count on the object by 1.
|
||||
impl<'p> Drop for pptr<'p> {
|
||||
|
||||
|
|
|
@ -43,7 +43,9 @@ pub trait PyDowncastFrom<'p> : Sized {
|
|||
pub trait PyDowncastInto<'p> : Sized {
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn downcast_into(Python<'p>, PyObject) -> Result<Self, PyDowncastError<'p>>;
|
||||
fn downcast_into<I>(Python<'p>, I)
|
||||
-> Result<Self, PyDowncastError<'p>>
|
||||
where I: ToPythonPointer + IntoPythonPointer;
|
||||
|
||||
/// Cast from ffi::PyObject to a concrete Python object type.
|
||||
fn downcast_from_owned_ptr(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
|
|
|
@ -55,7 +55,7 @@ fn empty_class() {
|
|||
#[py::class]
|
||||
struct EmptyClassInModule { }
|
||||
|
||||
//#[test]
|
||||
#[test]
|
||||
fn empty_class_in_module() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
@ -153,7 +153,7 @@ struct DataIsDropped {
|
|||
token: PythonToken<DataIsDropped>,
|
||||
}
|
||||
|
||||
//#[test]
|
||||
#[test]
|
||||
fn data_is_dropped() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
|
Loading…
Reference in New Issue