From f536ecef283e0ffe23e074629d269021a4169340 Mon Sep 17 00:00:00 2001 From: Icxolu <10486322+Icxolu@users.noreply.github.com> Date: Sat, 26 Oct 2024 18:33:38 +0200 Subject: [PATCH] move `IntoPy::type_output` to `IntoPyObject::type_output` (#4657) * move `IntoPy::type_output` to `IntoPyObject::type_output` * add newsfragment * fix MSRV --- newsfragments/4657.changed.md | 1 + src/conversion.rs | 34 ++++++------ src/conversions/smallvec.rs | 16 ++++-- src/conversions/std/map.rs | 34 ++++++++---- src/conversions/std/num.rs | 99 +++++++++++++++++++++++++---------- src/conversions/std/set.rs | 32 +++++++---- src/conversions/std/slice.rs | 16 +++--- src/conversions/std/string.rs | 70 ++++++++++++++----------- src/conversions/std/vec.rs | 16 ++++-- src/inspect/types.rs | 6 ++- src/types/boolobject.rs | 15 ++++-- src/types/float.rs | 30 +++++++---- src/types/tuple.rs | 21 ++++---- 13 files changed, 252 insertions(+), 138 deletions(-) create mode 100644 newsfragments/4657.changed.md diff --git a/newsfragments/4657.changed.md b/newsfragments/4657.changed.md new file mode 100644 index 00000000000..38018916001 --- /dev/null +++ b/newsfragments/4657.changed.md @@ -0,0 +1 @@ +`IntoPy::type_output` moved to `IntoPyObject::type_output` \ No newline at end of file diff --git a/src/conversion.rs b/src/conversion.rs index dcf07a61eb3..e551e7c1133 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -164,18 +164,6 @@ pub trait 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. - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::Any - } } /// Defines a conversion from a Rust type to a Python object, which may fail. @@ -205,6 +193,18 @@ pub trait IntoPyObject<'py>: Sized { /// Performs the conversion. fn into_pyobject(self, py: Python<'py>) -> Result; + /// 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. + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::Any + } + /// Converts sequence of Self into a Python object. Used to specialize `Vec`, `[u8; N]` /// and `SmallVec<[u8; N]>` as a sequence of bytes into a `bytes` object. #[doc(hidden)] @@ -379,8 +379,9 @@ pub trait FromPyObject<'py>: Sized { /// 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. + /// For most types, the return value for this method will be identical to that of + /// [`IntoPyObject::type_output`]. It may be different for some types, such as `Dict`, + /// to allow duck-typing: functions return `Dict` but take `Mapping` as argument. #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::Any @@ -440,8 +441,9 @@ pub trait FromPyObjectBound<'a, 'py>: Sized + from_py_object_bound_sealed::Seale /// 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. + /// For most types, the return value for this method will be identical to that of + /// [`IntoPyObject::type_output`]. It may be different for some types, such as `Dict`, + /// to allow duck-typing: functions return `Dict` but take `Mapping` as argument. #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::Any diff --git a/src/conversions/smallvec.rs b/src/conversions/smallvec.rs index dc8b18437a5..a01f204b73d 100644 --- a/src/conversions/smallvec.rs +++ b/src/conversions/smallvec.rs @@ -51,11 +51,6 @@ where let list = new_from_iter(py, &mut iter); list.into() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::list_of(A::Item::type_output()) - } } impl<'py, A> IntoPyObject<'py> for SmallVec @@ -75,12 +70,18 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { ::owned_sequence_into_pyobject(self, py, crate::conversion::private::Token) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::list_of(A::Item::type_output()) + } } impl<'a, 'py, A> IntoPyObject<'py> for &'a SmallVec where A: Array, &'a A::Item: IntoPyObject<'py>, + A::Item: 'a, // MSRV { type Target = PyAny; type Output = Bound<'py, Self::Target>; @@ -90,6 +91,11 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { self.as_slice().into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::list_of(<&A::Item>::type_output()) + } } impl<'py, A> FromPyObject<'py> for SmallVec diff --git a/src/conversions/std/map.rs b/src/conversions/std/map.rs index 888bd13c180..388c50b2f3e 100644 --- a/src/conversions/std/map.rs +++ b/src/conversions/std/map.rs @@ -55,11 +55,6 @@ where } dict.into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::dict_of(K::type_output(), V::type_output()) - } } impl<'py, K, V, H> IntoPyObject<'py> for collections::HashMap @@ -79,12 +74,19 @@ where } Ok(dict) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::dict_of(K::type_output(), V::type_output()) + } } impl<'a, 'py, K, V, H> IntoPyObject<'py> for &'a collections::HashMap where &'a K: IntoPyObject<'py> + cmp::Eq + hash::Hash, &'a V: IntoPyObject<'py>, + K: 'a, // MSRV + V: 'a, // MSRV H: hash::BuildHasher, { type Target = PyDict; @@ -98,6 +100,11 @@ where } Ok(dict) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::dict_of(<&K>::type_output(), <&V>::type_output()) + } } impl IntoPy for collections::BTreeMap @@ -112,11 +119,6 @@ where } dict.into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::dict_of(K::type_output(), V::type_output()) - } } impl<'py, K, V> IntoPyObject<'py> for collections::BTreeMap @@ -135,12 +137,19 @@ where } Ok(dict) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::dict_of(K::type_output(), V::type_output()) + } } impl<'a, 'py, K, V> IntoPyObject<'py> for &'a collections::BTreeMap where &'a K: IntoPyObject<'py> + cmp::Eq, &'a V: IntoPyObject<'py>, + K: 'a, + V: 'a, { type Target = PyDict; type Output = Bound<'py, Self::Target>; @@ -153,6 +162,11 @@ where } Ok(dict) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::dict_of(<&K>::type_output(), <&V>::type_output()) + } } impl<'py, K, V, S> FromPyObject<'py> for collections::HashMap diff --git a/src/conversions/std/num.rs b/src/conversions/std/num.rs index e7b8addac82..ded970ef9a1 100644 --- a/src/conversions/std/num.rs +++ b/src/conversions/std/num.rs @@ -31,11 +31,6 @@ macro_rules! int_fits_larger_int { fn into_py(self, py: Python<'_>) -> PyObject { self.into_pyobject(py).unwrap().into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - <$larger_type>::type_output() - } } impl<'py> IntoPyObject<'py> for $rust_type { @@ -46,6 +41,11 @@ macro_rules! int_fits_larger_int { fn into_pyobject(self, py: Python<'py>) -> Result { (self as $larger_type).into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + <$larger_type>::type_output() + } } impl<'py> IntoPyObject<'py> for &$rust_type { @@ -56,6 +56,11 @@ macro_rules! int_fits_larger_int { fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + <$larger_type>::type_output() + } } impl FromPyObject<'_> for $rust_type { @@ -112,11 +117,6 @@ macro_rules! int_convert_u64_or_i64 { fn into_py(self, py: Python<'_>) -> PyObject { self.into_pyobject(py).unwrap().into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::builtin("int") - } } impl<'py> IntoPyObject<'py> for $rust_type { type Target = PyInt; @@ -130,6 +130,11 @@ macro_rules! int_convert_u64_or_i64 { .downcast_into_unchecked()) } } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("int") + } } impl<'py> IntoPyObject<'py> for &$rust_type { type Target = PyInt; @@ -140,6 +145,11 @@ macro_rules! int_convert_u64_or_i64 { fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("int") + } } impl FromPyObject<'_> for $rust_type { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<$rust_type> { @@ -168,11 +178,6 @@ macro_rules! int_fits_c_long { fn into_py(self, py: Python<'_>) -> PyObject { self.into_pyobject(py).unwrap().into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::builtin("int") - } } impl<'py> IntoPyObject<'py> for $rust_type { @@ -187,6 +192,11 @@ macro_rules! int_fits_c_long { .downcast_into_unchecked()) } } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("int") + } } impl<'py> IntoPyObject<'py> for &$rust_type { @@ -198,6 +208,11 @@ macro_rules! int_fits_c_long { fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("int") + } } impl<'py> FromPyObject<'py> for $rust_type { @@ -227,10 +242,6 @@ impl IntoPy for u8 { fn into_py(self, py: Python<'_>) -> PyObject { self.into_pyobject(py).unwrap().into_any().unbind() } - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::builtin("int") - } } impl<'py> IntoPyObject<'py> for u8 { type Target = PyInt; @@ -245,6 +256,11 @@ impl<'py> IntoPyObject<'py> for u8 { } } + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("int") + } + #[inline] fn owned_sequence_into_pyobject( iter: I, @@ -267,6 +283,11 @@ impl<'py> IntoPyObject<'py> for &'_ u8 { u8::into_pyobject(*self, py) } + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("int") + } + #[inline] fn borrowed_sequence_into_pyobject( iter: I, @@ -345,11 +366,6 @@ mod fast_128bit_int_conversion { fn into_py(self, py: Python<'_>) -> PyObject { self.into_pyobject(py).unwrap().into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::builtin("int") - } } impl<'py> IntoPyObject<'py> for $rust_type { @@ -399,6 +415,11 @@ mod fast_128bit_int_conversion { } } } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("int") + } } impl<'py> IntoPyObject<'py> for &$rust_type { @@ -410,6 +431,11 @@ mod fast_128bit_int_conversion { fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("int") + } } impl FromPyObject<'_> for $rust_type { @@ -493,11 +519,6 @@ mod slow_128bit_int_conversion { fn into_py(self, py: Python<'_>) -> PyObject { self.into_pyobject(py).unwrap().into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::builtin("int") - } } impl<'py> IntoPyObject<'py> for $rust_type { @@ -518,6 +539,11 @@ mod slow_128bit_int_conversion { .downcast_into_unchecked()) } } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("int") + } } impl<'py> IntoPyObject<'py> for &$rust_type { @@ -529,6 +555,11 @@ mod slow_128bit_int_conversion { fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("int") + } } impl FromPyObject<'_> for $rust_type { @@ -602,6 +633,11 @@ macro_rules! nonzero_int_impl { fn into_pyobject(self, py: Python<'py>) -> Result { self.get().into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("int") + } } impl<'py> IntoPyObject<'py> for &$nonzero_type { @@ -613,6 +649,11 @@ macro_rules! nonzero_int_impl { fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("int") + } } impl FromPyObject<'_> for $nonzero_type { diff --git a/src/conversions/std/set.rs b/src/conversions/std/set.rs index ff5ab572bb5..0bd1b9d7ed6 100644 --- a/src/conversions/std/set.rs +++ b/src/conversions/std/set.rs @@ -51,11 +51,6 @@ where .expect("Failed to create Python set from HashSet") .into() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::set_of(K::type_output()) - } } impl<'py, K, S> IntoPyObject<'py> for collections::HashSet @@ -70,11 +65,17 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { try_new_from_iter(py, self) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::set_of(K::type_output()) + } } impl<'a, 'py, K, H> IntoPyObject<'py> for &'a collections::HashSet where &'a K: IntoPyObject<'py> + Eq + hash::Hash, + K: 'a, // MSRV H: hash::BuildHasher, { type Target = PySet; @@ -84,6 +85,11 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { try_new_from_iter(py, self.iter()) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::set_of(<&K>::type_output()) + } } impl<'py, K, S> FromPyObject<'py> for collections::HashSet @@ -119,11 +125,6 @@ where .expect("Failed to create Python set from BTreeSet") .into() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::set_of(K::type_output()) - } } impl<'py, K> IntoPyObject<'py> for collections::BTreeSet @@ -137,11 +138,17 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { try_new_from_iter(py, self) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::set_of(K::type_output()) + } } impl<'a, 'py, K> IntoPyObject<'py> for &'a collections::BTreeSet where &'a K: IntoPyObject<'py> + cmp::Ord, + K: 'a, { type Target = PySet; type Output = Bound<'py, Self::Target>; @@ -150,6 +157,11 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { try_new_from_iter(py, self.iter()) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::set_of(<&K>::type_output()) + } } impl<'py, K> FromPyObject<'py> for collections::BTreeSet diff --git a/src/conversions/std/slice.rs b/src/conversions/std/slice.rs index eb758271fcf..ea33cc8461b 100644 --- a/src/conversions/std/slice.rs +++ b/src/conversions/std/slice.rs @@ -14,16 +14,12 @@ impl IntoPy for &[u8] { fn into_py(self, py: Python<'_>) -> PyObject { PyBytes::new(py, self).unbind().into() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::builtin("bytes") - } } impl<'a, 'py, T> IntoPyObject<'py> for &'a [T] where &'a T: IntoPyObject<'py>, + T: 'a, // MSRV { type Target = PyAny; type Output = Bound<'py, Self::Target>; @@ -37,6 +33,14 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { <&T>::borrowed_sequence_into_pyobject(self, py, crate::conversion::private::Token) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::union_of(&[ + TypeInfo::builtin("bytes"), + TypeInfo::list_of(<&T>::type_output()), + ]) + } } impl<'a> crate::conversion::FromPyObjectBound<'a, '_> for &'a [u8] { @@ -46,7 +50,7 @@ impl<'a> crate::conversion::FromPyObjectBound<'a, '_> for &'a [u8] { #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { - Self::type_output() + TypeInfo::builtin("bytes") } } diff --git a/src/conversions/std/string.rs b/src/conversions/std/string.rs index 667edaaeb5f..b1eff507b7a 100644 --- a/src/conversions/std/string.rs +++ b/src/conversions/std/string.rs @@ -26,11 +26,6 @@ impl IntoPy for &str { fn into_py(self, py: Python<'_>) -> PyObject { self.into_pyobject(py).unwrap().into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - ::type_output() - } } impl IntoPy> for &str { @@ -38,11 +33,6 @@ impl IntoPy> for &str { fn into_py(self, py: Python<'_>) -> Py { self.into_pyobject(py).unwrap().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - ::type_output() - } } impl<'py> IntoPyObject<'py> for &str { @@ -54,6 +44,11 @@ impl<'py> IntoPyObject<'py> for &str { fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyString::new(py, self)) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + ::type_output() + } } impl<'py> IntoPyObject<'py> for &&str { @@ -65,6 +60,11 @@ impl<'py> IntoPyObject<'py> for &&str { fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + ::type_output() + } } /// Converts a Rust `Cow<'_, str>` to a Python object. @@ -82,11 +82,6 @@ impl IntoPy for Cow<'_, str> { fn into_py(self, py: Python<'_>) -> PyObject { self.into_pyobject(py).unwrap().into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - ::type_output() - } } impl<'py> IntoPyObject<'py> for Cow<'_, str> { @@ -98,6 +93,11 @@ impl<'py> IntoPyObject<'py> for Cow<'_, str> { fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + ::type_output() + } } impl<'py> IntoPyObject<'py> for &Cow<'_, str> { @@ -109,6 +109,11 @@ impl<'py> IntoPyObject<'py> for &Cow<'_, str> { fn into_pyobject(self, py: Python<'py>) -> Result { (&**self).into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + ::type_output() + } } /// Converts a Rust `String` to a Python object. @@ -134,11 +139,6 @@ impl IntoPy for char { fn into_py(self, py: Python<'_>) -> PyObject { self.into_pyobject(py).unwrap().into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - ::type_output() - } } impl<'py> IntoPyObject<'py> for char { @@ -150,6 +150,11 @@ impl<'py> IntoPyObject<'py> for char { let mut bytes = [0u8; 4]; Ok(PyString::new(py, self.encode_utf8(&mut bytes))) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + ::type_output() + } } impl<'py> IntoPyObject<'py> for &char { @@ -161,6 +166,11 @@ impl<'py> IntoPyObject<'py> for &char { fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + ::type_output() + } } impl IntoPy for String { @@ -168,11 +178,6 @@ impl IntoPy for String { fn into_py(self, py: Python<'_>) -> PyObject { self.into_pyobject(py).unwrap().into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::builtin("str") - } } impl<'py> IntoPyObject<'py> for String { @@ -183,6 +188,11 @@ impl<'py> IntoPyObject<'py> for String { fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyString::new(py, &self)) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("str") + } } impl IntoPy for &String { @@ -190,11 +200,6 @@ impl IntoPy for &String { fn into_py(self, py: Python<'_>) -> PyObject { self.into_pyobject(py).unwrap().into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - ::type_output() - } } impl<'py> IntoPyObject<'py> for &String { @@ -206,6 +211,11 @@ impl<'py> IntoPyObject<'py> for &String { fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyString::new(py, self)) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + ::type_output() + } } #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] diff --git a/src/conversions/std/vec.rs b/src/conversions/std/vec.rs index ea3fff117c0..a667460fd82 100644 --- a/src/conversions/std/vec.rs +++ b/src/conversions/std/vec.rs @@ -37,11 +37,6 @@ where let list = new_from_iter(py, &mut iter); list.into() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::list_of(T::type_output()) - } } impl<'py, T> IntoPyObject<'py> for Vec @@ -60,11 +55,17 @@ where fn into_pyobject(self, py: Python<'py>) -> Result { T::owned_sequence_into_pyobject(self, py, crate::conversion::private::Token) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::list_of(T::type_output()) + } } impl<'a, 'py, T> IntoPyObject<'py> for &'a Vec where &'a T: IntoPyObject<'py>, + T: 'a, // MSRV { type Target = PyAny; type Output = Bound<'py, Self::Target>; @@ -77,6 +78,11 @@ where // above which always returns a `PyAny` for `Vec`. self.as_slice().into_pyobject(py).map(Bound::into_any) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::list_of(<&T>::type_output()) + } } #[cfg(test)] diff --git a/src/inspect/types.rs b/src/inspect/types.rs index 13ce62585b1..50674ce96f9 100644 --- a/src/inspect/types.rs +++ b/src/inspect/types.rs @@ -277,6 +277,7 @@ mod test { use crate::inspect::types::{ModuleName, TypeInfo}; + #[track_caller] pub fn assert_display(t: &TypeInfo, expected: &str) { assert_eq!(format!("{}", t), expected) } @@ -405,7 +406,7 @@ mod conversion { use std::collections::{HashMap, HashSet}; use crate::inspect::types::test::assert_display; - use crate::{FromPyObject, IntoPy}; + use crate::{FromPyObject, IntoPyObject}; #[test] fn unsigned_int() { @@ -463,7 +464,8 @@ mod conversion { assert_display(&String::type_output(), "str"); assert_display(&String::type_input(), "str"); - assert_display(&<&[u8]>::type_output(), "bytes"); + assert_display(&<&[u8]>::type_output(), "Union[bytes, List[int]]"); + assert_display(&<&[String]>::type_output(), "Union[bytes, List[str]]"); assert_display( &<&[u8] as crate::conversion::FromPyObjectBound>::type_input(), "bytes", diff --git a/src/types/boolobject.rs b/src/types/boolobject.rs index 6f90329900d..d54bddc8848 100644 --- a/src/types/boolobject.rs +++ b/src/types/boolobject.rs @@ -160,11 +160,6 @@ impl IntoPy for bool { fn into_py(self, py: Python<'_>) -> PyObject { self.into_pyobject(py).unwrap().into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::builtin("bool") - } } impl<'py> IntoPyObject<'py> for bool { @@ -176,6 +171,11 @@ impl<'py> IntoPyObject<'py> for bool { fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyBool::new(py, self)) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("bool") + } } impl<'py> IntoPyObject<'py> for &bool { @@ -187,6 +187,11 @@ impl<'py> IntoPyObject<'py> for &bool { fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("bool") + } } /// Converts a Python `bool` to a Rust `bool`. diff --git a/src/types/float.rs b/src/types/float.rs index f9bf673ac98..8438629e577 100644 --- a/src/types/float.rs +++ b/src/types/float.rs @@ -91,11 +91,6 @@ impl IntoPy for f64 { fn into_py(self, py: Python<'_>) -> PyObject { self.into_pyobject(py).unwrap().into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::builtin("float") - } } impl<'py> IntoPyObject<'py> for f64 { @@ -107,6 +102,11 @@ impl<'py> IntoPyObject<'py> for f64 { fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyFloat::new(py, self)) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("float") + } } impl<'py> IntoPyObject<'py> for &f64 { @@ -118,6 +118,11 @@ impl<'py> IntoPyObject<'py> for &f64 { fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("float") + } } impl<'py> FromPyObject<'py> for f64 { @@ -163,11 +168,6 @@ impl IntoPy for f32 { fn into_py(self, py: Python<'_>) -> PyObject { self.into_pyobject(py).unwrap().into_any().unbind() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::builtin("float") - } } impl<'py> IntoPyObject<'py> for f32 { @@ -179,6 +179,11 @@ impl<'py> IntoPyObject<'py> for f32 { fn into_pyobject(self, py: Python<'py>) -> Result { Ok(PyFloat::new(py, self.into())) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("float") + } } impl<'py> IntoPyObject<'py> for &f32 { @@ -190,6 +195,11 @@ impl<'py> IntoPyObject<'py> for &f32 { fn into_pyobject(self, py: Python<'py>) -> Result { (*self).into_pyobject(py) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::builtin("float") + } } impl<'py> FromPyObject<'py> for f32 { diff --git a/src/types/tuple.rs b/src/types/tuple.rs index 189cec126bd..1b6a95abb14 100644 --- a/src/types/tuple.rs +++ b/src/types/tuple.rs @@ -529,11 +529,6 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+ fn into_py(self, py: Python<'_>) -> PyObject { array_into_tuple(py, [$(self.$n.into_py(py)),+]).into() } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::Tuple(Some(vec![$( $T::type_output() ),+])) - } } impl <'py, $($T),+> IntoPyObject<'py> for ($($T,)+) @@ -547,11 +542,17 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+ fn into_pyobject(self, py: Python<'py>) -> Result { Ok(array_into_tuple(py, [$(self.$n.into_pyobject(py).map_err(Into::into)?.into_any().unbind()),+]).into_bound(py)) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::Tuple(Some(vec![$( $T::type_output() ),+])) + } } impl <'a, 'py, $($T),+> IntoPyObject<'py> for &'a ($($T,)+) where $(&'a $T: IntoPyObject<'py>,)+ + $($T: 'a,)+ // MSRV { type Target = PyTuple; type Output = Bound<'py, Self::Target>; @@ -560,17 +561,17 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+ fn into_pyobject(self, py: Python<'py>) -> Result { Ok(array_into_tuple(py, [$(self.$n.into_pyobject(py).map_err(Into::into)?.into_any().unbind()),+]).into_bound(py)) } + + #[cfg(feature = "experimental-inspect")] + fn type_output() -> TypeInfo { + TypeInfo::Tuple(Some(vec![$( <&$T>::type_output() ),+])) + } } impl <$($T: IntoPy),+> IntoPy> for ($($T,)+) { fn into_py(self, py: Python<'_>) -> Py { array_into_tuple(py, [$(self.$n.into_py(py)),+]) } - - #[cfg(feature = "experimental-inspect")] - fn type_output() -> TypeInfo { - TypeInfo::Tuple(Some(vec![$( $T::type_output() ),+])) - } } impl<'py, $($T: FromPyObject<'py>),+> FromPyObject<'py> for ($($T,)+) {