Fix #19: allow extracting a Vec from anything implementing the sequence protocol, not just from list
.
This commit is contained in:
parent
fbe1a07d10
commit
a48d74c62c
|
@ -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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use python::{Python, PythonObject};
|
use python::{Python, PythonObject};
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use ffi;
|
use ffi;
|
||||||
use python::{Python, PythonObject, ToPythonPointer, PyClone};
|
use python::{Python, PythonObject, ToPythonPointer, PyClone, PyDrop};
|
||||||
use conversion::ToPyObject;
|
use conversion::{FromPyObject, ToPyObject};
|
||||||
use objects::{PyObject, PyList, PyTuple, PyIterator};
|
use objects::{PyObject, PyList, PyTuple, PyIterator};
|
||||||
use ffi::Py_ssize_t;
|
use ffi::Py_ssize_t;
|
||||||
use err;
|
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)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std;
|
use std;
|
||||||
|
@ -386,8 +401,8 @@ mod test {
|
||||||
let concat_seq = seq.concat(py, &seq).unwrap().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());
|
assert_eq!(12, concat_seq.len(py).unwrap());
|
||||||
/*let concat_v = "stringstring".to_owned();
|
/*let concat_v = "stringstring".to_owned();
|
||||||
for (el, cc) in seq.into_iter(py).zip(concat_v.chars()) {
|
for (el, cc) in seq.iter(py).unwrap().zip(concat_v.chars()) {
|
||||||
assert_eq!(cc, el.extract::<char>(py).unwrap()); TODO: extract::<char>() is not implemented
|
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();
|
let seq = v.to_py_object(py).into_object().cast_into::<PySequence>(py).unwrap();
|
||||||
assert!(seq.tuple(py).is_ok());
|
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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue