Mercurial > public > mercurial-scm > hg-stable
comparison rust/pyo3-sharedref/tests/test_sharedref.rs @ 52633:d85514a88706
rust-pyo3-sharedref: reworked constructors
We had previously duplicated the `new` associated function on
`PySharedRef` with a method on `PySharedRefCell`: in `rust-cpython`,
the former was hidden by the accessor defined by the `py_class!` macro,
which we did not port yet.
On `PySharedRefCell` itself, replacing the `new` associated function
by the `From` trait carries all the needed semantics, and has the
advantage of less repetititons of the type name, which will help
with further refactorings and renamings.
author | Georges Racinet <georges.racinet@cloudcrane.io> |
---|---|
date | Sun, 15 Dec 2024 14:42:53 +0100 |
parents | a7d2529ed6dd |
children | d1e304025b90 |
comparison
equal
deleted
inserted
replaced
52632:a7d2529ed6dd | 52633:d85514a88706 |
---|---|
8 | 8 |
9 #[pymethods] | 9 #[pymethods] |
10 impl Owner { | 10 impl Owner { |
11 #[new] | 11 #[new] |
12 fn new(s: String) -> Self { | 12 fn new(s: String) -> Self { |
13 Self { | 13 Self { string: s.into() } |
14 string: PySharedRefCell::new(s), | |
15 } | |
16 } | 14 } |
17 } | 15 } |
18 | 16 |
19 fn with_setup( | 17 fn with_setup( |
20 test: impl FnOnce(Python<'_>, &Bound<'_, Owner>) -> PyResult<()>, | 18 test: impl FnOnce(Python<'_>, &Bound<'_, Owner>) -> PyResult<()>, |
28 | 26 |
29 /// "leak" in the sense of `UnsafePyLeaked` the `string` data field, | 27 /// "leak" in the sense of `UnsafePyLeaked` the `string` data field, |
30 /// taking care of all the boilerplate | 28 /// taking care of all the boilerplate |
31 fn leak_string(owner: &Bound<'_, Owner>) -> UnsafePyLeaked<&'static String> { | 29 fn leak_string(owner: &Bound<'_, Owner>) -> UnsafePyLeaked<&'static String> { |
32 let cell = &owner.borrow().string; | 30 let cell = &owner.borrow().string; |
33 let shared_ref = unsafe { cell.borrow(owner) }; | 31 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
34 shared_ref.leak_immutable() | 32 shared_ref.leak_immutable() |
35 } | 33 } |
36 | 34 |
37 fn try_leak_string( | 35 fn try_leak_string( |
38 owner: &Bound<'_, Owner>, | 36 owner: &Bound<'_, Owner>, |
39 ) -> Result<UnsafePyLeaked<&'static String>, TryLeakError> { | 37 ) -> Result<UnsafePyLeaked<&'static String>, TryLeakError> { |
40 let cell = &owner.borrow().string; | 38 let cell = &owner.borrow().string; |
41 let shared_ref = unsafe { cell.borrow(owner) }; | 39 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
42 shared_ref.try_leak_immutable() | 40 shared_ref.try_leak_immutable() |
43 } | 41 } |
44 | 42 |
45 /// Mutate the `string` field of `owner` as would be done from Python code | 43 /// Mutate the `string` field of `owner` as would be done from Python code |
46 /// | 44 /// |
52 fn mutate_string<'py>( | 50 fn mutate_string<'py>( |
53 owner: &'py Bound<'py, Owner>, | 51 owner: &'py Bound<'py, Owner>, |
54 f: impl FnOnce(&mut String), | 52 f: impl FnOnce(&mut String), |
55 ) -> () { | 53 ) -> () { |
56 let cell = &owner.borrow_mut().string; | 54 let cell = &owner.borrow_mut().string; |
57 let shared_ref = unsafe { cell.borrow(owner) }; | 55 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
58 f(&mut shared_ref.borrow_mut()); | 56 f(&mut shared_ref.borrow_mut()); |
59 } | 57 } |
60 | 58 |
61 #[test] | 59 #[test] |
62 fn test_leaked_borrow() -> PyResult<()> { | 60 fn test_leaked_borrow() -> PyResult<()> { |
121 /// | 119 /// |
122 /// Simply returning the `Result` is not possible, because that is | 120 /// Simply returning the `Result` is not possible, because that is |
123 /// returning a reference to data owned by the function | 121 /// returning a reference to data owned by the function |
124 fn assert_try_borrow_string_mut_ok(owner: &Bound<'_, Owner>) { | 122 fn assert_try_borrow_string_mut_ok(owner: &Bound<'_, Owner>) { |
125 let cell = &owner.borrow().string; | 123 let cell = &owner.borrow().string; |
126 let shared_ref = unsafe { cell.borrow(owner) }; | 124 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
127 assert!(shared_ref.try_borrow_mut().is_ok()); | 125 assert!(shared_ref.try_borrow_mut().is_ok()); |
128 } | 126 } |
129 | 127 |
130 fn assert_try_borrow_string_mut_err(owner: &Bound<'_, Owner>) { | 128 fn assert_try_borrow_string_mut_err(owner: &Bound<'_, Owner>) { |
131 let cell = &owner.borrow().string; | 129 let cell = &owner.borrow().string; |
132 let shared_ref = unsafe { cell.borrow(owner) }; | 130 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
133 assert!(shared_ref.try_borrow_mut().is_err()); | 131 assert!(shared_ref.try_borrow_mut().is_err()); |
134 } | 132 } |
135 | 133 |
136 fn assert_try_borrow_string_err(owner: &Bound<'_, Owner>) { | 134 fn assert_try_borrow_string_err(owner: &Bound<'_, Owner>) { |
137 let cell = &owner.borrow().string; | 135 let cell = &owner.borrow().string; |
138 let shared_ref = unsafe { cell.borrow(owner) }; | 136 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
139 assert!(shared_ref.try_borrow().is_err()); | 137 assert!(shared_ref.try_borrow().is_err()); |
140 } | 138 } |
141 | 139 |
142 #[test] | 140 #[test] |
143 fn test_try_borrow_mut_while_leaked_ref() -> PyResult<()> { | 141 fn test_try_borrow_mut_while_leaked_ref() -> PyResult<()> { |
176 | 174 |
177 #[test] | 175 #[test] |
178 fn test_try_leak_while_borrow_mut() -> PyResult<()> { | 176 fn test_try_leak_while_borrow_mut() -> PyResult<()> { |
179 with_setup(|_py, owner| { | 177 with_setup(|_py, owner| { |
180 let cell = &owner.borrow().string; | 178 let cell = &owner.borrow().string; |
181 let shared_ref = unsafe { cell.borrow(owner) }; | 179 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
182 let _mut_ref = shared_ref.borrow_mut(); | 180 let _mut_ref = shared_ref.borrow_mut(); |
183 | 181 |
184 assert!(try_leak_string(owner).is_err()); | 182 assert!(try_leak_string(owner).is_err()); |
185 Ok(()) | 183 Ok(()) |
186 }) | 184 }) |
189 #[test] | 187 #[test] |
190 #[should_panic(expected = "already mutably borrowed")] | 188 #[should_panic(expected = "already mutably borrowed")] |
191 fn test_leak_while_borrow_mut() { | 189 fn test_leak_while_borrow_mut() { |
192 with_setup(|_py, owner| { | 190 with_setup(|_py, owner| { |
193 let cell = &owner.borrow().string; | 191 let cell = &owner.borrow().string; |
194 let shared_ref = unsafe { cell.borrow(owner) }; | 192 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
195 let _mut_ref = shared_ref.borrow_mut(); | 193 let _mut_ref = shared_ref.borrow_mut(); |
196 | 194 |
197 leak_string(owner); | 195 leak_string(owner); |
198 Ok(()) | 196 Ok(()) |
199 }) | 197 }) |
202 | 200 |
203 #[test] | 201 #[test] |
204 fn test_try_borrow_mut_while_borrow() -> PyResult<()> { | 202 fn test_try_borrow_mut_while_borrow() -> PyResult<()> { |
205 with_setup(|_py, owner| { | 203 with_setup(|_py, owner| { |
206 let cell = &owner.borrow().string; | 204 let cell = &owner.borrow().string; |
207 let shared_ref = unsafe { cell.borrow(owner) }; | 205 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
208 let _ref = shared_ref.borrow(); | 206 let _ref = shared_ref.borrow(); |
209 | 207 |
210 assert_try_borrow_string_mut_err(owner); | 208 assert_try_borrow_string_mut_err(owner); |
211 Ok(()) | 209 Ok(()) |
212 }) | 210 }) |
215 #[test] | 213 #[test] |
216 #[should_panic(expected = "already borrowed")] | 214 #[should_panic(expected = "already borrowed")] |
217 fn test_borrow_mut_while_borrow() { | 215 fn test_borrow_mut_while_borrow() { |
218 with_setup(|_py, owner| { | 216 with_setup(|_py, owner| { |
219 let cell = &owner.borrow().string; | 217 let cell = &owner.borrow().string; |
220 let shared_ref = unsafe { cell.borrow(owner) }; | 218 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
221 let _ref = shared_ref.borrow(); | 219 let _ref = shared_ref.borrow(); |
222 | 220 |
223 let shared_ref2 = unsafe { cell.borrow(owner) }; | 221 let shared_ref2 = unsafe { cell.borrow_with_owner(owner) }; |
224 let _mut_ref = shared_ref2.borrow_mut(); | 222 let _mut_ref = shared_ref2.borrow_mut(); |
225 Ok(()) | 223 Ok(()) |
226 }) | 224 }) |
227 .expect("should already have panicked") | 225 .expect("should already have panicked") |
228 } | 226 } |
229 | 227 |
230 #[test] | 228 #[test] |
231 fn test_try_borrow_while_borrow_mut() -> PyResult<()> { | 229 fn test_try_borrow_while_borrow_mut() -> PyResult<()> { |
232 with_setup(|_py, owner| { | 230 with_setup(|_py, owner| { |
233 let cell = &owner.borrow().string; | 231 let cell = &owner.borrow().string; |
234 let shared_ref = unsafe { cell.borrow(owner) }; | 232 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
235 let _mut_ref = shared_ref.borrow_mut(); | 233 let _mut_ref = shared_ref.borrow_mut(); |
236 | 234 |
237 assert_try_borrow_string_err(owner); | 235 assert_try_borrow_string_err(owner); |
238 Ok(()) | 236 Ok(()) |
239 }) | 237 }) |
242 #[test] | 240 #[test] |
243 #[should_panic(expected = "already mutably borrowed")] | 241 #[should_panic(expected = "already mutably borrowed")] |
244 fn test_borrow_while_borrow_mut() { | 242 fn test_borrow_while_borrow_mut() { |
245 with_setup(|_py, owner| { | 243 with_setup(|_py, owner| { |
246 let cell = &owner.borrow().string; | 244 let cell = &owner.borrow().string; |
247 let shared_ref = unsafe { cell.borrow(owner) }; | 245 let shared_ref = unsafe { cell.borrow_with_owner(owner) }; |
248 let _mut_ref = shared_ref.borrow_mut(); | 246 let _mut_ref = shared_ref.borrow_mut(); |
249 | 247 |
250 let shared_ref2 = unsafe { cell.borrow(owner) }; | 248 let shared_ref2 = unsafe { cell.borrow_with_owner(owner) }; |
251 let _ref = shared_ref2.borrow(); | 249 let _ref = shared_ref2.borrow(); |
252 Ok(()) | 250 Ok(()) |
253 }) | 251 }) |
254 .expect("should already have panicked") | 252 .expect("should already have panicked") |
255 } | 253 } |