Merge pull request #889 from kngwyu/refactor-pymethods-inventory
Unify PyMethodsInventoryDispatch and PyMethodsProtocol
This commit is contained in:
commit
17cf97df7d
|
@ -24,6 +24,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
* `&'static Py~` being allowed as arguments. [#869](https://github.com/PyO3/pyo3/pull/869)
|
||||
* `#[pyo3(get)]` for `Py<T>`. [#880](https://github.com/PyO3/pyo3/pull/880)
|
||||
|
||||
### Removed
|
||||
* `PyMethodsProtocol` is now renamed to `PyMethodsImpl` and hidden. [#889](https://github.com/PyO3/pyo3/pull/889)
|
||||
|
||||
|
||||
## [0.9.2]
|
||||
|
||||
|
|
|
@ -63,11 +63,11 @@ impl pyo3::IntoPy<PyObject> for MyClass {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct MyClassGeneratedPyo3Inventory {
|
||||
pub struct Pyo3MethodsInventoryForMyClass {
|
||||
methods: &'static [pyo3::class::PyMethodDefType],
|
||||
}
|
||||
|
||||
impl pyo3::class::methods::PyMethodsInventory for MyClassGeneratedPyo3Inventory {
|
||||
impl pyo3::class::methods::PyMethodsInventory for Pyo3MethodsInventoryForMyClass {
|
||||
fn new(methods: &'static [pyo3::class::PyMethodDefType]) -> Self {
|
||||
Self { methods }
|
||||
}
|
||||
|
@ -77,11 +77,11 @@ impl pyo3::class::methods::PyMethodsInventory for MyClassGeneratedPyo3Inventory
|
|||
}
|
||||
}
|
||||
|
||||
impl pyo3::class::methods::PyMethodsInventoryDispatch for MyClass {
|
||||
type InventoryType = MyClassGeneratedPyo3Inventory;
|
||||
impl pyo3::class::methods::PyMethodsImpl for MyClass {
|
||||
type Methods = Pyo3MethodsInventoryForMyClass;
|
||||
}
|
||||
|
||||
pyo3::inventory::collect!(MyClassGeneratedPyo3Inventory);
|
||||
pyo3::inventory::collect!(Pyo3MethodsInventoryForMyClass);
|
||||
# let gil = Python::acquire_gil();
|
||||
# let py = gil.python();
|
||||
# let cls = py.get_type::<MyClass>();
|
||||
|
|
|
@ -213,7 +213,7 @@ fn parse_descriptors(item: &mut syn::Field) -> syn::Result<Vec<FnType>> {
|
|||
fn impl_inventory(cls: &syn::Ident) -> TokenStream {
|
||||
// Try to build a unique type that gives a hint about it's function when
|
||||
// it comes up in error messages
|
||||
let name = cls.to_string() + "GeneratedPyo3Inventory";
|
||||
let name = format!("Pyo3MethodsInventoryFor{}", cls);
|
||||
let inventory_cls = syn::Ident::new(&name, Span::call_site());
|
||||
|
||||
quote! {
|
||||
|
@ -234,8 +234,8 @@ fn impl_inventory(cls: &syn::Ident) -> TokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
impl pyo3::class::methods::PyMethodsInventoryDispatch for #cls {
|
||||
type InventoryType = #inventory_cls;
|
||||
impl pyo3::class::methods::PyMethodsImpl for #cls {
|
||||
type Methods = #inventory_cls;
|
||||
}
|
||||
|
||||
pyo3::inventory::collect!(#inventory_cls);
|
||||
|
@ -461,7 +461,7 @@ fn impl_descriptors(
|
|||
Ok(quote! {
|
||||
pyo3::inventory::submit! {
|
||||
#![crate = pyo3] {
|
||||
type ClsInventory = <#cls as pyo3::class::methods::PyMethodsInventoryDispatch>::InventoryType;
|
||||
type ClsInventory = <#cls as pyo3::class::methods::PyMethodsImpl>::Methods;
|
||||
<ClsInventory as pyo3::class::methods::PyMethodsInventory>::new(&[#(#py_methods),*])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ pub fn impl_methods(ty: &syn::Type, impls: &mut Vec<syn::ImplItem>) -> syn::Resu
|
|||
Ok(quote! {
|
||||
pyo3::inventory::submit! {
|
||||
#![crate = pyo3] {
|
||||
type TyInventory = <#ty as pyo3::class::methods::PyMethodsInventoryDispatch>::InventoryType;
|
||||
type TyInventory = <#ty as pyo3::class::methods::PyMethodsImpl>::Methods;
|
||||
<TyInventory as pyo3::class::methods::PyMethodsInventory>::new(&[#(
|
||||
#(#cfg_attributes)*
|
||||
#methods
|
||||
|
|
|
@ -115,16 +115,10 @@ impl PySetterDef {
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)] // Only to be used through the proc macros, use PyMethodsProtocol in custom code
|
||||
/// This trait is implemented for all pyclass so to implement the [PyMethodsProtocol]
|
||||
/// through inventory
|
||||
pub trait PyMethodsInventoryDispatch {
|
||||
/// This allows us to get the inventory type when only the pyclass is in scope
|
||||
type InventoryType: PyMethodsInventory;
|
||||
}
|
||||
|
||||
#[doc(hidden)] // Only to be used through the proc macros, use PyMethodsProtocol in custom code
|
||||
/// Allows arbitrary pymethod blocks to submit their methods, which are eventually collected by pyclass
|
||||
/// Implementation detail. Only to be used through the proc macros.
|
||||
/// Allows arbitrary pymethod blocks to submit their methods, which are eventually
|
||||
/// collected by pyclass.
|
||||
#[doc(hidden)]
|
||||
pub trait PyMethodsInventory: inventory::Collect {
|
||||
/// Create a new instance
|
||||
fn new(methods: &'static [PyMethodDefType]) -> Self;
|
||||
|
@ -133,20 +127,16 @@ pub trait PyMethodsInventory: inventory::Collect {
|
|||
fn get_methods(&self) -> &'static [PyMethodDefType];
|
||||
}
|
||||
|
||||
/// The implementation of this trait defines which methods a Python type has.
|
||||
///
|
||||
/// For pyclass derived structs this is implemented by collecting all impl blocks through inventory
|
||||
pub trait PyMethodsProtocol {
|
||||
/// Returns all methods that are defined for a class
|
||||
fn py_methods() -> Vec<&'static PyMethodDefType>;
|
||||
}
|
||||
/// Implementation detail. Only to be used through the proc macros.
|
||||
/// For pyclass derived structs, this trait collects method from all impl blocks using inventory.
|
||||
#[doc(hidden)]
|
||||
pub trait PyMethodsImpl {
|
||||
/// Normal methods. Mainly defined by `#[pymethod]`.
|
||||
type Methods: PyMethodsInventory;
|
||||
|
||||
impl<T> PyMethodsProtocol for T
|
||||
where
|
||||
T: PyMethodsInventoryDispatch,
|
||||
{
|
||||
/// Returns all methods that are defined for a class.
|
||||
fn py_methods() -> Vec<&'static PyMethodDefType> {
|
||||
inventory::iter::<T::InventoryType>
|
||||
inventory::iter::<Self::Methods>
|
||||
.into_iter()
|
||||
.flat_map(PyMethodsInventory::get_methods)
|
||||
.collect()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//! `PyClass` trait
|
||||
use crate::class::methods::{PyMethodDefType, PyMethodsProtocol};
|
||||
use crate::class::methods::{PyMethodDefType, PyMethodsImpl};
|
||||
use crate::pyclass_slots::{PyClassDict, PyClassWeakRef};
|
||||
use crate::type_object::{type_flags, PyLayout};
|
||||
use crate::{class, ffi, PyCell, PyErr, PyNativeType, PyResult, PyTypeInfo, Python};
|
||||
|
@ -71,7 +71,7 @@ pub unsafe fn tp_free_fallback(obj: *mut ffi::PyObject) {
|
|||
/// The `#[pyclass]` attribute automatically implements this trait for your Rust struct,
|
||||
/// so you don't have to use this trait directly.
|
||||
pub trait PyClass:
|
||||
PyTypeInfo<Layout = PyCell<Self>> + Sized + PyClassAlloc + PyMethodsProtocol
|
||||
PyTypeInfo<Layout = PyCell<Self>> + Sized + PyClassAlloc + PyMethodsImpl
|
||||
{
|
||||
/// Specify this class has `#[pyclass(dict)]` or not.
|
||||
type Dict: PyClassDict;
|
||||
|
@ -215,7 +215,7 @@ fn py_class_flags<T: PyTypeInfo>(type_object: &mut ffi::PyTypeObject) {
|
|||
}
|
||||
}
|
||||
|
||||
fn py_class_method_defs<T: PyMethodsProtocol>() -> (
|
||||
fn py_class_method_defs<T: PyMethodsImpl>() -> (
|
||||
Option<ffi::newfunc>,
|
||||
Option<ffi::PyCFunctionWithKeywords>,
|
||||
Vec<ffi::PyMethodDef>,
|
||||
|
@ -274,7 +274,7 @@ fn py_class_async_methods<T>(defs: &mut Vec<ffi::PyMethodDef>) {
|
|||
}
|
||||
}
|
||||
|
||||
fn py_class_properties<T: PyMethodsProtocol>() -> Vec<ffi::PyGetSetDef> {
|
||||
fn py_class_properties<T: PyMethodsImpl>() -> Vec<ffi::PyGetSetDef> {
|
||||
let mut defs = std::collections::HashMap::new();
|
||||
|
||||
for def in T::py_methods() {
|
||||
|
|
Loading…
Reference in New Issue