Skip to content

Commit 91ef5fe

Browse files
committed
FromPyObject docs take 2
1 parent c467e71 commit 91ef5fe

File tree

1 file changed

+32
-34
lines changed

1 file changed

+32
-34
lines changed

src/conversion.rs

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,8 @@ impl<'a, 'py, T> IntoPyObject<'py> for &'a Py<T> {
409409
/// Extract a type from a Python object.
410410
///
411411
///
412-
/// Normal usage is through the `extract` methods on [`Bound`], [`Borrowed`] and
413-
/// [`Py`], which forward to this trait.
412+
/// Normal usage is through the `extract` methods on [`Bound`], [`Borrowed`] and [`Py`], which
413+
/// forward to this trait.
414414
///
415415
/// # Examples
416416
///
@@ -434,38 +434,27 @@ impl<'a, 'py, T> IntoPyObject<'py> for &'a Py<T> {
434434
/// # }
435435
/// ```
436436
///
437-
/// Note: depending on the implementation, the extracted result may depend on
438-
/// the Python lifetime `'py` or the input lifetime `'a` of `obj`.
439-
///
440-
/// For example, when extracting a [`Cow<'a, str>`] the result may or may not
441-
/// borrow from the input lifetime `'a`. The behavior depends on the runtime
442-
/// type of the Python object. For a Python byte string, the existing string
443-
/// data can be borrowed (lifetime: `'a`) into a [`Cow::Borrowed`]. For a Python
444-
/// Unicode string, the data may have to be reencoded to UTF-8, and copied into
445-
/// a [`Cow::Owned`]. It does _not_ depend on the Python lifetime `'py`
446-
///
447-
/// An example of a type depending on the Python lifetime `'py` would be
448-
/// [`Bound<'py, PyString>`]. This type holds the invariant of beeing allowed to
449-
/// interact with the Python interpreter, so it inherits the Python lifetime
450-
/// from the input. It is however _not_ tied to the input lifetime `'a` and can
451-
/// be passed around independently of `obj`.
452-
///
453-
/// Special care needs to be taken for collection types, for example [`PyList`].
454-
/// In contrast to a Rust's [`Vec`] a Python list will not hand out references
455-
/// tied to its own lifetime, but "owned" references independent of it. (Similar
456-
/// to [`Vec<Arc<T>>`] where you clone the [`Arc<T>`] out). This makes it
457-
/// impossible to collect borrowed types in a collection, since they would not
458-
/// borrow from the original input list, but the much shorter lived element
459-
/// reference. This restriction is represented in PyO3 using
460-
/// [`FromPyObjectOwned`]. It is used by [`FromPyObject`] implementations on
461-
/// collection types to specify it can only collect types which do _not_ borrow
462-
/// from the input.
437+
/// Note: Depending on the Python version and implementation, some [`FromPyObject`] implementations
438+
/// may produce a result that borrows into the Python type. This is described by the input lifetime
439+
/// `'a` of `obj`.
440+
///
441+
/// Types that must not borrow from the input can use [`FromPyObjectOwned`] as a restriction. This
442+
/// is most often the case for collection types. See its documentation for more details.
443+
///
444+
/// # Details
445+
/// [`Cow<'a, str>`] is an example of an output type that may or may not borrow from the input
446+
/// lifetime `'a`. Which variant will be produced depends on the runtime type of the Python object.
447+
/// For a Python byte string, the existing string data can be borrowed for `'a` into a
448+
/// [`Cow::Borrowed`]. For a Python Unicode string, the data may have to be reencoded to UTF-8, and
449+
/// copied into a [`Cow::Owned`]. It does _not_ depend on the Python lifetime `'py`.
450+
///
451+
/// The output type may also depend on the Python lifetime `'py`. This allows the output type to
452+
/// keep interacting with the Python interpreter. See also [`Bound<'py, T>`].
463453
///
464454
/// [`Cow<'a, str>`]: std::borrow::Cow
465455
/// [`Cow::Borrowed`]: std::borrow::Cow::Borrowed
466456
/// [`Cow::Owned`]: std::borrow::Cow::Owned
467-
/// [`PyList`]: crate::types::PyList
468-
/// [`Arc<T>`]: std::sync::Arc
457+
469458
pub trait FromPyObject<'a, 'py>: Sized {
470459
/// Extracts `Self` from the bound smart pointer `obj`.
471460
///
@@ -492,11 +481,17 @@ pub trait FromPyObject<'a, 'py>: Sized {
492481
}
493482
}
494483

495-
/// A data structure that can be extracted without borrowing any data from the input
484+
/// A data structure that can be extracted without borrowing any data from the input.
485+
///
486+
/// This is primarily useful for trait bounds. For example a [`FromPyObject`] implementation of a
487+
/// wrapper type may be able to borrow data from the input, but a [`FromPyObject`] implementation of
488+
/// a collection type may only extract owned data.
496489
///
497-
/// This is primarily useful for trait bounds. For example a `FromPyObject` implementation of a
498-
/// wrapper type may be able to borrow data from the input, but a `FromPyObject` implementation of a
499-
/// collection type may only extract owned data.
490+
/// For example [`PyList`] will not hand out references tied to its own lifetime, but "owned"
491+
/// references independent of it. (Similar to [`Vec<Arc<T>>`] where you clone the [`Arc<T>`] out).
492+
/// This makes it impossible to collect borrowed types in a collection, since they would not borrow
493+
/// from the original [`PyList`], but the much shorter lived element reference. See the example
494+
/// below.
500495
///
501496
/// ```
502497
/// # use pyo3::prelude::*;
@@ -527,6 +522,9 @@ pub trait FromPyObject<'a, 'py>: Sized {
527522
/// }
528523
/// }
529524
/// ```
525+
///
526+
/// [`PyList`]: crate::types::PyList
527+
/// [`Arc<T>`]: std::sync::Arc
530528
pub trait FromPyObjectOwned<'py>: for<'a> FromPyObject<'a, 'py> {}
531529
impl<'py, T> FromPyObjectOwned<'py> for T where T: for<'a> FromPyObject<'a, 'py> {}
532530

0 commit comments

Comments
 (0)