Replace IntoInitializer<T> with Into<PyClassInitializer<T>>
This commit is contained in:
parent
b602b4bf6c
commit
f26e07cfd6
|
@ -189,12 +189,8 @@ created from Rust, but not from Python.
|
|||
For arguments, see the `Method arguments` section below.
|
||||
|
||||
### Return type
|
||||
Generally, `#[new]` method have to return `T: IntoInitializer<Self>` or
|
||||
`PyResult<T> where T: IntoInitializer<Self>`.
|
||||
|
||||
If your `T: PyClass` inherits just `PyAny`, you can return just `Self` or `PyResult<Self>`.
|
||||
But if it inherits other `U: PyClass`, you have to return tuple `(T, U)` or
|
||||
`PyClassInitializer<T>`.
|
||||
Generally, `#[new]` method have to return `T: Into<PyClassInitializer<Self>>` or
|
||||
`PyResult<T> where T: Into<PyClassInitializer<Self>>`.
|
||||
|
||||
For constructors that may fail, you should wrap the return type in a PyResult as well.
|
||||
Consult the table below to determine which type your constructor should return:
|
||||
|
@ -209,7 +205,7 @@ Consult the table below to determine which type your constructor should return:
|
|||
By default, `PyAny` is used as the base class. To override this default,
|
||||
use the `extends` parameter for `pyclass` with the full path to the base class.
|
||||
|
||||
For convinience, `(T, U)` implements `IntoInitializer<T>` where `U` is the
|
||||
For convinience, `(T, U)` implements `Into<PyClassInitializer<T>>` where `U` is the
|
||||
baseclass of `T`.
|
||||
But for more deeply nested inheritance, you have to return `PyClassInitializer<T>`
|
||||
explicitly.
|
||||
|
@ -261,8 +257,7 @@ struct SubSubClass {
|
|||
impl SubSubClass {
|
||||
#[new]
|
||||
fn new() -> PyClassInitializer<Self> {
|
||||
SubClass::new()
|
||||
.into_initializer()
|
||||
PyClassInitializer::from(SubClass::new())
|
||||
.add_subclass(SubSubClass{val3: 20})
|
||||
}
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ pub fn impl_wrap_new(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {
|
|||
|
||||
#body
|
||||
|
||||
match _result.and_then(|init| init.into_initializer().create_shell(_py)) {
|
||||
match _result.and_then(|init| pyo3::PyClassInitializer::from(init).create_shell(_py)) {
|
||||
Ok(slf) => slf as _,
|
||||
Err(e) => e.restore_and_null(_py),
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::exceptions::TypeError;
|
|||
use crate::init_once;
|
||||
use crate::instance::PyNativeType;
|
||||
use crate::pyclass::PyClass;
|
||||
use crate::pyclass_init::IntoInitializer;
|
||||
use crate::pyclass_init::PyClassInitializer;
|
||||
use crate::types::{PyAny, PyDict, PyModule, PyTuple};
|
||||
use crate::{ffi, GILPool, IntoPy, PyObject, Python};
|
||||
use std::ptr;
|
||||
|
@ -184,17 +184,17 @@ impl<T: IntoPy<PyObject>> IntoPyResult<T> for PyResult<T> {
|
|||
|
||||
/// 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>> {
|
||||
pub trait IntoPyNewResult<T: PyClass, I: Into<PyClassInitializer<T>>> {
|
||||
fn into_pynew_result(self) -> PyResult<I>;
|
||||
}
|
||||
|
||||
impl<T: PyClass, I: IntoInitializer<T>> IntoPyNewResult<T, I> for I {
|
||||
impl<T: PyClass, I: Into<PyClassInitializer<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> {
|
||||
impl<T: PyClass, I: Into<PyClassInitializer<T>>> IntoPyNewResult<T, I> for PyResult<I> {
|
||||
fn into_pynew_result(self) -> PyResult<I> {
|
||||
self
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::gil;
|
|||
use crate::object::PyObject;
|
||||
use crate::objectprotocol::ObjectProtocol;
|
||||
use crate::pyclass::{PyClass, PyClassShell};
|
||||
use crate::pyclass_init::IntoInitializer;
|
||||
use crate::pyclass_init::PyClassInitializer;
|
||||
use crate::type_object::{PyObjectLayout, PyTypeInfo};
|
||||
use crate::types::PyAny;
|
||||
use crate::{ffi, IntoPy};
|
||||
|
@ -36,13 +36,13 @@ unsafe impl<T> Sync for Py<T> {}
|
|||
|
||||
impl<T> Py<T> {
|
||||
/// Create new instance of T and move it under python management
|
||||
pub fn new(py: Python, value: impl IntoInitializer<T>) -> PyResult<Py<T>>
|
||||
pub fn new(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<Py<T>>
|
||||
where
|
||||
T: PyClass,
|
||||
<T::BaseType as PyTypeInfo>::ConcreteLayout:
|
||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
let initializer = value.into_initializer();
|
||||
let initializer = value.into();
|
||||
let obj = unsafe { initializer.create_shell(py)? };
|
||||
let ob = unsafe { Py::from_owned_ptr(obj as _) };
|
||||
Ok(ob)
|
||||
|
|
2
src/lib.rs
Executable file → Normal file
2
src/lib.rs
Executable file → Normal file
|
@ -128,7 +128,7 @@ pub use crate::instance::{AsPyRef, ManagedPyRef, Py, PyNativeType};
|
|||
pub use crate::object::PyObject;
|
||||
pub use crate::objectprotocol::ObjectProtocol;
|
||||
pub use crate::pyclass::{PyClass, PyClassShell};
|
||||
pub use crate::pyclass_init::{IntoInitializer, PyClassInitializer};
|
||||
pub use crate::pyclass_init::PyClassInitializer;
|
||||
pub use crate::python::{prepare_freethreaded_python, Python};
|
||||
pub use crate::type_object::{type_flags, PyTypeInfo};
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ pub use crate::objectprotocol::ObjectProtocol;
|
|||
pub use crate::python::Python;
|
||||
pub use crate::{FromPy, FromPyObject, IntoPy, IntoPyPointer, PyTryFrom, PyTryInto, ToPyObject};
|
||||
// This is only part of the prelude because we need it for the pymodule function
|
||||
pub use crate::pyclass_init::{IntoInitializer, PyClassInitializer};
|
||||
pub use crate::pyclass_init::PyClassInitializer;
|
||||
pub use crate::types::PyModule;
|
||||
pub use pyo3cls::pymodule;
|
||||
pub use pyo3cls::{pyclass, pyfunction, pymethods, pyproto};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! An experiment module which has all codes related only to #[pyclass]
|
||||
use crate::class::methods::{PyMethodDefType, PyMethodsProtocol};
|
||||
use crate::conversion::{AsPyPointer, FromPyPointer, ToPyObject};
|
||||
use crate::pyclass_init::IntoInitializer;
|
||||
use crate::pyclass_init::PyClassInitializer;
|
||||
use crate::pyclass_slots::{PyClassDict, PyClassWeakRef};
|
||||
use crate::type_object::{type_flags, PyObjectLayout, PyObjectSizedLayout, PyTypeObject};
|
||||
use crate::types::PyAny;
|
||||
|
@ -130,26 +130,26 @@ pub struct PyClassShell<T: PyClass> {
|
|||
|
||||
impl<T: PyClass> PyClassShell<T> {
|
||||
/// Make new `PyClassShell` on the Python heap and returns the reference of it.
|
||||
pub fn new_ref(py: Python, value: impl IntoInitializer<T>) -> PyResult<&Self>
|
||||
pub fn new_ref(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<&Self>
|
||||
where
|
||||
<T::BaseType as PyTypeInfo>::ConcreteLayout:
|
||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
unsafe {
|
||||
let initializer = value.into_initializer();
|
||||
let initializer = value.into();
|
||||
let self_ = initializer.create_shell(py)?;
|
||||
FromPyPointer::from_owned_ptr_or_err(py, self_ as _)
|
||||
}
|
||||
}
|
||||
|
||||
/// Make new `PyClassShell` on the Python heap and returns the mutable reference of it.
|
||||
pub fn new_mut(py: Python, value: impl IntoInitializer<T>) -> PyResult<&mut Self>
|
||||
pub fn new_mut(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<&mut Self>
|
||||
where
|
||||
<T::BaseType as PyTypeInfo>::ConcreteLayout:
|
||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
unsafe {
|
||||
let initializer = value.into_initializer();
|
||||
let initializer = value.into();
|
||||
let self_ = initializer.create_shell(py)?;
|
||||
FromPyPointer::from_owned_ptr_or_err(py, self_ as _)
|
||||
}
|
||||
|
|
|
@ -109,34 +109,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// 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,
|
||||
U: Into<PyClassInitializer<T>>,
|
||||
{
|
||||
fn into_initializer(self) -> PyClassInitializer<T> {
|
||||
self.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, B> IntoInitializer<S> for (S, B)
|
||||
impl<S, B> From<(S, B)> for PyClassInitializer<S>
|
||||
where
|
||||
S: PyClass + PyTypeInfo<BaseType = B>,
|
||||
B: PyClass + PyTypeInfo<Initializer = PyClassInitializer<B>>,
|
||||
B::BaseType: PyTypeInfo<Initializer = PyNativeTypeInitializer<B::BaseType>>,
|
||||
{
|
||||
fn into_initializer(self) -> PyClassInitializer<S> {
|
||||
let (sub, base_init) = self;
|
||||
base_init.into_initializer().add_subclass(sub)
|
||||
fn from(sub_and_base: (S, B)) -> PyClassInitializer<S> {
|
||||
let (sub, base) = sub_and_base;
|
||||
PyClassInitializer::from(base).add_subclass(sub)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue