Simplify IntoInitializer
This commit is contained in:
parent
18e565fab5
commit
60edeb889e
|
@ -257,10 +257,10 @@ struct SubSubClass {
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl SubSubClass {
|
impl SubSubClass {
|
||||||
#[new]
|
#[new]
|
||||||
fn new() -> impl IntoInitializer<Self> {
|
fn new() -> PyClassInitializer<Self> {
|
||||||
Ok(SubClass::new()
|
SubClass::new()
|
||||||
.into_initializer()?
|
.into_initializer()
|
||||||
.add_subclass(SubSubClass{val3: 20}))
|
.add_subclass(SubSubClass{val3: 20})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn method3(self_: &PyClassShell<Self>) -> PyResult<usize> {
|
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_(
|
let body = impl_arg_params_(
|
||||||
spec,
|
spec,
|
||||||
cb,
|
cb,
|
||||||
quote! { pyo3::pyclass_init::IntoInitializer::into_initializer },
|
quote! { pyo3::derive_utils::IntoPyNewResult::into_pynew_result },
|
||||||
);
|
);
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
|
@ -174,7 +174,7 @@ pub fn impl_wrap_new(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
|
||||||
|
|
||||||
#body
|
#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 _,
|
Ok(slf) => slf as _,
|
||||||
Err(e) => e.restore_and_null(_py),
|
Err(e) => e.restore_and_null(_py),
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::init_once;
|
||||||
use crate::instance::PyNativeType;
|
use crate::instance::PyNativeType;
|
||||||
use crate::types::{PyAny, PyDict, PyModule, PyTuple};
|
use crate::types::{PyAny, PyDict, PyModule, PyTuple};
|
||||||
use crate::{ffi, GILPool, IntoPy, PyObject, Python};
|
use crate::{ffi, GILPool, IntoPy, PyObject, Python};
|
||||||
|
use crate::pyclass_init::IntoInitializer;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
/// Description of a python parameter; used for `parse_args()`.
|
/// Description of a python parameter; used for `parse_args()`.
|
||||||
|
@ -179,3 +180,23 @@ impl<T: IntoPy<PyObject>> IntoPyResult<T> for PyResult<T> {
|
||||||
self
|
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:
|
<T::BaseType as PyTypeInfo>::ConcreteLayout:
|
||||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||||
{
|
{
|
||||||
let initializer = value.into_initializer()?;
|
let initializer = value.into_initializer();
|
||||||
let obj = unsafe { initializer.create_shell(py)? };
|
let obj = unsafe { initializer.create_shell(py)? };
|
||||||
let ob = unsafe { Py::from_owned_ptr(obj as _) };
|
let ob = unsafe { Py::from_owned_ptr(obj as _) };
|
||||||
Ok(ob)
|
Ok(ob)
|
||||||
|
|
|
@ -136,7 +136,7 @@ impl<T: PyClass> PyClassShell<T> {
|
||||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
let initializer = value.into_initializer()?;
|
let initializer = value.into_initializer();
|
||||||
let self_ = initializer.create_shell(py)?;
|
let self_ = initializer.create_shell(py)?;
|
||||||
FromPyPointer::from_owned_ptr_or_err(py, self_ as _)
|
FromPyPointer::from_owned_ptr_or_err(py, self_ as _)
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ impl<T: PyClass> PyClassShell<T> {
|
||||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
let initializer = value.into_initializer()?;
|
let initializer = value.into_initializer();
|
||||||
let self_ = initializer.create_shell(py)?;
|
let self_ = initializer.create_shell(py)?;
|
||||||
FromPyPointer::from_owned_ptr_or_err(py, self_ as _)
|
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`.
|
impl<T> From<T> for PyClassInitializer<T>
|
||||||
///
|
|
||||||
/// 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
|
|
||||||
where
|
where
|
||||||
T: PyClass,
|
T: PyClass,
|
||||||
T::BaseType: PyTypeInfo<Initializer = PyNativeTypeInitializer<T::BaseType>>,
|
T::BaseType: PyTypeInfo<Initializer = PyNativeTypeInitializer<T::BaseType>>,
|
||||||
{
|
{
|
||||||
fn into_initializer(self) -> PyResult<PyClassInitializer<T>> {
|
fn from(value: T) -> PyClassInitializer<T> {
|
||||||
Ok(PyClassInitializer::from_value(self))
|
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
|
where
|
||||||
T: PyClass,
|
T: PyClass,
|
||||||
T::BaseType: PyTypeInfo<Initializer = PyNativeTypeInitializer<T::BaseType>>,
|
U: Into<PyClassInitializer<T>>
|
||||||
{
|
{
|
||||||
fn into_initializer(self) -> PyResult<PyClassInitializer<T>> {
|
fn into_initializer(self) -> PyClassInitializer<T> {
|
||||||
self.map(PyClassInitializer::from_value)
|
self.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,31 +145,8 @@ where
|
||||||
B: PyClass + PyTypeInfo<Initializer = PyClassInitializer<B>>,
|
B: PyClass + PyTypeInfo<Initializer = PyClassInitializer<B>>,
|
||||||
B::BaseType: PyTypeInfo<Initializer = PyNativeTypeInitializer<B::BaseType>>,
|
B::BaseType: PyTypeInfo<Initializer = PyNativeTypeInitializer<B::BaseType>>,
|
||||||
{
|
{
|
||||||
fn into_initializer(self) -> PyResult<PyClassInitializer<S>> {
|
fn into_initializer(self) -> PyClassInitializer<S> {
|
||||||
let (sub, base) = self;
|
let (sub, base_init) = self;
|
||||||
Ok(PyClassInitializer::from_value(base).add_subclass(sub))
|
base_init.into_initializer().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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue