Merge pull request #361 from kngwyu/pydictitem

Introduce PyDictItem
This commit is contained in:
konstin 2019-02-18 20:13:32 +01:00 committed by GitHub
commit 625093ce5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 33 deletions

View File

@ -53,7 +53,7 @@ pub trait PyNativeType: PyObjectWithGIL {}
/// let gil = Python::acquire_gil(); /// let gil = Python::acquire_gil();
/// let py = gil.python(); /// let py = gil.python();
/// let obj = PyRef::new(gil.python(), Point { x: 3, y: 4 }).unwrap(); /// let obj = PyRef::new(gil.python(), Point { x: 3, y: 4 }).unwrap();
/// let d = vec![("p", obj)].into_py_dict(py); /// let d = [("p", obj)].into_py_dict(py);
/// py.run("assert p.length() == 12", None, Some(d)).unwrap(); /// py.run("assert p.length() == 12", None, Some(d)).unwrap();
/// ``` /// ```
#[derive(Debug)] #[derive(Debug)]

View File

@ -196,12 +196,7 @@ where
H: hash::BuildHasher, H: hash::BuildHasher,
{ {
fn to_object(&self, py: Python) -> PyObject { fn to_object(&self, py: Python) -> PyObject {
let dict = PyDict::new(py); IntoPyDict::into_py_dict(self, py).into()
for (key, value) in self {
dict.set_item(key, value)
.expect("Failed to set_item on dict");
}
dict.into()
} }
} }
@ -211,12 +206,7 @@ where
V: ToPyObject, V: ToPyObject,
{ {
fn to_object(&self, py: Python) -> PyObject { fn to_object(&self, py: Python) -> PyObject {
let dict = PyDict::new(py); IntoPyDict::into_py_dict(self, py).into()
for (key, value) in self {
dict.set_item(key, value)
.expect("Failed to set_item on dict");
}
dict.into()
} }
} }
@ -227,27 +217,23 @@ where
H: hash::BuildHasher, H: hash::BuildHasher,
{ {
fn into_object(self, py: Python) -> PyObject { fn into_object(self, py: Python) -> PyObject {
let dict = PyDict::new(py); let iter = self
for (key, value) in self { .into_iter()
dict.set_item(key.into_object(py), value.into_object(py)) .map(|(k, v)| (k.into_object(py), v.into_object(py)));
.expect("Failed to set_item on dict"); IntoPyDict::into_py_dict(iter, py).into()
}
dict.into()
} }
} }
impl<K, V> IntoPyObject for collections::BTreeMap<K, V> impl<K, V> IntoPyObject for collections::BTreeMap<K, V>
where where
K: cmp::Eq + ToPyObject, K: cmp::Eq + IntoPyObject,
V: ToPyObject, V: IntoPyObject,
{ {
fn into_object(self, py: Python) -> PyObject { fn into_object(self, py: Python) -> PyObject {
let dict = PyDict::new(py); let iter = self
for (key, value) in self { .into_iter()
dict.set_item(key, value) .map(|(k, v)| (k.into_object(py), v.into_object(py)));
.expect("Failed to set_item on dict"); IntoPyDict::into_py_dict(iter, py).into()
}
dict.into()
} }
} }
@ -259,22 +245,59 @@ pub trait IntoPyDict {
fn into_py_dict(self, py: Python) -> &PyDict; fn into_py_dict(self, py: Python) -> &PyDict;
} }
impl<K, V, I> IntoPyDict for I impl<T, I> IntoPyDict for I
where where
K: ToPyObject, T: PyDictItem,
V: ToPyObject, I: IntoIterator<Item = T>,
I: IntoIterator<Item = (K, V)>,
{ {
fn into_py_dict(self, py: Python) -> &PyDict { fn into_py_dict(self, py: Python) -> &PyDict {
let dict = PyDict::new(py); let dict = PyDict::new(py);
for (key, value) in self { for item in self {
dict.set_item(key, value) dict.set_item(item.key(), item.value())
.expect("Failed to set_item on dict"); .expect("Failed to set_item on dict");
} }
dict dict
} }
} }
/// Represents a tuple which can be used as a PyDict item.
pub trait PyDictItem {
type K: ToPyObject;
type V: ToPyObject;
fn key(&self) -> &Self::K;
fn value(&self) -> &Self::V;
}
impl<K, V> PyDictItem for (K, V)
where
K: ToPyObject,
V: ToPyObject,
{
type K = K;
type V = V;
fn key(&self) -> &Self::K {
&self.0
}
fn value(&self) -> &Self::V {
&self.1
}
}
impl<K, V> PyDictItem for &(K, V)
where
K: ToPyObject,
V: ToPyObject,
{
type K = K;
type V = V;
fn key(&self) -> &Self::K {
&self.0
}
fn value(&self) -> &Self::V {
&self.1
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::conversion::{IntoPyObject, PyTryFrom, ToPyObject}; use crate::conversion::{IntoPyObject, PyTryFrom, ToPyObject};
@ -637,4 +660,16 @@ mod test {
assert_eq!(py_map.len(), 3); assert_eq!(py_map.len(), 3);
assert_eq!(py_map.get_item("b").unwrap().extract::<i32>().unwrap(), 2); assert_eq!(py_map.get_item("b").unwrap().extract::<i32>().unwrap(), 2);
} }
#[test]
fn test_slice_into_dict() {
let gil = Python::acquire_gil();
let py = gil.python();
let arr = [("a", 1), ("b", 2), ("c", 3)];
let py_map = arr.into_py_dict(py);
assert_eq!(py_map.len(), 3);
assert_eq!(py_map.get_item("b").unwrap().extract::<i32>().unwrap(), 2);
}
} }