pyo3/
conversion.rs

1//! Defines conversions between Rust and Python types.
2use crate::err::PyResult;
3use crate::impl_::pyclass::ExtractPyClassWithClone;
4#[cfg(feature = "experimental-inspect")]
5use crate::inspect::types::TypeInfo;
6use crate::pyclass::boolean_struct::False;
7use crate::pyclass::{PyClassGuardError, PyClassGuardMutError};
8use crate::types::PyTuple;
9use crate::{
10    Borrowed, Bound, BoundObject, Py, PyAny, PyClass, PyClassGuard, PyErr, PyRef, PyRefMut, Python,
11};
12use std::convert::Infallible;
13#[cfg(return_position_impl_trait_in_traits)]
14use std::marker::PhantomData;
15
16/// Defines a conversion from a Rust type to a Python object, which may fail.
17///
18/// This trait has `#[derive(IntoPyObject)]` to automatically implement it for simple types and
19/// `#[derive(IntoPyObjectRef)]` to implement the same for references.
20///
21/// It functions similarly to std's [`TryInto`] trait, but requires a [`Python<'py>`] token
22/// as an argument.
23///
24/// The [`into_pyobject`][IntoPyObject::into_pyobject] method is designed for maximum flexibility and efficiency; it
25///  - allows for a concrete Python type to be returned (the [`Target`][IntoPyObject::Target] associated type)
26///  - allows for the smart pointer containing the Python object to be either `Bound<'py, Self::Target>` or `Borrowed<'a, 'py, Self::Target>`
27///    to avoid unnecessary reference counting overhead
28///  - allows for a custom error type to be returned in the event of a conversion error to avoid
29///    unnecessarily creating a Python exception
30///
31/// # See also
32///
33/// - The [`IntoPyObjectExt`] trait, which provides convenience methods for common usages of
34///   `IntoPyObject` which erase type information and convert errors to `PyErr`.
35#[cfg_attr(
36    diagnostic_namespace,
37    diagnostic::on_unimplemented(
38        message = "`{Self}` cannot be converted to a Python object",
39        note = "`IntoPyObject` is automatically implemented by the `#[pyclass]` macro",
40        note = "if you do not wish to have a corresponding Python type, implement it manually",
41        note = "if you do not own `{Self}` you can perform a manual conversion to one of the types in `pyo3::types::*`"
42    )
43)]
44pub trait IntoPyObject<'py>: Sized {
45    /// The Python output type
46    type Target;
47    /// The smart pointer type to use.
48    ///
49    /// This will usually be [`Bound<'py, Target>`], but in special cases [`Borrowed<'a, 'py, Target>`] can be
50    /// used to minimize reference counting overhead.
51    type Output: BoundObject<'py, Self::Target>;
52    /// The type returned in the event of a conversion error.
53    type Error: Into<PyErr>;
54
55    /// Extracts the type hint information for this type when it appears as a return value.
56    ///
57    /// For example, `Vec<u32>` would return `List[int]`.
58    /// The default implementation returns `Any`, which is correct for any type.
59    ///
60    /// For most types, the return value for this method will be identical to that of [`FromPyObject::INPUT_TYPE`].
61    /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument.
62    #[cfg(feature = "experimental-inspect")]
63    const OUTPUT_TYPE: &'static str = "typing.Any";
64
65    /// Performs the conversion.
66    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error>;
67
68    /// Extracts the type hint information for this type when it appears as a return value.
69    ///
70    /// For example, `Vec<u32>` would return `List[int]`.
71    /// The default implementation returns `Any`, which is correct for any type.
72    ///
73    /// For most types, the return value for this method will be identical to that of [`FromPyObject::type_input`].
74    /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument.
75    #[cfg(feature = "experimental-inspect")]
76    fn type_output() -> TypeInfo {
77        TypeInfo::Any
78    }
79
80    /// Converts sequence of Self into a Python object. Used to specialize `Vec<u8>`, `[u8; N]`
81    /// and `SmallVec<[u8; N]>` as a sequence of bytes into a `bytes` object.
82    #[doc(hidden)]
83    fn owned_sequence_into_pyobject<I>(
84        iter: I,
85        py: Python<'py>,
86        _: private::Token,
87    ) -> Result<Bound<'py, PyAny>, PyErr>
88    where
89        I: IntoIterator<Item = Self> + AsRef<[Self]>,
90        I::IntoIter: ExactSizeIterator<Item = Self>,
91    {
92        let mut iter = iter.into_iter().map(|e| e.into_bound_py_any(py));
93        let list = crate::types::list::try_new_from_iter(py, &mut iter);
94        list.map(Bound::into_any)
95    }
96
97    /// Converts sequence of Self into a Python object. Used to specialize `&[u8]` and `Cow<[u8]>`
98    /// as a sequence of bytes into a `bytes` object.
99    #[doc(hidden)]
100    fn borrowed_sequence_into_pyobject<I>(
101        iter: I,
102        py: Python<'py>,
103        _: private::Token,
104    ) -> Result<Bound<'py, PyAny>, PyErr>
105    where
106        Self: private::Reference,
107        I: IntoIterator<Item = Self> + AsRef<[<Self as private::Reference>::BaseType]>,
108        I::IntoIter: ExactSizeIterator<Item = Self>,
109    {
110        let mut iter = iter.into_iter().map(|e| e.into_bound_py_any(py));
111        let list = crate::types::list::try_new_from_iter(py, &mut iter);
112        list.map(Bound::into_any)
113    }
114}
115
116pub(crate) mod private {
117    pub struct Token;
118
119    pub trait Reference {
120        type BaseType;
121    }
122
123    impl<T> Reference for &'_ T {
124        type BaseType = T;
125    }
126}
127
128impl<'py, T> IntoPyObject<'py> for Bound<'py, T> {
129    type Target = T;
130    type Output = Bound<'py, Self::Target>;
131    type Error = Infallible;
132
133    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {
134        Ok(self)
135    }
136}
137
138impl<'a, 'py, T> IntoPyObject<'py> for &'a Bound<'py, T> {
139    type Target = T;
140    type Output = Borrowed<'a, 'py, Self::Target>;
141    type Error = Infallible;
142
143    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {
144        Ok(self.as_borrowed())
145    }
146}
147
148impl<'a, 'py, T> IntoPyObject<'py> for Borrowed<'a, 'py, T> {
149    type Target = T;
150    type Output = Borrowed<'a, 'py, Self::Target>;
151    type Error = Infallible;
152
153    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {
154        Ok(self)
155    }
156}
157
158impl<'a, 'py, T> IntoPyObject<'py> for &Borrowed<'a, 'py, T> {
159    type Target = T;
160    type Output = Borrowed<'a, 'py, Self::Target>;
161    type Error = Infallible;
162
163    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {
164        Ok(*self)
165    }
166}
167
168impl<'py, T> IntoPyObject<'py> for Py<T> {
169    type Target = T;
170    type Output = Bound<'py, Self::Target>;
171    type Error = Infallible;
172
173    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
174        Ok(self.into_bound(py))
175    }
176}
177
178impl<'a, 'py, T> IntoPyObject<'py> for &'a Py<T> {
179    type Target = T;
180    type Output = Borrowed<'a, 'py, Self::Target>;
181    type Error = Infallible;
182
183    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
184        Ok(self.bind_borrowed(py))
185    }
186}
187
188impl<'a, 'py, T> IntoPyObject<'py> for &&'a T
189where
190    &'a T: IntoPyObject<'py>,
191{
192    type Target = <&'a T as IntoPyObject<'py>>::Target;
193    type Output = <&'a T as IntoPyObject<'py>>::Output;
194    type Error = <&'a T as IntoPyObject<'py>>::Error;
195
196    #[cfg(feature = "experimental-inspect")]
197    const OUTPUT_TYPE: &'static str = <&'a T as IntoPyObject<'py>>::OUTPUT_TYPE;
198
199    #[inline]
200    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
201        (*self).into_pyobject(py)
202    }
203}
204
205mod into_pyobject_ext {
206    pub trait Sealed {}
207    impl<'py, T> Sealed for T where T: super::IntoPyObject<'py> {}
208}
209
210/// Convenience methods for common usages of [`IntoPyObject`]. Every type that implements
211/// [`IntoPyObject`] also implements this trait.
212///
213/// These methods:
214///   - Drop type information from the output, returning a `PyAny` object.
215///   - Always convert the `Error` type to `PyErr`, which may incur a performance penalty but it
216///     more convenient in contexts where the `?` operator would produce a `PyErr` anyway.
217pub trait IntoPyObjectExt<'py>: IntoPyObject<'py> + into_pyobject_ext::Sealed {
218    /// Converts `self` into an owned Python object, dropping type information.
219    #[inline]
220    fn into_bound_py_any(self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
221        match self.into_pyobject(py) {
222            Ok(obj) => Ok(obj.into_any().into_bound()),
223            Err(err) => Err(err.into()),
224        }
225    }
226
227    /// Converts `self` into an owned Python object, dropping type information and unbinding it
228    /// from the `'py` lifetime.
229    #[inline]
230    fn into_py_any(self, py: Python<'py>) -> PyResult<Py<PyAny>> {
231        match self.into_pyobject(py) {
232            Ok(obj) => Ok(obj.into_any().unbind()),
233            Err(err) => Err(err.into()),
234        }
235    }
236
237    /// Converts `self` into a Python object.
238    ///
239    /// This is equivalent to calling [`into_pyobject`][IntoPyObject::into_pyobject] followed
240    /// with `.map_err(Into::into)` to convert the error type to [`PyErr`]. This is helpful
241    /// for generic code which wants to make use of the `?` operator.
242    #[inline]
243    fn into_pyobject_or_pyerr(self, py: Python<'py>) -> PyResult<Self::Output> {
244        match self.into_pyobject(py) {
245            Ok(obj) => Ok(obj),
246            Err(err) => Err(err.into()),
247        }
248    }
249}
250
251impl<'py, T> IntoPyObjectExt<'py> for T where T: IntoPyObject<'py> {}
252
253/// Extract a type from a Python object.
254///
255///
256/// Normal usage is through the `extract` methods on [`Bound`], [`Borrowed`] and [`Py`], which
257/// forward to this trait.
258///
259/// # Examples
260///
261/// ```rust
262/// use pyo3::prelude::*;
263/// use pyo3::types::PyString;
264///
265/// # fn main() -> PyResult<()> {
266/// Python::attach(|py| {
267///     // Calling `.extract()` on a `Bound` smart pointer
268///     let obj: Bound<'_, PyString> = PyString::new(py, "blah");
269///     let s: String = obj.extract()?;
270/// #   assert_eq!(s, "blah");
271///
272///     // Calling `.extract(py)` on a `Py` smart pointer
273///     let obj: Py<PyString> = obj.unbind();
274///     let s: String = obj.extract(py)?;
275/// #   assert_eq!(s, "blah");
276/// #   Ok(())
277/// })
278/// # }
279/// ```
280///
281/// Note: Depending on the Python version and implementation, some [`FromPyObject`] implementations
282/// may produce a result that borrows into the Python type. This is described by the input lifetime
283/// `'a` of `obj`.
284///
285/// Types that must not borrow from the input can use [`FromPyObjectOwned`] as a restriction. This
286/// is most often the case for collection types. See its documentation for more details.
287///
288/// # How to implement [`FromPyObject`]?
289/// ## `#[derive(FromPyObject)]`
290/// The simplest way to implement [`FromPyObject`] for a custom type is to make use of our derive
291/// macro.
292/// ```rust,no_run
293/// # #![allow(dead_code)]
294/// use pyo3::prelude::*;
295///
296/// #[derive(FromPyObject)]
297/// struct MyObject {
298///     msg: String,
299///     list: Vec<u32>
300/// }
301/// # fn main() {}
302/// ```
303/// By default this will try to extract each field from the Python object by attribute access, but
304/// this can be customized. For more information about the derive macro, its configuration as well
305/// as its working principle for other types, take a look at the [guide].
306///
307/// In case the derive macro is not sufficient or can not be used for some other reason,
308/// [`FromPyObject`] can be implemented manually. In the following types without lifetime parameters
309/// are handled first, because they are a little bit simpler. Types with lifetime parameters are
310/// explained below.
311///
312/// ## Manual implementation for types without lifetime
313/// Types that do not contain lifetime parameters are unable to borrow from the Python object, so
314/// the lifetimes of [`FromPyObject`] can be elided:
315/// ```rust,no_run
316/// # #![allow(dead_code)]
317/// use pyo3::prelude::*;
318///
319/// struct MyObject {
320///     msg: String,
321///     list: Vec<u32>
322/// }
323///
324/// impl FromPyObject<'_, '_> for MyObject {
325///     type Error = PyErr;
326///
327///     fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {
328///         Ok(MyObject {
329///             msg: obj.getattr("msg")?.extract()?,
330///             list: obj.getattr("list")?.extract()?,
331///         })
332///     }
333/// }
334///
335/// # fn main() {}
336/// ```
337/// This is basically what the derive macro above expands to.
338///
339/// ## Manual implementation for types with lifetime paramaters
340/// For types that contain lifetimes, these lifetimes need to be bound to the corresponding
341/// [`FromPyObject`] lifetime. This is roughly how the extraction of a typed [`Bound`] is
342/// implemented within PyO3.
343///
344/// ```rust,no_run
345/// # #![allow(dead_code)]
346/// use pyo3::prelude::*;
347/// use pyo3::types::PyString;
348///
349/// struct MyObject<'py>(Bound<'py, PyString>);
350///
351/// impl<'py> FromPyObject<'_, 'py> for MyObject<'py> {
352///     type Error = PyErr;
353///
354///     fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
355///         Ok(MyObject(obj.cast()?.to_owned()))
356///     }
357/// }
358///
359/// # fn main() {}
360/// ```
361///
362/// # Details
363/// [`Cow<'a, str>`] is an example of an output type that may or may not borrow from the input
364/// lifetime `'a`. Which variant will be produced depends on the runtime type of the Python object.
365/// For a Python byte string, the existing string data can be borrowed for `'a` into a
366/// [`Cow::Borrowed`]. For a Python Unicode string, the data may have to be reencoded to UTF-8, and
367/// copied into a [`Cow::Owned`]. It does _not_ depend on the Python lifetime `'py`.
368///
369/// The output type may also depend on the Python lifetime `'py`. This allows the output type to
370/// keep interacting with the Python interpreter. See also [`Bound<'py, T>`].
371///
372/// [`Cow<'a, str>`]: std::borrow::Cow
373/// [`Cow::Borrowed`]: std::borrow::Cow::Borrowed
374/// [`Cow::Owned`]: std::borrow::Cow::Owned
375/// [guide]: https://pyo3.rs/latest/conversions/traits.html#deriving-frompyobject
376pub trait FromPyObject<'a, 'py>: Sized {
377    /// The type returned in the event of a conversion error.
378    ///
379    /// For most use cases defaulting to [PyErr] here is perfectly acceptable. Using a custom error
380    /// type can be used to avoid having to create a Python exception object in the case where that
381    /// exception never reaches Python. This may lead to slightly better performance under certain
382    /// conditions.
383    ///
384    /// # Note
385    /// Unfortunately `Try` and thus `?` is based on [`From`], not [`Into`], so implementations may
386    /// need to use `.map_err(Into::into)` sometimes to convert a generic `Error` into a [`PyErr`].
387    type Error: Into<PyErr>;
388
389    /// Provides the type hint information for this type when it appears as an argument.
390    ///
391    /// For example, `Vec<u32>` would be `collections.abc.Sequence[int]`.
392    /// The default value is `typing.Any`, which is correct for any type.
393    #[cfg(feature = "experimental-inspect")]
394    const INPUT_TYPE: &'static str = "typing.Any";
395
396    /// Extracts `Self` from the bound smart pointer `obj`.
397    ///
398    /// Users are advised against calling this method directly: instead, use this via
399    /// [`Bound<'_, PyAny>::extract`](crate::types::any::PyAnyMethods::extract) or [`Py::extract`].
400    fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error>;
401
402    /// Extracts the type hint information for this type when it appears as an argument.
403    ///
404    /// For example, `Vec<u32>` would return `Sequence[int]`.
405    /// The default implementation returns `Any`, which is correct for any type.
406    ///
407    /// For most types, the return value for this method will be identical to that of
408    /// [`IntoPyObject::type_output`]. It may be different for some types, such as `Dict`,
409    /// to allow duck-typing: functions return `Dict` but take `Mapping` as argument.
410    #[cfg(feature = "experimental-inspect")]
411    fn type_input() -> TypeInfo {
412        TypeInfo::Any
413    }
414
415    /// Specialization hook for extracting sequences for types like `Vec<u8>` and `[u8; N]`,
416    /// where the bytes can be directly copied from some python objects without going through
417    /// iteration.
418    #[doc(hidden)]
419    #[inline(always)]
420    #[cfg(return_position_impl_trait_in_traits)]
421    fn sequence_extractor(
422        _obj: Borrowed<'_, 'py, PyAny>,
423        _: private::Token,
424    ) -> Option<impl FromPyObjectSequence<Target = Self>> {
425        struct NeverASequence<T>(PhantomData<T>);
426
427        impl<T> FromPyObjectSequence for NeverASequence<T> {
428            type Target = T;
429
430            fn to_vec(&self) -> Vec<Self::Target> {
431                unreachable!()
432            }
433
434            fn to_array<const N: usize>(&self) -> PyResult<[Self::Target; N]> {
435                unreachable!()
436            }
437        }
438
439        Option::<NeverASequence<Self>>::None
440    }
441
442    /// Equivalent to the above for MSRV < 1.75, which pays an additional allocation cost.
443    #[doc(hidden)]
444    #[inline(always)]
445    #[cfg(not(return_position_impl_trait_in_traits))]
446    fn sequence_extractor<'b>(
447        _obj: Borrowed<'b, 'b, PyAny>,
448        _: private::Token,
449    ) -> Option<Box<dyn FromPyObjectSequence<Target = Self> + 'b>> {
450        None
451    }
452
453    /// Helper used to make a specialized path in extracting `DateTime<Tz>` where `Tz` is
454    /// `chrono::Local`, which will accept "naive" datetime objects as being in the local timezone.
455    #[cfg(feature = "chrono-local")]
456    #[inline]
457    fn as_local_tz(_: private::Token) -> Option<Self> {
458        None
459    }
460}
461
462mod from_py_object_sequence {
463    use crate::PyResult;
464
465    /// Private trait for implementing specialized sequence extraction for `Vec<u8>` and `[u8; N]`
466    #[doc(hidden)]
467    pub trait FromPyObjectSequence {
468        type Target;
469
470        fn to_vec(&self) -> Vec<Self::Target>;
471
472        #[cfg(return_position_impl_trait_in_traits)]
473        fn to_array<const N: usize>(&self) -> PyResult<[Self::Target; N]>;
474
475        /// Fills an uninit slice with values from the object.
476        ///
477        /// on success, `out` is fully initialized, on failure, `out` should be considered uninitialized.
478        #[cfg(not(return_position_impl_trait_in_traits))]
479        fn fill_slice(&self, out: &mut [std::mem::MaybeUninit<Self::Target>]) -> PyResult<()>;
480    }
481}
482
483// Only reachable / implementable inside PyO3 itself.
484pub(crate) use from_py_object_sequence::FromPyObjectSequence;
485
486/// A data structure that can be extracted without borrowing any data from the input.
487///
488/// This is primarily useful for trait bounds. For example a [`FromPyObject`] implementation of a
489/// wrapper type may be able to borrow data from the input, but a [`FromPyObject`] implementation of
490/// a collection type may only extract owned data.
491///
492/// For example [`PyList`] will not hand out references tied to its own lifetime, but "owned"
493/// references independent of it. (Similar to [`Vec<Arc<T>>`] where you clone the [`Arc<T>`] out).
494/// This makes it impossible to collect borrowed types in a collection, since they would not borrow
495/// from the original [`PyList`], but the much shorter lived element reference. See the example
496/// below.
497///
498/// ```,no_run
499/// # use pyo3::prelude::*;
500/// # #[allow(dead_code)]
501/// pub struct MyWrapper<T>(T);
502///
503/// impl<'a, 'py, T> FromPyObject<'a, 'py> for MyWrapper<T>
504/// where
505///     T: FromPyObject<'a, 'py>
506/// {
507///     type Error = T::Error;
508///
509///     fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
510///         obj.extract().map(MyWrapper)
511///     }
512/// }
513///
514/// # #[allow(dead_code)]
515/// pub struct MyVec<T>(Vec<T>);
516///
517/// impl<'py, T> FromPyObject<'_, 'py> for MyVec<T>
518/// where
519///     T: FromPyObjectOwned<'py> // 👈 can only extract owned values, because each `item` below
520///                               //    is a temporary short lived owned reference
521/// {
522///     type Error = PyErr;
523///
524///     fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
525///         let mut v = MyVec(Vec::new());
526///         for item in obj.try_iter()? {
527///             v.0.push(item?.extract::<T>().map_err(Into::into)?);
528///         }
529///         Ok(v)
530///     }
531/// }
532/// ```
533///
534/// [`PyList`]: crate::types::PyList
535/// [`Arc<T>`]: std::sync::Arc
536pub trait FromPyObjectOwned<'py>: for<'a> FromPyObject<'a, 'py> {}
537impl<'py, T> FromPyObjectOwned<'py> for T where T: for<'a> FromPyObject<'a, 'py> {}
538
539impl<'a, 'py, T> FromPyObject<'a, 'py> for T
540where
541    T: PyClass + Clone + ExtractPyClassWithClone,
542{
543    type Error = PyClassGuardError<'a, 'py>;
544
545    #[cfg(feature = "experimental-inspect")]
546    const INPUT_TYPE: &'static str = <T as crate::impl_::pyclass::PyClassImpl>::TYPE_NAME;
547
548    fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
549        Ok(obj.extract::<PyClassGuard<'_, T>>()?.clone())
550    }
551}
552
553impl<'a, 'py, T> FromPyObject<'a, 'py> for PyRef<'py, T>
554where
555    T: PyClass,
556{
557    type Error = PyClassGuardError<'a, 'py>;
558
559    #[cfg(feature = "experimental-inspect")]
560    const INPUT_TYPE: &'static str = <T as crate::impl_::pyclass::PyClassImpl>::TYPE_NAME;
561
562    fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
563        obj.cast::<T>()
564            .map_err(|e| PyClassGuardError(Some(e)))?
565            .try_borrow()
566            .map_err(|_| PyClassGuardError(None))
567    }
568}
569
570impl<'a, 'py, T> FromPyObject<'a, 'py> for PyRefMut<'py, T>
571where
572    T: PyClass<Frozen = False>,
573{
574    type Error = PyClassGuardMutError<'a, 'py>;
575
576    #[cfg(feature = "experimental-inspect")]
577    const INPUT_TYPE: &'static str = <T as crate::impl_::pyclass::PyClassImpl>::TYPE_NAME;
578
579    fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
580        obj.cast::<T>()
581            .map_err(|e| PyClassGuardMutError(Some(e)))?
582            .try_borrow_mut()
583            .map_err(|_| PyClassGuardMutError(None))
584    }
585}
586
587impl<'py> IntoPyObject<'py> for () {
588    type Target = PyTuple;
589    type Output = Bound<'py, Self::Target>;
590    type Error = Infallible;
591
592    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
593        Ok(PyTuple::empty(py))
594    }
595}
596
597/// ```rust,compile_fail
598/// use pyo3::prelude::*;
599///
600/// #[pyclass]
601/// struct TestClass {
602///     num: u32,
603/// }
604///
605/// let t = TestClass { num: 10 };
606///
607/// Python::attach(|py| {
608///     let pyvalue = Py::new(py, t).unwrap().to_object(py);
609///     let t: TestClass = pyvalue.extract(py).unwrap();
610/// })
611/// ```
612mod test_no_clone {}
613
614#[cfg(test)]
615mod tests {
616    #[test]
617    #[cfg(feature = "macros")]
618    fn test_pyclass_skip_from_py_object() {
619        use crate::{types::PyAnyMethods, FromPyObject, IntoPyObject, PyErr, Python};
620
621        #[crate::pyclass(crate = "crate", skip_from_py_object)]
622        #[derive(Clone)]
623        struct Foo(i32);
624
625        impl<'py> FromPyObject<'_, 'py> for Foo {
626            type Error = PyErr;
627
628            fn extract(obj: crate::Borrowed<'_, 'py, crate::PyAny>) -> Result<Self, Self::Error> {
629                if let Ok(obj) = obj.cast::<Self>() {
630                    Ok(obj.borrow().clone())
631                } else {
632                    obj.extract::<i32>().map(Self)
633                }
634            }
635        }
636        Python::attach(|py| {
637            let foo1 = 42i32.into_pyobject(py)?;
638            assert_eq!(foo1.extract::<Foo>()?.0, 42);
639
640            let foo2 = Foo(0).into_pyobject(py)?;
641            assert_eq!(foo2.extract::<Foo>()?.0, 0);
642
643            Ok::<_, PyErr>(())
644        })
645        .unwrap();
646    }
647
648    #[test]
649    #[cfg(feature = "macros")]
650    fn test_pyclass_from_py_object() {
651        use crate::{types::PyAnyMethods, IntoPyObject, PyErr, Python};
652
653        #[crate::pyclass(crate = "crate", from_py_object)]
654        #[derive(Clone)]
655        struct Foo(i32);
656
657        Python::attach(|py| {
658            let foo1 = 42i32.into_pyobject(py)?;
659            assert!(foo1.extract::<Foo>().is_err());
660
661            let foo2 = Foo(0).into_pyobject(py)?;
662            assert_eq!(foo2.extract::<Foo>()?.0, 0);
663
664            Ok::<_, PyErr>(())
665        })
666        .unwrap();
667    }
668}