Skip to content

Commit f840ea7

Browse files
committed
Add tests for integration with serde_path_to_err crate
1 parent 94c7091 commit f840ea7

2 files changed

Lines changed: 208 additions & 0 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ serde = { version = "1.0", default-features = false, features = ["derive"] }
2020
pyo3 = { version = "0.20.0", default-features = false, features = ["auto-initialize", "macros"] }
2121
serde_json = "1.0"
2222
maplit = "1.0.2"
23+
serde_path_to_error = "0.1.15"
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
use std::collections::BTreeMap;
2+
3+
use pyo3::{
4+
types::{PyDict, PyList},
5+
Py, PyAny, Python,
6+
};
7+
use pythonize::PythonizeTypes;
8+
use serde::{Deserialize, Serialize};
9+
10+
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
11+
struct Root<T> {
12+
root_key: String,
13+
root_map: BTreeMap<String, Nested<T>>,
14+
}
15+
16+
impl<T> PythonizeTypes for Root<T> {
17+
type Map = PyDict;
18+
type List = PyList;
19+
}
20+
21+
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
22+
struct Nested<T> {
23+
nested_key: T,
24+
}
25+
26+
#[derive(Deserialize, Debug, PartialEq, Eq)]
27+
struct CannotSerialize {}
28+
29+
impl Serialize for CannotSerialize {
30+
fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
31+
where
32+
S: serde::Serializer,
33+
{
34+
Err(serde::ser::Error::custom(
35+
"something went intentionally wrong",
36+
))
37+
}
38+
}
39+
40+
#[test]
41+
fn test_de_valid() {
42+
Python::with_gil(|py| {
43+
let pyroot = PyDict::new(py);
44+
pyroot.set_item("root_key", "root_value").unwrap();
45+
46+
let nested = PyDict::new(py);
47+
let nested_0 = PyDict::new(py);
48+
nested_0.set_item("nested_key", "nested_value_0").unwrap();
49+
nested.set_item("nested_0", nested_0).unwrap();
50+
let nested_1 = PyDict::new(py);
51+
nested_1.set_item("nested_key", "nested_value_1").unwrap();
52+
nested.set_item("nested_1", nested_1).unwrap();
53+
54+
pyroot.set_item("root_map", nested).unwrap();
55+
56+
let de = &mut pythonize::Depythonizer::from_object(pyroot);
57+
let root: Root<String> = serde_path_to_error::deserialize(de).unwrap();
58+
59+
assert_eq!(
60+
root,
61+
Root {
62+
root_key: String::from("root_value"),
63+
root_map: BTreeMap::from([
64+
(
65+
String::from("nested_0"),
66+
Nested {
67+
nested_key: String::from("nested_value_0")
68+
}
69+
),
70+
(
71+
String::from("nested_1"),
72+
Nested {
73+
nested_key: String::from("nested_value_1")
74+
}
75+
)
76+
])
77+
}
78+
);
79+
})
80+
}
81+
82+
#[test]
83+
fn test_de_invalid() {
84+
Python::with_gil(|py| {
85+
let pyroot = PyDict::new(py);
86+
pyroot.set_item("root_key", "root_value").unwrap();
87+
88+
let nested = PyDict::new(py);
89+
let nested_0 = PyDict::new(py);
90+
nested_0.set_item("nested_key", "nested_value_0").unwrap();
91+
nested.set_item("nested_0", nested_0).unwrap();
92+
let nested_1 = PyDict::new(py);
93+
nested_1.set_item("nested_key", 1).unwrap();
94+
nested.set_item("nested_1", nested_1).unwrap();
95+
96+
pyroot.set_item("root_map", nested).unwrap();
97+
98+
let de = &mut pythonize::Depythonizer::from_object(pyroot);
99+
let err = serde_path_to_error::deserialize::<_, Root<String>>(de).unwrap_err();
100+
101+
assert_eq!(err.path().to_string(), "root_map.nested_1.nested_key");
102+
assert_eq!(err.to_string(), "root_map.nested_1.nested_key: unexpected type: 'int' object cannot be converted to 'PyString'");
103+
})
104+
}
105+
106+
#[test]
107+
fn test_ser_valid() {
108+
Python::with_gil(|py| {
109+
let root = Root {
110+
root_key: String::from("root_value"),
111+
root_map: BTreeMap::from([
112+
(
113+
String::from("nested_0"),
114+
Nested {
115+
nested_key: String::from("nested_value_0"),
116+
},
117+
),
118+
(
119+
String::from("nested_1"),
120+
Nested {
121+
nested_key: String::from("nested_value_1"),
122+
},
123+
),
124+
]),
125+
};
126+
127+
let ser = pythonize::Pythonizer::<Root<String>>::from(py);
128+
let pyroot: Py<PyAny> = serde_path_to_error::serialize(&root, ser).unwrap();
129+
130+
let pyroot: &PyDict = pyroot.downcast(py).unwrap();
131+
assert_eq!(pyroot.len(), 2);
132+
133+
let root_value: &str = pyroot
134+
.get_item("root_key")
135+
.unwrap()
136+
.unwrap()
137+
.extract()
138+
.unwrap();
139+
assert_eq!(root_value, "root_value");
140+
141+
let root_map: &PyDict = pyroot
142+
.get_item("root_map")
143+
.unwrap()
144+
.unwrap()
145+
.extract()
146+
.unwrap();
147+
assert_eq!(root_map.len(), 2);
148+
149+
let nested_0: &PyDict = root_map
150+
.get_item("nested_0")
151+
.unwrap()
152+
.unwrap()
153+
.extract()
154+
.unwrap();
155+
assert_eq!(nested_0.len(), 1);
156+
let nested_key_0: &str = nested_0
157+
.get_item("nested_key")
158+
.unwrap()
159+
.unwrap()
160+
.extract()
161+
.unwrap();
162+
assert_eq!(nested_key_0, "nested_value_0");
163+
164+
let nested_1: &PyDict = root_map
165+
.get_item("nested_1")
166+
.unwrap()
167+
.unwrap()
168+
.extract()
169+
.unwrap();
170+
assert_eq!(nested_1.len(), 1);
171+
let nested_key_1: &str = nested_1
172+
.get_item("nested_key")
173+
.unwrap()
174+
.unwrap()
175+
.extract()
176+
.unwrap();
177+
assert_eq!(nested_key_1, "nested_value_1");
178+
});
179+
}
180+
181+
#[test]
182+
fn test_ser_invalid() {
183+
Python::with_gil(|py| {
184+
let root = Root {
185+
root_key: String::from("root_value"),
186+
root_map: BTreeMap::from([
187+
(
188+
String::from("nested_0"),
189+
Nested {
190+
nested_key: CannotSerialize {},
191+
},
192+
),
193+
(
194+
String::from("nested_1"),
195+
Nested {
196+
nested_key: CannotSerialize {},
197+
},
198+
),
199+
]),
200+
};
201+
202+
let ser = pythonize::Pythonizer::<Root<String>>::from(py);
203+
let err = serde_path_to_error::serialize(&root, ser).unwrap_err();
204+
205+
assert_eq!(err.path().to_string(), "root_map.nested_0.nested_key");
206+
});
207+
}

0 commit comments

Comments
 (0)