pyo3/
conversion.rs

1//! Defines conversions between Rust and Python types.
2use crate::err::PyResult;
3#[cfg(feature = "experimental-inspect")]
4use crate::inspect::types::TypeInfo;
5use crate::pyclass::boolean_struct::False;
6use crate::types::any::PyAnyMethods;
7use crate::types::PyTuple;
8use crate::{
9    ffi, Borrowed, Bound, BoundObject, Py, PyAny, PyClass, PyErr, PyObject, PyRef, PyRefMut, Python,
10};
11use std::convert::Infallible;
12
13/// Returns a borrowed pointer to a Python object.
14///
15/// The returned pointer will be valid for as long as `self` is. It may be null depending on the
16/// implementation.
17///
18/// # Examples
19///
20/// ```rust
21/// use pyo3::prelude::*;
22/// use pyo3::ffi;
23///
24/// Python::with_gil(|py| {
25///     let s = "foo".into_pyobject(py)?;
26///     let ptr = s.as_ptr();
27///
28///     let is_really_a_pystring = unsafe { ffi::PyUnicode_CheckExact(ptr) };
29///     assert_eq!(is_really_a_pystring, 1);
30/// #   Ok::<_, PyErr>(())
31/// })
32/// # .unwrap();
33/// ```
34///
35/// # Safety
36///
37/// For callers, it is your responsibility to make sure that the underlying Python object is not dropped too
38/// early. For example, the following code will cause undefined behavior:
39///
40/// ```rust,no_run
41/// # use pyo3::prelude::*;
42/// # use pyo3::ffi;
43/// #
44/// Python::with_gil(|py| {
45///     // ERROR: calling `.as_ptr()` will throw away the temporary object and leave `ptr` dangling.
46///     let ptr: *mut ffi::PyObject = 0xabad1dea_u32.into_pyobject(py)?.as_ptr();
47///
48///     let isnt_a_pystring = unsafe {
49///         // `ptr` is dangling, this is UB
50///         ffi::PyUnicode_CheckExact(ptr)
51///     };
52/// #   assert_eq!(isnt_a_pystring, 0);
53/// #   Ok::<_, PyErr>(())
54/// })
55/// # .unwrap();
56/// ```
57///
58/// This happens because the pointer returned by `as_ptr` does not carry any lifetime information
59/// and the Python object is dropped immediately after the `0xabad1dea_u32.into_pyobject(py).as_ptr()`
60/// expression is evaluated. To fix the problem, bind Python object to a local variable like earlier
61/// to keep the Python object alive until the end of its scope.
62///
63/// Implementors must ensure this returns a valid pointer to a Python object, which borrows a reference count from `&self`.
64pub unsafe trait AsPyPointer {
65    /// Returns the underlying FFI pointer as a borrowed pointer.
66    fn as_ptr(&self) -> *mut ffi::PyObject;
67}
68
69/// Conversion trait that allows various objects to be converted into `PyObject`.
70#[deprecated(
71    since = "0.23.0",
72    note = "`ToPyObject` is going to be replaced by `IntoPyObject`. See the migration guide (https://pyo3.rs/v0.23.0/migration) for more information."
73)]
74pub trait ToPyObject {
75    /// Converts self into a Python object.
76    fn to_object(&self, py: Python<'_>) -> PyObject;
77}
78
79/// Defines a conversion from a Rust type to a Python object.
80///
81/// It functions similarly to std's [`Into`] trait, but requires a [GIL token](Python)
82/// as an argument. Many functions and traits internal to PyO3 require this trait as a bound,
83/// so a lack of this trait can manifest itself in different error messages.
84///
85/// # Examples
86/// ## With `#[pyclass]`
87/// The easiest way to implement `IntoPy` is by exposing a struct as a native Python object
88/// by annotating it with [`#[pyclass]`](crate::prelude::pyclass).
89///
90/// ```rust
91/// use pyo3::prelude::*;
92///
93/// # #[allow(dead_code)]
94/// #[pyclass]
95/// struct Number {
96///     #[pyo3(get, set)]
97///     value: i32,
98/// }
99/// ```
100/// Python code will see this as an instance of the `Number` class with a `value` attribute.
101///
102/// ## Conversion to a Python object
103///
104/// However, it may not be desirable to expose the existence of `Number` to Python code.
105/// `IntoPy` allows us to define a conversion to an appropriate Python object.
106/// ```rust
107/// #![allow(deprecated)]
108/// use pyo3::prelude::*;
109///
110/// # #[allow(dead_code)]
111/// struct Number {
112///     value: i32,
113/// }
114///
115/// impl IntoPy<PyObject> for Number {
116///     fn into_py(self, py: Python<'_>) -> PyObject {
117///         // delegates to i32's IntoPy implementation.
118///         self.value.into_py(py)
119///     }
120/// }
121/// ```
122/// Python code will see this as an `int` object.
123///
124/// ## Dynamic conversion into Python objects.
125/// It is also possible to return a different Python object depending on some condition.
126/// This is useful for types like enums that can carry different types.
127///
128/// ```rust
129/// #![allow(deprecated)]
130/// use pyo3::prelude::*;
131///
132/// enum Value {
133///     Integer(i32),
134///     String(String),
135///     None,
136/// }
137///
138/// impl IntoPy<PyObject> for Value {
139///     fn into_py(self, py: Python<'_>) -> PyObject {
140///         match self {
141///             Self::Integer(val) => val.into_py(py),
142///             Self::String(val) => val.into_py(py),
143///             Self::None => py.None(),
144///         }
145///     }
146/// }
147/// # fn main() {
148/// #     Python::with_gil(|py| {
149/// #         let v = Value::Integer(73).into_py(py);
150/// #         let v = v.extract::<i32>(py).unwrap();
151/// #
152/// #         let v = Value::String("foo".into()).into_py(py);
153/// #         let v = v.extract::<String>(py).unwrap();
154/// #
155/// #         let v = Value::None.into_py(py);
156/// #         let v = v.extract::<Option<Vec<i32>>>(py).unwrap();
157/// #     });
158/// # }
159/// ```
160/// Python code will see this as any of the `int`, `string` or `None` objects.
161#[cfg_attr(
162    diagnostic_namespace,
163    diagnostic::on_unimplemented(
164        message = "`{Self}` cannot be converted to a Python object",
165        note = "`IntoPy` is automatically implemented by the `#[pyclass]` macro",
166        note = "if you do not wish to have a corresponding Python type, implement it manually",
167        note = "if you do not own `{Self}` you can perform a manual conversion to one of the types in `pyo3::types::*`"
168    )
169)]
170#[deprecated(
171    since = "0.23.0",
172    note = "`IntoPy` is going to be replaced by `IntoPyObject`. See the migration guide (https://pyo3.rs/v0.23.0/migration) for more information."
173)]
174pub trait IntoPy<T>: Sized {
175    /// Performs the conversion.
176    fn into_py(self, py: Python<'_>) -> T;
177}
178
179/// Defines a conversion from a Rust type to a Python object, which may fail.
180///
181/// This trait has `#[derive(IntoPyObject)]` to automatically implement it for simple types and
182/// `#[derive(IntoPyObjectRef)]` to implement the same for references.
183///
184/// It functions similarly to std's [`TryInto`] trait, but requires a [GIL token](Python)
185/// as an argument.
186///
187/// The [`into_pyobject`][IntoPyObject::into_pyobject] method is designed for maximum flexibility and efficiency; it
188///  - allows for a concrete Python type to be returned (the [`Target`][IntoPyObject::Target] associated type)
189///  - allows for the smart pointer containing the Python object to be either `Bound<'py, Self::Target>` or `Borrowed<'a, 'py, Self::Target>`
190///    to avoid unnecessary reference counting overhead
191///  - allows for a custom error type to be returned in the event of a conversion error to avoid
192///    unnecessarily creating a Python exception
193///
194/// # See also
195///
196/// - The [`IntoPyObjectExt`] trait, which provides convenience methods for common usages of
197///   `IntoPyObject` which erase type information and convert errors to `PyErr`.
198#[cfg_attr(
199    diagnostic_namespace,
200    diagnostic::on_unimplemented(
201        message = "`{Self}` cannot be converted to a Python object",
202        note = "`IntoPyObject` is automatically implemented by the `#[pyclass]` macro",
203        note = "if you do not wish to have a corresponding Python type, implement it manually",
204        note = "if you do not own `{Self}` you can perform a manual conversion to one of the types in `pyo3::types::*`"
205    )
206)]
207pub trait IntoPyObject<'py>: Sized {
208    /// The Python output type
209    type Target;
210    /// The smart pointer type to use.
211    ///
212    /// This will usually be [`Bound<'py, Target>`], but in special cases [`Borrowed<'a, 'py, Target>`] can be
213    /// used to minimize reference counting overhead.
214    type Output: BoundObject<'py, Self::Target>;
215    /// The type returned in the event of a conversion error.
216    type Error: Into<PyErr>;
217
218    /// Performs the conversion.
219    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error>;
220
221    /// Extracts the type hint information for this type when it appears as a return value.
222    ///
223    /// For example, `Vec<u32>` would return `List[int]`.
224    /// The default implementation returns `Any`, which is correct for any type.
225    ///
226    /// For most types, the return value for this method will be identical to that of [`FromPyObject::type_input`].
227    /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument.
228    #[cfg(feature = "experimental-inspect")]
229    fn type_output() -> TypeInfo {
230        TypeInfo::Any
231    }
232
233    /// Converts sequence of Self into a Python object. Used to specialize `Vec<u8>`, `[u8; N]`
234    /// and `SmallVec<[u8; N]>` as a sequence of bytes into a `bytes` object.
235    #[doc(hidden)]
236    fn owned_sequence_into_pyobject<I>(
237        iter: I,
238        py: Python<'py>,
239        _: private::Token,
240    ) -> Result<Bound<'py, PyAny>, PyErr>
241    where
242        I: IntoIterator<Item = Self> + AsRef<[Self]>,
243        I::IntoIter: ExactSizeIterator<Item = Self>,
244    {
245        let mut iter = iter.into_iter().map(|e| e.into_bound_py_any(py));
246        let list = crate::types::list::try_new_from_iter(py, &mut iter);
247        list.map(Bound::into_any)
248    }
249
250    /// Converts sequence of Self into a Python object. Used to specialize `&[u8]` and `Cow<[u8]>`
251    /// as a sequence of bytes into a `bytes` object.
252    #[doc(hidden)]
253    fn borrowed_sequence_into_pyobject<I>(
254        iter: I,
255        py: Python<'py>,
256        _: private::Token,
257    ) -> Result<Bound<'py, PyAny>, PyErr>
258    where
259        Self: private::Reference,
260        I: IntoIterator<Item = Self> + AsRef<[<Self as private::Reference>::BaseType]>,
261        I::IntoIter: ExactSizeIterator<Item = Self>,
262    {
263        let mut iter = iter.into_iter().map(|e| e.into_bound_py_any(py));
264        let list = crate::types::list::try_new_from_iter(py, &mut iter);
265        list.map(Bound::into_any)
266    }
267}
268
269pub(crate) mod private {
270    pub struct Token;
271
272    pub trait Reference {
273        type BaseType;
274    }
275
276    impl<T> Reference for &'_ T {
277        type BaseType = T;
278    }
279}
280
281impl<'py, T> IntoPyObject<'py> for Bound<'py, T> {
282    type Target = T;
283    type Output = Bound<'py, Self::Target>;
284    type Error = Infallible;
285
286    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {
287        Ok(self)
288    }
289}
290
291impl<'a, 'py, T> IntoPyObject<'py> for &'a Bound<'py, T> {
292    type Target = T;
293    type Output = Borrowed<'a, 'py, Self::Target>;
294    type Error = Infallible;
295
296    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {
297        Ok(self.as_borrowed())
298    }
299}
300
301impl<'a, 'py, T> IntoPyObject<'py> for Borrowed<'a, 'py, T> {
302    type Target = T;
303    type Output = Borrowed<'a, 'py, Self::Target>;
304    type Error = Infallible;
305
306    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {
307        Ok(self)
308    }
309}
310
311impl<'a, 'py, T> IntoPyObject<'py> for &Borrowed<'a, 'py, T> {
312    type Target = T;
313    type Output = Borrowed<'a, 'py, Self::Target>;
314    type Error = Infallible;
315
316    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {
317        Ok(*self)
318    }
319}
320
321impl<'py, T> IntoPyObject<'py> for Py<T> {
322    type Target = T;
323    type Output = Bound<'py, Self::Target>;
324    type Error = Infallible;
325
326    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
327        Ok(self.into_bound(py))
328    }
329}
330
331impl<'a, 'py, T> IntoPyObject<'py> for &'a Py<T> {
332    type Target = T;
333    type Output = Borrowed<'a, 'py, Self::Target>;
334    type Error = Infallible;
335
336    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
337        Ok(self.bind_borrowed(py))
338    }
339}
340
341impl<'a, 'py, T> IntoPyObject<'py> for &&'a T
342where
343    &'a T: IntoPyObject<'py>,
344{
345    type Target = <&'a T as IntoPyObject<'py>>::Target;
346    type Output = <&'a T as IntoPyObject<'py>>::Output;
347    type Error = <&'a T as IntoPyObject<'py>>::Error;
348
349    #[inline]
350    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
351        (*self).into_pyobject(py)
352    }
353}
354
355mod into_pyobject_ext {
356    pub trait Sealed {}
357    impl<'py, T> Sealed for T where T: super::IntoPyObject<'py> {}
358}
359
360/// Convenience methods for common usages of [`IntoPyObject`]. Every type that implements
361/// [`IntoPyObject`] also implements this trait.
362///
363/// These methods:
364///   - Drop type information from the output, returning a `PyAny` object.
365///   - Always convert the `Error` type to `PyErr`, which may incur a performance penalty but it
366///     more convenient in contexts where the `?` operator would produce a `PyErr` anyway.
367pub trait IntoPyObjectExt<'py>: IntoPyObject<'py> + into_pyobject_ext::Sealed {
368    /// Converts `self` into an owned Python object, dropping type information.
369    #[inline]
370    fn into_bound_py_any(self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
371        match self.into_pyobject(py) {
372            Ok(obj) => Ok(obj.into_any().into_bound()),
373            Err(err) => Err(err.into()),
374        }
375    }
376
377    /// Converts `self` into an owned Python object, dropping type information and unbinding it
378    /// from the `'py` lifetime.
379    #[inline]
380    fn into_py_any(self, py: Python<'py>) -> PyResult<Py<PyAny>> {
381        match self.into_pyobject(py) {
382            Ok(obj) => Ok(obj.into_any().unbind()),
383            Err(err) => Err(err.into()),
384        }
385    }
386
387    /// Converts `self` into a Python object.
388    ///
389    /// This is equivalent to calling [`into_pyobject`][IntoPyObject::into_pyobject] followed
390    /// with `.map_err(Into::into)` to convert the error type to [`PyErr`]. This is helpful
391    /// for generic code which wants to make use of the `?` operator.
392    #[inline]
393    fn into_pyobject_or_pyerr(self, py: Python<'py>) -> PyResult<Self::Output> {
394        match self.into_pyobject(py) {
395            Ok(obj) => Ok(obj),
396            Err(err) => Err(err.into()),
397        }
398    }
399}
400
401impl<'py, T> IntoPyObjectExt<'py> for T where T: IntoPyObject<'py> {}
402
403/// Extract a type from a Python object.
404///
405///
406/// Normal usage is through the `extract` methods on [`Bound`] and [`Py`], which forward to this trait.
407///
408/// # Examples
409///
410/// ```rust
411/// use pyo3::prelude::*;
412/// use pyo3::types::PyString;
413///
414/// # fn main() -> PyResult<()> {
415/// Python::with_gil(|py| {
416///     // Calling `.extract()` on a `Bound` smart pointer
417///     let obj: Bound<'_, PyString> = PyString::new(py, "blah");
418///     let s: String = obj.extract()?;
419/// #   assert_eq!(s, "blah");
420///
421///     // Calling `.extract(py)` on a `Py` smart pointer
422///     let obj: Py<PyString> = obj.unbind();
423///     let s: String = obj.extract(py)?;
424/// #   assert_eq!(s, "blah");
425/// #   Ok(())
426/// })
427/// # }
428/// ```
429///
430// /// FIXME: until `FromPyObject` can pick up a second lifetime, the below commentary is no longer
431// /// true. Update and restore this documentation at that time.
432// ///
433// /// Note: depending on the implementation, the lifetime of the extracted result may
434// /// depend on the lifetime of the `obj` or the `prepared` variable.
435// ///
436// /// For example, when extracting `&str` from a Python byte string, the resulting string slice will
437// /// point to the existing string data (lifetime: `'py`).
438// /// On the other hand, when extracting `&str` from a Python Unicode string, the preparation step
439// /// will convert the string to UTF-8, and the resulting string slice will have lifetime `'prepared`.
440// /// Since which case applies depends on the runtime type of the Python object,
441// /// both the `obj` and `prepared` variables must outlive the resulting string slice.
442///
443/// During the migration of PyO3 from the "GIL Refs" API to the `Bound<T>` smart pointer, this trait
444/// has two methods `extract` and `extract_bound` which are defaulted to call each other. To avoid
445/// infinite recursion, implementors must implement at least one of these methods. The recommendation
446/// is to implement `extract_bound` and leave `extract` as the default implementation.
447pub trait FromPyObject<'py>: Sized {
448    /// Extracts `Self` from the bound smart pointer `obj`.
449    ///
450    /// Implementors are encouraged to implement this method and leave `extract` defaulted, as
451    /// this will be most compatible with PyO3's future API.
452    fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self>;
453
454    /// Extracts the type hint information for this type when it appears as an argument.
455    ///
456    /// For example, `Vec<u32>` would return `Sequence[int]`.
457    /// The default implementation returns `Any`, which is correct for any type.
458    ///
459    /// For most types, the return value for this method will be identical to that of
460    /// [`IntoPyObject::type_output`]. It may be different for some types, such as `Dict`,
461    /// to allow duck-typing: functions return `Dict` but take `Mapping` as argument.
462    #[cfg(feature = "experimental-inspect")]
463    fn type_input() -> TypeInfo {
464        TypeInfo::Any
465    }
466}
467
468mod from_py_object_bound_sealed {
469    /// Private seal for the `FromPyObjectBound` trait.
470    ///
471    /// This prevents downstream types from implementing the trait before
472    /// PyO3 is ready to declare the trait as public API.
473    pub trait Sealed {}
474
475    // This generic implementation is why the seal is separate from
476    // `crate::sealed::Sealed`.
477    impl<'py, T> Sealed for T where T: super::FromPyObject<'py> {}
478    impl Sealed for &'_ str {}
479    impl Sealed for std::borrow::Cow<'_, str> {}
480    impl Sealed for &'_ [u8] {}
481    impl Sealed for std::borrow::Cow<'_, [u8]> {}
482}
483
484/// Expected form of [`FromPyObject`] to be used in a future PyO3 release.
485///
486/// The difference between this and `FromPyObject` is that this trait takes an
487/// additional lifetime `'a`, which is the lifetime of the input `Bound`.
488///
489/// This allows implementations for `&'a str` and `&'a [u8]`, which could not
490/// be expressed by the existing `FromPyObject` trait once the GIL Refs API was
491/// removed.
492///
493/// # Usage
494///
495/// Users are prevented from implementing this trait, instead they should implement
496/// the normal `FromPyObject` trait. This trait has a blanket implementation
497/// for `T: FromPyObject`.
498///
499/// The only case where this trait may have a use case to be implemented is when the
500/// lifetime of the extracted value is tied to the lifetime `'a` of the input `Bound`
501/// instead of the GIL lifetime `py`, as is the case for the `&'a str` implementation.
502///
503/// Please contact the PyO3 maintainers if you believe you have a use case for implementing
504/// this trait before PyO3 is ready to change the main `FromPyObject` trait to take an
505/// additional lifetime.
506///
507/// Similarly, users should typically not call these trait methods and should instead
508/// use this via the `extract` method on `Bound` and `Py`.
509pub trait FromPyObjectBound<'a, 'py>: Sized + from_py_object_bound_sealed::Sealed {
510    /// Extracts `Self` from the bound smart pointer `obj`.
511    ///
512    /// Users are advised against calling this method directly: instead, use this via
513    /// [`Bound<'_, PyAny>::extract`] or [`Py::extract`].
514    fn from_py_object_bound(ob: Borrowed<'a, 'py, PyAny>) -> PyResult<Self>;
515
516    /// Extracts the type hint information for this type when it appears as an argument.
517    ///
518    /// For example, `Vec<u32>` would return `Sequence[int]`.
519    /// The default implementation returns `Any`, which is correct for any type.
520    ///
521    /// For most types, the return value for this method will be identical to that of
522    /// [`IntoPyObject::type_output`]. It may be different for some types, such as `Dict`,
523    /// to allow duck-typing: functions return `Dict` but take `Mapping` as argument.
524    #[cfg(feature = "experimental-inspect")]
525    fn type_input() -> TypeInfo {
526        TypeInfo::Any
527    }
528}
529
530impl<'py, T> FromPyObjectBound<'_, 'py> for T
531where
532    T: FromPyObject<'py>,
533{
534    fn from_py_object_bound(ob: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {
535        Self::extract_bound(&ob)
536    }
537
538    #[cfg(feature = "experimental-inspect")]
539    fn type_input() -> TypeInfo {
540        <T as FromPyObject>::type_input()
541    }
542}
543
544/// Identity conversion: allows using existing `PyObject` instances where
545/// `T: ToPyObject` is expected.
546#[allow(deprecated)]
547impl<T: ?Sized + ToPyObject> ToPyObject for &'_ T {
548    #[inline]
549    fn to_object(&self, py: Python<'_>) -> PyObject {
550        <T as ToPyObject>::to_object(*self, py)
551    }
552}
553
554impl<T> FromPyObject<'_> for T
555where
556    T: PyClass + Clone,
557{
558    fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
559        let bound = obj.downcast::<Self>()?;
560        Ok(bound.try_borrow()?.clone())
561    }
562}
563
564impl<'py, T> FromPyObject<'py> for PyRef<'py, T>
565where
566    T: PyClass,
567{
568    fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {
569        obj.downcast::<T>()?.try_borrow().map_err(Into::into)
570    }
571}
572
573impl<'py, T> FromPyObject<'py> for PyRefMut<'py, T>
574where
575    T: PyClass<Frozen = False>,
576{
577    fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {
578        obj.downcast::<T>()?.try_borrow_mut().map_err(Into::into)
579    }
580}
581
582/// Converts `()` to an empty Python tuple.
583#[allow(deprecated)]
584impl IntoPy<Py<PyTuple>> for () {
585    fn into_py(self, py: Python<'_>) -> Py<PyTuple> {
586        PyTuple::empty(py).unbind()
587    }
588}
589
590impl<'py> IntoPyObject<'py> for () {
591    type Target = PyTuple;
592    type Output = Bound<'py, Self::Target>;
593    type Error = Infallible;
594
595    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
596        Ok(PyTuple::empty(py))
597    }
598}
599
600/// ```rust,compile_fail
601/// use pyo3::prelude::*;
602///
603/// #[pyclass]
604/// struct TestClass {
605///     num: u32,
606/// }
607///
608/// let t = TestClass { num: 10 };
609///
610/// Python::with_gil(|py| {
611///     let pyvalue = Py::new(py, t).unwrap().to_object(py);
612///     let t: TestClass = pyvalue.extract(py).unwrap();
613/// })
614/// ```
615mod test_no_clone {}