pyo3/conversion.rs
1//! Defines conversions between Rust and Python types.
2use crate::err::PyResult;
3use crate::ffi_ptr_ext::FfiPtrExt;
4#[cfg(feature = "experimental-inspect")]
5use crate::inspect::types::TypeInfo;
6use crate::pyclass::boolean_struct::False;
7use crate::types::any::PyAnyMethods;
8use crate::types::{PyDict, PyString, PyTuple};
9use crate::{ffi, Borrowed, Bound, Py, PyAny, PyClass, PyObject, PyRef, PyRefMut, Python};
10#[cfg(feature = "gil-refs")]
11use {
12 crate::{
13 err::{self, PyDowncastError},
14 gil, PyNativeType,
15 },
16 std::ptr::NonNull,
17};
18
19/// Returns a borrowed pointer to a Python object.
20///
21/// The returned pointer will be valid for as long as `self` is. It may be null depending on the
22/// implementation.
23///
24/// # Examples
25///
26/// ```rust
27/// use pyo3::prelude::*;
28/// use pyo3::types::PyString;
29/// use pyo3::ffi;
30///
31/// Python::with_gil(|py| {
32/// let s: Py<PyString> = "foo".into_py(py);
33/// let ptr = s.as_ptr();
34///
35/// let is_really_a_pystring = unsafe { ffi::PyUnicode_CheckExact(ptr) };
36/// assert_eq!(is_really_a_pystring, 1);
37/// });
38/// ```
39///
40/// # Safety
41///
42/// For callers, it is your responsibility to make sure that the underlying Python object is not dropped too
43/// early. For example, the following code will cause undefined behavior:
44///
45/// ```rust,no_run
46/// # use pyo3::prelude::*;
47/// # use pyo3::ffi;
48/// #
49/// Python::with_gil(|py| {
50/// let ptr: *mut ffi::PyObject = 0xabad1dea_u32.into_py(py).as_ptr();
51///
52/// let isnt_a_pystring = unsafe {
53/// // `ptr` is dangling, this is UB
54/// ffi::PyUnicode_CheckExact(ptr)
55/// };
56/// # assert_eq!(isnt_a_pystring, 0);
57/// });
58/// ```
59///
60/// This happens because the pointer returned by `as_ptr` does not carry any lifetime information
61/// and the Python object is dropped immediately after the `0xabad1dea_u32.into_py(py).as_ptr()`
62/// expression is evaluated. To fix the problem, bind Python object to a local variable like earlier
63/// to keep the Python object alive until the end of its scope.
64///
65/// Implementors must ensure this returns a valid pointer to a Python object, which borrows a reference count from `&self`.
66pub unsafe trait AsPyPointer {
67 /// Returns the underlying FFI pointer as a borrowed pointer.
68 fn as_ptr(&self) -> *mut ffi::PyObject;
69}
70
71/// Conversion trait that allows various objects to be converted into `PyObject`.
72pub trait ToPyObject {
73 /// Converts self into a Python object.
74 fn to_object(&self, py: Python<'_>) -> PyObject;
75}
76
77/// Defines a conversion from a Rust type to a Python object.
78///
79/// It functions similarly to std's [`Into`] trait, but requires a [GIL token](Python)
80/// as an argument. Many functions and traits internal to PyO3 require this trait as a bound,
81/// so a lack of this trait can manifest itself in different error messages.
82///
83/// # Examples
84/// ## With `#[pyclass]`
85/// The easiest way to implement `IntoPy` is by exposing a struct as a native Python object
86/// by annotating it with [`#[pyclass]`](crate::prelude::pyclass).
87///
88/// ```rust
89/// use pyo3::prelude::*;
90///
91/// # #[allow(dead_code)]
92/// #[pyclass]
93/// struct Number {
94/// #[pyo3(get, set)]
95/// value: i32,
96/// }
97/// ```
98/// Python code will see this as an instance of the `Number` class with a `value` attribute.
99///
100/// ## Conversion to a Python object
101///
102/// However, it may not be desirable to expose the existence of `Number` to Python code.
103/// `IntoPy` allows us to define a conversion to an appropriate Python object.
104/// ```rust
105/// use pyo3::prelude::*;
106///
107/// # #[allow(dead_code)]
108/// struct Number {
109/// value: i32,
110/// }
111///
112/// impl IntoPy<PyObject> for Number {
113/// fn into_py(self, py: Python<'_>) -> PyObject {
114/// // delegates to i32's IntoPy implementation.
115/// self.value.into_py(py)
116/// }
117/// }
118/// ```
119/// Python code will see this as an `int` object.
120///
121/// ## Dynamic conversion into Python objects.
122/// It is also possible to return a different Python object depending on some condition.
123/// This is useful for types like enums that can carry different types.
124///
125/// ```rust
126/// use pyo3::prelude::*;
127///
128/// enum Value {
129/// Integer(i32),
130/// String(String),
131/// None,
132/// }
133///
134/// impl IntoPy<PyObject> for Value {
135/// fn into_py(self, py: Python<'_>) -> PyObject {
136/// match self {
137/// Self::Integer(val) => val.into_py(py),
138/// Self::String(val) => val.into_py(py),
139/// Self::None => py.None(),
140/// }
141/// }
142/// }
143/// # fn main() {
144/// # Python::with_gil(|py| {
145/// # let v = Value::Integer(73).into_py(py);
146/// # let v = v.extract::<i32>(py).unwrap();
147/// #
148/// # let v = Value::String("foo".into()).into_py(py);
149/// # let v = v.extract::<String>(py).unwrap();
150/// #
151/// # let v = Value::None.into_py(py);
152/// # let v = v.extract::<Option<Vec<i32>>>(py).unwrap();
153/// # });
154/// # }
155/// ```
156/// Python code will see this as any of the `int`, `string` or `None` objects.
157#[cfg_attr(
158 diagnostic_namespace,
159 diagnostic::on_unimplemented(
160 message = "`{Self}` cannot be converted to a Python object",
161 note = "`IntoPy` is automatically implemented by the `#[pyclass]` macro",
162 note = "if you do not wish to have a corresponding Python type, implement it manually",
163 note = "if you do not own `{Self}` you can perform a manual conversion to one of the types in `pyo3::types::*`"
164 )
165)]
166pub trait IntoPy<T>: Sized {
167 /// Performs the conversion.
168 fn into_py(self, py: Python<'_>) -> T;
169
170 /// Extracts the type hint information for this type when it appears as a return value.
171 ///
172 /// For example, `Vec<u32>` would return `List[int]`.
173 /// The default implementation returns `Any`, which is correct for any type.
174 ///
175 /// For most types, the return value for this method will be identical to that of [`FromPyObject::type_input`].
176 /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument.
177 #[cfg(feature = "experimental-inspect")]
178 fn type_output() -> TypeInfo {
179 TypeInfo::Any
180 }
181
182 // The following methods are helpers to use the vectorcall API where possible.
183 // They are overridden on tuples to perform a vectorcall.
184 // Be careful when you're implementing these: they can never refer to `Bound` call methods,
185 // as those refer to these methods, so this will create an infinite recursion.
186 #[doc(hidden)]
187 #[inline]
188 fn __py_call_vectorcall1<'py>(
189 self,
190 py: Python<'py>,
191 function: Borrowed<'_, 'py, PyAny>,
192 _: private::Token,
193 ) -> PyResult<Bound<'py, PyAny>>
194 where
195 Self: IntoPy<Py<PyTuple>>,
196 {
197 #[inline]
198 fn inner<'py>(
199 py: Python<'py>,
200 function: Borrowed<'_, 'py, PyAny>,
201 args: Bound<'py, PyTuple>,
202 ) -> PyResult<Bound<'py, PyAny>> {
203 unsafe {
204 ffi::PyObject_Call(function.as_ptr(), args.as_ptr(), std::ptr::null_mut())
205 .assume_owned_or_err(py)
206 }
207 }
208 inner(
209 py,
210 function,
211 <Self as IntoPy<Py<PyTuple>>>::into_py(self, py).into_bound(py),
212 )
213 }
214
215 #[doc(hidden)]
216 #[inline]
217 fn __py_call_vectorcall<'py>(
218 self,
219 py: Python<'py>,
220 function: Borrowed<'_, 'py, PyAny>,
221 kwargs: Option<Borrowed<'_, '_, PyDict>>,
222 _: private::Token,
223 ) -> PyResult<Bound<'py, PyAny>>
224 where
225 Self: IntoPy<Py<PyTuple>>,
226 {
227 #[inline]
228 fn inner<'py>(
229 py: Python<'py>,
230 function: Borrowed<'_, 'py, PyAny>,
231 args: Bound<'py, PyTuple>,
232 kwargs: Option<Borrowed<'_, '_, PyDict>>,
233 ) -> PyResult<Bound<'py, PyAny>> {
234 unsafe {
235 ffi::PyObject_Call(
236 function.as_ptr(),
237 args.as_ptr(),
238 kwargs.map_or_else(std::ptr::null_mut, |kwargs| kwargs.as_ptr()),
239 )
240 .assume_owned_or_err(py)
241 }
242 }
243 inner(
244 py,
245 function,
246 <Self as IntoPy<Py<PyTuple>>>::into_py(self, py).into_bound(py),
247 kwargs,
248 )
249 }
250
251 #[doc(hidden)]
252 #[inline]
253 fn __py_call_method_vectorcall1<'py>(
254 self,
255 _py: Python<'py>,
256 object: Borrowed<'_, 'py, PyAny>,
257 method_name: Borrowed<'_, 'py, PyString>,
258 _: private::Token,
259 ) -> PyResult<Bound<'py, PyAny>>
260 where
261 Self: IntoPy<Py<PyTuple>>,
262 {
263 // Don't `self.into_py()`! This will lose the optimization of vectorcall.
264 object
265 .getattr(method_name.to_owned())
266 .and_then(|method| method.call1(self))
267 }
268}
269
270pub(crate) mod private {
271 pub struct Token;
272}
273
274/// Extract a type from a Python object.
275///
276///
277/// Normal usage is through the `extract` methods on [`Bound`] and [`Py`], which forward to this trait.
278///
279/// # Examples
280///
281/// ```rust
282/// use pyo3::prelude::*;
283/// use pyo3::types::PyString;
284///
285/// # fn main() -> PyResult<()> {
286/// Python::with_gil(|py| {
287/// // Calling `.extract()` on a `Bound` smart pointer
288/// let obj: Bound<'_, PyString> = PyString::new_bound(py, "blah");
289/// let s: String = obj.extract()?;
290/// # assert_eq!(s, "blah");
291///
292/// // Calling `.extract(py)` on a `Py` smart pointer
293/// let obj: Py<PyString> = obj.unbind();
294/// let s: String = obj.extract(py)?;
295/// # assert_eq!(s, "blah");
296/// # Ok(())
297/// })
298/// # }
299/// ```
300///
301// /// FIXME: until `FromPyObject` can pick up a second lifetime, the below commentary is no longer
302// /// true. Update and restore this documentation at that time.
303// ///
304// /// Note: depending on the implementation, the lifetime of the extracted result may
305// /// depend on the lifetime of the `obj` or the `prepared` variable.
306// ///
307// /// For example, when extracting `&str` from a Python byte string, the resulting string slice will
308// /// point to the existing string data (lifetime: `'py`).
309// /// On the other hand, when extracting `&str` from a Python Unicode string, the preparation step
310// /// will convert the string to UTF-8, and the resulting string slice will have lifetime `'prepared`.
311// /// Since which case applies depends on the runtime type of the Python object,
312// /// both the `obj` and `prepared` variables must outlive the resulting string slice.
313///
314/// During the migration of PyO3 from the "GIL Refs" API to the `Bound<T>` smart pointer, this trait
315/// has two methods `extract` and `extract_bound` which are defaulted to call each other. To avoid
316/// infinite recursion, implementors must implement at least one of these methods. The recommendation
317/// is to implement `extract_bound` and leave `extract` as the default implementation.
318pub trait FromPyObject<'py>: Sized {
319 /// Extracts `Self` from the source GIL Ref `obj`.
320 ///
321 /// Implementors are encouraged to implement `extract_bound` and leave this method as the
322 /// default implementation, which will forward calls to `extract_bound`.
323 #[cfg(feature = "gil-refs")]
324 fn extract(ob: &'py PyAny) -> PyResult<Self> {
325 Self::extract_bound(&ob.as_borrowed())
326 }
327
328 /// Extracts `Self` from the bound smart pointer `obj`.
329 ///
330 /// Implementors are encouraged to implement this method and leave `extract` defaulted, as
331 /// this will be most compatible with PyO3's future API.
332 fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self>;
333
334 /// Extracts the type hint information for this type when it appears as an argument.
335 ///
336 /// For example, `Vec<u32>` would return `Sequence[int]`.
337 /// The default implementation returns `Any`, which is correct for any type.
338 ///
339 /// For most types, the return value for this method will be identical to that of [`IntoPy::type_output`].
340 /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument.
341 #[cfg(feature = "experimental-inspect")]
342 fn type_input() -> TypeInfo {
343 TypeInfo::Any
344 }
345}
346
347mod from_py_object_bound_sealed {
348 /// Private seal for the `FromPyObjectBound` trait.
349 ///
350 /// This prevents downstream types from implementing the trait before
351 /// PyO3 is ready to declare the trait as public API.
352 pub trait Sealed {}
353
354 // This generic implementation is why the seal is separate from
355 // `crate::sealed::Sealed`.
356 impl<'py, T> Sealed for T where T: super::FromPyObject<'py> {}
357 #[cfg(not(feature = "gil-refs"))]
358 impl Sealed for &'_ str {}
359 #[cfg(not(feature = "gil-refs"))]
360 impl Sealed for std::borrow::Cow<'_, str> {}
361 #[cfg(not(feature = "gil-refs"))]
362 impl Sealed for &'_ [u8] {}
363 #[cfg(not(feature = "gil-refs"))]
364 impl Sealed for std::borrow::Cow<'_, [u8]> {}
365}
366
367/// Expected form of [`FromPyObject`] to be used in a future PyO3 release.
368///
369/// The difference between this and `FromPyObject` is that this trait takes an
370/// additional lifetime `'a`, which is the lifetime of the input `Bound`.
371///
372/// This allows implementations for `&'a str` and `&'a [u8]`, which could not
373/// be expressed by the existing `FromPyObject` trait once the GIL Refs API was
374/// removed.
375///
376/// # Usage
377///
378/// Users are prevented from implementing this trait, instead they should implement
379/// the normal `FromPyObject` trait. This trait has a blanket implementation
380/// for `T: FromPyObject`.
381///
382/// The only case where this trait may have a use case to be implemented is when the
383/// lifetime of the extracted value is tied to the lifetime `'a` of the input `Bound`
384/// instead of the GIL lifetime `py`, as is the case for the `&'a str` implementation.
385///
386/// Please contact the PyO3 maintainers if you believe you have a use case for implementing
387/// this trait before PyO3 is ready to change the main `FromPyObject` trait to take an
388/// additional lifetime.
389///
390/// Similarly, users should typically not call these trait methods and should instead
391/// use this via the `extract` method on `Bound` and `Py`.
392pub trait FromPyObjectBound<'a, 'py>: Sized + from_py_object_bound_sealed::Sealed {
393 /// Extracts `Self` from the bound smart pointer `obj`.
394 ///
395 /// Users are advised against calling this method directly: instead, use this via
396 /// [`Bound<'_, PyAny>::extract`] or [`Py::extract`].
397 fn from_py_object_bound(ob: Borrowed<'a, 'py, PyAny>) -> PyResult<Self>;
398
399 /// Extracts the type hint information for this type when it appears as an argument.
400 ///
401 /// For example, `Vec<u32>` would return `Sequence[int]`.
402 /// The default implementation returns `Any`, which is correct for any type.
403 ///
404 /// For most types, the return value for this method will be identical to that of [`IntoPy::type_output`].
405 /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument.
406 #[cfg(feature = "experimental-inspect")]
407 fn type_input() -> TypeInfo {
408 TypeInfo::Any
409 }
410}
411
412impl<'py, T> FromPyObjectBound<'_, 'py> for T
413where
414 T: FromPyObject<'py>,
415{
416 fn from_py_object_bound(ob: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {
417 Self::extract_bound(&ob)
418 }
419
420 #[cfg(feature = "experimental-inspect")]
421 fn type_input() -> TypeInfo {
422 <T as FromPyObject>::type_input()
423 }
424}
425
426/// Identity conversion: allows using existing `PyObject` instances where
427/// `T: ToPyObject` is expected.
428impl<T: ?Sized + ToPyObject> ToPyObject for &'_ T {
429 #[inline]
430 fn to_object(&self, py: Python<'_>) -> PyObject {
431 <T as ToPyObject>::to_object(*self, py)
432 }
433}
434
435impl IntoPy<PyObject> for &'_ PyAny {
436 #[inline]
437 fn into_py(self, py: Python<'_>) -> PyObject {
438 unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
439 }
440}
441
442impl<T> IntoPy<PyObject> for &'_ T
443where
444 T: AsRef<PyAny>,
445{
446 #[inline]
447 fn into_py(self, py: Python<'_>) -> PyObject {
448 unsafe { PyObject::from_borrowed_ptr(py, self.as_ref().as_ptr()) }
449 }
450}
451
452#[allow(deprecated)]
453#[cfg(feature = "gil-refs")]
454impl<'py, T> FromPyObject<'py> for &'py crate::PyCell<T>
455where
456 T: PyClass,
457{
458 fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {
459 obj.clone().into_gil_ref().downcast().map_err(Into::into)
460 }
461}
462
463impl<T> FromPyObject<'_> for T
464where
465 T: PyClass + Clone,
466{
467 fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
468 let bound = obj.downcast::<Self>()?;
469 Ok(bound.try_borrow()?.clone())
470 }
471}
472
473impl<'py, T> FromPyObject<'py> for PyRef<'py, T>
474where
475 T: PyClass,
476{
477 fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {
478 obj.downcast::<T>()?.try_borrow().map_err(Into::into)
479 }
480}
481
482impl<'py, T> FromPyObject<'py> for PyRefMut<'py, T>
483where
484 T: PyClass<Frozen = False>,
485{
486 fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {
487 obj.downcast::<T>()?.try_borrow_mut().map_err(Into::into)
488 }
489}
490
491/// Trait implemented by Python object types that allow a checked downcast.
492/// If `T` implements `PyTryFrom`, we can convert `&PyAny` to `&T`.
493///
494/// This trait is similar to `std::convert::TryFrom`
495#[cfg(feature = "gil-refs")]
496#[deprecated(since = "0.21.0")]
497pub trait PyTryFrom<'v>: Sized + PyNativeType {
498 /// Cast from a concrete Python object type to PyObject.
499 #[deprecated(
500 since = "0.21.0",
501 note = "use `value.downcast::<T>()` instead of `T::try_from(value)`"
502 )]
503 fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>>;
504
505 /// Cast from a concrete Python object type to PyObject. With exact type check.
506 #[deprecated(
507 since = "0.21.0",
508 note = "use `value.downcast_exact::<T>()` instead of `T::try_from_exact(value)`"
509 )]
510 fn try_from_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>>;
511
512 /// Cast a PyAny to a specific type of PyObject. The caller must
513 /// have already verified the reference is for this type.
514 ///
515 /// # Safety
516 ///
517 /// Callers must ensure that the type is valid or risk type confusion.
518 #[deprecated(
519 since = "0.21.0",
520 note = "use `value.downcast_unchecked::<T>()` instead of `T::try_from_unchecked(value)`"
521 )]
522 unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v Self;
523}
524
525/// Trait implemented by Python object types that allow a checked downcast.
526/// This trait is similar to `std::convert::TryInto`
527#[cfg(feature = "gil-refs")]
528#[deprecated(since = "0.21.0")]
529pub trait PyTryInto<T>: Sized {
530 /// Cast from PyObject to a concrete Python object type.
531 #[deprecated(
532 since = "0.21.0",
533 note = "use `value.downcast()` instead of `value.try_into()`"
534 )]
535 fn try_into(&self) -> Result<&T, PyDowncastError<'_>>;
536
537 /// Cast from PyObject to a concrete Python object type. With exact type check.
538 #[deprecated(
539 since = "0.21.0",
540 note = "use `value.downcast()` instead of `value.try_into_exact()`"
541 )]
542 fn try_into_exact(&self) -> Result<&T, PyDowncastError<'_>>;
543}
544
545#[cfg(feature = "gil-refs")]
546#[allow(deprecated)]
547mod implementations {
548 use super::*;
549 use crate::type_object::PyTypeInfo;
550
551 // TryFrom implies TryInto
552 impl<U> PyTryInto<U> for PyAny
553 where
554 U: for<'v> PyTryFrom<'v>,
555 {
556 fn try_into(&self) -> Result<&U, PyDowncastError<'_>> {
557 <U as PyTryFrom<'_>>::try_from(self)
558 }
559 fn try_into_exact(&self) -> Result<&U, PyDowncastError<'_>> {
560 U::try_from_exact(self)
561 }
562 }
563
564 impl<'v, T> PyTryFrom<'v> for T
565 where
566 T: PyTypeInfo<AsRefTarget = Self> + PyNativeType,
567 {
568 fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>> {
569 value.into().downcast()
570 }
571
572 fn try_from_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>> {
573 value.into().downcast_exact()
574 }
575
576 #[inline]
577 unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v Self {
578 value.into().downcast_unchecked()
579 }
580 }
581
582 impl<'v, T> PyTryFrom<'v> for crate::PyCell<T>
583 where
584 T: 'v + PyClass,
585 {
586 fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>> {
587 value.into().downcast()
588 }
589 fn try_from_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError<'v>> {
590 let value = value.into();
591 unsafe {
592 if T::is_exact_type_of(value) {
593 Ok(Self::try_from_unchecked(value))
594 } else {
595 Err(PyDowncastError::new(value, T::NAME))
596 }
597 }
598 }
599 #[inline]
600 unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v Self {
601 value.into().downcast_unchecked()
602 }
603 }
604}
605
606/// Converts `()` to an empty Python tuple.
607impl IntoPy<Py<PyTuple>> for () {
608 fn into_py(self, py: Python<'_>) -> Py<PyTuple> {
609 PyTuple::empty_bound(py).unbind()
610 }
611
612 #[inline]
613 fn __py_call_vectorcall1<'py>(
614 self,
615 py: Python<'py>,
616 function: Borrowed<'_, 'py, PyAny>,
617 _: private::Token,
618 ) -> PyResult<Bound<'py, PyAny>> {
619 unsafe { ffi::compat::PyObject_CallNoArgs(function.as_ptr()).assume_owned_or_err(py) }
620 }
621
622 #[inline]
623 fn __py_call_vectorcall<'py>(
624 self,
625 py: Python<'py>,
626 function: Borrowed<'_, 'py, PyAny>,
627 kwargs: Option<Borrowed<'_, '_, PyDict>>,
628 _: private::Token,
629 ) -> PyResult<Bound<'py, PyAny>> {
630 unsafe {
631 match kwargs {
632 Some(kwargs) => ffi::PyObject_Call(
633 function.as_ptr(),
634 PyTuple::empty_bound(py).as_ptr(),
635 kwargs.as_ptr(),
636 )
637 .assume_owned_or_err(py),
638 None => ffi::compat::PyObject_CallNoArgs(function.as_ptr()).assume_owned_or_err(py),
639 }
640 }
641 }
642
643 #[inline]
644 #[allow(clippy::used_underscore_binding)]
645 fn __py_call_method_vectorcall1<'py>(
646 self,
647 py: Python<'py>,
648 object: Borrowed<'_, 'py, PyAny>,
649 method_name: Borrowed<'_, 'py, PyString>,
650 _: private::Token,
651 ) -> PyResult<Bound<'py, PyAny>> {
652 unsafe {
653 ffi::compat::PyObject_CallMethodNoArgs(object.as_ptr(), method_name.as_ptr())
654 .assume_owned_or_err(py)
655 }
656 }
657}
658
659/// Raw level conversion between `*mut ffi::PyObject` and PyO3 types.
660///
661/// # Safety
662///
663/// See safety notes on individual functions.
664#[cfg(feature = "gil-refs")]
665#[deprecated(since = "0.21.0")]
666pub unsafe trait FromPyPointer<'p>: Sized {
667 /// Convert from an arbitrary `PyObject`.
668 ///
669 /// # Safety
670 ///
671 /// Implementations must ensure the object does not get freed during `'p`
672 /// and ensure that `ptr` is of the correct type.
673 /// Note that it must be safe to decrement the reference count of `ptr`.
674 #[deprecated(
675 since = "0.21.0",
676 note = "use `Py::from_owned_ptr_or_opt(py, ptr)` or `Bound::from_owned_ptr_or_opt(py, ptr)` instead"
677 )]
678 unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<&'p Self>;
679 /// Convert from an arbitrary `PyObject` or panic.
680 ///
681 /// # Safety
682 ///
683 /// Relies on [`from_owned_ptr_or_opt`](#method.from_owned_ptr_or_opt).
684 #[deprecated(
685 since = "0.21.0",
686 note = "use `Py::from_owned_ptr(py, ptr)` or `Bound::from_owned_ptr(py, ptr)` instead"
687 )]
688 unsafe fn from_owned_ptr_or_panic(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self {
689 #[allow(deprecated)]
690 Self::from_owned_ptr_or_opt(py, ptr).unwrap_or_else(|| err::panic_after_error(py))
691 }
692 /// Convert from an arbitrary `PyObject` or panic.
693 ///
694 /// # Safety
695 ///
696 /// Relies on [`from_owned_ptr_or_opt`](#method.from_owned_ptr_or_opt).
697 #[deprecated(
698 since = "0.21.0",
699 note = "use `Py::from_owned_ptr(py, ptr)` or `Bound::from_owned_ptr(py, ptr)` instead"
700 )]
701 unsafe fn from_owned_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self {
702 #[allow(deprecated)]
703 Self::from_owned_ptr_or_panic(py, ptr)
704 }
705 /// Convert from an arbitrary `PyObject`.
706 ///
707 /// # Safety
708 ///
709 /// Relies on [`from_owned_ptr_or_opt`](#method.from_owned_ptr_or_opt).
710 #[deprecated(
711 since = "0.21.0",
712 note = "use `Py::from_owned_ptr_or_err(py, ptr)` or `Bound::from_owned_ptr_or_err(py, ptr)` instead"
713 )]
714 unsafe fn from_owned_ptr_or_err(py: Python<'p>, ptr: *mut ffi::PyObject) -> PyResult<&'p Self> {
715 #[allow(deprecated)]
716 Self::from_owned_ptr_or_opt(py, ptr).ok_or_else(|| err::PyErr::fetch(py))
717 }
718 /// Convert from an arbitrary borrowed `PyObject`.
719 ///
720 /// # Safety
721 ///
722 /// Implementations must ensure the object does not get freed during `'p` and avoid type confusion.
723 #[deprecated(
724 since = "0.21.0",
725 note = "use `Py::from_borrowed_ptr_or_opt(py, ptr)` or `Bound::from_borrowed_ptr_or_opt(py, ptr)` instead"
726 )]
727 unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject)
728 -> Option<&'p Self>;
729 /// Convert from an arbitrary borrowed `PyObject`.
730 ///
731 /// # Safety
732 ///
733 /// Relies on unsafe fn [`from_borrowed_ptr_or_opt`](#method.from_borrowed_ptr_or_opt).
734 #[deprecated(
735 since = "0.21.0",
736 note = "use `Py::from_borrowed_ptr(py, ptr)` or `Bound::from_borrowed_ptr(py, ptr)` instead"
737 )]
738 unsafe fn from_borrowed_ptr_or_panic(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self {
739 #[allow(deprecated)]
740 Self::from_borrowed_ptr_or_opt(py, ptr).unwrap_or_else(|| err::panic_after_error(py))
741 }
742 /// Convert from an arbitrary borrowed `PyObject`.
743 ///
744 /// # Safety
745 ///
746 /// Relies on unsafe fn [`from_borrowed_ptr_or_opt`](#method.from_borrowed_ptr_or_opt).
747 #[deprecated(
748 since = "0.21.0",
749 note = "use `Py::from_borrowed_ptr(py, ptr)` or `Bound::from_borrowed_ptr(py, ptr)` instead"
750 )]
751 unsafe fn from_borrowed_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self {
752 #[allow(deprecated)]
753 Self::from_borrowed_ptr_or_panic(py, ptr)
754 }
755 /// Convert from an arbitrary borrowed `PyObject`.
756 ///
757 /// # Safety
758 ///
759 /// Relies on unsafe fn [`from_borrowed_ptr_or_opt`](#method.from_borrowed_ptr_or_opt).
760 #[deprecated(
761 since = "0.21.0",
762 note = "use `Py::from_borrowed_ptr_or_err(py, ptr)` or `Bound::from_borrowed_ptr_or_err(py, ptr)` instead"
763 )]
764 unsafe fn from_borrowed_ptr_or_err(
765 py: Python<'p>,
766 ptr: *mut ffi::PyObject,
767 ) -> PyResult<&'p Self> {
768 #[allow(deprecated)]
769 Self::from_borrowed_ptr_or_opt(py, ptr).ok_or_else(|| err::PyErr::fetch(py))
770 }
771}
772
773#[cfg(feature = "gil-refs")]
774#[allow(deprecated)]
775unsafe impl<'p, T> FromPyPointer<'p> for T
776where
777 T: 'p + crate::PyNativeType,
778{
779 unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<&'p Self> {
780 gil::register_owned(py, NonNull::new(ptr)?);
781 Some(&*(ptr as *mut Self))
782 }
783 unsafe fn from_borrowed_ptr_or_opt(
784 _py: Python<'p>,
785 ptr: *mut ffi::PyObject,
786 ) -> Option<&'p Self> {
787 NonNull::new(ptr as *mut Self).map(|p| &*p.as_ptr())
788 }
789}
790
791/// ```rust,compile_fail
792/// use pyo3::prelude::*;
793///
794/// #[pyclass]
795/// struct TestClass {
796/// num: u32,
797/// }
798///
799/// let t = TestClass { num: 10 };
800///
801/// Python::with_gil(|py| {
802/// let pyvalue = Py::new(py, t).unwrap().to_object(py);
803/// let t: TestClass = pyvalue.extract(py).unwrap();
804/// })
805/// ```
806mod test_no_clone {}
807
808#[cfg(test)]
809mod tests {
810 #[cfg(feature = "gil-refs")]
811 #[allow(deprecated)]
812 mod deprecated {
813 use super::super::PyTryFrom;
814 use crate::types::{IntoPyDict, PyAny, PyDict, PyList};
815 use crate::{Python, ToPyObject};
816
817 #[test]
818 fn test_try_from() {
819 Python::with_gil(|py| {
820 let list: &PyAny = vec![3, 6, 5, 4, 7].to_object(py).into_ref(py);
821 let dict: &PyAny = vec![("reverse", true)].into_py_dict(py).as_ref();
822
823 assert!(<PyList as PyTryFrom<'_>>::try_from(list).is_ok());
824 assert!(<PyDict as PyTryFrom<'_>>::try_from(dict).is_ok());
825
826 assert!(<PyAny as PyTryFrom<'_>>::try_from(list).is_ok());
827 assert!(<PyAny as PyTryFrom<'_>>::try_from(dict).is_ok());
828 });
829 }
830
831 #[test]
832 fn test_try_from_exact() {
833 Python::with_gil(|py| {
834 let list: &PyAny = vec![3, 6, 5, 4, 7].to_object(py).into_ref(py);
835 let dict: &PyAny = vec![("reverse", true)].into_py_dict(py).as_ref();
836
837 assert!(PyList::try_from_exact(list).is_ok());
838 assert!(PyDict::try_from_exact(dict).is_ok());
839
840 assert!(PyAny::try_from_exact(list).is_err());
841 assert!(PyAny::try_from_exact(dict).is_err());
842 });
843 }
844
845 #[test]
846 fn test_try_from_unchecked() {
847 Python::with_gil(|py| {
848 let list = PyList::new(py, [1, 2, 3]);
849 let val = unsafe { <PyList as PyTryFrom>::try_from_unchecked(list.as_ref()) };
850 assert!(list.is(val));
851 });
852 }
853 }
854}