Introduce PyDictItem

This commit is contained in:
kngwyu 2019-02-18 16:05:48 +09:00
parent f248aaddbe
commit 8d9b4dd153
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 py = gil.python();
/// 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();
/// ```
#[derive(Debug)]

View File

@ -196,12 +196,7 @@ where
H: hash::BuildHasher,
{
fn to_object(&self, py: Python) -> PyObject {
let dict = PyDict::new(py);
for (key, value) in self {
dict.set_item(key, value)
.expect("Failed to set_item on dict");
}
dict.into()
IntoPyDict::into_py_dict(self, py).into()
}
}
@ -211,12 +206,7 @@ where
V: ToPyObject,
{
fn to_object(&self, py: Python) -> PyObject {
let dict = PyDict::new(py);
for (key, value) in self {
dict.set_item(key, value)
.expect("Failed to set_item on dict");
}
dict.into()
IntoPyDict::into_py_dict(self, py).into()
}
}
@ -227,27 +217,23 @@ where
H: hash::BuildHasher,
{
fn into_object(self, py: Python) -> PyObject {
let dict = PyDict::new(py);
for (key, value) in self {
dict.set_item(key.into_object(py), value.into_object(py))
.expect("Failed to set_item on dict");
}
dict.into()
let iter = self
.into_iter()
.map(|(k, v)| (k.into_object(py), v.into_object(py)));
IntoPyDict::into_py_dict(iter, py).into()
}
}
impl<K, V> IntoPyObject for collections::BTreeMap<K, V>
where
K: cmp::Eq + ToPyObject,
V: ToPyObject,
K: cmp::Eq + IntoPyObject,
V: IntoPyObject,
{
fn into_object(self, py: Python) -> PyObject {
let dict = PyDict::new(py);
for (key, value) in self {
dict.set_item(key, value)
.expect("Failed to set_item on dict");
}
dict.into()
let iter = self
.into_iter()
.map(|(k, v)| (k.into_object(py), v.into_object(py)));
IntoPyDict::into_py_dict(iter, py).into()
}
}
@ -259,22 +245,59 @@ pub trait IntoPyDict {
fn into_py_dict(self, py: Python) -> &PyDict;
}
impl<K, V, I> IntoPyDict for I
impl<T, I> IntoPyDict for I
where
K: ToPyObject,
V: ToPyObject,
I: IntoIterator<Item = (K, V)>,
T: PyDictItem,
I: IntoIterator<Item = T>,
{
fn into_py_dict(self, py: Python) -> &PyDict {
let dict = PyDict::new(py);
for (key, value) in self {
dict.set_item(key, value)
for item in self {
dict.set_item(item.key(), item.value())
.expect("Failed to set_item on 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)]
mod test {
use crate::conversion::{IntoPyObject, PyTryFrom, ToPyObject};
@ -637,4 +660,16 @@ mod test {
assert_eq!(py_map.len(), 3);
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);
}
}