@@ -101,8 +101,11 @@ impl<T: PyClass> PyCellInner<T> {
101
101
/// [Interior Mutability Pattern](https://doc.rust-lang.org/book/ch15-05-interior-mutability.html)
102
102
/// like [std::cell::RefCell](https://doc.rust-lang.org/std/cell/struct.RefCell.html).
103
103
///
104
+ /// # Examples
105
+ ///
104
106
/// In most cases, `PyCell` is hidden behind `#[pymethods]`.
105
107
/// However, you can construct `&PyCell` directly to test your pyclass in Rust code.
108
+ ///
106
109
/// ```
107
110
/// # use pyo3::prelude::*;
108
111
/// #[pyclass]
@@ -121,23 +124,25 @@ impl<T: PyClass> PyCellInner<T> {
121
124
/// // you can expose PyCell to Python snippets
122
125
/// pyo3::py_run!(py, book_cell, "assert book_cell.name[-6:] == 'Castle'");
123
126
/// ```
124
- /// You can also use `slf: &PyCell<Self>` as an alternative `self` receiver of `#[pymethod]`.
127
+ /// You can use `slf: &PyCell<Self>` as an alternative `self` receiver of `#[pymethod]`,
128
+ /// though you rarely need it.
125
129
/// ```
126
130
/// # use pyo3::prelude::*;
127
131
/// use std::collections::HashMap;
128
132
/// #[pyclass]
129
133
/// #[derive(Default)]
130
134
/// struct Counter {
131
- /// data : HashMap<String, usize>,
135
+ /// counter : HashMap<String, usize>
132
136
/// }
133
137
/// #[pymethods]
134
138
/// impl Counter {
139
+ /// // You can use &mut self here, but now we use &PyCell for demonstration
135
140
/// fn increment(slf: &PyCell<Self>, name: String) -> PyResult<usize> {
136
141
/// let mut slf_mut = slf.try_borrow_mut()?;
137
- /// // Now a mutable reference exists so we cannot another one
142
+ /// // Now a mutable reference exists so we cannot get another one
138
143
/// assert!(slf.try_borrow().is_err());
139
144
/// assert!(slf.try_borrow_mut().is_err());
140
- /// let counter = slf_mut.data .entry(name).or_insert(0);
145
+ /// let counter = slf_mut.counter .entry(name).or_insert(0);
141
146
/// *counter += 1;
142
147
/// Ok(*counter)
143
148
/// }
@@ -156,6 +161,7 @@ pub struct PyCell<T: PyClass> {
156
161
157
162
impl < T : PyClass > PyCell < T > {
158
163
/// Make new `PyCell` on the Python heap and returns the reference of it.
164
+ ///
159
165
pub fn new ( py : Python , value : impl Into < PyClassInitializer < T > > ) -> PyResult < & Self >
160
166
where
161
167
T :: BaseLayout : crate :: type_object:: PyObjectSizedLayout < T :: BaseType > ,
@@ -167,14 +173,50 @@ impl<T: PyClass> PyCell<T> {
167
173
}
168
174
}
169
175
176
+ /// Immutably borrows the value `T`. This borrow lasts untill the returned `PyRef` exists.
177
+ ///
178
+ /// # Panics
179
+ ///
180
+ /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use
181
+ /// [`try_borrow`](#method.try_borrow).
170
182
pub fn borrow ( & self ) -> PyRef < ' _ , T > {
171
183
self . try_borrow ( ) . expect ( "Already mutably borrowed" )
172
184
}
173
185
186
+ /// Mutably borrows the value `T`. This borrow lasts untill the returned `PyRefMut` exists.
187
+ ///
188
+ /// # Panics
189
+ ///
190
+ /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use
191
+ /// [`try_borrow_mut`](#method.try_borrow_mut).
174
192
pub fn borrow_mut ( & self ) -> PyRefMut < ' _ , T > {
175
193
self . try_borrow_mut ( ) . expect ( "Already borrowed" )
176
194
}
177
195
196
+ /// Immutably borrows the value `T`, returning an error if the value is currently
197
+ /// mutably borrowed. This borrow lasts untill the returned `PyRef` exists.
198
+ ///
199
+ /// This is the non-panicking variant of [`borrow`](#method.borrow).
200
+ ///
201
+ /// # Examples
202
+ ///
203
+ /// ```
204
+ /// # use pyo3::prelude::*;
205
+ /// #[pyclass]
206
+ /// struct Class {}
207
+ /// let gil = Python::acquire_gil();
208
+ /// let py = gil.python();
209
+ /// let c = PyCell::new(py, Class {}).unwrap();
210
+ /// {
211
+ /// let m = c.borrow_mut();
212
+ /// assert!(c.try_borrow().is_err());
213
+ /// }
214
+ ///
215
+ /// {
216
+ /// let m = c.borrow();
217
+ /// assert!(c.try_borrow().is_ok());
218
+ /// }
219
+ /// ```
178
220
pub fn try_borrow ( & self ) -> Result < PyRef < ' _ , T > , PyBorrowError > {
179
221
let flag = self . inner . get_borrow_flag ( ) ;
180
222
if flag == BorrowFlag :: HAS_MUTABLE_BORROW {
@@ -185,6 +227,27 @@ impl<T: PyClass> PyCell<T> {
185
227
}
186
228
}
187
229
230
+ /// Mutably borrows the value `T`, returning an error if the value is currently borrowed.
231
+ /// This borrow lasts untill the returned `PyRefMut` exists.
232
+ ///
233
+ /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut).
234
+ ///
235
+ /// # Examples
236
+ ///
237
+ /// ```
238
+ /// # use pyo3::prelude::*;
239
+ /// #[pyclass]
240
+ /// struct Class {}
241
+ /// let gil = Python::acquire_gil();
242
+ /// let py = gil.python();
243
+ /// let c = PyCell::new(py, Class {}).unwrap();
244
+ /// {
245
+ /// let m = c.borrow();
246
+ /// assert!(c.try_borrow_mut().is_err());
247
+ /// }
248
+ ///
249
+ /// assert!(c.try_borrow_mut().is_ok());
250
+ /// ```
188
251
pub fn try_borrow_mut ( & self ) -> Result < PyRefMut < ' _ , T > , PyBorrowMutError > {
189
252
if self . inner . get_borrow_flag ( ) != BorrowFlag :: UNUSED {
190
253
Err ( PyBorrowMutError { _private : ( ) } )
@@ -194,6 +257,35 @@ impl<T: PyClass> PyCell<T> {
194
257
}
195
258
}
196
259
260
+ /// Immutably borrows the value `T`, returning an error if the value is
261
+ /// currently mutably borrowed.
262
+ ///
263
+ /// # Safety
264
+ ///
265
+ /// This method is unsafe because it does not return a `PyRef`,
266
+ /// thus leaving the borrow flag untouched. Mutably borrowing the `PyCell`
267
+ /// while the reference returned by this method is alive is undefined behaviour.
268
+ ///
269
+ /// # Examples
270
+ ///
271
+ /// ```
272
+ /// # use pyo3::prelude::*;
273
+ /// #[pyclass]
274
+ /// struct Class {}
275
+ /// let gil = Python::acquire_gil();
276
+ /// let py = gil.python();
277
+ /// let c = PyCell::new(py, Class {}).unwrap();
278
+ ///
279
+ /// {
280
+ /// let m = c.borrow_mut();
281
+ /// assert!(unsafe { c.try_borrow_unguarded() }.is_err());
282
+ /// }
283
+ ///
284
+ /// {
285
+ /// let m = c.borrow();
286
+ /// assert!(unsafe { c.try_borrow_unguarded() }.is_ok());
287
+ /// }
288
+ /// ```
197
289
pub unsafe fn try_borrow_unguarded ( & self ) -> Result < & T , PyBorrowError > {
198
290
if self . inner . get_borrow_flag ( ) == BorrowFlag :: HAS_MUTABLE_BORROW {
199
291
Err ( PyBorrowError { _private : ( ) } )
@@ -202,12 +294,35 @@ impl<T: PyClass> PyCell<T> {
202
294
}
203
295
}
204
296
205
- pub unsafe fn try_borrow_mut_unguarded ( & self ) -> Result < & mut T , PyBorrowMutError > {
206
- if self . inner . get_borrow_flag ( ) != BorrowFlag :: UNUSED {
207
- Err ( PyBorrowMutError { _private : ( ) } )
208
- } else {
209
- Ok ( & mut * self . inner . value . get ( ) )
210
- }
297
+ /// Replaces the wrapped value with a new one, returning the old value,
298
+ ///
299
+ /// # Panics
300
+ ///
301
+ /// Panics if the value is currently borrowed.
302
+ #[ inline]
303
+ pub fn replace ( & self , t : T ) -> T {
304
+ std:: mem:: replace ( & mut * self . borrow_mut ( ) , t)
305
+ }
306
+
307
+ /// Replaces the wrapped value with a new one computed from `f`, returning the old value.
308
+ ///
309
+ /// # Panics
310
+ ///
311
+ /// Panics if the value is currently borrowed.
312
+ pub fn replace_with < F : FnOnce ( & mut T ) -> T > ( & self , f : F ) -> T {
313
+ let mut_borrow = & mut * self . borrow_mut ( ) ;
314
+ let replacement = f ( mut_borrow) ;
315
+ std:: mem:: replace ( mut_borrow, replacement)
316
+ }
317
+
318
+ /// Swaps the wrapped value of `self` with the wrapped value of `other`.
319
+ ///
320
+ /// # Panics
321
+ ///
322
+ /// Panics if the value in either `PyCell` is currently borrowed.
323
+ #[ inline]
324
+ pub fn swap ( & self , other : & Self ) {
325
+ std:: mem:: swap ( & mut * self . borrow_mut ( ) , & mut * other. borrow_mut ( ) )
211
326
}
212
327
213
328
pub ( crate ) unsafe fn internal_new ( py : Python ) -> PyResult < * mut Self >
0 commit comments