diff --git a/CHANGELOG.md b/CHANGELOG.md index 06fe05f7..c611c8d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added `type_input()` and `type_output()` to get the Python type of any Python-compatible object. [#2490](https://github.com/PyO3/pyo3/pull/2490) + ### Removed - Remove the deprecated `pyproto` feature, `#[pyproto]` macro, and all accompanying APIs. [#2587](https://github.com/PyO3/pyo3/pull/2587) diff --git a/src/conversion.rs b/src/conversion.rs index 29119928..05633076 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -2,6 +2,7 @@ //! Defines conversions between Rust and Python types. use crate::err::{self, PyDowncastError, PyResult}; +use crate::inspect::types::TypeInfo; use crate::pyclass::boolean_struct::False; use crate::type_object::PyTypeInfo; use crate::types::PyTuple; @@ -244,6 +245,17 @@ impl ToBorrowedObject for T where T: ToPyObject {} pub trait IntoPy: Sized { /// Performs the conversion. fn into_py(self, py: Python<'_>) -> T; + + /// Extracts the type hint information for this type when it appears as a return value. + /// + /// For example, `Vec` would return `List[int]`. + /// The default implementation returns `Any`, which is correct for any type. + /// + /// For most types, the return value for this method will be identical to that of [`FromPyObject::type_input`]. + /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument. + fn type_output() -> TypeInfo { + TypeInfo::Any + } } /// Extract a type from a Python object. @@ -289,6 +301,17 @@ pub trait IntoPy: Sized { pub trait FromPyObject<'source>: Sized { /// Extracts `Self` from the source `PyObject`. fn extract(ob: &'source PyAny) -> PyResult; + + /// Extracts the type hint information for this type when it appears as an argument. + /// + /// For example, `Vec` would return `Sequence[int]`. + /// The default implementation returns `Any`, which is correct for any type. + /// + /// For most types, the return value for this method will be identical to that of [`IntoPy::type_output`]. + /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument. + fn type_input() -> TypeInfo { + TypeInfo::Any + } } /// Identity conversion: allows using existing `PyObject` instances where diff --git a/tests/ui/missing_intopy.stderr b/tests/ui/missing_intopy.stderr index 2419ef60..493f3e61 100644 --- a/tests/ui/missing_intopy.stderr +++ b/tests/ui/missing_intopy.stderr @@ -20,6 +20,9 @@ note: the following trait must be implemented | / pub trait IntoPy: Sized { | | /// Performs the conversion. | | fn into_py(self, py: Python<'_>) -> T; + | | +... | + | | } | | } | |_^ = note: this error originates in the attribute macro `pyo3::pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)