inventory: update to 0.2
This commit is contained in:
parent
af27fd373b
commit
f17e0d35cd
|
@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Update `paste` optional dependency to 1.0. [#2004](https://github.com/PyO3/pyo3/pull/2004)
|
||||
- Drop support for Python 3.6, remove `abi3-py36` feature. [#2006](https://github.com/PyO3/pyo3/pull/2006)
|
||||
- `pyo3-build-config` no longer enables the `resolve-config` feature by default. [#2008](https://github.com/PyO3/pyo3/pull/2008)
|
||||
- Update `inventory` optional dependency to 0.2. [#2019](https://github.com/PyO3/pyo3/pull/2019)
|
||||
|
||||
### Added
|
||||
|
||||
|
|
|
@ -26,8 +26,7 @@ paste = { version = "1.0.6", optional = true }
|
|||
unindent = { version = "0.1.4", optional = true }
|
||||
|
||||
# support crate for multiple-pymethods feature
|
||||
# must stay at 0.1.x for Rust 1.41 compatibility
|
||||
inventory = { version = "0.1.4", optional = true }
|
||||
inventory = { version = "0.2.0", optional = true }
|
||||
|
||||
# crate integrations that can be added using the eponymous features
|
||||
anyhow = { version = "1.0", optional = true }
|
||||
|
|
|
@ -594,7 +594,6 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
self.impl_pyclass(),
|
||||
self.impl_extractext(),
|
||||
self.impl_into_py(),
|
||||
self.impl_methods_inventory(),
|
||||
self.impl_pyclassimpl(),
|
||||
self.impl_freelist(),
|
||||
self.impl_gc(),
|
||||
|
@ -667,48 +666,6 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
quote! {}
|
||||
}
|
||||
}
|
||||
|
||||
/// To allow multiple #[pymethods] block, we define inventory types.
|
||||
fn impl_methods_inventory(&self) -> TokenStream {
|
||||
let cls = self.cls;
|
||||
let methods_type = self.methods_type;
|
||||
match methods_type {
|
||||
PyClassMethodsType::Specialization => quote! {},
|
||||
PyClassMethodsType::Inventory => {
|
||||
// Try to build a unique type for better error messages
|
||||
let name = format!("Pyo3MethodsInventoryFor{}", cls.unraw());
|
||||
let inventory_cls = syn::Ident::new(&name, Span::call_site());
|
||||
|
||||
quote! {
|
||||
#[doc(hidden)]
|
||||
pub struct #inventory_cls {
|
||||
methods: ::std::vec::Vec<::pyo3::class::PyMethodDefType>,
|
||||
slots: ::std::vec::Vec<::pyo3::ffi::PyType_Slot>,
|
||||
}
|
||||
impl ::pyo3::class::impl_::PyMethodsInventory for #inventory_cls {
|
||||
fn new(
|
||||
methods: ::std::vec::Vec<::pyo3::class::PyMethodDefType>,
|
||||
slots: ::std::vec::Vec<::pyo3::ffi::PyType_Slot>,
|
||||
) -> Self {
|
||||
Self { methods, slots }
|
||||
}
|
||||
fn methods(&'static self) -> &'static [::pyo3::class::PyMethodDefType] {
|
||||
&self.methods
|
||||
}
|
||||
fn slots(&'static self) -> &'static [::pyo3::ffi::PyType_Slot] {
|
||||
&self.slots
|
||||
}
|
||||
}
|
||||
|
||||
impl ::pyo3::class::impl_::HasMethodsInventory for #cls {
|
||||
type Methods = #inventory_cls;
|
||||
}
|
||||
|
||||
::pyo3::inventory::collect!(#inventory_cls);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn impl_pyclassimpl(&self) -> TokenStream {
|
||||
let cls = self.cls;
|
||||
let doc = self.doc.as_ref().map_or(quote! {"\0"}, |doc| quote! {#doc});
|
||||
|
@ -727,26 +684,37 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
quote! { ::pyo3::class::impl_::ThreadCheckerStub<#cls> }
|
||||
};
|
||||
|
||||
let methods_protos = match self.methods_type {
|
||||
PyClassMethodsType::Specialization => {
|
||||
quote! { visitor(collector.methods_protocol_slots()); }
|
||||
}
|
||||
let (for_each_py_method, methods_protos, inventory, inventory_class) = match self
|
||||
.methods_type
|
||||
{
|
||||
PyClassMethodsType::Specialization => (
|
||||
quote! { visitor(collector.py_methods()); },
|
||||
quote! { visitor(collector.methods_protocol_slots()); },
|
||||
None,
|
||||
None,
|
||||
),
|
||||
PyClassMethodsType::Inventory => {
|
||||
quote! {
|
||||
for inventory in ::pyo3::inventory::iter::<<Self as ::pyo3::class::impl_::HasMethodsInventory>::Methods>() {
|
||||
visitor(::pyo3::class::impl_::PyMethodsInventory::slots(inventory));
|
||||
}
|
||||
}
|
||||
// To allow multiple #[pymethods] block, we define inventory types.
|
||||
let inventory_class_name = syn::Ident::new(
|
||||
&format!("Pyo3MethodsInventoryFor{}", cls.unraw()),
|
||||
Span::call_site(),
|
||||
);
|
||||
(
|
||||
quote! {
|
||||
for inventory in ::pyo3::inventory::iter::<<Self as ::pyo3::class::impl_::PyClassImpl>::Inventory>() {
|
||||
visitor(::pyo3::class::impl_::PyClassInventory::methods(inventory));
|
||||
}
|
||||
},
|
||||
quote! {
|
||||
for inventory in ::pyo3::inventory::iter::<<Self as ::pyo3::class::impl_::PyClassImpl>::Inventory>() {
|
||||
visitor(::pyo3::class::impl_::PyClassInventory::slots(inventory));
|
||||
}
|
||||
},
|
||||
Some(quote! { type Inventory = #inventory_class_name; }),
|
||||
Some(define_inventory_class(&inventory_class_name)),
|
||||
)
|
||||
}
|
||||
};
|
||||
let for_each_py_method = match self.methods_type {
|
||||
PyClassMethodsType::Specialization => quote! { visitor(collector.py_methods()); },
|
||||
PyClassMethodsType::Inventory => quote! {
|
||||
for inventory in ::pyo3::inventory::iter::<<Self as ::pyo3::class::impl_::HasMethodsInventory>::Methods>() {
|
||||
visitor(::pyo3::class::impl_::PyMethodsInventory::methods(inventory));
|
||||
}
|
||||
},
|
||||
};
|
||||
quote! {
|
||||
impl ::pyo3::class::impl_::PyClassImpl for #cls {
|
||||
const DOC: &'static str = #doc;
|
||||
|
@ -757,6 +725,7 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
type Layout = ::pyo3::PyCell<Self>;
|
||||
type BaseType = #base;
|
||||
type ThreadChecker = #thread_checker;
|
||||
#inventory
|
||||
|
||||
fn for_each_method_def(visitor: &mut dyn ::std::ops::FnMut(&[::pyo3::class::PyMethodDefType])) {
|
||||
use ::pyo3::class::impl_::*;
|
||||
|
@ -807,6 +776,8 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
collector.buffer_procs()
|
||||
}
|
||||
}
|
||||
|
||||
#inventory_class
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -865,3 +836,36 @@ impl<'a> PyClassImplsBuilder<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn define_inventory_class(inventory_class_name: &syn::Ident) -> TokenStream {
|
||||
quote! {
|
||||
#[doc(hidden)]
|
||||
pub struct #inventory_class_name {
|
||||
methods: &'static [::pyo3::class::PyMethodDefType],
|
||||
slots: &'static [::pyo3::ffi::PyType_Slot],
|
||||
}
|
||||
impl #inventory_class_name {
|
||||
const fn new(
|
||||
methods: &'static [::pyo3::class::PyMethodDefType],
|
||||
slots: &'static [::pyo3::ffi::PyType_Slot],
|
||||
) -> Self {
|
||||
Self { methods, slots }
|
||||
}
|
||||
}
|
||||
|
||||
impl ::pyo3::class::impl_::PyClassInventory for #inventory_class_name {
|
||||
fn methods(&'static self) -> &'static [::pyo3::class::PyMethodDefType] {
|
||||
self.methods
|
||||
}
|
||||
fn slots(&'static self) -> &'static [::pyo3::ffi::PyType_Slot] {
|
||||
self.slots
|
||||
}
|
||||
}
|
||||
|
||||
// inventory requires these bounds
|
||||
unsafe impl ::std::marker::Send for #inventory_class_name {}
|
||||
unsafe impl ::std::marker::Sync for #inventory_class_name {}
|
||||
|
||||
::pyo3::inventory::collect!(#inventory_class_name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -211,10 +211,8 @@ fn submit_methods_inventory(
|
|||
) -> TokenStream {
|
||||
quote! {
|
||||
::pyo3::inventory::submit! {
|
||||
#![crate = ::pyo3] {
|
||||
type Inventory = <#ty as ::pyo3::class::impl_::HasMethodsInventory>::Methods;
|
||||
<Inventory as ::pyo3::class::impl_::PyMethodsInventory>::new(::std::vec![#(#methods),*], ::std::vec![#(#proto_impls),*])
|
||||
}
|
||||
type Inventory = <#ty as ::pyo3::class::impl_::PyClassImpl>::Inventory;
|
||||
Inventory::new(&[#(#methods),*], &[#(#proto_impls),*])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,9 @@ pub trait PyClassImpl: Sized {
|
|||
/// can be accessed by multiple threads by `threading` module.
|
||||
type ThreadChecker: PyClassThreadChecker<Self>;
|
||||
|
||||
#[cfg(feature = "multiple-pymethods")]
|
||||
type Inventory: PyClassInventory;
|
||||
|
||||
fn for_each_method_def(_visitor: &mut dyn FnMut(&[PyMethodDefType])) {}
|
||||
fn get_new() -> Option<ffi::newfunc> {
|
||||
None
|
||||
|
@ -607,11 +610,8 @@ macro_rules! methods_trait {
|
|||
/// Method storage for `#[pyclass]`.
|
||||
/// Allows arbitrary `#[pymethod]` blocks to submit their methods,
|
||||
/// which are eventually collected by `#[pyclass]`.
|
||||
#[cfg(all(feature = "macros", feature = "multiple-pymethods"))]
|
||||
pub trait PyMethodsInventory: inventory::Collect {
|
||||
/// Create a new instance
|
||||
fn new(methods: Vec<PyMethodDefType>, slots: Vec<ffi::PyType_Slot>) -> Self;
|
||||
|
||||
#[cfg(feature = "multiple-pymethods")]
|
||||
pub trait PyClassInventory: inventory::Collect {
|
||||
/// Returns the methods for a single `#[pymethods] impl` block
|
||||
fn methods(&'static self) -> &'static [PyMethodDefType];
|
||||
|
||||
|
@ -619,13 +619,6 @@ pub trait PyMethodsInventory: inventory::Collect {
|
|||
fn slots(&'static self) -> &'static [ffi::PyType_Slot];
|
||||
}
|
||||
|
||||
/// Implemented for `#[pyclass]` in our proc macro code.
|
||||
/// Indicates that the pyclass has its own method storage.
|
||||
#[cfg(all(feature = "macros", feature = "multiple-pymethods"))]
|
||||
pub trait HasMethodsInventory {
|
||||
type Methods: PyMethodsInventory;
|
||||
}
|
||||
|
||||
// Methods from #[pyo3(get, set)] on struct fields.
|
||||
methods_trait!(PyClassDescriptors, py_class_descriptors);
|
||||
|
||||
|
|
Loading…
Reference in New Issue