Fix #19: allow extracting a Vec from anything implementing the sequence protocol, not just from list.

This commit is contained in:
Daniel Grunwald 2017-01-20 01:08:12 +01:00
parent fbe1a07d10
commit a48d74c62c
2 changed files with 35 additions and 20 deletions

View file

@ -143,22 +143,6 @@ impl <T> ToPyObject for Vec<T> where T: ToPyObject {
}
}
impl <'source, T> FromPyObject<'source> for Vec<T>
where for<'a> T: FromPyObject<'a>
{
fn extract(py: Python, obj: &'source PyObject) -> PyResult<Self> {
let list = try!(obj.cast_as::<PyList>(py));
let len = list.len(py);
let mut v = Vec::with_capacity(len);
for i in 0 .. len {
let item = list.get_item(py, i);
v.push(try!(T::extract(py, &item)));
item.release_ref(py);
}
Ok(v)
}
}
#[cfg(test)]
mod test {
use python::{Python, PythonObject};

View file

@ -18,8 +18,8 @@
use std::mem;
use ffi;
use python::{Python, PythonObject, ToPythonPointer, PyClone};
use conversion::ToPyObject;
use python::{Python, PythonObject, ToPythonPointer, PyClone, PyDrop};
use conversion::{FromPyObject, ToPyObject};
use objects::{PyObject, PyList, PyTuple, PyIterator};
use ffi::Py_ssize_t;
use err;
@ -208,6 +208,21 @@ impl PySequence {
}
}
impl <'source, T> FromPyObject<'source> for Vec<T>
where for<'a> T: FromPyObject<'a>
{
fn extract(py: Python, obj: &'source PyObject) -> PyResult<Self> {
let seq = try!(obj.cast_as::<PySequence>(py));
let mut v = Vec::new();
for item in try!(seq.iter(py)) {
let item = try!(item);
v.push(try!(T::extract(py, &item)));
item.release_ref(py);
}
Ok(v)
}
}
#[cfg(test)]
mod test {
use std;
@ -386,8 +401,8 @@ mod test {
let concat_seq = seq.concat(py, &seq).unwrap().cast_into::<PySequence>(py).unwrap();
assert_eq!(12, concat_seq.len(py).unwrap());
/*let concat_v = "stringstring".to_owned();
for (el, cc) in seq.into_iter(py).zip(concat_v.chars()) {
assert_eq!(cc, el.extract::<char>(py).unwrap()); TODO: extract::<char>() is not implemented
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
}*/
}
@ -440,4 +455,20 @@ mod test {
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
assert!(seq.tuple(py).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();
assert!(v == [1, 2]);
}
#[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();
assert!(v == [1, 2, 3, 4]);
}
}