Simplify IntoInitializer
This commit is contained in:
parent
18e565fab5
commit
60edeb889e
|
@ -257,10 +257,10 @@ struct SubSubClass {
|
|||
#[pymethods]
|
||||
impl SubSubClass {
|
||||
#[new]
|
||||
fn new() -> impl IntoInitializer<Self> {
|
||||
Ok(SubClass::new()
|
||||
.into_initializer()?
|
||||
.add_subclass(SubSubClass{val3: 20}))
|
||||
fn new() -> PyClassInitializer<Self> {
|
||||
SubClass::new()
|
||||
.into_initializer()
|
||||
.add_subclass(SubSubClass{val3: 20})
|
||||
}
|
||||
|
||||
fn method3(self_: &PyClassShell<Self>) -> PyResult<usize> {
|
||||
|
|
|
@ -154,7 +154,7 @@ pub fn impl_wrap_new(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
|
|||
let body = impl_arg_params_(
|
||||
spec,
|
||||
cb,
|
||||
quote! { pyo3::pyclass_init::IntoInitializer::into_initializer },
|
||||
quote! { pyo3::derive_utils::IntoPyNewResult::into_pynew_result },
|
||||
);
|
||||
|
||||
quote! {
|
||||
|
@ -174,7 +174,7 @@ pub fn impl_wrap_new(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
|
|||
|
||||
#body
|
||||
|
||||
match _result.and_then(|init| init.create_shell(_py)) {
|
||||
match _result.and_then(|init| init.into_initializer().create_shell(_py)) {
|
||||
Ok(slf) => slf as _,
|
||||
Err(e) => e.restore_and_null(_py),
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ use crate::init_once;
|
|||
use crate::instance::PyNativeType;
|
||||
use crate::types::{PyAny, PyDict, PyModule, PyTuple};
|
||||
use crate::{ffi, GILPool, IntoPy, PyObject, Python};
|
||||
use crate::pyclass_init::IntoInitializer;
|
||||
use std::ptr;
|
||||
|
||||
/// Description of a python parameter; used for `parse_args()`.
|
||||
|
@ -179,3 +180,23 @@ impl<T: IntoPy<PyObject>> IntoPyResult<T> for PyResult<T> {
|
|||
self
|
||||
}
|
||||
}
|
||||
|
||||
use crate::pyclass::PyClass;
|
||||
|
||||
/// Variant of IntoPyResult for the specific case of #[new]. In the case of returning (Sub, Base)
|
||||
/// from #[new], IntoPyResult can't apply because (Sub, Base) doesn't implement IntoPy<PyObject>.
|
||||
pub trait IntoPyNewResult<T: PyClass, I: IntoInitializer<T>> {
|
||||
fn into_pynew_result(self) -> PyResult<I>;
|
||||
}
|
||||
|
||||
impl<T: PyClass, I: IntoInitializer<T>> IntoPyNewResult<T, I> for I {
|
||||
fn into_pynew_result(self) -> PyResult<I> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass, I: IntoInitializer<T>> IntoPyNewResult<T, I> for PyResult<I> {
|
||||
fn into_pynew_result(self) -> PyResult<I> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ impl<T> Py<T> {
|
|||
<T::BaseType as PyTypeInfo>::ConcreteLayout:
|
||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
let initializer = value.into_initializer()?;
|
||||
let initializer = value.into_initializer();
|
||||
let obj = unsafe { initializer.create_shell(py)? };
|
||||
let ob = unsafe { Py::from_owned_ptr(obj as _) };
|
||||
Ok(ob)
|
||||
|
|
|
@ -136,7 +136,7 @@ impl<T: PyClass> PyClassShell<T> {
|
|||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
unsafe {
|
||||
let initializer = value.into_initializer()?;
|
||||
let initializer = value.into_initializer();
|
||||
let self_ = initializer.create_shell(py)?;
|
||||
FromPyPointer::from_owned_ptr_or_err(py, self_ as _)
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ impl<T: PyClass> PyClassShell<T> {
|
|||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
unsafe {
|
||||
let initializer = value.into_initializer()?;
|
||||
let initializer = value.into_initializer();
|
||||
let self_ = initializer.create_shell(py)?;
|
||||
FromPyPointer::from_owned_ptr_or_err(py, self_ as _)
|
||||
}
|
||||
|
|
|
@ -109,30 +109,33 @@ impl<T: PyClass> PyObjectInit<T> for PyClassInitializer<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represets that we can convert the type to `PyClassInitializer`.
|
||||
///
|
||||
/// It is mainly used in our proc-macro code.
|
||||
pub trait IntoInitializer<T: PyClass> {
|
||||
fn into_initializer(self) -> PyResult<PyClassInitializer<T>>;
|
||||
}
|
||||
|
||||
impl<T> IntoInitializer<T> for T
|
||||
impl<T> From<T> for PyClassInitializer<T>
|
||||
where
|
||||
T: PyClass,
|
||||
T::BaseType: PyTypeInfo<Initializer = PyNativeTypeInitializer<T::BaseType>>,
|
||||
{
|
||||
fn into_initializer(self) -> PyResult<PyClassInitializer<T>> {
|
||||
Ok(PyClassInitializer::from_value(self))
|
||||
fn from(value: T) -> PyClassInitializer<T> {
|
||||
PyClassInitializer::from_value(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoInitializer<T> for PyResult<T>
|
||||
/// An extension of Into which extends the range of possible types from `#[pyclass]`'s `#[new]`.
|
||||
///
|
||||
/// In particular it permits for the return type of `#[new]` to be a (SubType, BaseType) pair
|
||||
/// which will also be initialized.
|
||||
///
|
||||
/// It is mainly used in our proc-macro code.
|
||||
pub trait IntoInitializer<T: PyClass> {
|
||||
fn into_initializer(self) -> PyClassInitializer<T>;
|
||||
}
|
||||
|
||||
impl<T, U> IntoInitializer<T> for U
|
||||
where
|
||||
T: PyClass,
|
||||
T::BaseType: PyTypeInfo<Initializer = PyNativeTypeInitializer<T::BaseType>>,
|
||||
U: Into<PyClassInitializer<T>>
|
||||
{
|
||||
fn into_initializer(self) -> PyResult<PyClassInitializer<T>> {
|
||||
self.map(PyClassInitializer::from_value)
|
||||
fn into_initializer(self) -> PyClassInitializer<T> {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,31 +145,8 @@ where
|
|||
B: PyClass + PyTypeInfo<Initializer = PyClassInitializer<B>>,
|
||||
B::BaseType: PyTypeInfo<Initializer = PyNativeTypeInitializer<B::BaseType>>,
|
||||
{
|
||||
fn into_initializer(self) -> PyResult<PyClassInitializer<S>> {
|
||||
let (sub, base) = self;
|
||||
Ok(PyClassInitializer::from_value(base).add_subclass(sub))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, B> IntoInitializer<S> for PyResult<(S, B)>
|
||||
where
|
||||
S: PyClass + PyTypeInfo<BaseType = B>,
|
||||
B: PyClass + PyTypeInfo<Initializer = PyClassInitializer<B>>,
|
||||
B::BaseType: PyTypeInfo<Initializer = PyNativeTypeInitializer<B::BaseType>>,
|
||||
{
|
||||
fn into_initializer(self) -> PyResult<PyClassInitializer<S>> {
|
||||
self.map(|(sub, base)| PyClassInitializer::from_value(base).add_subclass(sub))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> IntoInitializer<T> for PyClassInitializer<T> {
|
||||
fn into_initializer(self) -> PyResult<PyClassInitializer<T>> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PyClass> IntoInitializer<T> for PyResult<PyClassInitializer<T>> {
|
||||
fn into_initializer(self) -> PyResult<PyClassInitializer<T>> {
|
||||
self
|
||||
fn into_initializer(self) -> PyClassInitializer<S> {
|
||||
let (sub, base_init) = self;
|
||||
base_init.into_initializer().add_subclass(sub)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue