| 1 | use crate::conversion::IntoPyObject; |
| 2 | use crate::err::{self, PyErr, PyResult}; |
| 3 | use crate::impl_::pycell::PyClassObject; |
| 4 | use crate::internal_tricks::ptr_from_ref; |
| 5 | use crate::pycell::{PyBorrowError, PyBorrowMutError}; |
| 6 | use crate::pyclass::boolean_struct::{False, True}; |
| 7 | use crate::types::{any::PyAnyMethods, string::PyStringMethods, typeobject::PyTypeMethods}; |
| 8 | use crate::types::{DerefToPyAny, PyDict, PyString, PyTuple}; |
| 9 | use crate::{ |
| 10 | ffi, AsPyPointer, DowncastError, FromPyObject, PyAny, PyClass, PyClassInitializer, PyRef, |
| 11 | PyRefMut, PyTypeInfo, Python, |
| 12 | }; |
| 13 | use crate::{gil, PyTypeCheck}; |
| 14 | #[allow (deprecated)] |
| 15 | use crate::{IntoPy, ToPyObject}; |
| 16 | use std::marker::PhantomData; |
| 17 | use std::mem::ManuallyDrop; |
| 18 | use std::ops::Deref; |
| 19 | use std::ptr; |
| 20 | use std::ptr::NonNull; |
| 21 | |
| 22 | /// Owned or borrowed gil-bound Python smart pointer |
| 23 | /// |
| 24 | /// This is implemented for [`Bound`] and [`Borrowed`]. |
| 25 | pub trait BoundObject<'py, T>: bound_object_sealed::Sealed { |
| 26 | /// Type erased version of `Self` |
| 27 | type Any: BoundObject<'py, PyAny>; |
| 28 | /// Borrow this smart pointer. |
| 29 | fn as_borrowed(&self) -> Borrowed<'_, 'py, T>; |
| 30 | /// Turns this smart pointer into an owned [`Bound<'py, T>`] |
| 31 | fn into_bound(self) -> Bound<'py, T>; |
| 32 | /// Upcast the target type of this smart pointer |
| 33 | fn into_any(self) -> Self::Any; |
| 34 | /// Turn this smart pointer into a strong reference pointer |
| 35 | fn into_ptr(self) -> *mut ffi::PyObject; |
| 36 | /// Turn this smart pointer into a borrowed reference pointer |
| 37 | fn as_ptr(&self) -> *mut ffi::PyObject; |
| 38 | /// Turn this smart pointer into an owned [`Py<T>`] |
| 39 | fn unbind(self) -> Py<T>; |
| 40 | } |
| 41 | |
| 42 | mod bound_object_sealed { |
| 43 | /// # Safety |
| 44 | /// |
| 45 | /// Type must be layout-compatible with `*mut ffi::PyObject`. |
| 46 | pub unsafe trait Sealed {} |
| 47 | |
| 48 | // SAFETY: `Bound` is layout-compatible with `*mut ffi::PyObject`. |
| 49 | unsafe impl<T> Sealed for super::Bound<'_, T> {} |
| 50 | // SAFETY: `Borrowed` is layout-compatible with `*mut ffi::PyObject`. |
| 51 | unsafe impl<T> Sealed for super::Borrowed<'_, '_, T> {} |
| 52 | } |
| 53 | |
| 54 | /// A GIL-attached equivalent to [`Py<T>`]. |
| 55 | /// |
| 56 | /// This type can be thought of as equivalent to the tuple `(Py<T>, Python<'py>)`. By having the `'py` |
| 57 | /// lifetime of the [`Python<'py>`] token, this ties the lifetime of the [`Bound<'py, T>`] smart pointer |
| 58 | /// to the lifetime of the GIL and allows PyO3 to call Python APIs at maximum efficiency. |
| 59 | /// |
| 60 | /// To access the object in situations where the GIL is not held, convert it to [`Py<T>`] |
| 61 | /// using [`.unbind()`][Bound::unbind]. This includes situations where the GIL is temporarily |
| 62 | /// released, such as [`Python::allow_threads`](crate::Python::allow_threads)'s closure. |
| 63 | /// |
| 64 | /// See |
| 65 | #[doc = concat!("[the guide](https://pyo3.rs/v" , env!("CARGO_PKG_VERSION" ), "/types.html#boundpy-t)" )] |
| 66 | /// for more detail. |
| 67 | #[repr (transparent)] |
| 68 | pub struct Bound<'py, T>(Python<'py>, ManuallyDrop<Py<T>>); |
| 69 | |
| 70 | impl<'py, T> Bound<'py, T> |
| 71 | where |
| 72 | T: PyClass, |
| 73 | { |
| 74 | /// Creates a new instance `Bound<T>` of a `#[pyclass]` on the Python heap. |
| 75 | /// |
| 76 | /// # Examples |
| 77 | /// |
| 78 | /// ```rust |
| 79 | /// use pyo3::prelude::*; |
| 80 | /// |
| 81 | /// #[pyclass] |
| 82 | /// struct Foo {/* fields omitted */} |
| 83 | /// |
| 84 | /// # fn main() -> PyResult<()> { |
| 85 | /// let foo: Py<Foo> = Python::with_gil(|py| -> PyResult<_> { |
| 86 | /// let foo: Bound<'_, Foo> = Bound::new(py, Foo {})?; |
| 87 | /// Ok(foo.into()) |
| 88 | /// })?; |
| 89 | /// # Python::with_gil(move |_py| drop(foo)); |
| 90 | /// # Ok(()) |
| 91 | /// # } |
| 92 | /// ``` |
| 93 | pub fn new( |
| 94 | py: Python<'py>, |
| 95 | value: impl Into<PyClassInitializer<T>>, |
| 96 | ) -> PyResult<Bound<'py, T>> { |
| 97 | value.into().create_class_object(py) |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | impl<'py> Bound<'py, PyAny> { |
| 102 | /// Constructs a new `Bound<'py, PyAny>` from a pointer. Panics if `ptr` is null. |
| 103 | /// |
| 104 | /// # Safety |
| 105 | /// |
| 106 | /// - `ptr` must be a valid pointer to a Python object |
| 107 | /// - `ptr` must be an owned Python reference, as the `Bound<'py, PyAny>` will assume ownership |
| 108 | #[inline ] |
| 109 | #[track_caller ] |
| 110 | pub unsafe fn from_owned_ptr(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self { |
| 111 | Self( |
| 112 | py, |
| 113 | ManuallyDrop::new(unsafe { Py::from_owned_ptr(py, ptr) }), |
| 114 | ) |
| 115 | } |
| 116 | |
| 117 | /// Constructs a new `Bound<'py, PyAny>` from a pointer. Returns `None` if `ptr` is null. |
| 118 | /// |
| 119 | /// # Safety |
| 120 | /// |
| 121 | /// - `ptr` must be a valid pointer to a Python object, or null |
| 122 | /// - `ptr` must be an owned Python reference, as the `Bound<'py, PyAny>` will assume ownership |
| 123 | #[inline ] |
| 124 | pub unsafe fn from_owned_ptr_or_opt(py: Python<'py>, ptr: *mut ffi::PyObject) -> Option<Self> { |
| 125 | unsafe { Py::from_owned_ptr_or_opt(py, ptr) }.map(|obj| Self(py, ManuallyDrop::new(obj))) |
| 126 | } |
| 127 | |
| 128 | /// Constructs a new `Bound<'py, PyAny>` from a pointer. Returns an `Err` by calling `PyErr::fetch` |
| 129 | /// if `ptr` is null. |
| 130 | /// |
| 131 | /// # Safety |
| 132 | /// |
| 133 | /// - `ptr` must be a valid pointer to a Python object, or null |
| 134 | /// - `ptr` must be an owned Python reference, as the `Bound<'py, PyAny>` will assume ownership |
| 135 | #[inline ] |
| 136 | pub unsafe fn from_owned_ptr_or_err( |
| 137 | py: Python<'py>, |
| 138 | ptr: *mut ffi::PyObject, |
| 139 | ) -> PyResult<Self> { |
| 140 | unsafe { Py::from_owned_ptr_or_err(py, ptr) }.map(|obj| Self(py, ManuallyDrop::new(obj))) |
| 141 | } |
| 142 | |
| 143 | /// Constructs a new `Bound<'py, PyAny>` from a pointer without checking for null. |
| 144 | /// |
| 145 | /// # Safety |
| 146 | /// |
| 147 | /// - `ptr` must be a valid pointer to a Python object |
| 148 | /// - `ptr` must be a strong/owned reference |
| 149 | pub(crate) unsafe fn from_owned_ptr_unchecked( |
| 150 | py: Python<'py>, |
| 151 | ptr: *mut ffi::PyObject, |
| 152 | ) -> Self { |
| 153 | Self( |
| 154 | py, |
| 155 | ManuallyDrop::new(unsafe { Py::from_owned_ptr_unchecked(ptr) }), |
| 156 | ) |
| 157 | } |
| 158 | |
| 159 | /// Constructs a new `Bound<'py, PyAny>` from a pointer by creating a new Python reference. |
| 160 | /// Panics if `ptr` is null. |
| 161 | /// |
| 162 | /// # Safety |
| 163 | /// |
| 164 | /// - `ptr` must be a valid pointer to a Python object |
| 165 | #[inline ] |
| 166 | #[track_caller ] |
| 167 | pub unsafe fn from_borrowed_ptr(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self { |
| 168 | unsafe { Self(py, ManuallyDrop::new(Py::from_borrowed_ptr(py, ptr))) } |
| 169 | } |
| 170 | |
| 171 | /// Constructs a new `Bound<'py, PyAny>` from a pointer by creating a new Python reference. |
| 172 | /// Returns `None` if `ptr` is null. |
| 173 | /// |
| 174 | /// # Safety |
| 175 | /// |
| 176 | /// - `ptr` must be a valid pointer to a Python object, or null |
| 177 | #[inline ] |
| 178 | pub unsafe fn from_borrowed_ptr_or_opt( |
| 179 | py: Python<'py>, |
| 180 | ptr: *mut ffi::PyObject, |
| 181 | ) -> Option<Self> { |
| 182 | unsafe { Py::from_borrowed_ptr_or_opt(py, ptr).map(|obj| Self(py, ManuallyDrop::new(obj))) } |
| 183 | } |
| 184 | |
| 185 | /// Constructs a new `Bound<'py, PyAny>` from a pointer by creating a new Python reference. |
| 186 | /// Returns an `Err` by calling `PyErr::fetch` if `ptr` is null. |
| 187 | /// |
| 188 | /// # Safety |
| 189 | /// |
| 190 | /// - `ptr` must be a valid pointer to a Python object, or null |
| 191 | #[inline ] |
| 192 | pub unsafe fn from_borrowed_ptr_or_err( |
| 193 | py: Python<'py>, |
| 194 | ptr: *mut ffi::PyObject, |
| 195 | ) -> PyResult<Self> { |
| 196 | unsafe { Py::from_borrowed_ptr_or_err(py, ptr).map(|obj| Self(py, ManuallyDrop::new(obj))) } |
| 197 | } |
| 198 | |
| 199 | /// This slightly strange method is used to obtain `&Bound<PyAny>` from a pointer in macro code |
| 200 | /// where we need to constrain the lifetime `'a` safely. |
| 201 | /// |
| 202 | /// Note that `'py` is required to outlive `'a` implicitly by the nature of the fact that |
| 203 | /// `&'a Bound<'py>` means that `Bound<'py>` exists for at least the lifetime `'a`. |
| 204 | /// |
| 205 | /// # Safety |
| 206 | /// - `ptr` must be a valid pointer to a Python object for the lifetime `'a`. The `ptr` can |
| 207 | /// be either a borrowed reference or an owned reference, it does not matter, as this is |
| 208 | /// just `&Bound` there will never be any ownership transfer. |
| 209 | #[inline ] |
| 210 | pub(crate) unsafe fn ref_from_ptr<'a>( |
| 211 | _py: Python<'py>, |
| 212 | ptr: &'a *mut ffi::PyObject, |
| 213 | ) -> &'a Self { |
| 214 | unsafe { &*ptr_from_ref(ptr).cast::<Bound<'py, PyAny>>() } |
| 215 | } |
| 216 | |
| 217 | /// Variant of the above which returns `None` for null pointers. |
| 218 | /// |
| 219 | /// # Safety |
| 220 | /// - `ptr` must be a valid pointer to a Python object for the lifetime `'a, or null. |
| 221 | #[inline ] |
| 222 | pub(crate) unsafe fn ref_from_ptr_or_opt<'a>( |
| 223 | _py: Python<'py>, |
| 224 | ptr: &'a *mut ffi::PyObject, |
| 225 | ) -> &'a Option<Self> { |
| 226 | unsafe { &*ptr_from_ref(ptr).cast::<Option<Bound<'py, PyAny>>>() } |
| 227 | } |
| 228 | } |
| 229 | |
| 230 | impl<'py, T> Bound<'py, T> |
| 231 | where |
| 232 | T: PyClass, |
| 233 | { |
| 234 | /// Immutably borrows the value `T`. |
| 235 | /// |
| 236 | /// This borrow lasts while the returned [`PyRef`] exists. |
| 237 | /// Multiple immutable borrows can be taken out at the same time. |
| 238 | /// |
| 239 | /// For frozen classes, the simpler [`get`][Self::get] is available. |
| 240 | /// |
| 241 | /// # Examples |
| 242 | /// |
| 243 | /// ```rust |
| 244 | /// # use pyo3::prelude::*; |
| 245 | /// # |
| 246 | /// #[pyclass] |
| 247 | /// struct Foo { |
| 248 | /// inner: u8, |
| 249 | /// } |
| 250 | /// |
| 251 | /// # fn main() -> PyResult<()> { |
| 252 | /// Python::with_gil(|py| -> PyResult<()> { |
| 253 | /// let foo: Bound<'_, Foo> = Bound::new(py, Foo { inner: 73 })?; |
| 254 | /// let inner: &u8 = &foo.borrow().inner; |
| 255 | /// |
| 256 | /// assert_eq!(*inner, 73); |
| 257 | /// Ok(()) |
| 258 | /// })?; |
| 259 | /// # Ok(()) |
| 260 | /// # } |
| 261 | /// ``` |
| 262 | /// |
| 263 | /// # Panics |
| 264 | /// |
| 265 | /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use |
| 266 | /// [`try_borrow`](#method.try_borrow). |
| 267 | #[inline ] |
| 268 | #[track_caller ] |
| 269 | pub fn borrow(&self) -> PyRef<'py, T> { |
| 270 | PyRef::borrow(self) |
| 271 | } |
| 272 | |
| 273 | /// Mutably borrows the value `T`. |
| 274 | /// |
| 275 | /// This borrow lasts while the returned [`PyRefMut`] exists. |
| 276 | /// |
| 277 | /// # Examples |
| 278 | /// |
| 279 | /// ``` |
| 280 | /// # use pyo3::prelude::*; |
| 281 | /// # |
| 282 | /// #[pyclass] |
| 283 | /// struct Foo { |
| 284 | /// inner: u8, |
| 285 | /// } |
| 286 | /// |
| 287 | /// # fn main() -> PyResult<()> { |
| 288 | /// Python::with_gil(|py| -> PyResult<()> { |
| 289 | /// let foo: Bound<'_, Foo> = Bound::new(py, Foo { inner: 73 })?; |
| 290 | /// foo.borrow_mut().inner = 35; |
| 291 | /// |
| 292 | /// assert_eq!(foo.borrow().inner, 35); |
| 293 | /// Ok(()) |
| 294 | /// })?; |
| 295 | /// # Ok(()) |
| 296 | /// # } |
| 297 | /// ``` |
| 298 | /// |
| 299 | /// # Panics |
| 300 | /// Panics if the value is currently borrowed. For a non-panicking variant, use |
| 301 | /// [`try_borrow_mut`](#method.try_borrow_mut). |
| 302 | #[inline ] |
| 303 | #[track_caller ] |
| 304 | pub fn borrow_mut(&self) -> PyRefMut<'py, T> |
| 305 | where |
| 306 | T: PyClass<Frozen = False>, |
| 307 | { |
| 308 | PyRefMut::borrow(self) |
| 309 | } |
| 310 | |
| 311 | /// Attempts to immutably borrow the value `T`, returning an error if the value is currently mutably borrowed. |
| 312 | /// |
| 313 | /// The borrow lasts while the returned [`PyRef`] exists. |
| 314 | /// |
| 315 | /// This is the non-panicking variant of [`borrow`](#method.borrow). |
| 316 | /// |
| 317 | /// For frozen classes, the simpler [`get`][Self::get] is available. |
| 318 | #[inline ] |
| 319 | pub fn try_borrow(&self) -> Result<PyRef<'py, T>, PyBorrowError> { |
| 320 | PyRef::try_borrow(self) |
| 321 | } |
| 322 | |
| 323 | /// Attempts to mutably borrow the value `T`, returning an error if the value is currently borrowed. |
| 324 | /// |
| 325 | /// The borrow lasts while the returned [`PyRefMut`] exists. |
| 326 | /// |
| 327 | /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut). |
| 328 | #[inline ] |
| 329 | pub fn try_borrow_mut(&self) -> Result<PyRefMut<'py, T>, PyBorrowMutError> |
| 330 | where |
| 331 | T: PyClass<Frozen = False>, |
| 332 | { |
| 333 | PyRefMut::try_borrow(self) |
| 334 | } |
| 335 | |
| 336 | /// Provide an immutable borrow of the value `T` without acquiring the GIL. |
| 337 | /// |
| 338 | /// This is available if the class is [`frozen`][macro@crate::pyclass] and [`Sync`]. |
| 339 | /// |
| 340 | /// # Examples |
| 341 | /// |
| 342 | /// ``` |
| 343 | /// use std::sync::atomic::{AtomicUsize, Ordering}; |
| 344 | /// # use pyo3::prelude::*; |
| 345 | /// |
| 346 | /// #[pyclass(frozen)] |
| 347 | /// struct FrozenCounter { |
| 348 | /// value: AtomicUsize, |
| 349 | /// } |
| 350 | /// |
| 351 | /// Python::with_gil(|py| { |
| 352 | /// let counter = FrozenCounter { value: AtomicUsize::new(0) }; |
| 353 | /// |
| 354 | /// let py_counter = Bound::new(py, counter).unwrap(); |
| 355 | /// |
| 356 | /// py_counter.get().value.fetch_add(1, Ordering::Relaxed); |
| 357 | /// }); |
| 358 | /// ``` |
| 359 | #[inline ] |
| 360 | pub fn get(&self) -> &T |
| 361 | where |
| 362 | T: PyClass<Frozen = True> + Sync, |
| 363 | { |
| 364 | self.1.get() |
| 365 | } |
| 366 | |
| 367 | /// Upcast this `Bound<PyClass>` to its base type by reference. |
| 368 | /// |
| 369 | /// If this type defined an explicit base class in its `pyclass` declaration |
| 370 | /// (e.g. `#[pyclass(extends = BaseType)]`), the returned type will be |
| 371 | /// `&Bound<BaseType>`. If an explicit base class was _not_ declared, the |
| 372 | /// return value will be `&Bound<PyAny>` (making this method equivalent |
| 373 | /// to [`as_any`]). |
| 374 | /// |
| 375 | /// This method is particularly useful for calling methods defined in an |
| 376 | /// extension trait that has been implemented for `Bound<BaseType>`. |
| 377 | /// |
| 378 | /// See also the [`into_super`] method to upcast by value, and the |
| 379 | /// [`PyRef::as_super`]/[`PyRefMut::as_super`] methods for upcasting a pyclass |
| 380 | /// that has already been [`borrow`]ed. |
| 381 | /// |
| 382 | /// # Example: Calling a method defined on the `Bound` base type |
| 383 | /// |
| 384 | /// ```rust |
| 385 | /// # fn main() { |
| 386 | /// use pyo3::prelude::*; |
| 387 | /// |
| 388 | /// #[pyclass(subclass)] |
| 389 | /// struct BaseClass; |
| 390 | /// |
| 391 | /// trait MyClassMethods<'py> { |
| 392 | /// fn pyrepr(&self) -> PyResult<String>; |
| 393 | /// } |
| 394 | /// impl<'py> MyClassMethods<'py> for Bound<'py, BaseClass> { |
| 395 | /// fn pyrepr(&self) -> PyResult<String> { |
| 396 | /// self.call_method0("__repr__" )?.extract() |
| 397 | /// } |
| 398 | /// } |
| 399 | /// |
| 400 | /// #[pyclass(extends = BaseClass)] |
| 401 | /// struct SubClass; |
| 402 | /// |
| 403 | /// Python::with_gil(|py| { |
| 404 | /// let obj = Bound::new(py, (SubClass, BaseClass)).unwrap(); |
| 405 | /// assert!(obj.as_super().pyrepr().is_ok()); |
| 406 | /// }) |
| 407 | /// # } |
| 408 | /// ``` |
| 409 | /// |
| 410 | /// [`as_any`]: Bound::as_any |
| 411 | /// [`into_super`]: Bound::into_super |
| 412 | /// [`borrow`]: Bound::borrow |
| 413 | #[inline ] |
| 414 | pub fn as_super(&self) -> &Bound<'py, T::BaseType> { |
| 415 | // a pyclass can always be safely "downcast" to its base type |
| 416 | unsafe { self.as_any().downcast_unchecked() } |
| 417 | } |
| 418 | |
| 419 | /// Upcast this `Bound<PyClass>` to its base type by value. |
| 420 | /// |
| 421 | /// If this type defined an explicit base class in its `pyclass` declaration |
| 422 | /// (e.g. `#[pyclass(extends = BaseType)]`), the returned type will be |
| 423 | /// `Bound<BaseType>`. If an explicit base class was _not_ declared, the |
| 424 | /// return value will be `Bound<PyAny>` (making this method equivalent |
| 425 | /// to [`into_any`]). |
| 426 | /// |
| 427 | /// This method is particularly useful for calling methods defined in an |
| 428 | /// extension trait that has been implemented for `Bound<BaseType>`. |
| 429 | /// |
| 430 | /// See also the [`as_super`] method to upcast by reference, and the |
| 431 | /// [`PyRef::into_super`]/[`PyRefMut::into_super`] methods for upcasting a pyclass |
| 432 | /// that has already been [`borrow`]ed. |
| 433 | /// |
| 434 | /// # Example: Calling a method defined on the `Bound` base type |
| 435 | /// |
| 436 | /// ```rust |
| 437 | /// # fn main() { |
| 438 | /// use pyo3::prelude::*; |
| 439 | /// |
| 440 | /// #[pyclass(subclass)] |
| 441 | /// struct BaseClass; |
| 442 | /// |
| 443 | /// trait MyClassMethods<'py> { |
| 444 | /// fn pyrepr(self) -> PyResult<String>; |
| 445 | /// } |
| 446 | /// impl<'py> MyClassMethods<'py> for Bound<'py, BaseClass> { |
| 447 | /// fn pyrepr(self) -> PyResult<String> { |
| 448 | /// self.call_method0("__repr__" )?.extract() |
| 449 | /// } |
| 450 | /// } |
| 451 | /// |
| 452 | /// #[pyclass(extends = BaseClass)] |
| 453 | /// struct SubClass; |
| 454 | /// |
| 455 | /// Python::with_gil(|py| { |
| 456 | /// let obj = Bound::new(py, (SubClass, BaseClass)).unwrap(); |
| 457 | /// assert!(obj.into_super().pyrepr().is_ok()); |
| 458 | /// }) |
| 459 | /// # } |
| 460 | /// ``` |
| 461 | /// |
| 462 | /// [`into_any`]: Bound::into_any |
| 463 | /// [`as_super`]: Bound::as_super |
| 464 | /// [`borrow`]: Bound::borrow |
| 465 | #[inline ] |
| 466 | pub fn into_super(self) -> Bound<'py, T::BaseType> { |
| 467 | // a pyclass can always be safely "downcast" to its base type |
| 468 | unsafe { self.into_any().downcast_into_unchecked() } |
| 469 | } |
| 470 | |
| 471 | #[inline ] |
| 472 | pub(crate) fn get_class_object(&self) -> &PyClassObject<T> { |
| 473 | self.1.get_class_object() |
| 474 | } |
| 475 | } |
| 476 | |
| 477 | impl<T> std::fmt::Debug for Bound<'_, T> { |
| 478 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { |
| 479 | let any: &Bound<'_, PyAny> = self.as_any(); |
| 480 | python_format(any, format_result:any.repr(), f) |
| 481 | } |
| 482 | } |
| 483 | |
| 484 | impl<T> std::fmt::Display for Bound<'_, T> { |
| 485 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { |
| 486 | let any: &Bound<'_, PyAny> = self.as_any(); |
| 487 | python_format(any, format_result:any.str(), f) |
| 488 | } |
| 489 | } |
| 490 | |
| 491 | fn python_format( |
| 492 | any: &Bound<'_, PyAny>, |
| 493 | format_result: PyResult<Bound<'_, PyString>>, |
| 494 | f: &mut std::fmt::Formatter<'_>, |
| 495 | ) -> Result<(), std::fmt::Error> { |
| 496 | match format_result { |
| 497 | Result::Ok(s: Bound<'_, PyString>) => return f.write_str(&s.to_string_lossy()), |
| 498 | Result::Err(err: PyErr) => err.write_unraisable(any.py(), obj:Some(any)), |
| 499 | } |
| 500 | |
| 501 | match any.get_type().name() { |
| 502 | Result::Ok(name: Bound<'_, PyString>) => std::write!(f, "<unprintable {} object>" , name), |
| 503 | Result::Err(_err: PyErr) => f.write_str(data:"<unprintable object>" ), |
| 504 | } |
| 505 | } |
| 506 | |
| 507 | // The trait bound is needed to avoid running into the auto-deref recursion |
| 508 | // limit (error[E0055]), because `Bound<PyAny>` would deref into itself. See: |
| 509 | // https://github.com/rust-lang/rust/issues/19509 |
| 510 | impl<'py, T> Deref for Bound<'py, T> |
| 511 | where |
| 512 | T: DerefToPyAny, |
| 513 | { |
| 514 | type Target = Bound<'py, PyAny>; |
| 515 | |
| 516 | #[inline ] |
| 517 | fn deref(&self) -> &Bound<'py, PyAny> { |
| 518 | self.as_any() |
| 519 | } |
| 520 | } |
| 521 | |
| 522 | impl<'py, T> AsRef<Bound<'py, PyAny>> for Bound<'py, T> { |
| 523 | #[inline ] |
| 524 | fn as_ref(&self) -> &Bound<'py, PyAny> { |
| 525 | self.as_any() |
| 526 | } |
| 527 | } |
| 528 | |
| 529 | impl<T> Clone for Bound<'_, T> { |
| 530 | #[inline ] |
| 531 | fn clone(&self) -> Self { |
| 532 | Self(self.0, ManuallyDrop::new(self.1.clone_ref(self.0))) |
| 533 | } |
| 534 | } |
| 535 | |
| 536 | impl<T> Drop for Bound<'_, T> { |
| 537 | #[inline ] |
| 538 | fn drop(&mut self) { |
| 539 | unsafe { ffi::Py_DECREF(self.as_ptr()) } |
| 540 | } |
| 541 | } |
| 542 | |
| 543 | impl<'py, T> Bound<'py, T> { |
| 544 | /// Returns the GIL token associated with this object. |
| 545 | #[inline ] |
| 546 | pub fn py(&self) -> Python<'py> { |
| 547 | self.0 |
| 548 | } |
| 549 | |
| 550 | /// Returns the raw FFI pointer represented by self. |
| 551 | /// |
| 552 | /// # Safety |
| 553 | /// |
| 554 | /// Callers are responsible for ensuring that the pointer does not outlive self. |
| 555 | /// |
| 556 | /// The reference is borrowed; callers should not decrease the reference count |
| 557 | /// when they are finished with the pointer. |
| 558 | #[inline ] |
| 559 | pub fn as_ptr(&self) -> *mut ffi::PyObject { |
| 560 | self.1.as_ptr() |
| 561 | } |
| 562 | |
| 563 | /// Returns an owned raw FFI pointer represented by self. |
| 564 | /// |
| 565 | /// # Safety |
| 566 | /// |
| 567 | /// The reference is owned; when finished the caller should either transfer ownership |
| 568 | /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). |
| 569 | #[inline ] |
| 570 | pub fn into_ptr(self) -> *mut ffi::PyObject { |
| 571 | ManuallyDrop::new(self).as_ptr() |
| 572 | } |
| 573 | |
| 574 | /// Helper to cast to `Bound<'py, PyAny>`. |
| 575 | #[inline ] |
| 576 | pub fn as_any(&self) -> &Bound<'py, PyAny> { |
| 577 | // Safety: all Bound<T> have the same memory layout, and all Bound<T> are valid |
| 578 | // Bound<PyAny>, so pointer casting is valid. |
| 579 | unsafe { &*ptr_from_ref(self).cast::<Bound<'py, PyAny>>() } |
| 580 | } |
| 581 | |
| 582 | /// Helper to cast to `Bound<'py, PyAny>`, transferring ownership. |
| 583 | #[inline ] |
| 584 | pub fn into_any(self) -> Bound<'py, PyAny> { |
| 585 | // Safety: all Bound<T> are valid Bound<PyAny> |
| 586 | Bound(self.0, ManuallyDrop::new(self.unbind().into_any())) |
| 587 | } |
| 588 | |
| 589 | /// Casts this `Bound<T>` to a `Borrowed<T>` smart pointer. |
| 590 | #[inline ] |
| 591 | pub fn as_borrowed<'a>(&'a self) -> Borrowed<'a, 'py, T> { |
| 592 | Borrowed( |
| 593 | unsafe { NonNull::new_unchecked(self.as_ptr()) }, |
| 594 | PhantomData, |
| 595 | self.py(), |
| 596 | ) |
| 597 | } |
| 598 | |
| 599 | /// Removes the connection for this `Bound<T>` from the GIL, allowing |
| 600 | /// it to cross thread boundaries. |
| 601 | #[inline ] |
| 602 | pub fn unbind(self) -> Py<T> { |
| 603 | // Safety: the type T is known to be correct and the ownership of the |
| 604 | // pointer is transferred to the new Py<T> instance. |
| 605 | let non_null = (ManuallyDrop::new(self).1).0; |
| 606 | unsafe { Py::from_non_null(non_null) } |
| 607 | } |
| 608 | |
| 609 | /// Removes the connection for this `Bound<T>` from the GIL, allowing |
| 610 | /// it to cross thread boundaries, without transferring ownership. |
| 611 | #[inline ] |
| 612 | pub fn as_unbound(&self) -> &Py<T> { |
| 613 | &self.1 |
| 614 | } |
| 615 | } |
| 616 | |
| 617 | unsafe impl<T> AsPyPointer for Bound<'_, T> { |
| 618 | #[inline ] |
| 619 | fn as_ptr(&self) -> *mut ffi::PyObject { |
| 620 | self.1.as_ptr() |
| 621 | } |
| 622 | } |
| 623 | |
| 624 | impl<'py, T> BoundObject<'py, T> for Bound<'py, T> { |
| 625 | type Any = Bound<'py, PyAny>; |
| 626 | |
| 627 | fn as_borrowed(&self) -> Borrowed<'_, 'py, T> { |
| 628 | Bound::as_borrowed(self) |
| 629 | } |
| 630 | |
| 631 | fn into_bound(self) -> Bound<'py, T> { |
| 632 | self |
| 633 | } |
| 634 | |
| 635 | fn into_any(self) -> Self::Any { |
| 636 | self.into_any() |
| 637 | } |
| 638 | |
| 639 | fn into_ptr(self) -> *mut ffi::PyObject { |
| 640 | self.into_ptr() |
| 641 | } |
| 642 | |
| 643 | fn as_ptr(&self) -> *mut ffi::PyObject { |
| 644 | self.as_ptr() |
| 645 | } |
| 646 | |
| 647 | fn unbind(self) -> Py<T> { |
| 648 | self.unbind() |
| 649 | } |
| 650 | } |
| 651 | |
| 652 | /// A borrowed equivalent to `Bound`. |
| 653 | /// |
| 654 | /// The advantage of this over `&Bound` is that it avoids the need to have a pointer-to-pointer, as Bound |
| 655 | /// is already a pointer to an `ffi::PyObject``. |
| 656 | /// |
| 657 | /// Similarly, this type is `Copy` and `Clone`, like a shared reference (`&T`). |
| 658 | #[repr (transparent)] |
| 659 | pub struct Borrowed<'a, 'py, T>(NonNull<ffi::PyObject>, PhantomData<&'a Py<T>>, Python<'py>); |
| 660 | |
| 661 | impl<'a, 'py, T> Borrowed<'a, 'py, T> { |
| 662 | /// Creates a new owned [`Bound<T>`] from this borrowed reference by |
| 663 | /// increasing the reference count. |
| 664 | /// |
| 665 | /// # Example |
| 666 | /// ``` |
| 667 | /// use pyo3::{prelude::*, types::PyTuple}; |
| 668 | /// |
| 669 | /// # fn main() -> PyResult<()> { |
| 670 | /// Python::with_gil(|py| -> PyResult<()> { |
| 671 | /// let tuple = PyTuple::new(py, [1, 2, 3])?; |
| 672 | /// |
| 673 | /// // borrows from `tuple`, so can only be |
| 674 | /// // used while `tuple` stays alive |
| 675 | /// let borrowed = tuple.get_borrowed_item(0)?; |
| 676 | /// |
| 677 | /// // creates a new owned reference, which |
| 678 | /// // can be used indendently of `tuple` |
| 679 | /// let bound = borrowed.to_owned(); |
| 680 | /// drop(tuple); |
| 681 | /// |
| 682 | /// assert_eq!(bound.extract::<i32>().unwrap(), 1); |
| 683 | /// Ok(()) |
| 684 | /// }) |
| 685 | /// # } |
| 686 | pub fn to_owned(self) -> Bound<'py, T> { |
| 687 | (*self).clone() |
| 688 | } |
| 689 | |
| 690 | /// Returns the raw FFI pointer represented by self. |
| 691 | /// |
| 692 | /// # Safety |
| 693 | /// |
| 694 | /// Callers are responsible for ensuring that the pointer does not outlive self. |
| 695 | /// |
| 696 | /// The reference is borrowed; callers should not decrease the reference count |
| 697 | /// when they are finished with the pointer. |
| 698 | #[inline ] |
| 699 | pub fn as_ptr(self) -> *mut ffi::PyObject { |
| 700 | self.0.as_ptr() |
| 701 | } |
| 702 | |
| 703 | pub(crate) fn to_any(self) -> Borrowed<'a, 'py, PyAny> { |
| 704 | Borrowed(self.0, PhantomData, self.2) |
| 705 | } |
| 706 | } |
| 707 | |
| 708 | impl<'a, 'py> Borrowed<'a, 'py, PyAny> { |
| 709 | /// Constructs a new `Borrowed<'a, 'py, PyAny>` from a pointer. Panics if `ptr` is null. |
| 710 | /// |
| 711 | /// Prefer to use [`Bound::from_borrowed_ptr`], as that avoids the major safety risk |
| 712 | /// of needing to precisely define the lifetime `'a` for which the borrow is valid. |
| 713 | /// |
| 714 | /// # Safety |
| 715 | /// |
| 716 | /// - `ptr` must be a valid pointer to a Python object |
| 717 | /// - similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by |
| 718 | /// the caller and it is the caller's responsibility to ensure that the reference this is |
| 719 | /// derived from is valid for the lifetime `'a`. |
| 720 | #[inline ] |
| 721 | #[track_caller ] |
| 722 | pub unsafe fn from_ptr(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self { |
| 723 | Self( |
| 724 | NonNull::new(ptr).unwrap_or_else(|| crate::err::panic_after_error(py)), |
| 725 | PhantomData, |
| 726 | py, |
| 727 | ) |
| 728 | } |
| 729 | |
| 730 | /// Constructs a new `Borrowed<'a, 'py, PyAny>` from a pointer. Returns `None` if `ptr` is null. |
| 731 | /// |
| 732 | /// Prefer to use [`Bound::from_borrowed_ptr_or_opt`], as that avoids the major safety risk |
| 733 | /// of needing to precisely define the lifetime `'a` for which the borrow is valid. |
| 734 | /// |
| 735 | /// # Safety |
| 736 | /// |
| 737 | /// - `ptr` must be a valid pointer to a Python object, or null |
| 738 | /// - similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by |
| 739 | /// the caller and it is the caller's responsibility to ensure that the reference this is |
| 740 | /// derived from is valid for the lifetime `'a`. |
| 741 | #[inline ] |
| 742 | pub unsafe fn from_ptr_or_opt(py: Python<'py>, ptr: *mut ffi::PyObject) -> Option<Self> { |
| 743 | NonNull::new(ptr).map(|ptr| Self(ptr, PhantomData, py)) |
| 744 | } |
| 745 | |
| 746 | /// Constructs a new `Borrowed<'a, 'py, PyAny>` from a pointer. Returns an `Err` by calling `PyErr::fetch` |
| 747 | /// if `ptr` is null. |
| 748 | /// |
| 749 | /// Prefer to use [`Bound::from_borrowed_ptr_or_err`], as that avoids the major safety risk |
| 750 | /// of needing to precisely define the lifetime `'a` for which the borrow is valid. |
| 751 | /// |
| 752 | /// # Safety |
| 753 | /// |
| 754 | /// - `ptr` must be a valid pointer to a Python object, or null |
| 755 | /// - similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by |
| 756 | /// the caller and it is the caller's responsibility to ensure that the reference this is |
| 757 | /// derived from is valid for the lifetime `'a`. |
| 758 | #[inline ] |
| 759 | pub unsafe fn from_ptr_or_err(py: Python<'py>, ptr: *mut ffi::PyObject) -> PyResult<Self> { |
| 760 | NonNull::new(ptr).map_or_else( |
| 761 | || Err(PyErr::fetch(py)), |
| 762 | |ptr| Ok(Self(ptr, PhantomData, py)), |
| 763 | ) |
| 764 | } |
| 765 | |
| 766 | /// # Safety |
| 767 | /// This is similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by |
| 768 | /// the caller and it's the caller's responsibility to ensure that the reference this is |
| 769 | /// derived from is valid for the lifetime `'a`. |
| 770 | #[inline ] |
| 771 | pub(crate) unsafe fn from_ptr_unchecked(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self { |
| 772 | Self(unsafe { NonNull::new_unchecked(ptr) }, PhantomData, py) |
| 773 | } |
| 774 | |
| 775 | #[inline ] |
| 776 | pub(crate) fn downcast<T>(self) -> Result<Borrowed<'a, 'py, T>, DowncastError<'a, 'py>> |
| 777 | where |
| 778 | T: PyTypeCheck, |
| 779 | { |
| 780 | if T::type_check(&self) { |
| 781 | // Safety: type_check is responsible for ensuring that the type is correct |
| 782 | Ok(unsafe { self.downcast_unchecked() }) |
| 783 | } else { |
| 784 | Err(DowncastError::new_from_borrowed(self, T::NAME)) |
| 785 | } |
| 786 | } |
| 787 | |
| 788 | /// Converts this `PyAny` to a concrete Python type without checking validity. |
| 789 | /// |
| 790 | /// # Safety |
| 791 | /// Callers must ensure that the type is valid or risk type confusion. |
| 792 | #[inline ] |
| 793 | pub(crate) unsafe fn downcast_unchecked<T>(self) -> Borrowed<'a, 'py, T> { |
| 794 | Borrowed(self.0, PhantomData, self.2) |
| 795 | } |
| 796 | } |
| 797 | |
| 798 | impl<'a, 'py, T> From<&'a Bound<'py, T>> for Borrowed<'a, 'py, T> { |
| 799 | /// Create borrow on a Bound |
| 800 | #[inline ] |
| 801 | fn from(instance: &'a Bound<'py, T>) -> Self { |
| 802 | instance.as_borrowed() |
| 803 | } |
| 804 | } |
| 805 | |
| 806 | impl<T> std::fmt::Debug for Borrowed<'_, '_, T> { |
| 807 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 808 | Bound::fmt(self, f) |
| 809 | } |
| 810 | } |
| 811 | |
| 812 | impl<'py, T> Deref for Borrowed<'_, 'py, T> { |
| 813 | type Target = Bound<'py, T>; |
| 814 | |
| 815 | #[inline ] |
| 816 | fn deref(&self) -> &Bound<'py, T> { |
| 817 | // safety: Bound has the same layout as NonNull<ffi::PyObject> |
| 818 | unsafe { &*ptr_from_ref(&self.0).cast() } |
| 819 | } |
| 820 | } |
| 821 | |
| 822 | impl<T> Clone for Borrowed<'_, '_, T> { |
| 823 | #[inline ] |
| 824 | fn clone(&self) -> Self { |
| 825 | *self |
| 826 | } |
| 827 | } |
| 828 | |
| 829 | impl<T> Copy for Borrowed<'_, '_, T> {} |
| 830 | |
| 831 | #[allow (deprecated)] |
| 832 | impl<T> ToPyObject for Borrowed<'_, '_, T> { |
| 833 | /// Converts `Py` instance -> PyObject. |
| 834 | #[inline ] |
| 835 | fn to_object(&self, py: Python<'_>) -> PyObject { |
| 836 | (*self).into_py(py) |
| 837 | } |
| 838 | } |
| 839 | |
| 840 | #[allow (deprecated)] |
| 841 | impl<T> IntoPy<PyObject> for Borrowed<'_, '_, T> { |
| 842 | /// Converts `Py` instance -> PyObject. |
| 843 | #[inline ] |
| 844 | fn into_py(self, py: Python<'_>) -> PyObject { |
| 845 | self.to_owned().into_py(py) |
| 846 | } |
| 847 | } |
| 848 | |
| 849 | impl<'a, 'py, T> BoundObject<'py, T> for Borrowed<'a, 'py, T> { |
| 850 | type Any = Borrowed<'a, 'py, PyAny>; |
| 851 | |
| 852 | fn as_borrowed(&self) -> Borrowed<'a, 'py, T> { |
| 853 | *self |
| 854 | } |
| 855 | |
| 856 | fn into_bound(self) -> Bound<'py, T> { |
| 857 | (*self).to_owned() |
| 858 | } |
| 859 | |
| 860 | fn into_any(self) -> Self::Any { |
| 861 | self.to_any() |
| 862 | } |
| 863 | |
| 864 | fn into_ptr(self) -> *mut ffi::PyObject { |
| 865 | (*self).to_owned().into_ptr() |
| 866 | } |
| 867 | |
| 868 | fn as_ptr(&self) -> *mut ffi::PyObject { |
| 869 | (*self).as_ptr() |
| 870 | } |
| 871 | |
| 872 | fn unbind(self) -> Py<T> { |
| 873 | (*self).to_owned().unbind() |
| 874 | } |
| 875 | } |
| 876 | |
| 877 | /// A GIL-independent reference to an object allocated on the Python heap. |
| 878 | /// |
| 879 | /// This type does not auto-dereference to the inner object because you must prove you hold the GIL to access it. |
| 880 | /// Instead, call one of its methods to access the inner object: |
| 881 | /// - [`Py::bind`] or [`Py::into_bound`], to borrow a GIL-bound reference to the contained object. |
| 882 | /// - [`Py::borrow`], [`Py::try_borrow`], [`Py::borrow_mut`], or [`Py::try_borrow_mut`], |
| 883 | /// |
| 884 | /// to get a (mutable) reference to a contained pyclass, using a scheme similar to std's [`RefCell`]. |
| 885 | /// See the |
| 886 | #[doc = concat!("[guide entry](https://pyo3.rs/v" , env!("CARGO_PKG_VERSION" ), "/class.html#bound-and-interior-mutability)" )] |
| 887 | /// for more information. |
| 888 | /// - You can call methods directly on `Py` with [`Py::call_bound`], [`Py::call_method_bound`] and friends. |
| 889 | /// |
| 890 | /// These require passing in the [`Python<'py>`](crate::Python) token but are otherwise similar to the corresponding |
| 891 | /// methods on [`PyAny`]. |
| 892 | /// |
| 893 | /// # Example: Storing Python objects in `#[pyclass]` structs |
| 894 | /// |
| 895 | /// Usually `Bound<'py, T>` is recommended for interacting with Python objects as its lifetime `'py` |
| 896 | /// is an association to the GIL and that enables many operations to be done as efficiently as possible. |
| 897 | /// |
| 898 | /// However, `#[pyclass]` structs cannot carry a lifetime, so `Py<T>` is the only way to store |
| 899 | /// a Python object in a `#[pyclass]` struct. |
| 900 | /// |
| 901 | /// For example, this won't compile: |
| 902 | /// |
| 903 | /// ```compile_fail |
| 904 | /// # use pyo3::prelude::*; |
| 905 | /// # use pyo3::types::PyDict; |
| 906 | /// # |
| 907 | /// #[pyclass] |
| 908 | /// struct Foo<'py> { |
| 909 | /// inner: Bound<'py, PyDict>, |
| 910 | /// } |
| 911 | /// |
| 912 | /// impl Foo { |
| 913 | /// fn new() -> Foo { |
| 914 | /// let foo = Python::with_gil(|py| { |
| 915 | /// // `py` will only last for this scope. |
| 916 | /// |
| 917 | /// // `Bound<'py, PyDict>` inherits the GIL lifetime from `py` and |
| 918 | /// // so won't be able to outlive this closure. |
| 919 | /// let dict: Bound<'_, PyDict> = PyDict::new(py); |
| 920 | /// |
| 921 | /// // because `Foo` contains `dict` its lifetime |
| 922 | /// // is now also tied to `py`. |
| 923 | /// Foo { inner: dict } |
| 924 | /// }); |
| 925 | /// // Foo is no longer valid. |
| 926 | /// // Returning it from this function is a 💥 compiler error 💥 |
| 927 | /// foo |
| 928 | /// } |
| 929 | /// } |
| 930 | /// ``` |
| 931 | /// |
| 932 | /// [`Py`]`<T>` can be used to get around this by converting `dict` into a GIL-independent reference: |
| 933 | /// |
| 934 | /// ```rust |
| 935 | /// use pyo3::prelude::*; |
| 936 | /// use pyo3::types::PyDict; |
| 937 | /// |
| 938 | /// #[pyclass] |
| 939 | /// struct Foo { |
| 940 | /// inner: Py<PyDict>, |
| 941 | /// } |
| 942 | /// |
| 943 | /// #[pymethods] |
| 944 | /// impl Foo { |
| 945 | /// #[new] |
| 946 | /// fn __new__() -> Foo { |
| 947 | /// Python::with_gil(|py| { |
| 948 | /// let dict: Py<PyDict> = PyDict::new(py).unbind(); |
| 949 | /// Foo { inner: dict } |
| 950 | /// }) |
| 951 | /// } |
| 952 | /// } |
| 953 | /// # |
| 954 | /// # fn main() -> PyResult<()> { |
| 955 | /// # Python::with_gil(|py| { |
| 956 | /// # let m = pyo3::types::PyModule::new(py, "test" )?; |
| 957 | /// # m.add_class::<Foo>()?; |
| 958 | /// # |
| 959 | /// # let foo: Bound<'_, Foo> = m.getattr("Foo" )?.call0()?.downcast_into()?; |
| 960 | /// # let dict = &foo.borrow().inner; |
| 961 | /// # let dict: &Bound<'_, PyDict> = dict.bind(py); |
| 962 | /// # |
| 963 | /// # Ok(()) |
| 964 | /// # }) |
| 965 | /// # } |
| 966 | /// ``` |
| 967 | /// |
| 968 | /// This can also be done with other pyclasses: |
| 969 | /// ```rust |
| 970 | /// use pyo3::prelude::*; |
| 971 | /// |
| 972 | /// #[pyclass] |
| 973 | /// struct Bar {/* ... */} |
| 974 | /// |
| 975 | /// #[pyclass] |
| 976 | /// struct Foo { |
| 977 | /// inner: Py<Bar>, |
| 978 | /// } |
| 979 | /// |
| 980 | /// #[pymethods] |
| 981 | /// impl Foo { |
| 982 | /// #[new] |
| 983 | /// fn __new__() -> PyResult<Foo> { |
| 984 | /// Python::with_gil(|py| { |
| 985 | /// let bar: Py<Bar> = Py::new(py, Bar {})?; |
| 986 | /// Ok(Foo { inner: bar }) |
| 987 | /// }) |
| 988 | /// } |
| 989 | /// } |
| 990 | /// # |
| 991 | /// # fn main() -> PyResult<()> { |
| 992 | /// # Python::with_gil(|py| { |
| 993 | /// # let m = pyo3::types::PyModule::new(py, "test" )?; |
| 994 | /// # m.add_class::<Foo>()?; |
| 995 | /// # |
| 996 | /// # let foo: Bound<'_, Foo> = m.getattr("Foo" )?.call0()?.downcast_into()?; |
| 997 | /// # let bar = &foo.borrow().inner; |
| 998 | /// # let bar: &Bar = &*bar.borrow(py); |
| 999 | /// # |
| 1000 | /// # Ok(()) |
| 1001 | /// # }) |
| 1002 | /// # } |
| 1003 | /// ``` |
| 1004 | /// |
| 1005 | /// # Example: Shared ownership of Python objects |
| 1006 | /// |
| 1007 | /// `Py<T>` can be used to share ownership of a Python object, similar to std's [`Rc`]`<T>`. |
| 1008 | /// As with [`Rc`]`<T>`, cloning it increases its reference count rather than duplicating |
| 1009 | /// the underlying object. |
| 1010 | /// |
| 1011 | /// This can be done using either [`Py::clone_ref`] or [`Py`]`<T>`'s [`Clone`] trait implementation. |
| 1012 | /// [`Py::clone_ref`] will be faster if you happen to be already holding the GIL. |
| 1013 | /// |
| 1014 | /// ```rust |
| 1015 | /// use pyo3::prelude::*; |
| 1016 | /// use pyo3::types::PyDict; |
| 1017 | /// |
| 1018 | /// # fn main() { |
| 1019 | /// Python::with_gil(|py| { |
| 1020 | /// let first: Py<PyDict> = PyDict::new(py).unbind(); |
| 1021 | /// |
| 1022 | /// // All of these are valid syntax |
| 1023 | /// let second = Py::clone_ref(&first, py); |
| 1024 | /// let third = first.clone_ref(py); |
| 1025 | /// #[cfg (feature = "py-clone" )] |
| 1026 | /// let fourth = Py::clone(&first); |
| 1027 | /// #[cfg (feature = "py-clone" )] |
| 1028 | /// let fifth = first.clone(); |
| 1029 | /// |
| 1030 | /// // Disposing of our original `Py<PyDict>` just decrements the reference count. |
| 1031 | /// drop(first); |
| 1032 | /// |
| 1033 | /// // They all point to the same object |
| 1034 | /// assert!(second.is(&third)); |
| 1035 | /// #[cfg (feature = "py-clone" )] |
| 1036 | /// assert!(fourth.is(&fifth)); |
| 1037 | /// #[cfg (feature = "py-clone" )] |
| 1038 | /// assert!(second.is(&fourth)); |
| 1039 | /// }); |
| 1040 | /// # } |
| 1041 | /// ``` |
| 1042 | /// |
| 1043 | /// # Preventing reference cycles |
| 1044 | /// |
| 1045 | /// It is easy to accidentally create reference cycles using [`Py`]`<T>`. |
| 1046 | /// The Python interpreter can break these reference cycles within pyclasses if they |
| 1047 | /// [integrate with the garbage collector][gc]. If your pyclass contains other Python |
| 1048 | /// objects you should implement it to avoid leaking memory. |
| 1049 | /// |
| 1050 | /// # A note on Python reference counts |
| 1051 | /// |
| 1052 | /// Dropping a [`Py`]`<T>` will eventually decrease Python's reference count |
| 1053 | /// of the pointed-to variable, allowing Python's garbage collector to free |
| 1054 | /// the associated memory, but this may not happen immediately. This is |
| 1055 | /// because a [`Py`]`<T>` can be dropped at any time, but the Python reference |
| 1056 | /// count can only be modified when the GIL is held. |
| 1057 | /// |
| 1058 | /// If a [`Py`]`<T>` is dropped while its thread happens to be holding the |
| 1059 | /// GIL then the Python reference count will be decreased immediately. |
| 1060 | /// Otherwise, the reference count will be decreased the next time the GIL is |
| 1061 | /// reacquired. |
| 1062 | /// |
| 1063 | /// If you happen to be already holding the GIL, [`Py::drop_ref`] will decrease |
| 1064 | /// the Python reference count immediately and will execute slightly faster than |
| 1065 | /// relying on implicit [`Drop`]s. |
| 1066 | /// |
| 1067 | /// # A note on `Send` and `Sync` |
| 1068 | /// |
| 1069 | /// Accessing this object is thread-safe, since any access to its API requires a [`Python<'py>`](crate::Python) token. |
| 1070 | /// As you can only get this by acquiring the GIL, `Py<...>` implements [`Send`] and [`Sync`]. |
| 1071 | /// |
| 1072 | /// [`Rc`]: std::rc::Rc |
| 1073 | /// [`RefCell`]: std::cell::RefCell |
| 1074 | /// [gc]: https://pyo3.rs/main/class/protocols.html#garbage-collector-integration |
| 1075 | #[repr (transparent)] |
| 1076 | pub struct Py<T>(NonNull<ffi::PyObject>, PhantomData<T>); |
| 1077 | |
| 1078 | // The inner value is only accessed through ways that require proving the gil is held |
| 1079 | #[cfg (feature = "nightly" )] |
| 1080 | unsafe impl<T> crate::marker::Ungil for Py<T> {} |
| 1081 | unsafe impl<T> Send for Py<T> {} |
| 1082 | unsafe impl<T> Sync for Py<T> {} |
| 1083 | |
| 1084 | impl<T> Py<T> |
| 1085 | where |
| 1086 | T: PyClass, |
| 1087 | { |
| 1088 | /// Creates a new instance `Py<T>` of a `#[pyclass]` on the Python heap. |
| 1089 | /// |
| 1090 | /// # Examples |
| 1091 | /// |
| 1092 | /// ```rust |
| 1093 | /// use pyo3::prelude::*; |
| 1094 | /// |
| 1095 | /// #[pyclass] |
| 1096 | /// struct Foo {/* fields omitted */} |
| 1097 | /// |
| 1098 | /// # fn main() -> PyResult<()> { |
| 1099 | /// let foo = Python::with_gil(|py| -> PyResult<_> { |
| 1100 | /// let foo: Py<Foo> = Py::new(py, Foo {})?; |
| 1101 | /// Ok(foo) |
| 1102 | /// })?; |
| 1103 | /// # Python::with_gil(move |_py| drop(foo)); |
| 1104 | /// # Ok(()) |
| 1105 | /// # } |
| 1106 | /// ``` |
| 1107 | pub fn new(py: Python<'_>, value: impl Into<PyClassInitializer<T>>) -> PyResult<Py<T>> { |
| 1108 | Bound::new(py, value).map(op:Bound::unbind) |
| 1109 | } |
| 1110 | } |
| 1111 | |
| 1112 | impl<T> Py<T> { |
| 1113 | /// Returns the raw FFI pointer represented by self. |
| 1114 | /// |
| 1115 | /// # Safety |
| 1116 | /// |
| 1117 | /// Callers are responsible for ensuring that the pointer does not outlive self. |
| 1118 | /// |
| 1119 | /// The reference is borrowed; callers should not decrease the reference count |
| 1120 | /// when they are finished with the pointer. |
| 1121 | #[inline ] |
| 1122 | pub fn as_ptr(&self) -> *mut ffi::PyObject { |
| 1123 | self.0.as_ptr() |
| 1124 | } |
| 1125 | |
| 1126 | /// Returns an owned raw FFI pointer represented by self. |
| 1127 | /// |
| 1128 | /// # Safety |
| 1129 | /// |
| 1130 | /// The reference is owned; when finished the caller should either transfer ownership |
| 1131 | /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). |
| 1132 | #[inline ] |
| 1133 | pub fn into_ptr(self) -> *mut ffi::PyObject { |
| 1134 | ManuallyDrop::new(self).0.as_ptr() |
| 1135 | } |
| 1136 | |
| 1137 | /// Helper to cast to `Py<PyAny>`. |
| 1138 | #[inline ] |
| 1139 | pub fn as_any(&self) -> &Py<PyAny> { |
| 1140 | // Safety: all Py<T> have the same memory layout, and all Py<T> are valid |
| 1141 | // Py<PyAny>, so pointer casting is valid. |
| 1142 | unsafe { &*ptr_from_ref(self).cast::<Py<PyAny>>() } |
| 1143 | } |
| 1144 | |
| 1145 | /// Helper to cast to `Py<PyAny>`, transferring ownership. |
| 1146 | #[inline ] |
| 1147 | pub fn into_any(self) -> Py<PyAny> { |
| 1148 | // Safety: all Py<T> are valid Py<PyAny> |
| 1149 | unsafe { Py::from_non_null(ManuallyDrop::new(self).0) } |
| 1150 | } |
| 1151 | } |
| 1152 | |
| 1153 | impl<T> Py<T> |
| 1154 | where |
| 1155 | T: PyClass, |
| 1156 | { |
| 1157 | /// Immutably borrows the value `T`. |
| 1158 | /// |
| 1159 | /// This borrow lasts while the returned [`PyRef`] exists. |
| 1160 | /// Multiple immutable borrows can be taken out at the same time. |
| 1161 | /// |
| 1162 | /// For frozen classes, the simpler [`get`][Self::get] is available. |
| 1163 | /// |
| 1164 | /// Equivalent to `self.bind(py).borrow()` - see [`Bound::borrow`]. |
| 1165 | /// |
| 1166 | /// # Examples |
| 1167 | /// |
| 1168 | /// ```rust |
| 1169 | /// # use pyo3::prelude::*; |
| 1170 | /// # |
| 1171 | /// #[pyclass] |
| 1172 | /// struct Foo { |
| 1173 | /// inner: u8, |
| 1174 | /// } |
| 1175 | /// |
| 1176 | /// # fn main() -> PyResult<()> { |
| 1177 | /// Python::with_gil(|py| -> PyResult<()> { |
| 1178 | /// let foo: Py<Foo> = Py::new(py, Foo { inner: 73 })?; |
| 1179 | /// let inner: &u8 = &foo.borrow(py).inner; |
| 1180 | /// |
| 1181 | /// assert_eq!(*inner, 73); |
| 1182 | /// Ok(()) |
| 1183 | /// })?; |
| 1184 | /// # Ok(()) |
| 1185 | /// # } |
| 1186 | /// ``` |
| 1187 | /// |
| 1188 | /// # Panics |
| 1189 | /// |
| 1190 | /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use |
| 1191 | /// [`try_borrow`](#method.try_borrow). |
| 1192 | #[inline ] |
| 1193 | #[track_caller ] |
| 1194 | pub fn borrow<'py>(&'py self, py: Python<'py>) -> PyRef<'py, T> { |
| 1195 | self.bind(py).borrow() |
| 1196 | } |
| 1197 | |
| 1198 | /// Mutably borrows the value `T`. |
| 1199 | /// |
| 1200 | /// This borrow lasts while the returned [`PyRefMut`] exists. |
| 1201 | /// |
| 1202 | /// Equivalent to `self.bind(py).borrow_mut()` - see [`Bound::borrow_mut`]. |
| 1203 | /// |
| 1204 | /// # Examples |
| 1205 | /// |
| 1206 | /// ``` |
| 1207 | /// # use pyo3::prelude::*; |
| 1208 | /// # |
| 1209 | /// #[pyclass] |
| 1210 | /// struct Foo { |
| 1211 | /// inner: u8, |
| 1212 | /// } |
| 1213 | /// |
| 1214 | /// # fn main() -> PyResult<()> { |
| 1215 | /// Python::with_gil(|py| -> PyResult<()> { |
| 1216 | /// let foo: Py<Foo> = Py::new(py, Foo { inner: 73 })?; |
| 1217 | /// foo.borrow_mut(py).inner = 35; |
| 1218 | /// |
| 1219 | /// assert_eq!(foo.borrow(py).inner, 35); |
| 1220 | /// Ok(()) |
| 1221 | /// })?; |
| 1222 | /// # Ok(()) |
| 1223 | /// # } |
| 1224 | /// ``` |
| 1225 | /// |
| 1226 | /// # Panics |
| 1227 | /// Panics if the value is currently borrowed. For a non-panicking variant, use |
| 1228 | /// [`try_borrow_mut`](#method.try_borrow_mut). |
| 1229 | #[inline ] |
| 1230 | #[track_caller ] |
| 1231 | pub fn borrow_mut<'py>(&'py self, py: Python<'py>) -> PyRefMut<'py, T> |
| 1232 | where |
| 1233 | T: PyClass<Frozen = False>, |
| 1234 | { |
| 1235 | self.bind(py).borrow_mut() |
| 1236 | } |
| 1237 | |
| 1238 | /// Attempts to immutably borrow the value `T`, returning an error if the value is currently mutably borrowed. |
| 1239 | /// |
| 1240 | /// The borrow lasts while the returned [`PyRef`] exists. |
| 1241 | /// |
| 1242 | /// This is the non-panicking variant of [`borrow`](#method.borrow). |
| 1243 | /// |
| 1244 | /// For frozen classes, the simpler [`get`][Self::get] is available. |
| 1245 | /// |
| 1246 | /// Equivalent to `self.bind(py).try_borrow()` - see [`Bound::try_borrow`]. |
| 1247 | #[inline ] |
| 1248 | pub fn try_borrow<'py>(&'py self, py: Python<'py>) -> Result<PyRef<'py, T>, PyBorrowError> { |
| 1249 | self.bind(py).try_borrow() |
| 1250 | } |
| 1251 | |
| 1252 | /// Attempts to mutably borrow the value `T`, returning an error if the value is currently borrowed. |
| 1253 | /// |
| 1254 | /// The borrow lasts while the returned [`PyRefMut`] exists. |
| 1255 | /// |
| 1256 | /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut). |
| 1257 | /// |
| 1258 | /// Equivalent to `self.bind(py).try_borrow_mut()` - see [`Bound::try_borrow_mut`]. |
| 1259 | #[inline ] |
| 1260 | pub fn try_borrow_mut<'py>( |
| 1261 | &'py self, |
| 1262 | py: Python<'py>, |
| 1263 | ) -> Result<PyRefMut<'py, T>, PyBorrowMutError> |
| 1264 | where |
| 1265 | T: PyClass<Frozen = False>, |
| 1266 | { |
| 1267 | self.bind(py).try_borrow_mut() |
| 1268 | } |
| 1269 | |
| 1270 | /// Provide an immutable borrow of the value `T` without acquiring the GIL. |
| 1271 | /// |
| 1272 | /// This is available if the class is [`frozen`][macro@crate::pyclass] and [`Sync`]. |
| 1273 | /// |
| 1274 | /// # Examples |
| 1275 | /// |
| 1276 | /// ``` |
| 1277 | /// use std::sync::atomic::{AtomicUsize, Ordering}; |
| 1278 | /// # use pyo3::prelude::*; |
| 1279 | /// |
| 1280 | /// #[pyclass(frozen)] |
| 1281 | /// struct FrozenCounter { |
| 1282 | /// value: AtomicUsize, |
| 1283 | /// } |
| 1284 | /// |
| 1285 | /// let cell = Python::with_gil(|py| { |
| 1286 | /// let counter = FrozenCounter { value: AtomicUsize::new(0) }; |
| 1287 | /// |
| 1288 | /// Py::new(py, counter).unwrap() |
| 1289 | /// }); |
| 1290 | /// |
| 1291 | /// cell.get().value.fetch_add(1, Ordering::Relaxed); |
| 1292 | /// # Python::with_gil(move |_py| drop(cell)); |
| 1293 | /// ``` |
| 1294 | #[inline ] |
| 1295 | pub fn get(&self) -> &T |
| 1296 | where |
| 1297 | T: PyClass<Frozen = True> + Sync, |
| 1298 | { |
| 1299 | // Safety: The class itself is frozen and `Sync` |
| 1300 | unsafe { &*self.get_class_object().get_ptr() } |
| 1301 | } |
| 1302 | |
| 1303 | /// Get a view on the underlying `PyClass` contents. |
| 1304 | #[inline ] |
| 1305 | pub(crate) fn get_class_object(&self) -> &PyClassObject<T> { |
| 1306 | let class_object = self.as_ptr().cast::<PyClassObject<T>>(); |
| 1307 | // Safety: Bound<T: PyClass> is known to contain an object which is laid out in memory as a |
| 1308 | // PyClassObject<T>. |
| 1309 | unsafe { &*class_object } |
| 1310 | } |
| 1311 | } |
| 1312 | |
| 1313 | impl<T> Py<T> { |
| 1314 | /// Attaches this `Py` to the given Python context, allowing access to further Python APIs. |
| 1315 | #[inline ] |
| 1316 | pub fn bind<'py>(&self, _py: Python<'py>) -> &Bound<'py, T> { |
| 1317 | // Safety: `Bound` has the same layout as `Py` |
| 1318 | unsafe { &*ptr_from_ref(self).cast() } |
| 1319 | } |
| 1320 | |
| 1321 | /// Same as `bind` but takes ownership of `self`. |
| 1322 | #[inline ] |
| 1323 | pub fn into_bound(self, py: Python<'_>) -> Bound<'_, T> { |
| 1324 | Bound(py, ManuallyDrop::new(self)) |
| 1325 | } |
| 1326 | |
| 1327 | /// Same as `bind` but produces a `Borrowed<T>` instead of a `Bound<T>`. |
| 1328 | #[inline ] |
| 1329 | pub fn bind_borrowed<'a, 'py>(&'a self, py: Python<'py>) -> Borrowed<'a, 'py, T> { |
| 1330 | Borrowed(self.0, PhantomData, py) |
| 1331 | } |
| 1332 | |
| 1333 | /// Returns whether `self` and `other` point to the same object. To compare |
| 1334 | /// the equality of two objects (the `==` operator), use [`eq`](PyAnyMethods::eq). |
| 1335 | /// |
| 1336 | /// This is equivalent to the Python expression `self is other`. |
| 1337 | #[inline ] |
| 1338 | pub fn is<U: AsPyPointer>(&self, o: &U) -> bool { |
| 1339 | ptr::eq(self.as_ptr(), o.as_ptr()) |
| 1340 | } |
| 1341 | |
| 1342 | /// Gets the reference count of the `ffi::PyObject` pointer. |
| 1343 | #[inline ] |
| 1344 | pub fn get_refcnt(&self, _py: Python<'_>) -> isize { |
| 1345 | unsafe { ffi::Py_REFCNT(self.0.as_ptr()) } |
| 1346 | } |
| 1347 | |
| 1348 | /// Makes a clone of `self`. |
| 1349 | /// |
| 1350 | /// This creates another pointer to the same object, increasing its reference count. |
| 1351 | /// |
| 1352 | /// You should prefer using this method over [`Clone`] if you happen to be holding the GIL already. |
| 1353 | /// |
| 1354 | /// # Examples |
| 1355 | /// |
| 1356 | /// ```rust |
| 1357 | /// use pyo3::prelude::*; |
| 1358 | /// use pyo3::types::PyDict; |
| 1359 | /// |
| 1360 | /// # fn main() { |
| 1361 | /// Python::with_gil(|py| { |
| 1362 | /// let first: Py<PyDict> = PyDict::new(py).unbind(); |
| 1363 | /// let second = Py::clone_ref(&first, py); |
| 1364 | /// |
| 1365 | /// // Both point to the same object |
| 1366 | /// assert!(first.is(&second)); |
| 1367 | /// }); |
| 1368 | /// # } |
| 1369 | /// ``` |
| 1370 | #[inline ] |
| 1371 | pub fn clone_ref(&self, _py: Python<'_>) -> Py<T> { |
| 1372 | unsafe { |
| 1373 | ffi::Py_INCREF(self.as_ptr()); |
| 1374 | Self::from_non_null(self.0) |
| 1375 | } |
| 1376 | } |
| 1377 | |
| 1378 | /// Drops `self` and immediately decreases its reference count. |
| 1379 | /// |
| 1380 | /// This method is a micro-optimisation over [`Drop`] if you happen to be holding the GIL |
| 1381 | /// already. |
| 1382 | /// |
| 1383 | /// Note that if you are using [`Bound`], you do not need to use [`Self::drop_ref`] since |
| 1384 | /// [`Bound`] guarantees that the GIL is held. |
| 1385 | /// |
| 1386 | /// # Examples |
| 1387 | /// |
| 1388 | /// ```rust |
| 1389 | /// use pyo3::prelude::*; |
| 1390 | /// use pyo3::types::PyDict; |
| 1391 | /// |
| 1392 | /// # fn main() { |
| 1393 | /// Python::with_gil(|py| { |
| 1394 | /// let object: Py<PyDict> = PyDict::new(py).unbind(); |
| 1395 | /// |
| 1396 | /// // some usage of object |
| 1397 | /// |
| 1398 | /// object.drop_ref(py); |
| 1399 | /// }); |
| 1400 | /// # } |
| 1401 | /// ``` |
| 1402 | #[inline ] |
| 1403 | pub fn drop_ref(self, py: Python<'_>) { |
| 1404 | let _ = self.into_bound(py); |
| 1405 | } |
| 1406 | |
| 1407 | /// Returns whether the object is considered to be None. |
| 1408 | /// |
| 1409 | /// This is equivalent to the Python expression `self is None`. |
| 1410 | pub fn is_none(&self, _py: Python<'_>) -> bool { |
| 1411 | unsafe { ptr::eq(ffi::Py_None(), self.as_ptr()) } |
| 1412 | } |
| 1413 | |
| 1414 | /// Returns whether the object is considered to be true. |
| 1415 | /// |
| 1416 | /// This applies truth value testing equivalent to the Python expression `bool(self)`. |
| 1417 | pub fn is_truthy(&self, py: Python<'_>) -> PyResult<bool> { |
| 1418 | let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) }; |
| 1419 | err::error_on_minusone(py, v)?; |
| 1420 | Ok(v != 0) |
| 1421 | } |
| 1422 | |
| 1423 | /// Extracts some type from the Python object. |
| 1424 | /// |
| 1425 | /// This is a wrapper function around `FromPyObject::extract()`. |
| 1426 | pub fn extract<'a, 'py, D>(&'a self, py: Python<'py>) -> PyResult<D> |
| 1427 | where |
| 1428 | D: crate::conversion::FromPyObjectBound<'a, 'py>, |
| 1429 | // TODO it might be possible to relax this bound in future, to allow |
| 1430 | // e.g. `.extract::<&str>(py)` where `py` is short-lived. |
| 1431 | 'py: 'a, |
| 1432 | { |
| 1433 | self.bind(py).as_any().extract() |
| 1434 | } |
| 1435 | |
| 1436 | /// Retrieves an attribute value. |
| 1437 | /// |
| 1438 | /// This is equivalent to the Python expression `self.attr_name`. |
| 1439 | /// |
| 1440 | /// If calling this method becomes performance-critical, the [`intern!`](crate::intern) macro |
| 1441 | /// can be used to intern `attr_name`, thereby avoiding repeated temporary allocations of |
| 1442 | /// Python strings. |
| 1443 | /// |
| 1444 | /// # Example: `intern!`ing the attribute name |
| 1445 | /// |
| 1446 | /// ``` |
| 1447 | /// # use pyo3::{prelude::*, intern}; |
| 1448 | /// # |
| 1449 | /// #[pyfunction] |
| 1450 | /// fn version(sys: Py<PyModule>, py: Python<'_>) -> PyResult<PyObject> { |
| 1451 | /// sys.getattr(py, intern!(py, "version" )) |
| 1452 | /// } |
| 1453 | /// # |
| 1454 | /// # Python::with_gil(|py| { |
| 1455 | /// # let sys = py.import("sys" ).unwrap().unbind(); |
| 1456 | /// # version(sys, py).unwrap(); |
| 1457 | /// # }); |
| 1458 | /// ``` |
| 1459 | pub fn getattr<'py, N>(&self, py: Python<'py>, attr_name: N) -> PyResult<PyObject> |
| 1460 | where |
| 1461 | N: IntoPyObject<'py, Target = PyString>, |
| 1462 | { |
| 1463 | self.bind(py).as_any().getattr(attr_name).map(Bound::unbind) |
| 1464 | } |
| 1465 | |
| 1466 | /// Sets an attribute value. |
| 1467 | /// |
| 1468 | /// This is equivalent to the Python expression `self.attr_name = value`. |
| 1469 | /// |
| 1470 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) |
| 1471 | /// macro can be used to intern `attr_name`. |
| 1472 | /// |
| 1473 | /// # Example: `intern!`ing the attribute name |
| 1474 | /// |
| 1475 | /// ``` |
| 1476 | /// # use pyo3::{intern, pyfunction, types::PyModule, IntoPyObjectExt, PyObject, Python, PyResult}; |
| 1477 | /// # |
| 1478 | /// #[pyfunction] |
| 1479 | /// fn set_answer(ob: PyObject, py: Python<'_>) -> PyResult<()> { |
| 1480 | /// ob.setattr(py, intern!(py, "answer" ), 42) |
| 1481 | /// } |
| 1482 | /// # |
| 1483 | /// # Python::with_gil(|py| { |
| 1484 | /// # let ob = PyModule::new(py, "empty" ).unwrap().into_py_any(py).unwrap(); |
| 1485 | /// # set_answer(ob, py).unwrap(); |
| 1486 | /// # }); |
| 1487 | /// ``` |
| 1488 | pub fn setattr<'py, N, V>(&self, py: Python<'py>, attr_name: N, value: V) -> PyResult<()> |
| 1489 | where |
| 1490 | N: IntoPyObject<'py, Target = PyString>, |
| 1491 | V: IntoPyObject<'py>, |
| 1492 | { |
| 1493 | self.bind(py).as_any().setattr(attr_name, value) |
| 1494 | } |
| 1495 | |
| 1496 | /// Calls the object. |
| 1497 | /// |
| 1498 | /// This is equivalent to the Python expression `self(*args, **kwargs)`. |
| 1499 | pub fn call<'py, A>( |
| 1500 | &self, |
| 1501 | py: Python<'py>, |
| 1502 | args: A, |
| 1503 | kwargs: Option<&Bound<'py, PyDict>>, |
| 1504 | ) -> PyResult<PyObject> |
| 1505 | where |
| 1506 | A: IntoPyObject<'py, Target = PyTuple>, |
| 1507 | { |
| 1508 | self.bind(py) |
| 1509 | .as_any() |
| 1510 | .call( |
| 1511 | // FIXME(icxolu): remove explicit args conversion |
| 1512 | args.into_pyobject(py).map_err(Into::into)?.into_bound(), |
| 1513 | kwargs, |
| 1514 | ) |
| 1515 | .map(Bound::unbind) |
| 1516 | } |
| 1517 | |
| 1518 | /// Deprecated name for [`Py::call`]. |
| 1519 | #[deprecated (since = "0.23.0" , note = "renamed to `Py::call`" )] |
| 1520 | #[allow (deprecated)] |
| 1521 | #[inline ] |
| 1522 | pub fn call_bound( |
| 1523 | &self, |
| 1524 | py: Python<'_>, |
| 1525 | args: impl IntoPy<Py<PyTuple>>, |
| 1526 | kwargs: Option<&Bound<'_, PyDict>>, |
| 1527 | ) -> PyResult<PyObject> { |
| 1528 | self.call(py, args.into_py(py), kwargs) |
| 1529 | } |
| 1530 | |
| 1531 | /// Calls the object with only positional arguments. |
| 1532 | /// |
| 1533 | /// This is equivalent to the Python expression `self(*args)`. |
| 1534 | pub fn call1<'py, N>(&self, py: Python<'py>, args: N) -> PyResult<PyObject> |
| 1535 | where |
| 1536 | N: IntoPyObject<'py, Target = PyTuple>, |
| 1537 | { |
| 1538 | self.bind(py) |
| 1539 | .as_any() |
| 1540 | // FIXME(icxolu): remove explicit args conversion |
| 1541 | .call1(args.into_pyobject(py).map_err(Into::into)?.into_bound()) |
| 1542 | .map(Bound::unbind) |
| 1543 | } |
| 1544 | |
| 1545 | /// Calls the object without arguments. |
| 1546 | /// |
| 1547 | /// This is equivalent to the Python expression `self()`. |
| 1548 | pub fn call0(&self, py: Python<'_>) -> PyResult<PyObject> { |
| 1549 | self.bind(py).as_any().call0().map(Bound::unbind) |
| 1550 | } |
| 1551 | |
| 1552 | /// Calls a method on the object. |
| 1553 | /// |
| 1554 | /// This is equivalent to the Python expression `self.name(*args, **kwargs)`. |
| 1555 | /// |
| 1556 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) |
| 1557 | /// macro can be used to intern `name`. |
| 1558 | pub fn call_method<'py, N, A>( |
| 1559 | &self, |
| 1560 | py: Python<'py>, |
| 1561 | name: N, |
| 1562 | args: A, |
| 1563 | kwargs: Option<&Bound<'py, PyDict>>, |
| 1564 | ) -> PyResult<PyObject> |
| 1565 | where |
| 1566 | N: IntoPyObject<'py, Target = PyString>, |
| 1567 | A: IntoPyObject<'py, Target = PyTuple>, |
| 1568 | { |
| 1569 | self.bind(py) |
| 1570 | .as_any() |
| 1571 | .call_method( |
| 1572 | name, |
| 1573 | // FIXME(icxolu): remove explicit args conversion |
| 1574 | args.into_pyobject(py).map_err(Into::into)?.into_bound(), |
| 1575 | kwargs, |
| 1576 | ) |
| 1577 | .map(Bound::unbind) |
| 1578 | } |
| 1579 | |
| 1580 | /// Deprecated name for [`Py::call_method`]. |
| 1581 | #[deprecated (since = "0.23.0" , note = "renamed to `Py::call_method`" )] |
| 1582 | #[allow (deprecated)] |
| 1583 | #[inline ] |
| 1584 | pub fn call_method_bound<N, A>( |
| 1585 | &self, |
| 1586 | py: Python<'_>, |
| 1587 | name: N, |
| 1588 | args: A, |
| 1589 | kwargs: Option<&Bound<'_, PyDict>>, |
| 1590 | ) -> PyResult<PyObject> |
| 1591 | where |
| 1592 | N: IntoPy<Py<PyString>>, |
| 1593 | A: IntoPy<Py<PyTuple>>, |
| 1594 | { |
| 1595 | self.call_method(py, name.into_py(py), args.into_py(py), kwargs) |
| 1596 | } |
| 1597 | |
| 1598 | /// Calls a method on the object with only positional arguments. |
| 1599 | /// |
| 1600 | /// This is equivalent to the Python expression `self.name(*args)`. |
| 1601 | /// |
| 1602 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) |
| 1603 | /// macro can be used to intern `name`. |
| 1604 | pub fn call_method1<'py, N, A>(&self, py: Python<'py>, name: N, args: A) -> PyResult<PyObject> |
| 1605 | where |
| 1606 | N: IntoPyObject<'py, Target = PyString>, |
| 1607 | A: IntoPyObject<'py, Target = PyTuple>, |
| 1608 | { |
| 1609 | self.bind(py) |
| 1610 | .as_any() |
| 1611 | .call_method1( |
| 1612 | name, |
| 1613 | // FIXME(icxolu): remove explicit args conversion |
| 1614 | args.into_pyobject(py).map_err(Into::into)?.into_bound(), |
| 1615 | ) |
| 1616 | .map(Bound::unbind) |
| 1617 | } |
| 1618 | |
| 1619 | /// Calls a method on the object with no arguments. |
| 1620 | /// |
| 1621 | /// This is equivalent to the Python expression `self.name()`. |
| 1622 | /// |
| 1623 | /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) |
| 1624 | /// macro can be used to intern `name`. |
| 1625 | pub fn call_method0<'py, N>(&self, py: Python<'py>, name: N) -> PyResult<PyObject> |
| 1626 | where |
| 1627 | N: IntoPyObject<'py, Target = PyString>, |
| 1628 | { |
| 1629 | self.bind(py).as_any().call_method0(name).map(Bound::unbind) |
| 1630 | } |
| 1631 | |
| 1632 | /// Create a `Py<T>` instance by taking ownership of the given FFI pointer. |
| 1633 | /// |
| 1634 | /// # Safety |
| 1635 | /// `ptr` must be a pointer to a Python object of type T. |
| 1636 | /// |
| 1637 | /// Callers must own the object referred to by `ptr`, as this function |
| 1638 | /// implicitly takes ownership of that object. |
| 1639 | /// |
| 1640 | /// # Panics |
| 1641 | /// Panics if `ptr` is null. |
| 1642 | #[inline ] |
| 1643 | #[track_caller ] |
| 1644 | pub unsafe fn from_owned_ptr(py: Python<'_>, ptr: *mut ffi::PyObject) -> Py<T> { |
| 1645 | match NonNull::new(ptr) { |
| 1646 | Some(nonnull_ptr) => Py(nonnull_ptr, PhantomData), |
| 1647 | None => crate::err::panic_after_error(py), |
| 1648 | } |
| 1649 | } |
| 1650 | |
| 1651 | /// Create a `Py<T>` instance by taking ownership of the given FFI pointer. |
| 1652 | /// |
| 1653 | /// If `ptr` is null then the current Python exception is fetched as a [`PyErr`]. |
| 1654 | /// |
| 1655 | /// # Safety |
| 1656 | /// If non-null, `ptr` must be a pointer to a Python object of type T. |
| 1657 | #[inline ] |
| 1658 | pub unsafe fn from_owned_ptr_or_err( |
| 1659 | py: Python<'_>, |
| 1660 | ptr: *mut ffi::PyObject, |
| 1661 | ) -> PyResult<Py<T>> { |
| 1662 | match NonNull::new(ptr) { |
| 1663 | Some(nonnull_ptr) => Ok(Py(nonnull_ptr, PhantomData)), |
| 1664 | None => Err(PyErr::fetch(py)), |
| 1665 | } |
| 1666 | } |
| 1667 | |
| 1668 | /// Create a `Py<T>` instance by taking ownership of the given FFI pointer. |
| 1669 | /// |
| 1670 | /// If `ptr` is null then `None` is returned. |
| 1671 | /// |
| 1672 | /// # Safety |
| 1673 | /// If non-null, `ptr` must be a pointer to a Python object of type T. |
| 1674 | #[inline ] |
| 1675 | pub unsafe fn from_owned_ptr_or_opt(_py: Python<'_>, ptr: *mut ffi::PyObject) -> Option<Self> { |
| 1676 | NonNull::new(ptr).map(|nonnull_ptr| Py(nonnull_ptr, PhantomData)) |
| 1677 | } |
| 1678 | |
| 1679 | /// Constructs a new `Py<T>` instance by taking ownership of the given FFI pointer. |
| 1680 | /// |
| 1681 | /// # Safety |
| 1682 | /// |
| 1683 | /// - `ptr` must be a non-null pointer to a Python object or type `T`. |
| 1684 | pub(crate) unsafe fn from_owned_ptr_unchecked(ptr: *mut ffi::PyObject) -> Self { |
| 1685 | Py(unsafe { NonNull::new_unchecked(ptr) }, PhantomData) |
| 1686 | } |
| 1687 | |
| 1688 | /// Create a `Py<T>` instance by creating a new reference from the given FFI pointer. |
| 1689 | /// |
| 1690 | /// # Safety |
| 1691 | /// `ptr` must be a pointer to a Python object of type T. |
| 1692 | /// |
| 1693 | /// # Panics |
| 1694 | /// Panics if `ptr` is null. |
| 1695 | #[inline ] |
| 1696 | #[track_caller ] |
| 1697 | pub unsafe fn from_borrowed_ptr(py: Python<'_>, ptr: *mut ffi::PyObject) -> Py<T> { |
| 1698 | match unsafe { Self::from_borrowed_ptr_or_opt(py, ptr) } { |
| 1699 | Some(slf) => slf, |
| 1700 | None => crate::err::panic_after_error(py), |
| 1701 | } |
| 1702 | } |
| 1703 | |
| 1704 | /// Create a `Py<T>` instance by creating a new reference from the given FFI pointer. |
| 1705 | /// |
| 1706 | /// If `ptr` is null then the current Python exception is fetched as a `PyErr`. |
| 1707 | /// |
| 1708 | /// # Safety |
| 1709 | /// `ptr` must be a pointer to a Python object of type T. |
| 1710 | #[inline ] |
| 1711 | pub unsafe fn from_borrowed_ptr_or_err( |
| 1712 | py: Python<'_>, |
| 1713 | ptr: *mut ffi::PyObject, |
| 1714 | ) -> PyResult<Self> { |
| 1715 | unsafe { Self::from_borrowed_ptr_or_opt(py, ptr).ok_or_else(|| PyErr::fetch(py)) } |
| 1716 | } |
| 1717 | |
| 1718 | /// Create a `Py<T>` instance by creating a new reference from the given FFI pointer. |
| 1719 | /// |
| 1720 | /// If `ptr` is null then `None` is returned. |
| 1721 | /// |
| 1722 | /// # Safety |
| 1723 | /// `ptr` must be a pointer to a Python object of type T. |
| 1724 | #[inline ] |
| 1725 | pub unsafe fn from_borrowed_ptr_or_opt( |
| 1726 | _py: Python<'_>, |
| 1727 | ptr: *mut ffi::PyObject, |
| 1728 | ) -> Option<Self> { |
| 1729 | unsafe { |
| 1730 | NonNull::new(ptr).map(|nonnull_ptr| { |
| 1731 | ffi::Py_INCREF(ptr); |
| 1732 | Py(nonnull_ptr, PhantomData) |
| 1733 | }) |
| 1734 | } |
| 1735 | } |
| 1736 | |
| 1737 | /// For internal conversions. |
| 1738 | /// |
| 1739 | /// # Safety |
| 1740 | /// `ptr` must point to a Python object of type T. |
| 1741 | unsafe fn from_non_null(ptr: NonNull<ffi::PyObject>) -> Self { |
| 1742 | Self(ptr, PhantomData) |
| 1743 | } |
| 1744 | } |
| 1745 | |
| 1746 | #[allow (deprecated)] |
| 1747 | impl<T> ToPyObject for Py<T> { |
| 1748 | /// Converts `Py` instance -> PyObject. |
| 1749 | #[inline ] |
| 1750 | fn to_object(&self, py: Python<'_>) -> PyObject { |
| 1751 | self.clone_ref(py).into_any() |
| 1752 | } |
| 1753 | } |
| 1754 | |
| 1755 | #[allow (deprecated)] |
| 1756 | impl<T> IntoPy<PyObject> for Py<T> { |
| 1757 | /// Converts a `Py` instance to `PyObject`. |
| 1758 | /// Consumes `self` without calling `Py_DECREF()`. |
| 1759 | #[inline ] |
| 1760 | fn into_py(self, _py: Python<'_>) -> PyObject { |
| 1761 | self.into_any() |
| 1762 | } |
| 1763 | } |
| 1764 | |
| 1765 | #[allow (deprecated)] |
| 1766 | impl<T> IntoPy<PyObject> for &'_ Py<T> { |
| 1767 | #[inline ] |
| 1768 | fn into_py(self, py: Python<'_>) -> PyObject { |
| 1769 | self.into_pyobject(py).unwrap().into_any().unbind() |
| 1770 | } |
| 1771 | } |
| 1772 | |
| 1773 | #[allow (deprecated)] |
| 1774 | impl<T> ToPyObject for Bound<'_, T> { |
| 1775 | /// Converts `&Bound` instance -> PyObject, increasing the reference count. |
| 1776 | #[inline ] |
| 1777 | fn to_object(&self, py: Python<'_>) -> PyObject { |
| 1778 | self.clone().into_py(py) |
| 1779 | } |
| 1780 | } |
| 1781 | |
| 1782 | #[allow (deprecated)] |
| 1783 | impl<T> IntoPy<PyObject> for Bound<'_, T> { |
| 1784 | /// Converts a `Bound` instance to `PyObject`. |
| 1785 | #[inline ] |
| 1786 | fn into_py(self, _py: Python<'_>) -> PyObject { |
| 1787 | self.into_any().unbind() |
| 1788 | } |
| 1789 | } |
| 1790 | |
| 1791 | #[allow (deprecated)] |
| 1792 | impl<T> IntoPy<PyObject> for &Bound<'_, T> { |
| 1793 | /// Converts `&Bound` instance -> PyObject, increasing the reference count. |
| 1794 | #[inline ] |
| 1795 | fn into_py(self, py: Python<'_>) -> PyObject { |
| 1796 | self.into_pyobject(py).unwrap().into_any().unbind() |
| 1797 | } |
| 1798 | } |
| 1799 | |
| 1800 | unsafe impl<T> crate::AsPyPointer for Py<T> { |
| 1801 | /// Gets the underlying FFI pointer, returns a borrowed pointer. |
| 1802 | #[inline ] |
| 1803 | fn as_ptr(&self) -> *mut ffi::PyObject { |
| 1804 | self.0.as_ptr() |
| 1805 | } |
| 1806 | } |
| 1807 | |
| 1808 | impl<T> std::convert::From<Py<T>> for PyObject |
| 1809 | where |
| 1810 | T: DerefToPyAny, |
| 1811 | { |
| 1812 | #[inline ] |
| 1813 | fn from(other: Py<T>) -> Self { |
| 1814 | other.into_any() |
| 1815 | } |
| 1816 | } |
| 1817 | |
| 1818 | impl<T> std::convert::From<Bound<'_, T>> for PyObject |
| 1819 | where |
| 1820 | T: DerefToPyAny, |
| 1821 | { |
| 1822 | #[inline ] |
| 1823 | fn from(other: Bound<'_, T>) -> Self { |
| 1824 | other.into_any().unbind() |
| 1825 | } |
| 1826 | } |
| 1827 | |
| 1828 | impl<T> std::convert::From<Bound<'_, T>> for Py<T> { |
| 1829 | #[inline ] |
| 1830 | fn from(other: Bound<'_, T>) -> Self { |
| 1831 | other.unbind() |
| 1832 | } |
| 1833 | } |
| 1834 | |
| 1835 | impl<'a, T> std::convert::From<PyRef<'a, T>> for Py<T> |
| 1836 | where |
| 1837 | T: PyClass, |
| 1838 | { |
| 1839 | fn from(pyref: PyRef<'a, T>) -> Self { |
| 1840 | unsafe { Py::from_borrowed_ptr(pyref.py(), pyref.as_ptr()) } |
| 1841 | } |
| 1842 | } |
| 1843 | |
| 1844 | impl<'a, T> std::convert::From<PyRefMut<'a, T>> for Py<T> |
| 1845 | where |
| 1846 | T: PyClass<Frozen = False>, |
| 1847 | { |
| 1848 | fn from(pyref: PyRefMut<'a, T>) -> Self { |
| 1849 | unsafe { Py::from_borrowed_ptr(pyref.py(), pyref.as_ptr()) } |
| 1850 | } |
| 1851 | } |
| 1852 | |
| 1853 | /// If the GIL is held this increments `self`'s reference count. |
| 1854 | /// Otherwise, it will panic. |
| 1855 | /// |
| 1856 | /// Only available if the `py-clone` feature is enabled. |
| 1857 | #[cfg (feature = "py-clone" )] |
| 1858 | impl<T> Clone for Py<T> { |
| 1859 | #[track_caller ] |
| 1860 | fn clone(&self) -> Self { |
| 1861 | unsafe { |
| 1862 | gil::register_incref(self.0); |
| 1863 | } |
| 1864 | Self(self.0, PhantomData) |
| 1865 | } |
| 1866 | } |
| 1867 | |
| 1868 | /// Dropping a `Py` instance decrements the reference count |
| 1869 | /// on the object by one if the GIL is held. |
| 1870 | /// |
| 1871 | /// Otherwise and by default, this registers the underlying pointer to have its reference count |
| 1872 | /// decremented the next time PyO3 acquires the GIL. |
| 1873 | /// |
| 1874 | /// However, if the `pyo3_disable_reference_pool` conditional compilation flag |
| 1875 | /// is enabled, it will abort the process. |
| 1876 | impl<T> Drop for Py<T> { |
| 1877 | #[track_caller ] |
| 1878 | fn drop(&mut self) { |
| 1879 | unsafe { |
| 1880 | gil::register_decref(self.0); |
| 1881 | } |
| 1882 | } |
| 1883 | } |
| 1884 | |
| 1885 | impl<T> FromPyObject<'_> for Py<T> |
| 1886 | where |
| 1887 | T: PyTypeCheck, |
| 1888 | { |
| 1889 | /// Extracts `Self` from the source `PyObject`. |
| 1890 | fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult<Self> { |
| 1891 | ob.extract::<Bound<'_, T>>().map(op:Bound::unbind) |
| 1892 | } |
| 1893 | } |
| 1894 | |
| 1895 | impl<'py, T> FromPyObject<'py> for Bound<'py, T> |
| 1896 | where |
| 1897 | T: PyTypeCheck, |
| 1898 | { |
| 1899 | /// Extracts `Self` from the source `PyObject`. |
| 1900 | fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> { |
| 1901 | ob.downcast().cloned().map_err(op:Into::into) |
| 1902 | } |
| 1903 | } |
| 1904 | |
| 1905 | impl<T> std::fmt::Display for Py<T> |
| 1906 | where |
| 1907 | T: PyTypeInfo, |
| 1908 | { |
| 1909 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 1910 | Python::with_gil(|py: Python<'_>| std::fmt::Display::fmt(self.bind(py), f)) |
| 1911 | } |
| 1912 | } |
| 1913 | |
| 1914 | impl<T> std::fmt::Debug for Py<T> { |
| 1915 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 1916 | f.debug_tuple(name:"Py" ).field(&self.0.as_ptr()).finish() |
| 1917 | } |
| 1918 | } |
| 1919 | |
| 1920 | /// A commonly-used alias for `Py<PyAny>`. |
| 1921 | /// |
| 1922 | /// This is an owned reference a Python object without any type information. This value can also be |
| 1923 | /// safely sent between threads. |
| 1924 | /// |
| 1925 | /// See the documentation for [`Py`](struct.Py.html). |
| 1926 | pub type PyObject = Py<PyAny>; |
| 1927 | |
| 1928 | impl PyObject { |
| 1929 | /// Downcast this `PyObject` to a concrete Python type or pyclass. |
| 1930 | /// |
| 1931 | /// Note that you can often avoid downcasting yourself by just specifying |
| 1932 | /// the desired type in function or method signatures. |
| 1933 | /// However, manual downcasting is sometimes necessary. |
| 1934 | /// |
| 1935 | /// For extracting a Rust-only type, see [`Py::extract`](struct.Py.html#method.extract). |
| 1936 | /// |
| 1937 | /// # Example: Downcasting to a specific Python object |
| 1938 | /// |
| 1939 | /// ```rust |
| 1940 | /// use pyo3::prelude::*; |
| 1941 | /// use pyo3::types::{PyDict, PyList}; |
| 1942 | /// |
| 1943 | /// Python::with_gil(|py| { |
| 1944 | /// let any: PyObject = PyDict::new(py).into(); |
| 1945 | /// |
| 1946 | /// assert!(any.downcast_bound::<PyDict>(py).is_ok()); |
| 1947 | /// assert!(any.downcast_bound::<PyList>(py).is_err()); |
| 1948 | /// }); |
| 1949 | /// ``` |
| 1950 | /// |
| 1951 | /// # Example: Getting a reference to a pyclass |
| 1952 | /// |
| 1953 | /// This is useful if you want to mutate a `PyObject` that |
| 1954 | /// might actually be a pyclass. |
| 1955 | /// |
| 1956 | /// ```rust |
| 1957 | /// # fn main() -> Result<(), pyo3::PyErr> { |
| 1958 | /// use pyo3::prelude::*; |
| 1959 | /// |
| 1960 | /// #[pyclass] |
| 1961 | /// struct Class { |
| 1962 | /// i: i32, |
| 1963 | /// } |
| 1964 | /// |
| 1965 | /// Python::with_gil(|py| { |
| 1966 | /// let class: PyObject = Py::new(py, Class { i: 0 })?.into_any(); |
| 1967 | /// |
| 1968 | /// let class_bound = class.downcast_bound::<Class>(py)?; |
| 1969 | /// |
| 1970 | /// class_bound.borrow_mut().i += 1; |
| 1971 | /// |
| 1972 | /// // Alternatively you can get a `PyRefMut` directly |
| 1973 | /// let class_ref: PyRefMut<'_, Class> = class.extract(py)?; |
| 1974 | /// assert_eq!(class_ref.i, 1); |
| 1975 | /// Ok(()) |
| 1976 | /// }) |
| 1977 | /// # } |
| 1978 | /// ``` |
| 1979 | #[inline ] |
| 1980 | pub fn downcast_bound<'py, T>( |
| 1981 | &self, |
| 1982 | py: Python<'py>, |
| 1983 | ) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> |
| 1984 | where |
| 1985 | T: PyTypeCheck, |
| 1986 | { |
| 1987 | self.bind(py).downcast() |
| 1988 | } |
| 1989 | |
| 1990 | /// Casts the PyObject to a concrete Python object type without checking validity. |
| 1991 | /// |
| 1992 | /// # Safety |
| 1993 | /// |
| 1994 | /// Callers must ensure that the type is valid or risk type confusion. |
| 1995 | #[inline ] |
| 1996 | pub unsafe fn downcast_bound_unchecked<'py, T>(&self, py: Python<'py>) -> &Bound<'py, T> { |
| 1997 | unsafe { self.bind(py).downcast_unchecked() } |
| 1998 | } |
| 1999 | } |
| 2000 | |
| 2001 | #[cfg (test)] |
| 2002 | mod tests { |
| 2003 | use super::{Bound, IntoPyObject, Py, PyObject}; |
| 2004 | use crate::tests::common::generate_unique_module_name; |
| 2005 | use crate::types::{dict::IntoPyDict, PyAnyMethods, PyCapsule, PyDict, PyString}; |
| 2006 | use crate::{ffi, Borrowed, PyAny, PyResult, Python}; |
| 2007 | use pyo3_ffi::c_str; |
| 2008 | use std::ffi::CStr; |
| 2009 | |
| 2010 | #[test ] |
| 2011 | fn test_call() { |
| 2012 | Python::with_gil(|py| { |
| 2013 | let obj = py.get_type::<PyDict>().into_pyobject(py).unwrap(); |
| 2014 | |
| 2015 | let assert_repr = |obj: Bound<'_, PyAny>, expected: &str| { |
| 2016 | assert_eq!(obj.repr().unwrap(), expected); |
| 2017 | }; |
| 2018 | |
| 2019 | assert_repr(obj.call0().unwrap(), "{}" ); |
| 2020 | assert_repr(obj.call1(()).unwrap(), "{}" ); |
| 2021 | assert_repr(obj.call((), None).unwrap(), "{}" ); |
| 2022 | |
| 2023 | assert_repr(obj.call1(((('x' , 1),),)).unwrap(), "{'x': 1}" ); |
| 2024 | assert_repr( |
| 2025 | obj.call((), Some(&[('x' , 1)].into_py_dict(py).unwrap())) |
| 2026 | .unwrap(), |
| 2027 | "{'x': 1}" , |
| 2028 | ); |
| 2029 | }) |
| 2030 | } |
| 2031 | |
| 2032 | #[test ] |
| 2033 | fn test_call_tuple_ref() { |
| 2034 | let assert_repr = |obj: &Bound<'_, PyAny>, expected: &str| { |
| 2035 | use crate::prelude::PyStringMethods; |
| 2036 | assert_eq!( |
| 2037 | obj.repr() |
| 2038 | .unwrap() |
| 2039 | .to_cow() |
| 2040 | .unwrap() |
| 2041 | .trim_matches(|c| c == '{' || c == '}' ), |
| 2042 | expected.trim_matches(|c| c == ',' || c == ' ' ) |
| 2043 | ); |
| 2044 | }; |
| 2045 | |
| 2046 | macro_rules! tuple { |
| 2047 | ($py:ident, $($key: literal => $value: literal),+) => { |
| 2048 | let ty_obj = $py.get_type::<PyDict>().into_pyobject($py).unwrap(); |
| 2049 | assert!(ty_obj.call1(&(($(($key),)+),)).is_err()); |
| 2050 | let obj = ty_obj.call1(&(($(($key, i32::from($value)),)+),)).unwrap(); |
| 2051 | assert_repr(&obj, concat!($("'" , $key, "'" , ": " , stringify!($value), ", " ,)+)); |
| 2052 | assert!(obj.call_method1("update" , &(($(($key),)+),)).is_err()); |
| 2053 | obj.call_method1("update" , &(($((i32::from($value), $key),)+),)).unwrap(); |
| 2054 | assert_repr(&obj, concat!( |
| 2055 | concat!($("'" , $key, "'" , ": " , stringify!($value), ", " ,)+), |
| 2056 | concat!($(stringify!($value), ": " , "'" , $key, "'" , ", " ,)+) |
| 2057 | )); |
| 2058 | }; |
| 2059 | } |
| 2060 | |
| 2061 | Python::with_gil(|py| { |
| 2062 | tuple!(py, "a" => 1); |
| 2063 | tuple!(py, "a" => 1, "b" => 2); |
| 2064 | tuple!(py, "a" => 1, "b" => 2, "c" => 3); |
| 2065 | tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4); |
| 2066 | tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5); |
| 2067 | tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6); |
| 2068 | tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7); |
| 2069 | tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7, "h" => 8); |
| 2070 | tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7, "h" => 8, "i" => 9); |
| 2071 | tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7, "h" => 8, "i" => 9, "j" => 10, "k" => 11); |
| 2072 | tuple!(py, "a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7, "h" => 8, "i" => 9, "j" => 10, "k" => 11, "l" => 12); |
| 2073 | }) |
| 2074 | } |
| 2075 | |
| 2076 | #[test ] |
| 2077 | fn test_call_for_non_existing_method() { |
| 2078 | Python::with_gil(|py| { |
| 2079 | let obj: PyObject = PyDict::new(py).into(); |
| 2080 | assert!(obj.call_method0(py, "asdf" ).is_err()); |
| 2081 | assert!(obj |
| 2082 | .call_method(py, "nonexistent_method" , (1,), None) |
| 2083 | .is_err()); |
| 2084 | assert!(obj.call_method0(py, "nonexistent_method" ).is_err()); |
| 2085 | assert!(obj.call_method1(py, "nonexistent_method" , (1,)).is_err()); |
| 2086 | }); |
| 2087 | } |
| 2088 | |
| 2089 | #[test ] |
| 2090 | fn py_from_dict() { |
| 2091 | let dict: Py<PyDict> = Python::with_gil(|py| { |
| 2092 | let native = PyDict::new(py); |
| 2093 | Py::from(native) |
| 2094 | }); |
| 2095 | |
| 2096 | Python::with_gil(move |py| { |
| 2097 | assert_eq!(dict.get_refcnt(py), 1); |
| 2098 | }); |
| 2099 | } |
| 2100 | |
| 2101 | #[test ] |
| 2102 | fn pyobject_from_py() { |
| 2103 | Python::with_gil(|py| { |
| 2104 | let dict: Py<PyDict> = PyDict::new(py).unbind(); |
| 2105 | let cnt = dict.get_refcnt(py); |
| 2106 | let p: PyObject = dict.into(); |
| 2107 | assert_eq!(p.get_refcnt(py), cnt); |
| 2108 | }); |
| 2109 | } |
| 2110 | |
| 2111 | #[test ] |
| 2112 | fn attr() -> PyResult<()> { |
| 2113 | use crate::types::PyModule; |
| 2114 | |
| 2115 | Python::with_gil(|py| { |
| 2116 | const CODE: &CStr = c_str!( |
| 2117 | r#" |
| 2118 | class A: |
| 2119 | pass |
| 2120 | a = A() |
| 2121 | "# |
| 2122 | ); |
| 2123 | let module = |
| 2124 | PyModule::from_code(py, CODE, c_str!("" ), &generate_unique_module_name("" ))?; |
| 2125 | let instance: Py<PyAny> = module.getattr("a" )?.into(); |
| 2126 | |
| 2127 | instance.getattr(py, "foo" ).unwrap_err(); |
| 2128 | |
| 2129 | instance.setattr(py, "foo" , "bar" )?; |
| 2130 | |
| 2131 | assert!(instance |
| 2132 | .getattr(py, "foo" )? |
| 2133 | .bind(py) |
| 2134 | .eq(PyString::new(py, "bar" ))?); |
| 2135 | |
| 2136 | instance.getattr(py, "foo" )?; |
| 2137 | Ok(()) |
| 2138 | }) |
| 2139 | } |
| 2140 | |
| 2141 | #[test ] |
| 2142 | fn pystring_attr() -> PyResult<()> { |
| 2143 | use crate::types::PyModule; |
| 2144 | |
| 2145 | Python::with_gil(|py| { |
| 2146 | const CODE: &CStr = c_str!( |
| 2147 | r#" |
| 2148 | class A: |
| 2149 | pass |
| 2150 | a = A() |
| 2151 | "# |
| 2152 | ); |
| 2153 | let module = |
| 2154 | PyModule::from_code(py, CODE, c_str!("" ), &generate_unique_module_name("" ))?; |
| 2155 | let instance: Py<PyAny> = module.getattr("a" )?.into(); |
| 2156 | |
| 2157 | let foo = crate::intern!(py, "foo" ); |
| 2158 | let bar = crate::intern!(py, "bar" ); |
| 2159 | |
| 2160 | instance.getattr(py, foo).unwrap_err(); |
| 2161 | instance.setattr(py, foo, bar)?; |
| 2162 | assert!(instance.getattr(py, foo)?.bind(py).eq(bar)?); |
| 2163 | Ok(()) |
| 2164 | }) |
| 2165 | } |
| 2166 | |
| 2167 | #[test ] |
| 2168 | fn invalid_attr() -> PyResult<()> { |
| 2169 | Python::with_gil(|py| { |
| 2170 | let instance: Py<PyAny> = py.eval(ffi::c_str!("object()" ), None, None)?.into(); |
| 2171 | |
| 2172 | instance.getattr(py, "foo" ).unwrap_err(); |
| 2173 | |
| 2174 | // Cannot assign arbitrary attributes to `object` |
| 2175 | instance.setattr(py, "foo" , "bar" ).unwrap_err(); |
| 2176 | Ok(()) |
| 2177 | }) |
| 2178 | } |
| 2179 | |
| 2180 | #[test ] |
| 2181 | fn test_py2_from_py_object() { |
| 2182 | Python::with_gil(|py| { |
| 2183 | let instance = py.eval(ffi::c_str!("object()" ), None, None).unwrap(); |
| 2184 | let ptr = instance.as_ptr(); |
| 2185 | let instance: Bound<'_, PyAny> = instance.extract().unwrap(); |
| 2186 | assert_eq!(instance.as_ptr(), ptr); |
| 2187 | }) |
| 2188 | } |
| 2189 | |
| 2190 | #[test ] |
| 2191 | fn test_py2_into_py_object() { |
| 2192 | Python::with_gil(|py| { |
| 2193 | let instance = py.eval(ffi::c_str!("object()" ), None, None).unwrap(); |
| 2194 | let ptr = instance.as_ptr(); |
| 2195 | let instance: PyObject = instance.clone().unbind(); |
| 2196 | assert_eq!(instance.as_ptr(), ptr); |
| 2197 | }) |
| 2198 | } |
| 2199 | |
| 2200 | #[test ] |
| 2201 | fn test_debug_fmt() { |
| 2202 | Python::with_gil(|py| { |
| 2203 | let obj = "hello world" .into_pyobject(py).unwrap(); |
| 2204 | assert_eq!(format!("{:?}" , obj), "'hello world'" ); |
| 2205 | }); |
| 2206 | } |
| 2207 | |
| 2208 | #[test ] |
| 2209 | fn test_display_fmt() { |
| 2210 | Python::with_gil(|py| { |
| 2211 | let obj = "hello world" .into_pyobject(py).unwrap(); |
| 2212 | assert_eq!(format!("{}" , obj), "hello world" ); |
| 2213 | }); |
| 2214 | } |
| 2215 | |
| 2216 | #[test ] |
| 2217 | fn test_bound_as_any() { |
| 2218 | Python::with_gil(|py| { |
| 2219 | let obj = PyString::new(py, "hello world" ); |
| 2220 | let any = obj.as_any(); |
| 2221 | assert_eq!(any.as_ptr(), obj.as_ptr()); |
| 2222 | }); |
| 2223 | } |
| 2224 | |
| 2225 | #[test ] |
| 2226 | fn test_bound_into_any() { |
| 2227 | Python::with_gil(|py| { |
| 2228 | let obj = PyString::new(py, "hello world" ); |
| 2229 | let any = obj.clone().into_any(); |
| 2230 | assert_eq!(any.as_ptr(), obj.as_ptr()); |
| 2231 | }); |
| 2232 | } |
| 2233 | |
| 2234 | #[test ] |
| 2235 | fn test_bound_py_conversions() { |
| 2236 | Python::with_gil(|py| { |
| 2237 | let obj: Bound<'_, PyString> = PyString::new(py, "hello world" ); |
| 2238 | let obj_unbound: &Py<PyString> = obj.as_unbound(); |
| 2239 | let _: &Bound<'_, PyString> = obj_unbound.bind(py); |
| 2240 | |
| 2241 | let obj_unbound: Py<PyString> = obj.unbind(); |
| 2242 | let obj: Bound<'_, PyString> = obj_unbound.into_bound(py); |
| 2243 | |
| 2244 | assert_eq!(obj, "hello world" ); |
| 2245 | }); |
| 2246 | } |
| 2247 | |
| 2248 | #[test ] |
| 2249 | fn bound_from_borrowed_ptr_constructors() { |
| 2250 | // More detailed tests of the underlying semantics in pycell.rs |
| 2251 | Python::with_gil(|py| { |
| 2252 | fn check_drop<'py>( |
| 2253 | py: Python<'py>, |
| 2254 | method: impl FnOnce(*mut ffi::PyObject) -> Bound<'py, PyAny>, |
| 2255 | ) { |
| 2256 | let mut dropped = false; |
| 2257 | let capsule = PyCapsule::new_with_destructor( |
| 2258 | py, |
| 2259 | (&mut dropped) as *mut _ as usize, |
| 2260 | None, |
| 2261 | |ptr, _| unsafe { std::ptr::write(ptr as *mut bool, true) }, |
| 2262 | ) |
| 2263 | .unwrap(); |
| 2264 | |
| 2265 | let bound = method(capsule.as_ptr()); |
| 2266 | assert!(!dropped); |
| 2267 | |
| 2268 | // creating the bound should have increased the refcount |
| 2269 | drop(capsule); |
| 2270 | assert!(!dropped); |
| 2271 | |
| 2272 | // dropping the bound should now also decrease the refcount and free the object |
| 2273 | drop(bound); |
| 2274 | assert!(dropped); |
| 2275 | } |
| 2276 | |
| 2277 | check_drop(py, |ptr| unsafe { Bound::from_borrowed_ptr(py, ptr) }); |
| 2278 | check_drop(py, |ptr| unsafe { |
| 2279 | Bound::from_borrowed_ptr_or_opt(py, ptr).unwrap() |
| 2280 | }); |
| 2281 | check_drop(py, |ptr| unsafe { |
| 2282 | Bound::from_borrowed_ptr_or_err(py, ptr).unwrap() |
| 2283 | }); |
| 2284 | }) |
| 2285 | } |
| 2286 | |
| 2287 | #[test ] |
| 2288 | fn borrowed_ptr_constructors() { |
| 2289 | // More detailed tests of the underlying semantics in pycell.rs |
| 2290 | Python::with_gil(|py| { |
| 2291 | fn check_drop<'py>( |
| 2292 | py: Python<'py>, |
| 2293 | method: impl FnOnce(&*mut ffi::PyObject) -> Borrowed<'_, 'py, PyAny>, |
| 2294 | ) { |
| 2295 | let mut dropped = false; |
| 2296 | let capsule = PyCapsule::new_with_destructor( |
| 2297 | py, |
| 2298 | (&mut dropped) as *mut _ as usize, |
| 2299 | None, |
| 2300 | |ptr, _| unsafe { std::ptr::write(ptr as *mut bool, true) }, |
| 2301 | ) |
| 2302 | .unwrap(); |
| 2303 | |
| 2304 | let ptr = &capsule.as_ptr(); |
| 2305 | let _borrowed = method(ptr); |
| 2306 | assert!(!dropped); |
| 2307 | |
| 2308 | // creating the borrow should not have increased the refcount |
| 2309 | drop(capsule); |
| 2310 | assert!(dropped); |
| 2311 | } |
| 2312 | |
| 2313 | check_drop(py, |&ptr| unsafe { Borrowed::from_ptr(py, ptr) }); |
| 2314 | check_drop(py, |&ptr| unsafe { |
| 2315 | Borrowed::from_ptr_or_opt(py, ptr).unwrap() |
| 2316 | }); |
| 2317 | check_drop(py, |&ptr| unsafe { |
| 2318 | Borrowed::from_ptr_or_err(py, ptr).unwrap() |
| 2319 | }); |
| 2320 | }) |
| 2321 | } |
| 2322 | |
| 2323 | #[test ] |
| 2324 | fn explicit_drop_ref() { |
| 2325 | Python::with_gil(|py| { |
| 2326 | let object: Py<PyDict> = PyDict::new(py).unbind(); |
| 2327 | let object2 = object.clone_ref(py); |
| 2328 | |
| 2329 | assert_eq!(object.as_ptr(), object2.as_ptr()); |
| 2330 | assert_eq!(object.get_refcnt(py), 2); |
| 2331 | |
| 2332 | object.drop_ref(py); |
| 2333 | |
| 2334 | assert_eq!(object2.get_refcnt(py), 1); |
| 2335 | |
| 2336 | object2.drop_ref(py); |
| 2337 | }); |
| 2338 | } |
| 2339 | |
| 2340 | #[cfg (feature = "macros" )] |
| 2341 | mod using_macros { |
| 2342 | use super::*; |
| 2343 | |
| 2344 | #[crate::pyclass (crate = "crate" )] |
| 2345 | struct SomeClass(i32); |
| 2346 | |
| 2347 | #[test ] |
| 2348 | fn py_borrow_methods() { |
| 2349 | // More detailed tests of the underlying semantics in pycell.rs |
| 2350 | Python::with_gil(|py| { |
| 2351 | let instance = Py::new(py, SomeClass(0)).unwrap(); |
| 2352 | assert_eq!(instance.borrow(py).0, 0); |
| 2353 | assert_eq!(instance.try_borrow(py).unwrap().0, 0); |
| 2354 | assert_eq!(instance.borrow_mut(py).0, 0); |
| 2355 | assert_eq!(instance.try_borrow_mut(py).unwrap().0, 0); |
| 2356 | |
| 2357 | instance.borrow_mut(py).0 = 123; |
| 2358 | |
| 2359 | assert_eq!(instance.borrow(py).0, 123); |
| 2360 | assert_eq!(instance.try_borrow(py).unwrap().0, 123); |
| 2361 | assert_eq!(instance.borrow_mut(py).0, 123); |
| 2362 | assert_eq!(instance.try_borrow_mut(py).unwrap().0, 123); |
| 2363 | }) |
| 2364 | } |
| 2365 | |
| 2366 | #[test ] |
| 2367 | fn bound_borrow_methods() { |
| 2368 | // More detailed tests of the underlying semantics in pycell.rs |
| 2369 | Python::with_gil(|py| { |
| 2370 | let instance = Bound::new(py, SomeClass(0)).unwrap(); |
| 2371 | assert_eq!(instance.borrow().0, 0); |
| 2372 | assert_eq!(instance.try_borrow().unwrap().0, 0); |
| 2373 | assert_eq!(instance.borrow_mut().0, 0); |
| 2374 | assert_eq!(instance.try_borrow_mut().unwrap().0, 0); |
| 2375 | |
| 2376 | instance.borrow_mut().0 = 123; |
| 2377 | |
| 2378 | assert_eq!(instance.borrow().0, 123); |
| 2379 | assert_eq!(instance.try_borrow().unwrap().0, 123); |
| 2380 | assert_eq!(instance.borrow_mut().0, 123); |
| 2381 | assert_eq!(instance.try_borrow_mut().unwrap().0, 123); |
| 2382 | }) |
| 2383 | } |
| 2384 | |
| 2385 | #[crate::pyclass (frozen, crate = "crate" )] |
| 2386 | struct FrozenClass(i32); |
| 2387 | |
| 2388 | #[test ] |
| 2389 | fn test_frozen_get() { |
| 2390 | Python::with_gil(|py| { |
| 2391 | for i in 0..10 { |
| 2392 | let instance = Py::new(py, FrozenClass(i)).unwrap(); |
| 2393 | assert_eq!(instance.get().0, i); |
| 2394 | |
| 2395 | assert_eq!(instance.bind(py).get().0, i); |
| 2396 | } |
| 2397 | }) |
| 2398 | } |
| 2399 | |
| 2400 | #[crate::pyclass (crate = "crate" , subclass)] |
| 2401 | struct BaseClass; |
| 2402 | |
| 2403 | trait MyClassMethods<'py>: Sized { |
| 2404 | fn pyrepr_by_ref(&self) -> PyResult<String>; |
| 2405 | fn pyrepr_by_val(self) -> PyResult<String> { |
| 2406 | self.pyrepr_by_ref() |
| 2407 | } |
| 2408 | } |
| 2409 | impl<'py> MyClassMethods<'py> for Bound<'py, BaseClass> { |
| 2410 | fn pyrepr_by_ref(&self) -> PyResult<String> { |
| 2411 | self.call_method0("__repr__" )?.extract() |
| 2412 | } |
| 2413 | } |
| 2414 | |
| 2415 | #[crate::pyclass (crate = "crate" , extends = BaseClass)] |
| 2416 | struct SubClass; |
| 2417 | |
| 2418 | #[test ] |
| 2419 | fn test_as_super() { |
| 2420 | Python::with_gil(|py| { |
| 2421 | let obj = Bound::new(py, (SubClass, BaseClass)).unwrap(); |
| 2422 | let _: &Bound<'_, BaseClass> = obj.as_super(); |
| 2423 | let _: &Bound<'_, PyAny> = obj.as_super().as_super(); |
| 2424 | assert!(obj.as_super().pyrepr_by_ref().is_ok()); |
| 2425 | }) |
| 2426 | } |
| 2427 | |
| 2428 | #[test ] |
| 2429 | fn test_into_super() { |
| 2430 | Python::with_gil(|py| { |
| 2431 | let obj = Bound::new(py, (SubClass, BaseClass)).unwrap(); |
| 2432 | let _: Bound<'_, BaseClass> = obj.clone().into_super(); |
| 2433 | let _: Bound<'_, PyAny> = obj.clone().into_super().into_super(); |
| 2434 | assert!(obj.into_super().pyrepr_by_val().is_ok()); |
| 2435 | }) |
| 2436 | } |
| 2437 | } |
| 2438 | } |
| 2439 | |