serde_pyobject/
pylit.rs

1/// Create [`pyo3::types::PyDict`] from a list of key-value pairs.
2///
3/// Examples
4/// ---------
5///
6/// - When you have GIL marker `py`, you can pass it and get a Bound pointer `PyResult<Bound<PyDict>>`:
7///
8/// ```
9/// use pyo3::{Python, Bound, types::{PyDict, PyDictMethods, PyAnyMethods}};
10/// use serde_pyobject::pydict;
11///
12/// Python::attach(|py| {
13///     let dict: Bound<PyDict> = pydict! {
14///         py,
15///         "foo" => 42,
16///         "bar" => "baz"
17///     }
18///     .unwrap();
19///
20///     assert_eq!(
21///         dict.get_item("foo")
22///             .unwrap()
23///             .unwrap()
24///             .extract::<i32>()
25///             .unwrap(),
26///         42
27///     );
28///     assert_eq!(
29///         dict.get_item("bar")
30///             .unwrap()
31///             .unwrap()
32///             .extract::<String>()
33///             .unwrap(),
34///         "baz",
35///     );
36/// })
37/// ```
38///
39/// - When you don't have GIL marker, you get a `PyResult<Py<PyDict>>`:
40///
41/// ```
42/// use pyo3::{Python, Py, types::{PyDict, PyDictMethods, PyAnyMethods}};
43/// use serde_pyobject::pydict;
44///
45/// let dict: Py<PyDict> = pydict! {
46///     "foo" => 42,
47///     "bar" => "baz"
48/// }
49/// .unwrap();
50///
51/// Python::attach(|py| {
52///     let dict = dict.into_bound(py);
53///     assert_eq!(
54///         dict.get_item("foo")
55///             .unwrap()
56///             .unwrap()
57///             .extract::<i32>()
58///             .unwrap(),
59///         42
60///     );
61///     assert_eq!(
62///         dict.get_item("bar")
63///             .unwrap()
64///             .unwrap()
65///             .extract::<String>()
66///             .unwrap(),
67///         "baz",
68///     );
69/// })
70/// ```
71///
72#[macro_export]
73macro_rules! pydict {
74    ($py:expr, $($key:expr => $value:expr),*) => {
75        (|| -> $crate::pyo3::PyResult<$crate::pyo3::Bound<$crate::pyo3::types::PyDict>> {
76            use $crate::pyo3::types::PyDictMethods;
77            let dict = $crate::pyo3::types::PyDict::new($py);
78            $(dict.set_item($key, $value)?;)*
79            Ok(dict)
80        })()
81    };
82    ($($key:expr => $value:expr),*) => {
83        $crate::pyo3::Python::attach(|py| -> $crate::pyo3::PyResult<$crate::pyo3::Py<$crate::pyo3::types::PyDict>> {
84            let dict = pydict!(py, $($key => $value),*)?;
85            Ok(dict.into())
86        })
87    };
88}
89
90/// Create [`pyo3::types::PyList`] from a list of values.
91///
92/// Examples
93/// --------
94///
95/// - When you have GIL marker `py`, you can pass it and get a reference `PyResult<&PyList>`:
96///
97/// ```
98/// use pyo3::{Python, types::{PyList, PyListMethods, PyAnyMethods}};
99/// use serde_pyobject::pylist;
100///
101/// Python::attach(|py| {
102///     let list = pylist![py; 1, "two"].unwrap();
103///     assert_eq!(list.len(), 2);
104///     assert_eq!(list.get_item(0).unwrap().extract::<i32>().unwrap(), 1);
105///     assert_eq!(list.get_item(1).unwrap().extract::<String>().unwrap(), "two");
106/// })
107/// ```
108///
109/// - When you don't have GIL marker, you get a `PyResult<Py<PyList>>`:
110///
111/// ```
112/// use pyo3::{Python, Py, types::{PyList, PyListMethods, PyAnyMethods}};
113/// use serde_pyobject::pylist;
114///
115/// let list: Py<PyList> = pylist![1, "two"].unwrap();
116///
117/// Python::attach(|py| {
118///    let list = list.into_bound(py);
119///    assert_eq!(list.len(), 2);
120///    assert_eq!(list.get_item(0).unwrap().extract::<i32>().unwrap(), 1);
121///    assert_eq!(list.get_item(1).unwrap().extract::<String>().unwrap(), "two");
122/// });
123/// ```
124///
125#[macro_export]
126macro_rules! pylist {
127    ($py:expr; $($value:expr),*) => {
128        (|| -> $crate::pyo3::PyResult<$crate::pyo3::Bound<$crate::pyo3::types::PyList>> {
129            use $crate::pyo3::types::PyListMethods;
130            let list = $crate::pyo3::types::PyList::empty($py);
131            $(list.append($value)?;)*
132            Ok(list)
133        })()
134    };
135    ($($value:expr),*) => {
136        $crate::pyo3::Python::attach(|py| -> $crate::pyo3::PyResult<$crate::pyo3::Py<$crate::pyo3::types::PyList>> {
137            let list = pylist!(py; $($value),*)?;
138            Ok(list.into())
139        })
140    };
141}