@@ -89,13 +89,62 @@ impl Method {
89
89
}
90
90
}
91
91
92
- pub fn impl_py_class ( attr : AttributeArgs , item : Item ) -> TokenStream2 {
92
+ pub fn impl_pyimpl ( attr : AttributeArgs , item : Item ) -> TokenStream2 {
93
93
let mut imp = if let Item :: Impl ( imp) = item {
94
94
imp
95
95
} else {
96
96
return quote ! ( #item) ;
97
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 ;
113
+ let methods = methods. iter ( ) . map (
114
+ |Method {
115
+ py_name,
116
+ fn_name,
117
+ kind,
118
+ } | {
119
+ let constructor_fn = kind. to_ctx_constructor_fn ( ) ;
120
+ quote ! {
121
+ ctx. set_attr( class, #py_name, ctx. #constructor_fn( Self :: #fn_name) ) ;
122
+ }
123
+ } ,
124
+ ) ;
125
+
126
+ 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) *
134
+ }
135
+ }
136
+ }
137
+ }
138
+
139
+ pub fn impl_pyclass ( attr : AttributeArgs , item : Item ) -> TokenStream2 {
140
+ let struc = if let Item :: Struct ( struc) = item {
141
+ struc
142
+ } else {
143
+ panic ! ( "#[pyclass] can only be on a struct declaration" ) ;
144
+ } ;
145
+
98
146
let rp_path = rustpython_path_attr ( & attr) ;
147
+
99
148
let mut class_name = None ;
100
149
for attr in attr {
101
150
if let NestedMeta :: Meta ( meta) = attr {
@@ -110,9 +159,10 @@ pub fn impl_py_class(attr: AttributeArgs, item: Item) -> TokenStream2 {
110
159
}
111
160
}
112
161
}
113
- let class_name = class_name. expect ( "#[pyclass] must have a name" ) ;
162
+ let class_name = class_name. unwrap_or_else ( || struc. ident . to_string ( ) ) ;
163
+
114
164
let mut doc: Option < Vec < String > > = None ;
115
- for attr in imp . attrs . iter ( ) {
165
+ for attr in struc . attrs . iter ( ) {
116
166
if attr. path . is_ident ( "doc" ) {
117
167
let meta = attr. parse_meta ( ) . expect ( "expected doc attr to be a meta" ) ;
118
168
if let Meta :: NameValue ( name_value) = meta {
@@ -125,8 +175,6 @@ pub fn impl_py_class(attr: AttributeArgs, item: Item) -> TokenStream2 {
125
175
} else {
126
176
panic ! ( "expected #[doc = ...] to be a string" )
127
177
}
128
- } else {
129
- panic ! ( "expected #[doc] to be a NameValue, e.g. #[doc = \" ...\" " ) ;
130
178
}
131
179
}
132
180
}
@@ -137,42 +185,14 @@ pub fn impl_py_class(attr: AttributeArgs, item: Item) -> TokenStream2 {
137
185
}
138
186
None => quote ! ( None ) ,
139
187
} ;
140
- let methods = imp
141
- . items
142
- . iter_mut ( )
143
- . filter_map ( |item| {
144
- if let ImplItem :: Method ( meth) = item {
145
- Method :: from_syn ( & mut meth. attrs , & meth. sig )
146
- } else {
147
- None
148
- }
149
- } )
150
- . collect :: < Vec < _ > > ( ) ;
151
- let ty = & imp. self_ty ;
152
- let methods = methods. iter ( ) . map (
153
- |Method {
154
- py_name,
155
- fn_name,
156
- kind,
157
- } | {
158
- let constructor_fn = kind. to_ctx_constructor_fn ( ) ;
159
- quote ! {
160
- ctx. set_attr( class, #py_name, ctx. #constructor_fn( Self :: #fn_name) ) ;
161
- }
162
- } ,
163
- ) ;
188
+
189
+ let ty = & struc. ident ;
164
190
165
191
quote ! {
166
- #imp
167
- impl #rp_path:: pyobject:: IntoPyClass for #ty {
192
+ #struc
193
+ impl #rp_path:: pyobject:: PyClassDef for #ty {
168
194
const NAME : & ' static str = #class_name;
169
195
const DOC : Option <& ' static str > = #doc;
170
- fn _extend_class(
171
- ctx: & #rp_path:: pyobject:: PyContext ,
172
- class: & #rp_path:: obj:: objtype:: PyClassRef ,
173
- ) {
174
- #( #methods) *
175
- }
176
196
}
177
197
}
178
198
}
0 commit comments