1
1
use super :: rustpython_path_attr;
2
2
use proc_macro2:: { Span , TokenStream as TokenStream2 } ;
3
3
use quote:: quote;
4
- use syn:: { Attribute , AttributeArgs , Ident , ImplItem , Item , Lit , Meta , MethodSig , NestedMeta } ;
4
+ use syn:: {
5
+ Attribute , AttributeArgs , Ident , ImplItem , Item , Lit , Meta , MethodSig , NestedMeta , TraitItem ,
6
+ } ;
5
7
6
8
enum MethodKind {
7
9
Method ,
@@ -89,27 +91,7 @@ impl Method {
89
91
}
90
92
}
91
93
92
- pub fn impl_pyimpl ( attr : AttributeArgs , item : Item ) -> TokenStream2 {
93
- let mut imp = if let Item :: Impl ( imp) = item {
94
- imp
95
- } else {
96
- return quote ! ( #item) ;
97
- } ;
98
-
99
- let rp_path = rustpython_path_attr ( & attr) ;
100
-
101
- let methods = imp
102
- . items
103
- . iter_mut ( )
104
- . filter_map ( |item| {
105
- if let ImplItem :: Method ( meth) = item {
106
- Method :: from_syn ( & mut meth. attrs , & meth. sig )
107
- } else {
108
- None
109
- }
110
- } )
111
- . collect :: < Vec < _ > > ( ) ;
112
- let ty = & imp. self_ty ;
94
+ fn get_pyimpl_impl ( rp_path : & syn:: Path , methods : & [ Method ] ) -> TokenStream2 {
113
95
let methods = methods. iter ( ) . map (
114
96
|Method {
115
97
py_name,
@@ -122,17 +104,66 @@ pub fn impl_pyimpl(attr: AttributeArgs, item: Item) -> TokenStream2 {
122
104
}
123
105
} ,
124
106
) ;
125
-
126
107
quote ! {
127
- #imp
128
- impl #rp_path:: pyobject:: PyClassImpl for #ty {
129
- fn impl_extend_class(
130
- ctx: & #rp_path:: pyobject:: PyContext ,
131
- class: & #rp_path:: obj:: objtype:: PyClassRef ,
132
- ) {
133
- #( #methods) *
108
+ fn impl_extend_class(
109
+ ctx: & #rp_path:: pyobject:: PyContext ,
110
+ class: & #rp_path:: obj:: objtype:: PyClassRef ,
111
+ ) {
112
+ #( #methods) *
113
+ }
114
+ }
115
+ }
116
+
117
+ pub fn impl_pyimpl ( attr : AttributeArgs , item : Item ) -> TokenStream2 {
118
+ let rp_path = rustpython_path_attr ( & attr) ;
119
+ let pyclassimpl_path = quote ! ( #rp_path:: pyobject:: PyClassImpl ) ;
120
+ match item {
121
+ Item :: Impl ( mut imp) => {
122
+ let methods = imp
123
+ . items
124
+ . iter_mut ( )
125
+ . filter_map ( |item| {
126
+ if let ImplItem :: Method ( meth) = item {
127
+ Method :: from_syn ( & mut meth. attrs , & meth. sig )
128
+ } else {
129
+ None
130
+ }
131
+ } )
132
+ . collect :: < Vec < _ > > ( ) ;
133
+
134
+ let pyimpl_impl = get_pyimpl_impl ( & rp_path, & methods) ;
135
+ let ty = & imp. self_ty ;
136
+
137
+ quote ! {
138
+ #imp
139
+ impl #pyclassimpl_path for #ty {
140
+ #pyimpl_impl
141
+ }
142
+ }
143
+ }
144
+ Item :: Trait ( mut trai) => {
145
+ let methods = trai
146
+ . items
147
+ . iter_mut ( )
148
+ . filter_map ( |item| {
149
+ if let TraitItem :: Method ( meth) = item {
150
+ Method :: from_syn ( & mut meth. attrs , & meth. sig )
151
+ } else {
152
+ None
153
+ }
154
+ } )
155
+ . collect :: < Vec < _ > > ( ) ;
156
+
157
+ let pyimpl_impl = get_pyimpl_impl ( & rp_path, & methods) ;
158
+ let ty = & trai. ident ;
159
+
160
+ quote ! {
161
+ impl <T : #ty> #pyclassimpl_path for T {
162
+ #pyimpl_impl
163
+ }
134
164
}
135
165
}
166
+ _ => panic ! ( "#[pyimpl] can only be applied to impl blocks and trait definitions" ) ,
136
167
}
137
168
}
138
169
0 commit comments