1 | use crate::conversion::PyTryFrom; |
2 | use crate::err::{self, PyDowncastError, PyErr, PyResult}; |
3 | use crate::gil; |
4 | use crate::pycell::{PyBorrowError, PyBorrowMutError, PyCell}; |
5 | use crate::pyclass::boolean_struct::{False, True}; |
6 | use crate::types::{PyDict, PyString, PyTuple}; |
7 | use crate::{ |
8 | ffi, AsPyPointer, FromPyObject, IntoPy, PyAny, PyClass, PyClassInitializer, PyRef, PyRefMut, |
9 | PyTypeInfo, Python, ToPyObject, |
10 | }; |
11 | use std::marker::PhantomData; |
12 | use std::mem; |
13 | use std::ptr::NonNull; |
14 | |
15 | /// Types that are built into the Python interpreter. |
16 | /// |
17 | /// PyO3 is designed in a way that all references to those types are bound |
18 | /// to the GIL, which is why you can get a token from all references of those |
19 | /// types. |
20 | /// |
21 | /// # Safety |
22 | /// |
23 | /// This trait must only be implemented for types which cannot be accessed without the GIL. |
24 | pub unsafe trait PyNativeType: Sized { |
25 | /// Returns a GIL marker constrained to the lifetime of this type. |
26 | #[inline ] |
27 | fn py(&self) -> Python<'_> { |
28 | unsafe { Python::assume_gil_acquired() } |
29 | } |
30 | /// Cast `&PyAny` to `&Self` without no type checking. |
31 | /// |
32 | /// # Safety |
33 | /// |
34 | /// `obj` must have the same layout as `*const ffi::PyObject` and must be |
35 | /// an instance of a type corresponding to `Self`. |
36 | unsafe fn unchecked_downcast(obj: &PyAny) -> &Self { |
37 | &*(obj.as_ptr() as *const Self) |
38 | } |
39 | } |
40 | |
41 | /// A GIL-independent reference to an object allocated on the Python heap. |
42 | /// |
43 | /// This type does not auto-dereference to the inner object because you must prove you hold the GIL to access it. |
44 | /// Instead, call one of its methods to access the inner object: |
45 | /// - [`Py::as_ref`], to borrow a GIL-bound reference to the contained object. |
46 | /// - [`Py::borrow`], [`Py::try_borrow`], [`Py::borrow_mut`], or [`Py::try_borrow_mut`], |
47 | /// to get a (mutable) reference to a contained pyclass, using a scheme similar to std's [`RefCell`]. |
48 | /// See the [`PyCell` guide entry](https://pyo3.rs/latest/class.html#pycell-and-interior-mutability) |
49 | /// for more information. |
50 | /// - You can call methods directly on `Py` with [`Py::call`], [`Py::call_method`] and friends. |
51 | /// These require passing in the [`Python<'py>`](crate::Python) token but are otherwise similar to the corresponding |
52 | /// methods on [`PyAny`]. |
53 | /// |
54 | /// # Example: Storing Python objects in structs |
55 | /// |
56 | /// As all the native Python objects only appear as references, storing them in structs doesn't work well. |
57 | /// For example, this won't compile: |
58 | /// |
59 | /// ```compile_fail |
60 | /// # use pyo3::prelude::*; |
61 | /// # use pyo3::types::PyDict; |
62 | /// # |
63 | /// #[pyclass] |
64 | /// struct Foo<'py> { |
65 | /// inner: &'py PyDict, |
66 | /// } |
67 | /// |
68 | /// impl Foo { |
69 | /// fn new() -> Foo { |
70 | /// let foo = Python::with_gil(|py| { |
71 | /// // `py` will only last for this scope. |
72 | /// |
73 | /// // `&PyDict` derives its lifetime from `py` and |
74 | /// // so won't be able to outlive this closure. |
75 | /// let dict: &PyDict = PyDict::new(py); |
76 | /// |
77 | /// // because `Foo` contains `dict` its lifetime |
78 | /// // is now also tied to `py`. |
79 | /// Foo { inner: dict } |
80 | /// }); |
81 | /// // Foo is no longer valid. |
82 | /// // Returning it from this function is a 💥 compiler error 💥 |
83 | /// foo |
84 | /// } |
85 | /// } |
86 | /// ``` |
87 | /// |
88 | /// [`Py`]`<T>` can be used to get around this by converting `dict` into a GIL-independent reference: |
89 | /// |
90 | /// ```rust |
91 | /// use pyo3::prelude::*; |
92 | /// use pyo3::types::PyDict; |
93 | /// |
94 | /// #[pyclass] |
95 | /// struct Foo { |
96 | /// inner: Py<PyDict>, |
97 | /// } |
98 | /// |
99 | /// #[pymethods] |
100 | /// impl Foo { |
101 | /// #[new] |
102 | /// fn __new__() -> Foo { |
103 | /// Python::with_gil(|py| { |
104 | /// let dict: Py<PyDict> = PyDict::new(py).into(); |
105 | /// Foo { inner: dict } |
106 | /// }) |
107 | /// } |
108 | /// } |
109 | /// # |
110 | /// # fn main() -> PyResult<()> { |
111 | /// # Python::with_gil(|py| { |
112 | /// # let m = pyo3::types::PyModule::new(py, "test" )?; |
113 | /// # m.add_class::<Foo>()?; |
114 | /// # |
115 | /// # let foo: &PyCell<Foo> = m.getattr("Foo" )?.call0()?.downcast()?; |
116 | /// # let dict = &foo.borrow().inner; |
117 | /// # let dict: &PyDict = dict.as_ref(py); |
118 | /// # |
119 | /// # Ok(()) |
120 | /// # }) |
121 | /// # } |
122 | /// ``` |
123 | /// |
124 | /// This can also be done with other pyclasses: |
125 | /// ```rust |
126 | /// use pyo3::prelude::*; |
127 | /// |
128 | /// #[pyclass] |
129 | /// struct Bar {/* ... */} |
130 | /// |
131 | /// #[pyclass] |
132 | /// struct Foo { |
133 | /// inner: Py<Bar>, |
134 | /// } |
135 | /// |
136 | /// #[pymethods] |
137 | /// impl Foo { |
138 | /// #[new] |
139 | /// fn __new__() -> PyResult<Foo> { |
140 | /// Python::with_gil(|py| { |
141 | /// let bar: Py<Bar> = Py::new(py, Bar {})?; |
142 | /// Ok(Foo { inner: bar }) |
143 | /// }) |
144 | /// } |
145 | /// } |
146 | /// # |
147 | /// # fn main() -> PyResult<()> { |
148 | /// # Python::with_gil(|py| { |
149 | /// # let m = pyo3::types::PyModule::new(py, "test" )?; |
150 | /// # m.add_class::<Foo>()?; |
151 | /// # |
152 | /// # let foo: &PyCell<Foo> = m.getattr("Foo" )?.call0()?.downcast()?; |
153 | /// # let bar = &foo.borrow().inner; |
154 | /// # let bar: &Bar = &*bar.borrow(py); |
155 | /// # |
156 | /// # Ok(()) |
157 | /// # }) |
158 | /// # } |
159 | /// ``` |
160 | /// |
161 | /// # Example: Shared ownership of Python objects |
162 | /// |
163 | /// `Py<T>` can be used to share ownership of a Python object, similar to std's [`Rc`]`<T>`. |
164 | /// As with [`Rc`]`<T>`, cloning it increases its reference count rather than duplicating |
165 | /// the underlying object. |
166 | /// |
167 | /// This can be done using either [`Py::clone_ref`] or [`Py`]`<T>`'s [`Clone`] trait implementation. |
168 | /// [`Py::clone_ref`] will be faster if you happen to be already holding the GIL. |
169 | /// |
170 | /// ```rust |
171 | /// use pyo3::prelude::*; |
172 | /// use pyo3::types::PyDict; |
173 | /// |
174 | /// # fn main() { |
175 | /// Python::with_gil(|py| { |
176 | /// let first: Py<PyDict> = PyDict::new(py).into(); |
177 | /// |
178 | /// // All of these are valid syntax |
179 | /// let second = Py::clone_ref(&first, py); |
180 | /// let third = first.clone_ref(py); |
181 | /// let fourth = Py::clone(&first); |
182 | /// let fifth = first.clone(); |
183 | /// |
184 | /// // Disposing of our original `Py<PyDict>` just decrements the reference count. |
185 | /// drop(first); |
186 | /// |
187 | /// // They all point to the same object |
188 | /// assert!(second.is(&third)); |
189 | /// assert!(fourth.is(&fifth)); |
190 | /// assert!(second.is(&fourth)); |
191 | /// }); |
192 | /// # } |
193 | /// ``` |
194 | /// |
195 | /// # Preventing reference cycles |
196 | /// |
197 | /// It is easy to accidentally create reference cycles using [`Py`]`<T>`. |
198 | /// The Python interpreter can break these reference cycles within pyclasses if they |
199 | /// [integrate with the garbage collector][gc]. If your pyclass contains other Python |
200 | /// objects you should implement it to avoid leaking memory. |
201 | /// |
202 | /// # A note on Python reference counts |
203 | /// |
204 | /// Dropping a [`Py`]`<T>` will eventually decrease Python's reference count |
205 | /// of the pointed-to variable, allowing Python's garbage collector to free |
206 | /// the associated memory, but this may not happen immediately. This is |
207 | /// because a [`Py`]`<T>` can be dropped at any time, but the Python reference |
208 | /// count can only be modified when the GIL is held. |
209 | /// |
210 | /// If a [`Py`]`<T>` is dropped while its thread happens to be holding the |
211 | /// GIL then the Python reference count will be decreased immediately. |
212 | /// Otherwise, the reference count will be decreased the next time the GIL is |
213 | /// reacquired. |
214 | /// |
215 | /// # A note on `Send` and `Sync` |
216 | /// |
217 | /// Accessing this object is threadsafe, since any access to its API requires a [`Python<'py>`](crate::Python) token. |
218 | /// As you can only get this by acquiring the GIL, `Py<...>` "implements [`Send`] and [`Sync`]. |
219 | /// |
220 | /// [`Rc`]: std::rc::Rc |
221 | /// [`RefCell`]: std::cell::RefCell |
222 | /// [gc]: https://pyo3.rs/main/class/protocols.html#garbage-collector-integration |
223 | #[repr (transparent)] |
224 | pub struct Py<T>(NonNull<ffi::PyObject>, PhantomData<T>); |
225 | |
226 | // The inner value is only accessed through ways that require proving the gil is held |
227 | #[cfg (feature = "nightly" )] |
228 | unsafe impl<T> crate::marker::Ungil for Py<T> {} |
229 | unsafe impl<T> Send for Py<T> {} |
230 | unsafe impl<T> Sync for Py<T> {} |
231 | |
232 | impl<T> Py<T> |
233 | where |
234 | T: PyClass, |
235 | { |
236 | /// Creates a new instance `Py<T>` of a `#[pyclass]` on the Python heap. |
237 | /// |
238 | /// # Examples |
239 | /// |
240 | /// ```rust |
241 | /// use pyo3::prelude::*; |
242 | /// |
243 | /// #[pyclass] |
244 | /// struct Foo {/* fields omitted */} |
245 | /// |
246 | /// # fn main() -> PyResult<()> { |
247 | /// Python::with_gil(|py| -> PyResult<Py<Foo>> { |
248 | /// let foo: Py<Foo> = Py::new(py, Foo {})?; |
249 | /// Ok(foo) |
250 | /// })?; |
251 | /// # Ok(()) |
252 | /// # } |
253 | /// ``` |
254 | pub fn new(py: Python<'_>, value: impl Into<PyClassInitializer<T>>) -> PyResult<Py<T>> { |
255 | let initializer = value.into(); |
256 | let obj = initializer.create_cell(py)?; |
257 | let ob = unsafe { Py::from_owned_ptr(py, obj as _) }; |
258 | Ok(ob) |
259 | } |
260 | } |
261 | |
262 | impl<T> Py<T> |
263 | where |
264 | T: PyTypeInfo, |
265 | { |
266 | /// Borrows a GIL-bound reference to the contained `T`. |
267 | /// |
268 | /// By binding to the GIL lifetime, this allows the GIL-bound reference to not require |
269 | /// [`Python<'py>`](crate::Python) for any of its methods, which makes calling methods |
270 | /// on it more ergonomic. |
271 | /// |
272 | /// For native types, this reference is `&T`. For pyclasses, this is `&PyCell<T>`. |
273 | /// |
274 | /// Note that the lifetime of the returned reference is the shortest of `&self` and |
275 | /// [`Python<'py>`](crate::Python). |
276 | /// Consider using [`Py::into_ref`] instead if this poses a problem. |
277 | /// |
278 | /// # Examples |
279 | /// |
280 | /// Get access to `&PyList` from `Py<PyList>`: |
281 | /// |
282 | /// ``` |
283 | /// # use pyo3::prelude::*; |
284 | /// # use pyo3::types::PyList; |
285 | /// # |
286 | /// Python::with_gil(|py| { |
287 | /// let list: Py<PyList> = PyList::empty(py).into(); |
288 | /// let list: &PyList = list.as_ref(py); |
289 | /// assert_eq!(list.len(), 0); |
290 | /// }); |
291 | /// ``` |
292 | /// |
293 | /// Get access to `&PyCell<MyClass>` from `Py<MyClass>`: |
294 | /// |
295 | /// ``` |
296 | /// # use pyo3::prelude::*; |
297 | /// # |
298 | /// #[pyclass] |
299 | /// struct MyClass {} |
300 | /// |
301 | /// Python::with_gil(|py| { |
302 | /// let my_class: Py<MyClass> = Py::new(py, MyClass {}).unwrap(); |
303 | /// let my_class_cell: &PyCell<MyClass> = my_class.as_ref(py); |
304 | /// assert!(my_class_cell.try_borrow().is_ok()); |
305 | /// }); |
306 | /// ``` |
307 | pub fn as_ref<'py>(&'py self, _py: Python<'py>) -> &'py T::AsRefTarget { |
308 | let any = self.as_ptr() as *const PyAny; |
309 | unsafe { PyNativeType::unchecked_downcast(&*any) } |
310 | } |
311 | |
312 | /// Borrows a GIL-bound reference to the contained `T` independently of the lifetime of `T`. |
313 | /// |
314 | /// This method is similar to [`as_ref`](#method.as_ref) but consumes `self` and registers the |
315 | /// Python object reference in PyO3's object storage. The reference count for the Python |
316 | /// object will not be decreased until the GIL lifetime ends. |
317 | /// |
318 | /// You should prefer using [`as_ref`](#method.as_ref) if you can as it'll have less overhead. |
319 | /// |
320 | /// # Examples |
321 | /// |
322 | /// [`Py::as_ref`]'s lifetime limitation forbids creating a function that references a |
323 | /// variable created inside the function. |
324 | /// |
325 | /// ```rust,compile_fail |
326 | /// # use pyo3::prelude::*; |
327 | /// # |
328 | /// fn new_py_any<'py>(py: Python<'py>, value: impl IntoPy<Py<PyAny>>) -> &'py PyAny { |
329 | /// let obj: Py<PyAny> = value.into_py(py); |
330 | /// |
331 | /// // The lifetime of the return value of this function is the shortest |
332 | /// // of `obj` and `py`. As `obj` is owned by the current function, |
333 | /// // Rust won't let the return value escape this function! |
334 | /// obj.as_ref(py) |
335 | /// } |
336 | /// ``` |
337 | /// |
338 | /// This can be solved by using [`Py::into_ref`] instead, which does not suffer from this issue. |
339 | /// Note that the lifetime of the [`Python<'py>`](crate::Python) token is transferred to |
340 | /// the returned reference. |
341 | /// |
342 | /// ```rust |
343 | /// # use pyo3::prelude::*; |
344 | /// # #[allow (dead_code)] // This is just to show it compiles. |
345 | /// fn new_py_any<'py>(py: Python<'py>, value: impl IntoPy<Py<PyAny>>) -> &'py PyAny { |
346 | /// let obj: Py<PyAny> = value.into_py(py); |
347 | /// |
348 | /// // This reference's lifetime is determined by `py`'s lifetime. |
349 | /// // Because that originates from outside this function, |
350 | /// // this return value is allowed. |
351 | /// obj.into_ref(py) |
352 | /// } |
353 | /// ``` |
354 | pub fn into_ref(self, py: Python<'_>) -> &T::AsRefTarget { |
355 | unsafe { py.from_owned_ptr(self.into_ptr()) } |
356 | } |
357 | } |
358 | |
359 | impl<T> Py<T> { |
360 | /// Returns the raw FFI pointer represented by self. |
361 | /// |
362 | /// # Safety |
363 | /// |
364 | /// Callers are responsible for ensuring that the pointer does not outlive self. |
365 | /// |
366 | /// The reference is borrowed; callers should not decrease the reference count |
367 | /// when they are finished with the pointer. |
368 | #[inline ] |
369 | pub fn as_ptr(&self) -> *mut ffi::PyObject { |
370 | self.0.as_ptr() |
371 | } |
372 | |
373 | /// Returns an owned raw FFI pointer represented by self. |
374 | /// |
375 | /// # Safety |
376 | /// |
377 | /// The reference is owned; when finished the caller should either transfer ownership |
378 | /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). |
379 | #[inline ] |
380 | pub fn into_ptr(self) -> *mut ffi::PyObject { |
381 | let ptr = self.0.as_ptr(); |
382 | std::mem::forget(self); |
383 | ptr |
384 | } |
385 | } |
386 | |
387 | impl<T> Py<T> |
388 | where |
389 | T: PyClass, |
390 | { |
391 | /// Immutably borrows the value `T`. |
392 | /// |
393 | /// This borrow lasts while the returned [`PyRef`] exists. |
394 | /// Multiple immutable borrows can be taken out at the same time. |
395 | /// |
396 | /// For frozen classes, the simpler [`get`][Self::get] is available. |
397 | /// |
398 | /// Equivalent to `self.as_ref(py).borrow()` - |
399 | /// see [`PyCell::borrow`](crate::pycell::PyCell::borrow). |
400 | /// |
401 | /// # Examples |
402 | /// |
403 | /// ```rust |
404 | /// # use pyo3::prelude::*; |
405 | /// # |
406 | /// #[pyclass] |
407 | /// struct Foo { |
408 | /// inner: u8, |
409 | /// } |
410 | /// |
411 | /// # fn main() -> PyResult<()> { |
412 | /// Python::with_gil(|py| -> PyResult<()> { |
413 | /// let foo: Py<Foo> = Py::new(py, Foo { inner: 73 })?; |
414 | /// let inner: &u8 = &foo.borrow(py).inner; |
415 | /// |
416 | /// assert_eq!(*inner, 73); |
417 | /// Ok(()) |
418 | /// })?; |
419 | /// # Ok(()) |
420 | /// # } |
421 | /// ``` |
422 | /// |
423 | /// # Panics |
424 | /// |
425 | /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use |
426 | /// [`try_borrow`](#method.try_borrow). |
427 | pub fn borrow<'py>(&'py self, py: Python<'py>) -> PyRef<'py, T> { |
428 | self.as_ref(py).borrow() |
429 | } |
430 | |
431 | /// Mutably borrows the value `T`. |
432 | /// |
433 | /// This borrow lasts while the returned [`PyRefMut`] exists. |
434 | /// |
435 | /// Equivalent to `self.as_ref(py).borrow_mut()` - |
436 | /// see [`PyCell::borrow_mut`](crate::pycell::PyCell::borrow_mut). |
437 | /// |
438 | /// # Examples |
439 | /// |
440 | /// ``` |
441 | /// # use pyo3::prelude::*; |
442 | /// # |
443 | /// #[pyclass] |
444 | /// struct Foo { |
445 | /// inner: u8, |
446 | /// } |
447 | /// |
448 | /// # fn main() -> PyResult<()> { |
449 | /// Python::with_gil(|py| -> PyResult<()> { |
450 | /// let foo: Py<Foo> = Py::new(py, Foo { inner: 73 })?; |
451 | /// foo.borrow_mut(py).inner = 35; |
452 | /// |
453 | /// assert_eq!(foo.borrow(py).inner, 35); |
454 | /// Ok(()) |
455 | /// })?; |
456 | /// # Ok(()) |
457 | /// # } |
458 | /// ``` |
459 | /// |
460 | /// # Panics |
461 | /// Panics if the value is currently borrowed. For a non-panicking variant, use |
462 | /// [`try_borrow_mut`](#method.try_borrow_mut). |
463 | pub fn borrow_mut<'py>(&'py self, py: Python<'py>) -> PyRefMut<'py, T> |
464 | where |
465 | T: PyClass<Frozen = False>, |
466 | { |
467 | self.as_ref(py).borrow_mut() |
468 | } |
469 | |
470 | /// Attempts to immutably borrow the value `T`, returning an error if the value is currently mutably borrowed. |
471 | /// |
472 | /// The borrow lasts while the returned [`PyRef`] exists. |
473 | /// |
474 | /// This is the non-panicking variant of [`borrow`](#method.borrow). |
475 | /// |
476 | /// For frozen classes, the simpler [`get`][Self::get] is available. |
477 | /// |
478 | /// Equivalent to `self.as_ref(py).borrow_mut()` - |
479 | /// see [`PyCell::try_borrow`](crate::pycell::PyCell::try_borrow). |
480 | pub fn try_borrow<'py>(&'py self, py: Python<'py>) -> Result<PyRef<'py, T>, PyBorrowError> { |
481 | self.as_ref(py).try_borrow() |
482 | } |
483 | |
484 | /// Attempts to mutably borrow the value `T`, returning an error if the value is currently borrowed. |
485 | /// |
486 | /// The borrow lasts while the returned [`PyRefMut`] exists. |
487 | /// |
488 | /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut). |
489 | /// |
490 | /// Equivalent to `self.as_ref(py).try_borrow_mut()` - |
491 | /// see [`PyCell::try_borrow_mut`](crate::pycell::PyCell::try_borrow_mut). |
492 | pub fn try_borrow_mut<'py>( |
493 | &'py self, |
494 | py: Python<'py>, |
495 | ) -> Result<PyRefMut<'py, T>, PyBorrowMutError> |
496 | where |
497 | T: PyClass<Frozen = False>, |
498 | { |
499 | self.as_ref(py).try_borrow_mut() |
500 | } |
501 | |
502 | /// Provide an immutable borrow of the value `T` without acquiring the GIL. |
503 | /// |
504 | /// This is available if the class is [`frozen`][macro@crate::pyclass] and [`Sync`]. |
505 | /// |
506 | /// # Examples |
507 | /// |
508 | /// ``` |
509 | /// use std::sync::atomic::{AtomicUsize, Ordering}; |
510 | /// # use pyo3::prelude::*; |
511 | /// |
512 | /// #[pyclass(frozen)] |
513 | /// struct FrozenCounter { |
514 | /// value: AtomicUsize, |
515 | /// } |
516 | /// |
517 | /// let cell = Python::with_gil(|py| { |
518 | /// let counter = FrozenCounter { value: AtomicUsize::new(0) }; |
519 | /// |
520 | /// Py::new(py, counter).unwrap() |
521 | /// }); |
522 | /// |
523 | /// cell.get().value.fetch_add(1, Ordering::Relaxed); |
524 | /// ``` |
525 | pub fn get(&self) -> &T |
526 | where |
527 | T: PyClass<Frozen = True> + Sync, |
528 | { |
529 | let any = self.as_ptr() as *const PyAny; |
530 | // SAFETY: The class itself is frozen and `Sync` and we do not access anything but `cell.contents.value`. |
531 | unsafe { |
532 | let cell: &PyCell<T> = PyNativeType::unchecked_downcast(&*any); |
533 | &*cell.get_ptr() |
534 | } |
535 | } |
536 | } |
537 | |
538 | impl<T> Py<T> { |
539 | /// Returns whether `self` and `other` point to the same object. To compare |
540 | /// the equality of two objects (the `==` operator), use [`eq`](PyAny::eq). |
541 | /// |
542 | /// This is equivalent to the Python expression `self is other`. |
543 | #[inline ] |
544 | pub fn is<U: AsPyPointer>(&self, o: &U) -> bool { |
545 | self.as_ptr() == o.as_ptr() |
546 | } |
547 | |
548 | /// Gets the reference count of the `ffi::PyObject` pointer. |
549 | #[inline ] |
550 | pub fn get_refcnt(&self, _py: Python<'_>) -> isize { |
551 | unsafe { ffi::Py_REFCNT(self.0.as_ptr()) } |
552 | } |
553 | |
554 | /// Makes a clone of `self`. |
555 | /// |
556 | /// This creates another pointer to the same object, increasing its reference count. |
557 | /// |
558 | /// You should prefer using this method over [`Clone`] if you happen to be holding the GIL already. |
559 | /// |
560 | /// # Examples |
561 | /// |
562 | /// ```rust |
563 | /// use pyo3::prelude::*; |
564 | /// use pyo3::types::PyDict; |
565 | /// |
566 | /// # fn main() { |
567 | /// Python::with_gil(|py| { |
568 | /// let first: Py<PyDict> = PyDict::new(py).into(); |
569 | /// let second = Py::clone_ref(&first, py); |
570 | /// |
571 | /// // Both point to the same object |
572 | /// assert!(first.is(&second)); |
573 | /// }); |
574 | /// # } |
575 | /// ``` |
576 | #[inline ] |
577 | pub fn clone_ref(&self, py: Python<'_>) -> Py<T> { |
578 | unsafe { Py::from_borrowed_ptr(py, self.0.as_ptr()) } |
579 | } |
580 | |
581 | /// Returns whether the object is considered to be None. |
582 | /// |
583 | /// This is equivalent to the Python expression `self is None`. |
584 | pub fn is_none(&self, _py: Python<'_>) -> bool { |
585 | unsafe { ffi::Py_None() == self.as_ptr() } |
586 | } |
587 | |
588 | /// Returns whether the object is Ellipsis, e.g. `...`. |
589 | /// |
590 | /// This is equivalent to the Python expression `self is ...`. |
591 | pub fn is_ellipsis(&self) -> bool { |
592 | unsafe { ffi::Py_Ellipsis() == self.as_ptr() } |
593 | } |
594 | |
595 | /// Returns whether the object is considered to be true. |
596 | /// |
597 | /// This is equivalent to the Python expression `bool(self)`. |
598 | pub fn is_true(&self, py: Python<'_>) -> PyResult<bool> { |
599 | let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) }; |
600 | err::error_on_minusone(py, v)?; |
601 | Ok(v != 0) |
602 | } |
603 | |
604 | /// Extracts some type from the Python object. |
605 | /// |
606 | /// This is a wrapper function around `FromPyObject::extract()`. |
607 | pub fn extract<'p, D>(&'p self, py: Python<'p>) -> PyResult<D> |
608 | where |
609 | D: FromPyObject<'p>, |
610 | { |
611 | FromPyObject::extract(unsafe { py.from_borrowed_ptr(self.as_ptr()) }) |
612 | } |
613 | |
614 | /// Retrieves an attribute value. |
615 | /// |
616 | /// This is equivalent to the Python expression `self.attr_name`. |
617 | /// |
618 | /// If calling this method becomes performance-critical, the [`intern!`](crate::intern) macro |
619 | /// can be used to intern `attr_name`, thereby avoiding repeated temporary allocations of |
620 | /// Python strings. |
621 | /// |
622 | /// # Example: `intern!`ing the attribute name |
623 | /// |
624 | /// ``` |
625 | /// # use pyo3::{intern, pyfunction, types::PyModule, IntoPy, Py, Python, PyObject, PyResult}; |
626 | /// # |
627 | /// #[pyfunction] |
628 | /// fn version(sys: Py<PyModule>, py: Python<'_>) -> PyResult<PyObject> { |
629 | /// sys.getattr(py, intern!(py, "version" )) |
630 | /// } |
631 | /// # |
632 | /// # Python::with_gil(|py| { |
633 | /// # let sys = py.import("sys" ).unwrap().into_py(py); |
634 | /// # version(sys, py).unwrap(); |
635 | /// # }); |
636 | /// ``` |
637 | pub fn getattr<N>(&self, py: Python<'_>, attr_name: N) -> PyResult<PyObject> |
638 | where |
639 | N: IntoPy<Py<PyString>>, |
640 | { |
641 | let attr_name = attr_name.into_py(py); |
642 | |
643 | unsafe { |
644 | PyObject::from_owned_ptr_or_err( |
645 | py, |
646 | ffi::PyObject_GetAttr(self.as_ptr(), attr_name.as_ptr()), |
647 | ) |
648 | } |
649 | } |
650 | |
651 | /// Sets an attribute value. |
652 | /// |
653 | /// This is equivalent to the Python expression `self.attr_name = value`. |
654 | /// |
655 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) |
656 | /// macro can be used to intern `attr_name`. |
657 | /// |
658 | /// # Example: `intern!`ing the attribute name |
659 | /// |
660 | /// ``` |
661 | /// # use pyo3::{intern, pyfunction, types::PyModule, IntoPy, PyObject, Python, PyResult}; |
662 | /// # |
663 | /// #[pyfunction] |
664 | /// fn set_answer(ob: PyObject, py: Python<'_>) -> PyResult<()> { |
665 | /// ob.setattr(py, intern!(py, "answer" ), 42) |
666 | /// } |
667 | /// # |
668 | /// # Python::with_gil(|py| { |
669 | /// # let ob = PyModule::new(py, "empty" ).unwrap().into_py(py); |
670 | /// # set_answer(ob, py).unwrap(); |
671 | /// # }); |
672 | /// ``` |
673 | pub fn setattr<N, V>(&self, py: Python<'_>, attr_name: N, value: V) -> PyResult<()> |
674 | where |
675 | N: IntoPy<Py<PyString>>, |
676 | V: IntoPy<Py<PyAny>>, |
677 | { |
678 | let attr_name = attr_name.into_py(py); |
679 | let value = value.into_py(py); |
680 | |
681 | err::error_on_minusone(py, unsafe { |
682 | ffi::PyObject_SetAttr(self.as_ptr(), attr_name.as_ptr(), value.as_ptr()) |
683 | }) |
684 | } |
685 | |
686 | /// Calls the object. |
687 | /// |
688 | /// This is equivalent to the Python expression `self(*args, **kwargs)`. |
689 | pub fn call( |
690 | &self, |
691 | py: Python<'_>, |
692 | args: impl IntoPy<Py<PyTuple>>, |
693 | kwargs: Option<&PyDict>, |
694 | ) -> PyResult<PyObject> { |
695 | let args = args.into_py(py); |
696 | let kwargs = kwargs.map_or(std::ptr::null_mut(), |p| p.into_ptr()); |
697 | |
698 | unsafe { |
699 | let ret = PyObject::from_owned_ptr_or_err( |
700 | py, |
701 | ffi::PyObject_Call(self.as_ptr(), args.as_ptr(), kwargs), |
702 | ); |
703 | ffi::Py_XDECREF(kwargs); |
704 | ret |
705 | } |
706 | } |
707 | |
708 | /// Calls the object with only positional arguments. |
709 | /// |
710 | /// This is equivalent to the Python expression `self(*args)`. |
711 | pub fn call1(&self, py: Python<'_>, args: impl IntoPy<Py<PyTuple>>) -> PyResult<PyObject> { |
712 | self.call(py, args, None) |
713 | } |
714 | |
715 | /// Calls the object without arguments. |
716 | /// |
717 | /// This is equivalent to the Python expression `self()`. |
718 | pub fn call0(&self, py: Python<'_>) -> PyResult<PyObject> { |
719 | cfg_if::cfg_if! { |
720 | if #[cfg(all( |
721 | not(PyPy), |
722 | any(Py_3_10, all(not(Py_LIMITED_API), Py_3_9)) // PyObject_CallNoArgs was added to python in 3.9 but to limited API in 3.10 |
723 | ))] { |
724 | // Optimized path on python 3.9+ |
725 | unsafe { |
726 | PyObject::from_owned_ptr_or_err(py, ffi::PyObject_CallNoArgs(self.as_ptr())) |
727 | } |
728 | } else { |
729 | self.call(py, (), None) |
730 | } |
731 | } |
732 | } |
733 | |
734 | /// Calls a method on the object. |
735 | /// |
736 | /// This is equivalent to the Python expression `self.name(*args, **kwargs)`. |
737 | /// |
738 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) |
739 | /// macro can be used to intern `name`. |
740 | pub fn call_method<N, A>( |
741 | &self, |
742 | py: Python<'_>, |
743 | name: N, |
744 | args: A, |
745 | kwargs: Option<&PyDict>, |
746 | ) -> PyResult<PyObject> |
747 | where |
748 | N: IntoPy<Py<PyString>>, |
749 | A: IntoPy<Py<PyTuple>>, |
750 | { |
751 | let callee = self.getattr(py, name)?; |
752 | let args: Py<PyTuple> = args.into_py(py); |
753 | let kwargs = kwargs.map_or(std::ptr::null_mut(), |p| p.into_ptr()); |
754 | |
755 | unsafe { |
756 | let result = PyObject::from_owned_ptr_or_err( |
757 | py, |
758 | ffi::PyObject_Call(callee.as_ptr(), args.as_ptr(), kwargs), |
759 | ); |
760 | ffi::Py_XDECREF(kwargs); |
761 | result |
762 | } |
763 | } |
764 | |
765 | /// Calls a method on the object with only positional arguments. |
766 | /// |
767 | /// This is equivalent to the Python expression `self.name(*args)`. |
768 | /// |
769 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) |
770 | /// macro can be used to intern `name`. |
771 | pub fn call_method1<N, A>(&self, py: Python<'_>, name: N, args: A) -> PyResult<PyObject> |
772 | where |
773 | N: IntoPy<Py<PyString>>, |
774 | A: IntoPy<Py<PyTuple>>, |
775 | { |
776 | self.call_method(py, name, args, None) |
777 | } |
778 | |
779 | /// Calls a method on the object with no arguments. |
780 | /// |
781 | /// This is equivalent to the Python expression `self.name()`. |
782 | /// |
783 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) |
784 | /// macro can be used to intern `name`. |
785 | pub fn call_method0<N>(&self, py: Python<'_>, name: N) -> PyResult<PyObject> |
786 | where |
787 | N: IntoPy<Py<PyString>>, |
788 | { |
789 | cfg_if::cfg_if! { |
790 | if #[cfg(all(Py_3_9, not(any(Py_LIMITED_API, PyPy))))] { |
791 | // Optimized path on python 3.9+ |
792 | unsafe { |
793 | let name: Py<PyString> = name.into_py(py); |
794 | PyObject::from_owned_ptr_or_err(py, ffi::PyObject_CallMethodNoArgs(self.as_ptr(), name.as_ptr())) |
795 | } |
796 | } else { |
797 | self.call_method(py, name, (), None) |
798 | } |
799 | } |
800 | } |
801 | |
802 | /// Create a `Py<T>` instance by taking ownership of the given FFI pointer. |
803 | /// |
804 | /// # Safety |
805 | /// `ptr` must be a pointer to a Python object of type T. |
806 | /// |
807 | /// Callers must own the object referred to by `ptr`, as this function |
808 | /// implicitly takes ownership of that object. |
809 | /// |
810 | /// # Panics |
811 | /// Panics if `ptr` is null. |
812 | #[inline ] |
813 | pub unsafe fn from_owned_ptr(py: Python<'_>, ptr: *mut ffi::PyObject) -> Py<T> { |
814 | match NonNull::new(ptr) { |
815 | Some(nonnull_ptr) => Py(nonnull_ptr, PhantomData), |
816 | None => crate::err::panic_after_error(py), |
817 | } |
818 | } |
819 | |
820 | /// Create a `Py<T>` instance by taking ownership of the given FFI pointer. |
821 | /// |
822 | /// If `ptr` is null then the current Python exception is fetched as a [`PyErr`]. |
823 | /// |
824 | /// # Safety |
825 | /// If non-null, `ptr` must be a pointer to a Python object of type T. |
826 | #[inline ] |
827 | pub unsafe fn from_owned_ptr_or_err( |
828 | py: Python<'_>, |
829 | ptr: *mut ffi::PyObject, |
830 | ) -> PyResult<Py<T>> { |
831 | match NonNull::new(ptr) { |
832 | Some(nonnull_ptr) => Ok(Py(nonnull_ptr, PhantomData)), |
833 | None => Err(PyErr::fetch(py)), |
834 | } |
835 | } |
836 | |
837 | /// Create a `Py<T>` instance by taking ownership of the given FFI pointer. |
838 | /// |
839 | /// If `ptr` is null then `None` is returned. |
840 | /// |
841 | /// # Safety |
842 | /// If non-null, `ptr` must be a pointer to a Python object of type T. |
843 | #[inline ] |
844 | pub unsafe fn from_owned_ptr_or_opt(_py: Python<'_>, ptr: *mut ffi::PyObject) -> Option<Self> { |
845 | NonNull::new(ptr).map(|nonnull_ptr| Py(nonnull_ptr, PhantomData)) |
846 | } |
847 | |
848 | /// Create a `Py<T>` instance by creating a new reference from the given FFI pointer. |
849 | /// |
850 | /// # Safety |
851 | /// `ptr` must be a pointer to a Python object of type T. |
852 | /// |
853 | /// # Panics |
854 | /// Panics if `ptr` is null. |
855 | #[inline ] |
856 | pub unsafe fn from_borrowed_ptr(py: Python<'_>, ptr: *mut ffi::PyObject) -> Py<T> { |
857 | match Self::from_borrowed_ptr_or_opt(py, ptr) { |
858 | Some(slf) => slf, |
859 | None => crate::err::panic_after_error(py), |
860 | } |
861 | } |
862 | |
863 | /// Create a `Py<T>` instance by creating a new reference from the given FFI pointer. |
864 | /// |
865 | /// If `ptr` is null then the current Python exception is fetched as a `PyErr`. |
866 | /// |
867 | /// # Safety |
868 | /// `ptr` must be a pointer to a Python object of type T. |
869 | #[inline ] |
870 | pub unsafe fn from_borrowed_ptr_or_err( |
871 | py: Python<'_>, |
872 | ptr: *mut ffi::PyObject, |
873 | ) -> PyResult<Self> { |
874 | Self::from_borrowed_ptr_or_opt(py, ptr).ok_or_else(|| PyErr::fetch(py)) |
875 | } |
876 | |
877 | /// Create a `Py<T>` instance by creating a new reference from the given FFI pointer. |
878 | /// |
879 | /// If `ptr` is null then `None` is returned. |
880 | /// |
881 | /// # Safety |
882 | /// `ptr` must be a pointer to a Python object of type T. |
883 | #[inline ] |
884 | pub unsafe fn from_borrowed_ptr_or_opt( |
885 | _py: Python<'_>, |
886 | ptr: *mut ffi::PyObject, |
887 | ) -> Option<Self> { |
888 | NonNull::new(ptr).map(|nonnull_ptr| { |
889 | ffi::Py_INCREF(ptr); |
890 | Py(nonnull_ptr, PhantomData) |
891 | }) |
892 | } |
893 | |
894 | /// For internal conversions. |
895 | /// |
896 | /// # Safety |
897 | /// `ptr` must point to a Python object of type T. |
898 | #[inline ] |
899 | unsafe fn from_non_null(ptr: NonNull<ffi::PyObject>) -> Self { |
900 | Self(ptr, PhantomData) |
901 | } |
902 | |
903 | /// Returns the inner pointer without decreasing the refcount. |
904 | #[inline ] |
905 | fn into_non_null(self) -> NonNull<ffi::PyObject> { |
906 | let pointer = self.0; |
907 | mem::forget(self); |
908 | pointer |
909 | } |
910 | } |
911 | |
912 | impl<T> ToPyObject for Py<T> { |
913 | /// Converts `Py` instance -> PyObject. |
914 | fn to_object(&self, py: Python<'_>) -> PyObject { |
915 | unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) } |
916 | } |
917 | } |
918 | |
919 | impl<T> IntoPy<PyObject> for Py<T> { |
920 | /// Converts a `Py` instance to `PyObject`. |
921 | /// Consumes `self` without calling `Py_DECREF()`. |
922 | #[inline ] |
923 | fn into_py(self, _py: Python<'_>) -> PyObject { |
924 | unsafe { PyObject::from_non_null(self.into_non_null()) } |
925 | } |
926 | } |
927 | |
928 | impl<T> IntoPy<PyObject> for &'_ Py<T> { |
929 | #[inline ] |
930 | fn into_py(self, py: Python<'_>) -> PyObject { |
931 | self.to_object(py) |
932 | } |
933 | } |
934 | |
935 | unsafe impl<T> crate::AsPyPointer for Py<T> { |
936 | /// Gets the underlying FFI pointer, returns a borrowed pointer. |
937 | #[inline ] |
938 | fn as_ptr(&self) -> *mut ffi::PyObject { |
939 | self.0.as_ptr() |
940 | } |
941 | } |
942 | |
943 | impl std::convert::From<&'_ PyAny> for PyObject { |
944 | fn from(obj: &PyAny) -> Self { |
945 | unsafe { Py::from_borrowed_ptr(obj.py(), obj.as_ptr()) } |
946 | } |
947 | } |
948 | |
949 | impl<T> std::convert::From<&'_ T> for PyObject |
950 | where |
951 | T: PyNativeType + AsRef<PyAny>, |
952 | { |
953 | fn from(obj: &T) -> Self { |
954 | unsafe { Py::from_borrowed_ptr(obj.py(), obj.as_ref().as_ptr()) } |
955 | } |
956 | } |
957 | |
958 | impl<T> std::convert::From<Py<T>> for PyObject |
959 | where |
960 | T: AsRef<PyAny>, |
961 | { |
962 | #[inline ] |
963 | fn from(other: Py<T>) -> Self { |
964 | unsafe { Self::from_non_null(ptr:other.into_non_null()) } |
965 | } |
966 | } |
967 | |
968 | // `&PyCell<T>` can be converted to `Py<T>` |
969 | impl<T> std::convert::From<&PyCell<T>> for Py<T> |
970 | where |
971 | T: PyClass, |
972 | { |
973 | fn from(cell: &PyCell<T>) -> Self { |
974 | unsafe { Py::from_borrowed_ptr(cell.py(), cell.as_ptr()) } |
975 | } |
976 | } |
977 | |
978 | impl<'a, T> std::convert::From<PyRef<'a, T>> for Py<T> |
979 | where |
980 | T: PyClass, |
981 | { |
982 | fn from(pyref: PyRef<'a, T>) -> Self { |
983 | unsafe { Py::from_borrowed_ptr(pyref.py(), pyref.as_ptr()) } |
984 | } |
985 | } |
986 | |
987 | impl<'a, T> std::convert::From<PyRefMut<'a, T>> for Py<T> |
988 | where |
989 | T: PyClass<Frozen = False>, |
990 | { |
991 | fn from(pyref: PyRefMut<'a, T>) -> Self { |
992 | unsafe { Py::from_borrowed_ptr(pyref.py(), pyref.as_ptr()) } |
993 | } |
994 | } |
995 | |
996 | /// If the GIL is held this increments `self`'s reference count. |
997 | /// Otherwise this registers the [`Py`]`<T>` instance to have its reference count |
998 | /// incremented the next time PyO3 acquires the GIL. |
999 | impl<T> Clone for Py<T> { |
1000 | fn clone(&self) -> Self { |
1001 | unsafe { |
1002 | gil::register_incref(self.0); |
1003 | } |
1004 | Self(self.0, PhantomData) |
1005 | } |
1006 | } |
1007 | |
1008 | /// Dropping a `Py` instance decrements the reference count on the object by 1. |
1009 | impl<T> Drop for Py<T> { |
1010 | fn drop(&mut self) { |
1011 | unsafe { |
1012 | gil::register_decref(self.0); |
1013 | } |
1014 | } |
1015 | } |
1016 | |
1017 | impl<'a, T> FromPyObject<'a> for Py<T> |
1018 | where |
1019 | T: PyTypeInfo, |
1020 | &'a T::AsRefTarget: FromPyObject<'a>, |
1021 | T::AsRefTarget: 'a + AsPyPointer, |
1022 | { |
1023 | /// Extracts `Self` from the source `PyObject`. |
1024 | fn extract(ob: &'a PyAny) -> PyResult<Self> { |
1025 | unsafe { |
1026 | ob.extract::<&T::AsRefTarget>() |
1027 | .map(|val: &::AsRefTarget| Py::from_borrowed_ptr(ob.py(), val.as_ptr())) |
1028 | } |
1029 | } |
1030 | } |
1031 | |
1032 | /// `Py<T>` can be used as an error when T is an Error. |
1033 | /// |
1034 | /// However for GIL lifetime reasons, cause() cannot be implemented for `Py<T>`. |
1035 | /// Use .as_ref() to get the GIL-scoped error if you need to inspect the cause. |
1036 | impl<T> std::error::Error for Py<T> |
1037 | where |
1038 | T: std::error::Error + PyTypeInfo, |
1039 | T::AsRefTarget: std::fmt::Display, |
1040 | { |
1041 | } |
1042 | |
1043 | impl<T> std::fmt::Display for Py<T> |
1044 | where |
1045 | T: PyTypeInfo, |
1046 | T::AsRefTarget: std::fmt::Display, |
1047 | { |
1048 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
1049 | Python::with_gil(|py: Python<'_>| std::fmt::Display::fmt(self.as_ref(py), f)) |
1050 | } |
1051 | } |
1052 | |
1053 | impl<T> std::fmt::Debug for Py<T> { |
1054 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
1055 | f.debug_tuple(name:"Py" ).field(&self.0.as_ptr()).finish() |
1056 | } |
1057 | } |
1058 | |
1059 | /// A commonly-used alias for `Py<PyAny>`. |
1060 | /// |
1061 | /// This is an owned reference a Python object without any type information. This value can also be |
1062 | /// safely sent between threads. |
1063 | /// |
1064 | /// See the documentation for [`Py`](struct.Py.html). |
1065 | pub type PyObject = Py<PyAny>; |
1066 | |
1067 | impl PyObject { |
1068 | /// Downcast this `PyObject` to a concrete Python type or pyclass. |
1069 | /// |
1070 | /// Note that you can often avoid downcasting yourself by just specifying |
1071 | /// the desired type in function or method signatures. |
1072 | /// However, manual downcasting is sometimes necessary. |
1073 | /// |
1074 | /// For extracting a Rust-only type, see [`Py::extract`](struct.Py.html#method.extract). |
1075 | /// |
1076 | /// # Example: Downcasting to a specific Python object |
1077 | /// |
1078 | /// ```rust |
1079 | /// use pyo3::prelude::*; |
1080 | /// use pyo3::types::{PyDict, PyList}; |
1081 | /// |
1082 | /// Python::with_gil(|py| { |
1083 | /// let any: PyObject = PyDict::new(py).into(); |
1084 | /// |
1085 | /// assert!(any.downcast::<PyDict>(py).is_ok()); |
1086 | /// assert!(any.downcast::<PyList>(py).is_err()); |
1087 | /// }); |
1088 | /// ``` |
1089 | /// |
1090 | /// # Example: Getting a reference to a pyclass |
1091 | /// |
1092 | /// This is useful if you want to mutate a `PyObject` that |
1093 | /// might actually be a pyclass. |
1094 | /// |
1095 | /// ```rust |
1096 | /// # fn main() -> Result<(), pyo3::PyErr> { |
1097 | /// use pyo3::prelude::*; |
1098 | /// |
1099 | /// #[pyclass] |
1100 | /// struct Class { |
1101 | /// i: i32, |
1102 | /// } |
1103 | /// |
1104 | /// Python::with_gil(|py| { |
1105 | /// let class: PyObject = Py::new(py, Class { i: 0 }).unwrap().into_py(py); |
1106 | /// |
1107 | /// let class_cell: &PyCell<Class> = class.downcast(py)?; |
1108 | /// |
1109 | /// class_cell.borrow_mut().i += 1; |
1110 | /// |
1111 | /// // Alternatively you can get a `PyRefMut` directly |
1112 | /// let class_ref: PyRefMut<'_, Class> = class.extract(py)?; |
1113 | /// assert_eq!(class_ref.i, 1); |
1114 | /// Ok(()) |
1115 | /// }) |
1116 | /// # } |
1117 | /// ``` |
1118 | #[inline ] |
1119 | pub fn downcast<'p, T>(&'p self, py: Python<'p>) -> Result<&T, PyDowncastError<'_>> |
1120 | where |
1121 | T: PyTryFrom<'p>, |
1122 | { |
1123 | <T as PyTryFrom<'_>>::try_from(self.as_ref(py)) |
1124 | } |
1125 | |
1126 | /// Casts the PyObject to a concrete Python object type without checking validity. |
1127 | /// |
1128 | /// # Safety |
1129 | /// |
1130 | /// Callers must ensure that the type is valid or risk type confusion. |
1131 | #[inline ] |
1132 | pub unsafe fn downcast_unchecked<'p, T>(&'p self, py: Python<'p>) -> &T |
1133 | where |
1134 | T: PyTryFrom<'p>, |
1135 | { |
1136 | <T as PyTryFrom<'_>>::try_from_unchecked(self.as_ref(py)) |
1137 | } |
1138 | } |
1139 | |
1140 | #[cfg (test)] |
1141 | mod tests { |
1142 | use super::{Py, PyObject}; |
1143 | use crate::types::{PyDict, PyString}; |
1144 | use crate::{PyAny, PyResult, Python, ToPyObject}; |
1145 | |
1146 | #[test ] |
1147 | fn test_call0() { |
1148 | Python::with_gil(|py| { |
1149 | let obj = py.get_type::<PyDict>().to_object(py); |
1150 | assert_eq!( |
1151 | obj.call0(py) |
1152 | .unwrap() |
1153 | .as_ref(py) |
1154 | .repr() |
1155 | .unwrap() |
1156 | .to_string_lossy(), |
1157 | "{}" |
1158 | ); |
1159 | }) |
1160 | } |
1161 | |
1162 | #[test ] |
1163 | fn test_call_for_non_existing_method() { |
1164 | Python::with_gil(|py| { |
1165 | let obj: PyObject = PyDict::new(py).into(); |
1166 | assert!(obj.call_method0(py, "asdf" ).is_err()); |
1167 | assert!(obj |
1168 | .call_method(py, "nonexistent_method" , (1,), None) |
1169 | .is_err()); |
1170 | assert!(obj.call_method0(py, "nonexistent_method" ).is_err()); |
1171 | assert!(obj.call_method1(py, "nonexistent_method" , (1,)).is_err()); |
1172 | }); |
1173 | } |
1174 | |
1175 | #[test ] |
1176 | fn py_from_dict() { |
1177 | let dict: Py<PyDict> = Python::with_gil(|py| { |
1178 | let native = PyDict::new(py); |
1179 | Py::from(native) |
1180 | }); |
1181 | |
1182 | assert_eq!(Python::with_gil(|py| dict.get_refcnt(py)), 1); |
1183 | } |
1184 | |
1185 | #[test ] |
1186 | fn pyobject_from_py() { |
1187 | Python::with_gil(|py| { |
1188 | let dict: Py<PyDict> = PyDict::new(py).into(); |
1189 | let cnt = dict.get_refcnt(py); |
1190 | let p: PyObject = dict.into(); |
1191 | assert_eq!(p.get_refcnt(py), cnt); |
1192 | }); |
1193 | } |
1194 | |
1195 | #[test ] |
1196 | fn attr() -> PyResult<()> { |
1197 | use crate::types::PyModule; |
1198 | |
1199 | Python::with_gil(|py| { |
1200 | const CODE: &str = r#" |
1201 | class A: |
1202 | pass |
1203 | a = A() |
1204 | "# ; |
1205 | let module = PyModule::from_code(py, CODE, "" , "" )?; |
1206 | let instance: Py<PyAny> = module.getattr("a" )?.into(); |
1207 | |
1208 | instance.getattr(py, "foo" ).unwrap_err(); |
1209 | |
1210 | instance.setattr(py, "foo" , "bar" )?; |
1211 | |
1212 | assert!(instance |
1213 | .getattr(py, "foo" )? |
1214 | .as_ref(py) |
1215 | .eq(PyString::new(py, "bar" ))?); |
1216 | |
1217 | instance.getattr(py, "foo" )?; |
1218 | Ok(()) |
1219 | }) |
1220 | } |
1221 | |
1222 | #[test ] |
1223 | fn pystring_attr() -> PyResult<()> { |
1224 | use crate::types::PyModule; |
1225 | |
1226 | Python::with_gil(|py| { |
1227 | const CODE: &str = r#" |
1228 | class A: |
1229 | pass |
1230 | a = A() |
1231 | "# ; |
1232 | let module = PyModule::from_code(py, CODE, "" , "" )?; |
1233 | let instance: Py<PyAny> = module.getattr("a" )?.into(); |
1234 | |
1235 | let foo = crate::intern!(py, "foo" ); |
1236 | let bar = crate::intern!(py, "bar" ); |
1237 | |
1238 | instance.getattr(py, foo).unwrap_err(); |
1239 | instance.setattr(py, foo, bar)?; |
1240 | assert!(instance.getattr(py, foo)?.as_ref(py).eq(bar)?); |
1241 | Ok(()) |
1242 | }) |
1243 | } |
1244 | |
1245 | #[test ] |
1246 | fn invalid_attr() -> PyResult<()> { |
1247 | Python::with_gil(|py| { |
1248 | let instance: Py<PyAny> = py.eval("object()" , None, None)?.into(); |
1249 | |
1250 | instance.getattr(py, "foo" ).unwrap_err(); |
1251 | |
1252 | // Cannot assign arbitrary attributes to `object` |
1253 | instance.setattr(py, "foo" , "bar" ).unwrap_err(); |
1254 | Ok(()) |
1255 | }) |
1256 | } |
1257 | |
1258 | #[test ] |
1259 | fn test_is_ellipsis() { |
1260 | Python::with_gil(|py| { |
1261 | let v = py |
1262 | .eval("..." , None, None) |
1263 | .map_err(|e| e.display(py)) |
1264 | .unwrap() |
1265 | .to_object(py); |
1266 | |
1267 | assert!(v.is_ellipsis()); |
1268 | |
1269 | let not_ellipsis = 5.to_object(py); |
1270 | assert!(!not_ellipsis.is_ellipsis()); |
1271 | }); |
1272 | } |
1273 | |
1274 | #[cfg (feature = "macros" )] |
1275 | mod using_macros { |
1276 | use super::*; |
1277 | |
1278 | #[crate::pyclass ] |
1279 | #[pyo3(crate = "crate" )] |
1280 | struct SomeClass(i32); |
1281 | |
1282 | #[test ] |
1283 | fn instance_borrow_methods() { |
1284 | // More detailed tests of the underlying semantics in pycell.rs |
1285 | Python::with_gil(|py| { |
1286 | let instance = Py::new(py, SomeClass(0)).unwrap(); |
1287 | assert_eq!(instance.borrow(py).0, 0); |
1288 | assert_eq!(instance.try_borrow(py).unwrap().0, 0); |
1289 | assert_eq!(instance.borrow_mut(py).0, 0); |
1290 | assert_eq!(instance.try_borrow_mut(py).unwrap().0, 0); |
1291 | |
1292 | instance.borrow_mut(py).0 = 123; |
1293 | |
1294 | assert_eq!(instance.borrow(py).0, 123); |
1295 | assert_eq!(instance.try_borrow(py).unwrap().0, 123); |
1296 | assert_eq!(instance.borrow_mut(py).0, 123); |
1297 | assert_eq!(instance.try_borrow_mut(py).unwrap().0, 123); |
1298 | }) |
1299 | } |
1300 | } |
1301 | } |
1302 | |