Skip to content

Commit

Permalink
Implement *Py* traits for arrays (up to 32)
Browse files Browse the repository at this point in the history
  • Loading branch information
c410-f3r committed Feb 29, 2020
1 parent 90b14fb commit 4d5241d
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 30 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

### Changed

* Implement `FromPyObject` and `IntoPy<PyObject>` traits for arrays (up to 32). [#683](https://github.com/PyO3/pyo3/pull/778)
* `#[new]` does not take `PyRawObject` and can return `Self`. [#683](https://github.com/PyO3/pyo3/pull/683)
* The blanket implementations for `FromPyObject` for `&T` and `&mut T` are no longer specializable. Implement `PyTryFrom` for your type to control the behavior of `FromPyObject::extract()` for your types. [#713](https://github.com/PyO3/pyo3/pull/713)
* The implementation for `IntoPy<U> for T` where `U: FromPy<T>` is no longer specializable. Control the behavior of this via the implementation of `FromPy`. [#713](https://github.com/PyO3/pyo3/pull/713)
Expand Down
58 changes: 47 additions & 11 deletions src/types/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,33 @@ where
}
}

macro_rules! array_impls {
($($N:expr),+) => {
$(
impl<T> IntoPy<PyObject> for [T; $N]
where
T: Copy + IntoPy<PyObject>,
{
fn into_py(self, py: Python) -> PyObject {
unsafe {
let ptr = ffi::PyList_New(self.len() as Py_ssize_t);
for (i, e) in self.iter().copied().enumerate() {
let obj = e.into_py(py).into_ptr();
ffi::PyList_SetItem(ptr, i as Py_ssize_t, obj);
}
PyObject::from_owned_ptr_or_panic(py, ptr)
}
}
}
)+
}
}

array_impls!(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32
);

impl<T> ToPyObject for Vec<T>
where
T: ToPyObject,
Expand Down Expand Up @@ -205,6 +232,9 @@ where

#[cfg(test)]
mod test {
macro_rules! create_tests {
($module:ident $($vec:tt$mark:tt)?) => {
mod $module {
use crate::instance::AsPyRef;
use crate::objectprotocol::ObjectProtocol;
use crate::types::PyList;
Expand All @@ -215,7 +245,7 @@ mod test {
fn test_new() {
let gil = Python::acquire_gil();
let py = gil.python();
let v = vec![2, 3, 5, 7];
let v = $($vec$mark)?[2, 3, 5, 7];
let list = PyList::new(py, &v);
assert_eq!(2, list.get_item(0).extract::<i32>().unwrap());
assert_eq!(3, list.get_item(1).extract::<i32>().unwrap());
Expand All @@ -227,7 +257,7 @@ mod test {
fn test_len() {
let gil = Python::acquire_gil();
let py = gil.python();
let v = vec![1, 2, 3, 4];
let v = $($vec$mark)?[1, 2, 3, 4];
let ob = v.to_object(py);
let list = <PyList as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
assert_eq!(4, list.len());
Expand All @@ -237,7 +267,7 @@ mod test {
fn test_get_item() {
let gil = Python::acquire_gil();
let py = gil.python();
let v = vec![2, 3, 5, 7];
let v = $($vec$mark)?[2, 3, 5, 7];
let ob = v.to_object(py);
let list = <PyList as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
assert_eq!(2, list.get_item(0).extract::<i32>().unwrap());
Expand All @@ -250,7 +280,7 @@ mod test {
fn test_get_parked_item() {
let gil = Python::acquire_gil();
let py = gil.python();
let v = vec![2, 3, 5, 7];
let v = $($vec$mark)?[2, 3, 5, 7];
let ob = v.to_object(py);
let list = <PyList as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
assert_eq!(2, list.get_parked_item(0).extract::<i32>(py).unwrap());
Expand All @@ -263,7 +293,7 @@ mod test {
fn test_set_item() {
let gil = Python::acquire_gil();
let py = gil.python();
let v = vec![2, 3, 5, 7];
let v = $($vec$mark)?[2, 3, 5, 7];
let ob = v.to_object(py);
let list = <PyList as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
let val = 42i32.to_object(py);
Expand All @@ -280,7 +310,7 @@ mod test {
let cnt;
{
let _pool = crate::GILPool::new(py);
let v = vec![2];
let v = $($vec$mark)?[2];
let ob = v.to_object(py);
let list = <PyList as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
let none = py.None();
Expand All @@ -295,7 +325,7 @@ mod test {
fn test_insert() {
let gil = Python::acquire_gil();
let py = gil.python();
let v = vec![2, 3, 5, 7];
let v = $($vec$mark)?[2, 3, 5, 7];
let ob = v.to_object(py);
let list = <PyList as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
let val = 42i32.to_object(py);
Expand Down Expand Up @@ -356,7 +386,7 @@ mod test {
fn test_iter() {
let gil = Python::acquire_gil();
let py = gil.python();
let v = vec![2, 3, 5, 7];
let v = $($vec$mark)?[2, 3, 5, 7];
let ob = v.to_object(py);
let list = <PyList as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
let mut idx = 0;
Expand All @@ -371,7 +401,7 @@ mod test {
fn test_into_iter() {
let gil = Python::acquire_gil();
let py = gil.python();
let v = vec![1, 2, 3, 4];
let v = $($vec$mark)?[1, 2, 3, 4];
let ob = v.to_object(py);
let list = <PyList as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
for (i, item) in list.iter().enumerate() {
Expand All @@ -394,7 +424,7 @@ mod test {
fn test_sort() {
let gil = Python::acquire_gil();
let py = gil.python();
let v = vec![7, 3, 2, 5];
let v = $($vec$mark)?[7, 3, 2, 5];
let list = PyList::new(py, &v);
assert_eq!(7, list.get_item(0).extract::<i32>().unwrap());
assert_eq!(3, list.get_item(1).extract::<i32>().unwrap());
Expand All @@ -411,7 +441,7 @@ mod test {
fn test_reverse() {
let gil = Python::acquire_gil();
let py = gil.python();
let v = vec![2, 3, 5, 7];
let v = $($vec$mark)?[2, 3, 5, 7];
let list = PyList::new(py, &v);
assert_eq!(2, list.get_item(0).extract::<i32>().unwrap());
assert_eq!(3, list.get_item(1).extract::<i32>().unwrap());
Expand All @@ -423,4 +453,10 @@ mod test {
assert_eq!(3, list.get_item(2).extract::<i32>().unwrap());
assert_eq!(2, list.get_item(3).extract::<i32>().unwrap());
}
}
};
}

create_tests!(array);
create_tests!(vec vec!);
}
Loading

0 comments on commit 4d5241d

Please sign in to comment.