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)
|
- 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)
|
- 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)
|
- `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
|
### Added
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,7 @@ paste = { version = "1.0.6", optional = true }
|
||||||
unindent = { version = "0.1.4", optional = true }
|
unindent = { version = "0.1.4", optional = true }
|
||||||
|
|
||||||
# support crate for multiple-pymethods feature
|
# support crate for multiple-pymethods feature
|
||||||
# must stay at 0.1.x for Rust 1.41 compatibility
|
inventory = { version = "0.2.0", optional = true }
|
||||||
inventory = { version = "0.1.4", optional = true }
|
|
||||||
|
|
||||||
# crate integrations that can be added using the eponymous features
|
# crate integrations that can be added using the eponymous features
|
||||||
anyhow = { version = "1.0", optional = true }
|
anyhow = { version = "1.0", optional = true }
|
||||||
|
|
|
@ -594,7 +594,6 @@ impl<'a> PyClassImplsBuilder<'a> {
|
||||||
self.impl_pyclass(),
|
self.impl_pyclass(),
|
||||||
self.impl_extractext(),
|
self.impl_extractext(),
|
||||||
self.impl_into_py(),
|
self.impl_into_py(),
|
||||||
self.impl_methods_inventory(),
|
|
||||||
self.impl_pyclassimpl(),
|
self.impl_pyclassimpl(),
|
||||||
self.impl_freelist(),
|
self.impl_freelist(),
|
||||||
self.impl_gc(),
|
self.impl_gc(),
|
||||||
|
@ -667,48 +666,6 @@ impl<'a> PyClassImplsBuilder<'a> {
|
||||||
quote! {}
|
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 {
|
fn impl_pyclassimpl(&self) -> TokenStream {
|
||||||
let cls = self.cls;
|
let cls = self.cls;
|
||||||
let doc = self.doc.as_ref().map_or(quote! {"\0"}, |doc| quote! {#doc});
|
let doc = self.doc.as_ref().map_or(quote! {"\0"}, |doc| quote! {#doc});
|
||||||
|
@ -727,25 +684,36 @@ impl<'a> PyClassImplsBuilder<'a> {
|
||||||
quote! { ::pyo3::class::impl_::ThreadCheckerStub<#cls> }
|
quote! { ::pyo3::class::impl_::ThreadCheckerStub<#cls> }
|
||||||
};
|
};
|
||||||
|
|
||||||
let methods_protos = match self.methods_type {
|
let (for_each_py_method, methods_protos, inventory, inventory_class) = match self
|
||||||
PyClassMethodsType::Specialization => {
|
.methods_type
|
||||||
quote! { visitor(collector.methods_protocol_slots()); }
|
{
|
||||||
}
|
PyClassMethodsType::Specialization => (
|
||||||
|
quote! { visitor(collector.py_methods()); },
|
||||||
|
quote! { visitor(collector.methods_protocol_slots()); },
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
),
|
||||||
PyClassMethodsType::Inventory => {
|
PyClassMethodsType::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! {
|
quote! {
|
||||||
for inventory in ::pyo3::inventory::iter::<<Self as ::pyo3::class::impl_::HasMethodsInventory>::Methods>() {
|
for inventory in ::pyo3::inventory::iter::<<Self as ::pyo3::class::impl_::PyClassImpl>::Inventory>() {
|
||||||
visitor(::pyo3::class::impl_::PyMethodsInventory::slots(inventory));
|
visitor(::pyo3::class::impl_::PyClassInventory::methods(inventory));
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
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! {
|
||||||
|
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)),
|
||||||
|
)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
quote! {
|
quote! {
|
||||||
impl ::pyo3::class::impl_::PyClassImpl for #cls {
|
impl ::pyo3::class::impl_::PyClassImpl for #cls {
|
||||||
|
@ -757,6 +725,7 @@ impl<'a> PyClassImplsBuilder<'a> {
|
||||||
type Layout = ::pyo3::PyCell<Self>;
|
type Layout = ::pyo3::PyCell<Self>;
|
||||||
type BaseType = #base;
|
type BaseType = #base;
|
||||||
type ThreadChecker = #thread_checker;
|
type ThreadChecker = #thread_checker;
|
||||||
|
#inventory
|
||||||
|
|
||||||
fn for_each_method_def(visitor: &mut dyn ::std::ops::FnMut(&[::pyo3::class::PyMethodDefType])) {
|
fn for_each_method_def(visitor: &mut dyn ::std::ops::FnMut(&[::pyo3::class::PyMethodDefType])) {
|
||||||
use ::pyo3::class::impl_::*;
|
use ::pyo3::class::impl_::*;
|
||||||
|
@ -807,6 +776,8 @@ impl<'a> PyClassImplsBuilder<'a> {
|
||||||
collector.buffer_procs()
|
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 {
|
) -> TokenStream {
|
||||||
quote! {
|
quote! {
|
||||||
::pyo3::inventory::submit! {
|
::pyo3::inventory::submit! {
|
||||||
#![crate = ::pyo3] {
|
type Inventory = <#ty as ::pyo3::class::impl_::PyClassImpl>::Inventory;
|
||||||
type Inventory = <#ty as ::pyo3::class::impl_::HasMethodsInventory>::Methods;
|
Inventory::new(&[#(#methods),*], &[#(#proto_impls),*])
|
||||||
<Inventory as ::pyo3::class::impl_::PyMethodsInventory>::new(::std::vec![#(#methods),*], ::std::vec![#(#proto_impls),*])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,9 @@ pub trait PyClassImpl: Sized {
|
||||||
/// can be accessed by multiple threads by `threading` module.
|
/// can be accessed by multiple threads by `threading` module.
|
||||||
type ThreadChecker: PyClassThreadChecker<Self>;
|
type ThreadChecker: PyClassThreadChecker<Self>;
|
||||||
|
|
||||||
|
#[cfg(feature = "multiple-pymethods")]
|
||||||
|
type Inventory: PyClassInventory;
|
||||||
|
|
||||||
fn for_each_method_def(_visitor: &mut dyn FnMut(&[PyMethodDefType])) {}
|
fn for_each_method_def(_visitor: &mut dyn FnMut(&[PyMethodDefType])) {}
|
||||||
fn get_new() -> Option<ffi::newfunc> {
|
fn get_new() -> Option<ffi::newfunc> {
|
||||||
None
|
None
|
||||||
|
@ -607,11 +610,8 @@ macro_rules! methods_trait {
|
||||||
/// Method storage for `#[pyclass]`.
|
/// Method storage for `#[pyclass]`.
|
||||||
/// Allows arbitrary `#[pymethod]` blocks to submit their methods,
|
/// Allows arbitrary `#[pymethod]` blocks to submit their methods,
|
||||||
/// which are eventually collected by `#[pyclass]`.
|
/// which are eventually collected by `#[pyclass]`.
|
||||||
#[cfg(all(feature = "macros", feature = "multiple-pymethods"))]
|
#[cfg(feature = "multiple-pymethods")]
|
||||||
pub trait PyMethodsInventory: inventory::Collect {
|
pub trait PyClassInventory: inventory::Collect {
|
||||||
/// Create a new instance
|
|
||||||
fn new(methods: Vec<PyMethodDefType>, slots: Vec<ffi::PyType_Slot>) -> Self;
|
|
||||||
|
|
||||||
/// Returns the methods for a single `#[pymethods] impl` block
|
/// Returns the methods for a single `#[pymethods] impl` block
|
||||||
fn methods(&'static self) -> &'static [PyMethodDefType];
|
fn methods(&'static self) -> &'static [PyMethodDefType];
|
||||||
|
|
||||||
|
@ -619,13 +619,6 @@ pub trait PyMethodsInventory: inventory::Collect {
|
||||||
fn slots(&'static self) -> &'static [ffi::PyType_Slot];
|
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 from #[pyo3(get, set)] on struct fields.
|
||||||
methods_trait!(PyClassDescriptors, py_class_descriptors);
|
methods_trait!(PyClassDescriptors, py_class_descriptors);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue