@@ -11,6 +11,10 @@ enum ClassItem {
11
11
item_ident : Ident ,
12
12
py_name : String ,
13
13
} ,
14
+ ClassMethod {
15
+ item_ident : Ident ,
16
+ py_name : String ,
17
+ } ,
14
18
Property {
15
19
item_ident : Ident ,
16
20
py_name : String ,
@@ -49,8 +53,8 @@ impl ClassItem {
49
53
let nesteds = meta_to_vec ( meta) . map_err ( |meta| {
50
54
err_span ! (
51
55
meta,
52
- "#[pyproperty = \" ...\" ] cannot be a name/value, you probably meant \
53
- #[pyproperty (name = \" ...\" )]",
56
+ "#[pymethod = \" ...\" ] cannot be a name/value, you probably meant \
57
+ #[pymethod (name = \" ...\" )]",
54
58
)
55
59
} ) ?;
56
60
let mut py_name = None ;
@@ -80,6 +84,47 @@ impl ClassItem {
80
84
py_name : py_name. unwrap_or_else ( || sig. ident . to_string ( ) ) ,
81
85
} ) ;
82
86
attr_idx = Some ( i) ;
87
+ } else if name == "pyclassmethod" {
88
+ if item. is_some ( ) {
89
+ bail_span ! (
90
+ sig. ident,
91
+ "You can only have one #[py*] attribute on an impl item"
92
+ )
93
+ }
94
+ let nesteds = meta_to_vec ( meta) . map_err ( |meta| {
95
+ err_span ! (
96
+ meta,
97
+ "#[pyclassmethod = \" ...\" ] cannot be a name/value, you probably meant \
98
+ #[pyclassmethod(name = \" ...\" )]",
99
+ )
100
+ } ) ?;
101
+ let mut py_name = None ;
102
+ for meta in nesteds {
103
+ let meta = match meta {
104
+ NestedMeta :: Meta ( meta) => meta,
105
+ NestedMeta :: Literal ( _) => continue ,
106
+ } ;
107
+ match meta {
108
+ Meta :: NameValue ( name_value) => {
109
+ if name_value. ident == "name" {
110
+ if let Lit :: Str ( s) = & name_value. lit {
111
+ py_name = Some ( s. value ( ) ) ;
112
+ } else {
113
+ bail_span ! (
114
+ & sig. ident,
115
+ "#[pyclassmethod(name = ...)] must be a string"
116
+ ) ;
117
+ }
118
+ }
119
+ }
120
+ _ => { }
121
+ }
122
+ }
123
+ item = Some ( ClassItem :: ClassMethod {
124
+ item_ident : sig. ident . clone ( ) ,
125
+ py_name : py_name. unwrap_or_else ( || sig. ident . to_string ( ) ) ,
126
+ } ) ;
127
+ attr_idx = Some ( i) ;
83
128
} else if name == "pyproperty" {
84
129
if item. is_some ( ) {
85
130
bail_span ! (
@@ -210,18 +255,20 @@ pub fn impl_pyimpl(_attr: AttributeArgs, item: Item) -> Result<TokenStream2, Dia
210
255
_ => { }
211
256
}
212
257
}
213
- let methods = items. iter ( ) . filter_map ( |item| {
214
- if let ClassItem :: Method {
258
+ let methods = items. iter ( ) . filter_map ( |item| match item {
259
+ ClassItem :: Method {
215
260
item_ident,
216
261
py_name,
217
- } = item
218
- {
219
- Some ( quote ! {
220
- class. set_str_attr( #py_name, ctx. new_rustfunc( Self :: #item_ident) ) ;
221
- } )
222
- } else {
223
- None
224
- }
262
+ } => Some ( quote ! {
263
+ class. set_str_attr( #py_name, ctx. new_rustfunc( Self :: #item_ident) ) ;
264
+ } ) ,
265
+ ClassItem :: ClassMethod {
266
+ item_ident,
267
+ py_name,
268
+ } => Some ( quote ! {
269
+ class. set_str_attr( #py_name, ctx. new_classmethod( Self :: #item_ident) ) ;
270
+ } ) ,
271
+ _ => None ,
225
272
} ) ;
226
273
let properties = properties
227
274
. iter ( )
0 commit comments