Skip to content

Commit a0d3ab0

Browse files
authored
Merge pull request #2019 from davidhewitt/inventory-0.2.0
inventory: update to 0.2
2 parents c4147cd + f17e0d3 commit a0d3ab0

File tree

5 files changed

+73
-78
lines changed

5 files changed

+73
-78
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515
- Update `paste` optional dependency to 1.0. [#2004](https://github.com/PyO3/pyo3/pull/2004)
1616
- Drop support for Python 3.6, remove `abi3-py36` feature. [#2006](https://github.com/PyO3/pyo3/pull/2006)
1717
- `pyo3-build-config` no longer enables the `resolve-config` feature by default. [#2008](https://github.com/PyO3/pyo3/pull/2008)
18+
- Update `inventory` optional dependency to 0.2. [#2019](https://github.com/PyO3/pyo3/pull/2019)
1819

1920
### Added
2021

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ paste = { version = "1.0.6", optional = true }
2626
unindent = { version = "0.1.4", optional = true }
2727

2828
# support crate for multiple-pymethods feature
29-
# must stay at 0.1.x for Rust 1.41 compatibility
30-
inventory = { version = "0.1.4", optional = true }
29+
inventory = { version = "0.2.0", optional = true }
3130

3231
# crate integrations that can be added using the eponymous features
3332
anyhow = { version = "1.0", optional = true }

pyo3-macros-backend/src/pyclass.rs

Lines changed: 64 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,6 @@ impl<'a> PyClassImplsBuilder<'a> {
594594
self.impl_pyclass(),
595595
self.impl_extractext(),
596596
self.impl_into_py(),
597-
self.impl_methods_inventory(),
598597
self.impl_pyclassimpl(),
599598
self.impl_freelist(),
600599
self.impl_gc(),
@@ -667,48 +666,6 @@ impl<'a> PyClassImplsBuilder<'a> {
667666
quote! {}
668667
}
669668
}
670-
671-
/// To allow multiple #[pymethods] block, we define inventory types.
672-
fn impl_methods_inventory(&self) -> TokenStream {
673-
let cls = self.cls;
674-
let methods_type = self.methods_type;
675-
match methods_type {
676-
PyClassMethodsType::Specialization => quote! {},
677-
PyClassMethodsType::Inventory => {
678-
// Try to build a unique type for better error messages
679-
let name = format!("Pyo3MethodsInventoryFor{}", cls.unraw());
680-
let inventory_cls = syn::Ident::new(&name, Span::call_site());
681-
682-
quote! {
683-
#[doc(hidden)]
684-
pub struct #inventory_cls {
685-
methods: ::std::vec::Vec<::pyo3::class::PyMethodDefType>,
686-
slots: ::std::vec::Vec<::pyo3::ffi::PyType_Slot>,
687-
}
688-
impl ::pyo3::class::impl_::PyMethodsInventory for #inventory_cls {
689-
fn new(
690-
methods: ::std::vec::Vec<::pyo3::class::PyMethodDefType>,
691-
slots: ::std::vec::Vec<::pyo3::ffi::PyType_Slot>,
692-
) -> Self {
693-
Self { methods, slots }
694-
}
695-
fn methods(&'static self) -> &'static [::pyo3::class::PyMethodDefType] {
696-
&self.methods
697-
}
698-
fn slots(&'static self) -> &'static [::pyo3::ffi::PyType_Slot] {
699-
&self.slots
700-
}
701-
}
702-
703-
impl ::pyo3::class::impl_::HasMethodsInventory for #cls {
704-
type Methods = #inventory_cls;
705-
}
706-
707-
::pyo3::inventory::collect!(#inventory_cls);
708-
}
709-
}
710-
}
711-
}
712669
fn impl_pyclassimpl(&self) -> TokenStream {
713670
let cls = self.cls;
714671
let doc = self.doc.as_ref().map_or(quote! {"\0"}, |doc| quote! {#doc});
@@ -727,26 +684,37 @@ impl<'a> PyClassImplsBuilder<'a> {
727684
quote! { ::pyo3::class::impl_::ThreadCheckerStub<#cls> }
728685
};
729686

730-
let methods_protos = match self.methods_type {
731-
PyClassMethodsType::Specialization => {
732-
quote! { visitor(collector.methods_protocol_slots()); }
733-
}
687+
let (for_each_py_method, methods_protos, inventory, inventory_class) = match self
688+
.methods_type
689+
{
690+
PyClassMethodsType::Specialization => (
691+
quote! { visitor(collector.py_methods()); },
692+
quote! { visitor(collector.methods_protocol_slots()); },
693+
None,
694+
None,
695+
),
734696
PyClassMethodsType::Inventory => {
735-
quote! {
736-
for inventory in ::pyo3::inventory::iter::<<Self as ::pyo3::class::impl_::HasMethodsInventory>::Methods>() {
737-
visitor(::pyo3::class::impl_::PyMethodsInventory::slots(inventory));
738-
}
739-
}
697+
// To allow multiple #[pymethods] block, we define inventory types.
698+
let inventory_class_name = syn::Ident::new(
699+
&format!("Pyo3MethodsInventoryFor{}", cls.unraw()),
700+
Span::call_site(),
701+
);
702+
(
703+
quote! {
704+
for inventory in ::pyo3::inventory::iter::<<Self as ::pyo3::class::impl_::PyClassImpl>::Inventory>() {
705+
visitor(::pyo3::class::impl_::PyClassInventory::methods(inventory));
706+
}
707+
},
708+
quote! {
709+
for inventory in ::pyo3::inventory::iter::<<Self as ::pyo3::class::impl_::PyClassImpl>::Inventory>() {
710+
visitor(::pyo3::class::impl_::PyClassInventory::slots(inventory));
711+
}
712+
},
713+
Some(quote! { type Inventory = #inventory_class_name; }),
714+
Some(define_inventory_class(&inventory_class_name)),
715+
)
740716
}
741717
};
742-
let for_each_py_method = match self.methods_type {
743-
PyClassMethodsType::Specialization => quote! { visitor(collector.py_methods()); },
744-
PyClassMethodsType::Inventory => quote! {
745-
for inventory in ::pyo3::inventory::iter::<<Self as ::pyo3::class::impl_::HasMethodsInventory>::Methods>() {
746-
visitor(::pyo3::class::impl_::PyMethodsInventory::methods(inventory));
747-
}
748-
},
749-
};
750718
quote! {
751719
impl ::pyo3::class::impl_::PyClassImpl for #cls {
752720
const DOC: &'static str = #doc;
@@ -757,6 +725,7 @@ impl<'a> PyClassImplsBuilder<'a> {
757725
type Layout = ::pyo3::PyCell<Self>;
758726
type BaseType = #base;
759727
type ThreadChecker = #thread_checker;
728+
#inventory
760729

761730
fn for_each_method_def(visitor: &mut dyn ::std::ops::FnMut(&[::pyo3::class::PyMethodDefType])) {
762731
use ::pyo3::class::impl_::*;
@@ -807,6 +776,8 @@ impl<'a> PyClassImplsBuilder<'a> {
807776
collector.buffer_procs()
808777
}
809778
}
779+
780+
#inventory_class
810781
}
811782
}
812783

@@ -865,3 +836,36 @@ impl<'a> PyClassImplsBuilder<'a> {
865836
}
866837
}
867838
}
839+
840+
fn define_inventory_class(inventory_class_name: &syn::Ident) -> TokenStream {
841+
quote! {
842+
#[doc(hidden)]
843+
pub struct #inventory_class_name {
844+
methods: &'static [::pyo3::class::PyMethodDefType],
845+
slots: &'static [::pyo3::ffi::PyType_Slot],
846+
}
847+
impl #inventory_class_name {
848+
const fn new(
849+
methods: &'static [::pyo3::class::PyMethodDefType],
850+
slots: &'static [::pyo3::ffi::PyType_Slot],
851+
) -> Self {
852+
Self { methods, slots }
853+
}
854+
}
855+
856+
impl ::pyo3::class::impl_::PyClassInventory for #inventory_class_name {
857+
fn methods(&'static self) -> &'static [::pyo3::class::PyMethodDefType] {
858+
self.methods
859+
}
860+
fn slots(&'static self) -> &'static [::pyo3::ffi::PyType_Slot] {
861+
self.slots
862+
}
863+
}
864+
865+
// inventory requires these bounds
866+
unsafe impl ::std::marker::Send for #inventory_class_name {}
867+
unsafe impl ::std::marker::Sync for #inventory_class_name {}
868+
869+
::pyo3::inventory::collect!(#inventory_class_name);
870+
}
871+
}

pyo3-macros-backend/src/pyimpl.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,8 @@ fn submit_methods_inventory(
211211
) -> TokenStream {
212212
quote! {
213213
::pyo3::inventory::submit! {
214-
#![crate = ::pyo3] {
215-
type Inventory = <#ty as ::pyo3::class::impl_::HasMethodsInventory>::Methods;
216-
<Inventory as ::pyo3::class::impl_::PyMethodsInventory>::new(::std::vec![#(#methods),*], ::std::vec![#(#proto_impls),*])
217-
}
214+
type Inventory = <#ty as ::pyo3::class::impl_::PyClassImpl>::Inventory;
215+
Inventory::new(&[#(#methods),*], &[#(#proto_impls),*])
218216
}
219217
}
220218
}

src/class/impl_.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ pub trait PyClassImpl: Sized {
6767
/// can be accessed by multiple threads by `threading` module.
6868
type ThreadChecker: PyClassThreadChecker<Self>;
6969

70+
#[cfg(feature = "multiple-pymethods")]
71+
type Inventory: PyClassInventory;
72+
7073
fn for_each_method_def(_visitor: &mut dyn FnMut(&[PyMethodDefType])) {}
7174
fn get_new() -> Option<ffi::newfunc> {
7275
None
@@ -607,25 +610,15 @@ macro_rules! methods_trait {
607610
/// Method storage for `#[pyclass]`.
608611
/// Allows arbitrary `#[pymethod]` blocks to submit their methods,
609612
/// which are eventually collected by `#[pyclass]`.
610-
#[cfg(all(feature = "macros", feature = "multiple-pymethods"))]
611-
pub trait PyMethodsInventory: inventory::Collect {
612-
/// Create a new instance
613-
fn new(methods: Vec<PyMethodDefType>, slots: Vec<ffi::PyType_Slot>) -> Self;
614-
613+
#[cfg(feature = "multiple-pymethods")]
614+
pub trait PyClassInventory: inventory::Collect {
615615
/// Returns the methods for a single `#[pymethods] impl` block
616616
fn methods(&'static self) -> &'static [PyMethodDefType];
617617

618618
/// Returns the slots for a single `#[pymethods] impl` block
619619
fn slots(&'static self) -> &'static [ffi::PyType_Slot];
620620
}
621621

622-
/// Implemented for `#[pyclass]` in our proc macro code.
623-
/// Indicates that the pyclass has its own method storage.
624-
#[cfg(all(feature = "macros", feature = "multiple-pymethods"))]
625-
pub trait HasMethodsInventory {
626-
type Methods: PyMethodsInventory;
627-
}
628-
629622
// Methods from #[pyo3(get, set)] on struct fields.
630623
methods_trait!(PyClassDescriptors, py_class_descriptors);
631624

0 commit comments

Comments
 (0)