From 816c50a649220677da4bf5ac534ebfe8bbad703f Mon Sep 17 00:00:00 2001 From: kngwyu Date: Sat, 2 May 2020 17:48:25 +0900 Subject: [PATCH 1/2] Unify PyMethodsInventoryDispatch and PyMethodsProtocol --- guide/src/class.md | 10 +++++----- pyo3-derive-backend/src/pyclass.rs | 8 ++++---- pyo3-derive-backend/src/pyimpl.rs | 2 +- src/class/methods.rs | 29 ++++++++--------------------- src/pyclass.rs | 8 ++++---- 5 files changed, 22 insertions(+), 35 deletions(-) diff --git a/guide/src/class.md b/guide/src/class.md index 5362fd687e8..990f10e11e2 100644 --- a/guide/src/class.md +++ b/guide/src/class.md @@ -63,11 +63,11 @@ impl pyo3::IntoPy 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::(); diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs index 5c92a75beac..32d5381a91c 100644 --- a/pyo3-derive-backend/src/pyclass.rs +++ b/pyo3-derive-backend/src/pyclass.rs @@ -213,7 +213,7 @@ fn parse_descriptors(item: &mut syn::Field) -> syn::Result> { 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; ::new(&[#(#py_methods),*]) } } diff --git a/pyo3-derive-backend/src/pyimpl.rs b/pyo3-derive-backend/src/pyimpl.rs index e62df4f338a..8c71188cdc8 100644 --- a/pyo3-derive-backend/src/pyimpl.rs +++ b/pyo3-derive-backend/src/pyimpl.rs @@ -33,7 +33,7 @@ pub fn impl_methods(ty: &syn::Type, impls: &mut Vec) -> 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; ::new(&[#( #(#cfg_attributes)* #methods diff --git a/src/class/methods.rs b/src/class/methods.rs index b31e9163b60..bdc6c5c99ab 100644 --- a/src/class/methods.rs +++ b/src/class/methods.rs @@ -115,15 +115,7 @@ 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 +#[doc(hidden)] // Only to be used through the proc macros /// Allows arbitrary pymethod blocks to submit their methods, which are eventually collected by pyclass pub trait PyMethodsInventory: inventory::Collect { /// Create a new instance @@ -133,20 +125,15 @@ 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>; -} +#[doc(hidden)] // Only to be used through the proc macros +/// For pyclass derived structs, this trait collects method from all impl blocks using inventory. +pub trait PyMethodsImpl { + /// Normal methods, mainly defined by `#[pymethod]`. + type Methods: PyMethodsInventory; -impl PyMethodsProtocol for T -where - T: PyMethodsInventoryDispatch, -{ + /// Returns all methods that are defined for a class fn py_methods() -> Vec<&'static PyMethodDefType> { - inventory::iter:: + inventory::iter:: .into_iter() .flat_map(PyMethodsInventory::get_methods) .collect() diff --git a/src/pyclass.rs b/src/pyclass.rs index 4f0f9ec194e..829cf3dbb47 100644 --- a/src/pyclass.rs +++ b/src/pyclass.rs @@ -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> + Sized + PyClassAlloc + PyMethodsProtocol + PyTypeInfo> + Sized + PyClassAlloc + PyMethodsImpl { /// Specify this class has `#[pyclass(dict)]` or not. type Dict: PyClassDict; @@ -215,7 +215,7 @@ fn py_class_flags(type_object: &mut ffi::PyTypeObject) { } } -fn py_class_method_defs() -> ( +fn py_class_method_defs() -> ( Option, Option, Vec, @@ -274,7 +274,7 @@ fn py_class_async_methods(defs: &mut Vec) { } } -fn py_class_properties() -> Vec { +fn py_class_properties() -> Vec { let mut defs = std::collections::HashMap::new(); for def in T::py_methods() { From b6befcfb93e05f823e6c3f743f575c411969c1dd Mon Sep 17 00:00:00 2001 From: kngwyu Date: Sat, 2 May 2020 18:33:38 +0900 Subject: [PATCH 2/2] CHANGELOG and better docs for PyMethodsImpl --- CHANGELOG.md | 3 +++ src/class/methods.rs | 13 ++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2184bf24e03..20ebe0100d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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`. [#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] diff --git a/src/class/methods.rs b/src/class/methods.rs index bdc6c5c99ab..1240c97296c 100644 --- a/src/class/methods.rs +++ b/src/class/methods.rs @@ -115,8 +115,10 @@ impl PySetterDef { } } -#[doc(hidden)] // Only to be used through the proc macros -/// 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; @@ -125,13 +127,14 @@ pub trait PyMethodsInventory: inventory::Collect { fn get_methods(&self) -> &'static [PyMethodDefType]; } -#[doc(hidden)] // Only to be used through the proc macros +/// 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]`. + /// Normal methods. Mainly defined by `#[pymethod]`. type Methods: PyMethodsInventory; - /// Returns all methods that are defined for a class + /// Returns all methods that are defined for a class. fn py_methods() -> Vec<&'static PyMethodDefType> { inventory::iter:: .into_iter()