1
1
use crate :: error:: Diagnostic ;
2
2
use crate :: util:: {
3
- iter_use_idents, path_eq , pyclass_ident_and_attrs, text_signature, AttributeExt , ClassItemMeta ,
4
- ContentItem , ContentItemInner , ErrorVec , ItemMeta , ItemNursery , SimpleItemMeta ,
3
+ iter_use_idents, pyclass_ident_and_attrs, text_signature, AttrItemMeta , AttributeExt ,
4
+ ClassItemMeta , ContentItem , ContentItemInner , ErrorVec , ItemMeta , ItemNursery , SimpleItemMeta ,
5
5
ALL_ALLOWED_NAMES ,
6
6
} ;
7
7
use proc_macro2:: TokenStream ;
@@ -37,41 +37,6 @@ pub fn impl_pymodule(attr: AttributeArgs, module_item: Item) -> Result<TokenStre
37
37
// collect to context
38
38
for item in items. iter_mut ( ) {
39
39
let r = item. try_split_attr_mut ( |attrs, item| {
40
- // If attribute is #[pyattr] and item is ItemFn, then
41
- // wrapping it with static_cell for preventing it from using it as function
42
- if attrs. iter ( ) . any ( |attr| {
43
- path_eq ( & attr. path , "pyattr" )
44
- && if let Ok ( syn:: Meta :: List ( l) ) = attr. parse_meta ( ) {
45
- l. nested
46
- . into_iter ( )
47
- . any ( |n| n. get_ident ( ) . map_or ( false , |p| p == "once" ) )
48
- } else {
49
- false
50
- }
51
- } ) {
52
- if let Item :: Fn ( syn:: ItemFn { sig, block, .. } ) = item {
53
- let stmts = & block. stmts ;
54
- let return_type = match & sig. output {
55
- syn:: ReturnType :: Default => {
56
- unreachable ! ( "#[pyattr] attached function must have return type." )
57
- }
58
- syn:: ReturnType :: Type ( _, ty) => ty,
59
- } ;
60
- let stmt: syn:: Stmt = parse_quote ! {
61
- {
62
- rustpython_common:: static_cell! {
63
- static ERROR : #return_type;
64
- }
65
- ERROR
66
- . get_or_init( || {
67
- #( #stmts) *
68
- } )
69
- . clone( )
70
- }
71
- } ;
72
- block. stmts = vec ! [ stmt] ;
73
- }
74
- }
75
40
let ( pyitems, cfgs) = attrs_to_module_items ( attrs, new_module_item) ?;
76
41
for pyitem in pyitems. iter ( ) . rev ( ) {
77
42
let r = pyitem. gen_module_item ( ModuleItemArgs {
@@ -276,7 +241,7 @@ impl ContentItem for AttributeItem {
276
241
}
277
242
278
243
struct ModuleItemArgs < ' a > {
279
- item : & ' a Item ,
244
+ item : & ' a mut Item ,
280
245
attrs : & ' a mut Vec < Attribute > ,
281
246
context : & ' a mut ModuleContext ,
282
247
cfgs : & ' a [ Attribute ] ,
@@ -405,15 +370,36 @@ impl ModuleItem for AttributeItem {
405
370
fn gen_module_item ( & self , args : ModuleItemArgs < ' _ > ) -> Result < ( ) > {
406
371
let cfgs = args. cfgs . to_vec ( ) ;
407
372
let attr = args. attrs . remove ( self . index ( ) ) ;
408
- let get_py_name = |attr : & Attribute , ident : & Ident | -> Result < _ > {
409
- let item_meta = SimpleItemMeta :: from_attr ( ident. clone ( ) , attr) ?;
410
- let py_name = item_meta. simple_name ( ) ?;
411
- Ok ( py_name)
412
- } ;
413
373
let ( py_name, tokens) = match args. item {
414
- Item :: Fn ( syn:: ItemFn { sig, .. } ) => {
374
+ Item :: Fn ( syn:: ItemFn { sig, block , .. } ) => {
415
375
let ident = & sig. ident ;
416
- let py_name = get_py_name ( & attr, ident) ?;
376
+ // If `once` keyword is in #[pyattr],
377
+ // wrapping it with static_cell for preventing it from using it as function
378
+ let attr_meta = AttrItemMeta :: from_attr ( ident. clone ( ) , & attr) ?;
379
+ if attr_meta. inner ( ) . _bool ( "once" ) ? {
380
+ let stmts = & block. stmts ;
381
+ let return_type = match & sig. output {
382
+ syn:: ReturnType :: Default => {
383
+ unreachable ! ( "#[pyattr] attached function must have return type." )
384
+ }
385
+ syn:: ReturnType :: Type ( _, ty) => ty,
386
+ } ;
387
+ let stmt: syn:: Stmt = parse_quote ! {
388
+ {
389
+ rustpython_common:: static_cell! {
390
+ static ERROR : #return_type;
391
+ }
392
+ ERROR
393
+ . get_or_init( || {
394
+ #( #stmts) *
395
+ } )
396
+ . clone( )
397
+ }
398
+ } ;
399
+ block. stmts = vec ! [ stmt] ;
400
+ }
401
+
402
+ let py_name = attr_meta. simple_name ( ) ?;
417
403
(
418
404
py_name. clone ( ) ,
419
405
quote_spanned ! { ident. span( ) =>
@@ -422,7 +408,8 @@ impl ModuleItem for AttributeItem {
422
408
)
423
409
}
424
410
Item :: Const ( syn:: ItemConst { ident, .. } ) => {
425
- let py_name = get_py_name ( & attr, ident) ?;
411
+ let item_meta = SimpleItemMeta :: from_attr ( ident. clone ( ) , & attr) ?;
412
+ let py_name = item_meta. simple_name ( ) ?;
426
413
(
427
414
py_name. clone ( ) ,
428
415
quote_spanned ! { ident. span( ) =>
0 commit comments