Merge pull request #889 from kngwyu/refactor-pymethods-inventory

Unify PyMethodsInventoryDispatch and PyMethodsProtocol
This commit is contained in:
Yuji Kanagawa 2020-05-02 21:48:29 +09:00 committed by GitHub
commit 17cf97df7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 29 additions and 36 deletions

View File

@ -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]

View File

@ -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>();

View File

@ -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),*])
}
}

View File

@ -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

View File

@ -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()

View File

@ -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() {