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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#[macro_export]
macro_rules! pydict {
    ($py:expr, $($key:expr => $value:expr),*) => {
        (|| -> $crate::pyo3::PyResult<& $crate::pyo3::types::PyDict> {
            let dict = $crate::pyo3::types::PyDict::new($py);
            $(dict.set_item($key, $value)?;)*
            Ok(dict)
        })()
    };
    ($($key:expr => $value:expr),*) => {
        $crate::pyo3::Python::with_gil(|py| -> $crate::pyo3::PyResult<$crate::pyo3::Py<$crate::pyo3::types::PyDict>> {
            let dict = pydict!(py, $($key => $value),*)?;
            Ok(dict.into())
        })
    };
}

#[macro_export]
macro_rules! pylist {
    ($py:expr, $($value:expr),*) => {
        (|| -> $crate::pyo3::PyResult<& $crate::pyo3::types::PyList> {
            let list = $crate::pyo3::types::PyList::new($py, vec![ $($value),* ]);
            Ok(list)
        })()
    };
    ($($value:expr),*) => {
        $crate::pyo3::Python::with_gil(|py| -> $crate::pyo3::PyResult<$crate::pyo3::Py<$crate::pyo3::types::PyList>> {
            let list = pylist!(py, $($value),*)?;
            Ok(list.into())
        })
    };
}

#[cfg(test)]
mod test {
    use pyo3::prelude::*;

    #[test]
    fn create_pylist() {
        Python::with_gil(|py| {
            let list = pylist![py, 1, 2, 3].unwrap();
            assert_eq!(list.len(), 3);
            assert_eq!(list.get_item(0).unwrap().extract::<i32>().unwrap(), 1);
            assert_eq!(list.get_item(1).unwrap().extract::<i32>().unwrap(), 2);
            assert_eq!(list.get_item(2).unwrap().extract::<i32>().unwrap(), 3);
        })
    }

    #[test]
    fn create_pydict() {
        Python::with_gil(|py| {
            let dict = pydict! {
                py,
                "foo" => 42,
                "bar" => "baz"
            }
            .unwrap();

            assert_eq!(
                dict.get_item("foo")
                    .unwrap()
                    .unwrap()
                    .extract::<i32>()
                    .unwrap(),
                42
            );
            assert_eq!(
                dict.get_item("bar")
                    .unwrap()
                    .unwrap()
                    .extract::<String>()
                    .unwrap(),
                "baz",
            );
        })
    }
}