use crate::err::PyResult;
#[cfg(feature = "experimental-inspect")]
use crate::inspect::types::TypeInfo;
use crate::pyclass::boolean_struct::False;
use crate::types::any::PyAnyMethods;
use crate::types::PyTuple;
use crate::{
ffi, Borrowed, Bound, BoundObject, Py, PyAny, PyClass, PyErr, PyObject, PyRef, PyRefMut, Python,
};
use std::convert::Infallible;
pub unsafe trait AsPyPointer {
fn as_ptr(&self) -> *mut ffi::PyObject;
}
#[deprecated(
since = "0.23.0",
note = "`ToPyObject` is going to be replaced by `IntoPyObject`. See the migration guide (https://pyo3.rs/v0.23.0/migration) for more information."
)]
pub trait ToPyObject {
fn to_object(&self, py: Python<'_>) -> PyObject;
}
#[cfg_attr(
diagnostic_namespace,
diagnostic::on_unimplemented(
message = "`{Self}` cannot be converted to a Python object",
note = "`IntoPy` is automatically implemented by the `#[pyclass]` macro",
note = "if you do not wish to have a corresponding Python type, implement it manually",
note = "if you do not own `{Self}` you can perform a manual conversion to one of the types in `pyo3::types::*`"
)
)]
#[deprecated(
since = "0.23.0",
note = "`IntoPy` is going to be replaced by `IntoPyObject`. See the migration guide (https://pyo3.rs/v0.23.0/migration) for more information."
)]
pub trait IntoPy<T>: Sized {
fn into_py(self, py: Python<'_>) -> T;
}
#[cfg_attr(
diagnostic_namespace,
diagnostic::on_unimplemented(
message = "`{Self}` cannot be converted to a Python object",
note = "`IntoPyObject` is automatically implemented by the `#[pyclass]` macro",
note = "if you do not wish to have a corresponding Python type, implement it manually",
note = "if you do not own `{Self}` you can perform a manual conversion to one of the types in `pyo3::types::*`"
)
)]
pub trait IntoPyObject<'py>: Sized {
type Target;
type Output: BoundObject<'py, Self::Target>;
type Error: Into<PyErr>;
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error>;
#[cfg(feature = "experimental-inspect")]
fn type_output() -> TypeInfo {
TypeInfo::Any
}
#[doc(hidden)]
fn owned_sequence_into_pyobject<I>(
iter: I,
py: Python<'py>,
_: private::Token,
) -> Result<Bound<'py, PyAny>, PyErr>
where
I: IntoIterator<Item = Self> + AsRef<[Self]>,
I::IntoIter: ExactSizeIterator<Item = Self>,
{
let mut iter = iter.into_iter().map(|e| e.into_bound_py_any(py));
let list = crate::types::list::try_new_from_iter(py, &mut iter);
list.map(Bound::into_any)
}
#[doc(hidden)]
fn borrowed_sequence_into_pyobject<I>(
iter: I,
py: Python<'py>,
_: private::Token,
) -> Result<Bound<'py, PyAny>, PyErr>
where
Self: private::Reference,
I: IntoIterator<Item = Self> + AsRef<[<Self as private::Reference>::BaseType]>,
I::IntoIter: ExactSizeIterator<Item = Self>,
{
let mut iter = iter.into_iter().map(|e| e.into_bound_py_any(py));
let list = crate::types::list::try_new_from_iter(py, &mut iter);
list.map(Bound::into_any)
}
}
pub(crate) mod private {
pub struct Token;
pub trait Reference {
type BaseType;
}
impl<T> Reference for &'_ T {
type BaseType = T;
}
}
impl<'py, T> IntoPyObject<'py> for Bound<'py, T> {
type Target = T;
type Output = Bound<'py, Self::Target>;
type Error = Infallible;
fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {
Ok(self)
}
}
impl<'a, 'py, T> IntoPyObject<'py> for &'a Bound<'py, T> {
type Target = T;
type Output = Borrowed<'a, 'py, Self::Target>;
type Error = Infallible;
fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {
Ok(self.as_borrowed())
}
}
impl<'a, 'py, T> IntoPyObject<'py> for Borrowed<'a, 'py, T> {
type Target = T;
type Output = Borrowed<'a, 'py, Self::Target>;
type Error = Infallible;
fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {
Ok(self)
}
}
impl<'a, 'py, T> IntoPyObject<'py> for &Borrowed<'a, 'py, T> {
type Target = T;
type Output = Borrowed<'a, 'py, Self::Target>;
type Error = Infallible;
fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {
Ok(*self)
}
}
impl<'py, T> IntoPyObject<'py> for Py<T> {
type Target = T;
type Output = Bound<'py, Self::Target>;
type Error = Infallible;
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
Ok(self.into_bound(py))
}
}
impl<'a, 'py, T> IntoPyObject<'py> for &'a Py<T> {
type Target = T;
type Output = Borrowed<'a, 'py, Self::Target>;
type Error = Infallible;
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
Ok(self.bind_borrowed(py))
}
}
impl<'a, 'py, T> IntoPyObject<'py> for &&'a T
where
&'a T: IntoPyObject<'py>,
{
type Target = <&'a T as IntoPyObject<'py>>::Target;
type Output = <&'a T as IntoPyObject<'py>>::Output;
type Error = <&'a T as IntoPyObject<'py>>::Error;
#[inline]
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
(*self).into_pyobject(py)
}
}
mod into_pyobject_ext {
pub trait Sealed {}
impl<'py, T> Sealed for T where T: super::IntoPyObject<'py> {}
}
pub trait IntoPyObjectExt<'py>: IntoPyObject<'py> + into_pyobject_ext::Sealed {
#[inline]
fn into_bound_py_any(self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
match self.into_pyobject(py) {
Ok(obj) => Ok(obj.into_any().into_bound()),
Err(err) => Err(err.into()),
}
}
#[inline]
fn into_py_any(self, py: Python<'py>) -> PyResult<Py<PyAny>> {
match self.into_pyobject(py) {
Ok(obj) => Ok(obj.into_any().unbind()),
Err(err) => Err(err.into()),
}
}
#[inline]
fn into_pyobject_or_pyerr(self, py: Python<'py>) -> PyResult<Self::Output> {
match self.into_pyobject(py) {
Ok(obj) => Ok(obj),
Err(err) => Err(err.into()),
}
}
}
impl<'py, T> IntoPyObjectExt<'py> for T where T: IntoPyObject<'py> {}
pub trait FromPyObject<'py>: Sized {
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self>;
#[cfg(feature = "experimental-inspect")]
fn type_input() -> TypeInfo {
TypeInfo::Any
}
}
mod from_py_object_bound_sealed {
pub trait Sealed {}
impl<'py, T> Sealed for T where T: super::FromPyObject<'py> {}
impl Sealed for &'_ str {}
impl Sealed for std::borrow::Cow<'_, str> {}
impl Sealed for &'_ [u8] {}
impl Sealed for std::borrow::Cow<'_, [u8]> {}
}
pub trait FromPyObjectBound<'a, 'py>: Sized + from_py_object_bound_sealed::Sealed {
fn from_py_object_bound(ob: Borrowed<'a, 'py, PyAny>) -> PyResult<Self>;
#[cfg(feature = "experimental-inspect")]
fn type_input() -> TypeInfo {
TypeInfo::Any
}
}
impl<'py, T> FromPyObjectBound<'_, 'py> for T
where
T: FromPyObject<'py>,
{
fn from_py_object_bound(ob: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {
Self::extract_bound(&ob)
}
#[cfg(feature = "experimental-inspect")]
fn type_input() -> TypeInfo {
<T as FromPyObject>::type_input()
}
}
#[allow(deprecated)]
impl<T: ?Sized + ToPyObject> ToPyObject for &'_ T {
#[inline]
fn to_object(&self, py: Python<'_>) -> PyObject {
<T as ToPyObject>::to_object(*self, py)
}
}
impl<T> FromPyObject<'_> for T
where
T: PyClass + Clone,
{
fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
let bound = obj.downcast::<Self>()?;
Ok(bound.try_borrow()?.clone())
}
}
impl<'py, T> FromPyObject<'py> for PyRef<'py, T>
where
T: PyClass,
{
fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {
obj.downcast::<T>()?.try_borrow().map_err(Into::into)
}
}
impl<'py, T> FromPyObject<'py> for PyRefMut<'py, T>
where
T: PyClass<Frozen = False>,
{
fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {
obj.downcast::<T>()?.try_borrow_mut().map_err(Into::into)
}
}
#[allow(deprecated)]
impl IntoPy<Py<PyTuple>> for () {
fn into_py(self, py: Python<'_>) -> Py<PyTuple> {
PyTuple::empty(py).unbind()
}
}
impl<'py> IntoPyObject<'py> for () {
type Target = PyTuple;
type Output = Bound<'py, Self::Target>;
type Error = Infallible;
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
Ok(PyTuple::empty(py))
}
}
mod test_no_clone {}