4141 "print" ,
4242}
4343
44+ TRIG_DECORATORS = {
45+ "time_trigger" ,
46+ "state_trigger" ,
47+ "event_trigger" ,
48+ "mqtt_trigger" ,
49+ "state_active" ,
50+ "time_active" ,
51+ "task_unique" ,
52+ }
53+
54+ ALL_DECORATORS = TRIG_DECORATORS .union ({"service" })
4455
4556def ast_eval_exec_factory (ast_ctx , mode ):
4657 """Generate a function that executes eval() or exec() with given ast_ctx."""
@@ -255,7 +266,6 @@ def __init__(self, func_def, code_list, code_str, global_ctx):
255266 self .trigger = None
256267 self .trigger_service = False
257268 self .has_closure = False
258- self .perform_call = None
259269
260270 def get_name (self ):
261271 """Return the function name."""
@@ -281,15 +291,6 @@ async def trigger_init(self):
281291 "event_trigger" ,
282292 "mqtt_trigger" ,
283293 }
284- trig_decorators = {
285- "time_trigger" ,
286- "state_trigger" ,
287- "event_trigger" ,
288- "mqtt_trigger" ,
289- "state_active" ,
290- "time_active" ,
291- "task_unique" ,
292- }
293294 decorator_used = set ()
294295 for dec in self .decorators :
295296 dec_name , dec_args , dec_kwargs = dec [0 ], dec [1 ], dec [2 ]
@@ -304,7 +305,7 @@ async def trigger_init(self):
304305 decorator_used .add (dec_name )
305306 if dec_name in trig_decorators_reqd :
306307 got_reqd_dec = True
307- if dec_name in trig_decorators :
308+ if dec_name in TRIG_DECORATORS :
308309 if dec_name not in trig_args :
309310 trig_args [dec_name ] = {}
310311 trig_args [dec_name ]["args" ] = []
@@ -384,7 +385,7 @@ async def do_service_call(func, ast_ctx, data):
384385 dec_name ,
385386 )
386387
387- for dec_name in trig_decorators :
388+ for dec_name in TRIG_DECORATORS :
388389 if dec_name in trig_args and len (trig_args [dec_name ]["args" ]) == 0 :
389390 trig_args [dec_name ]["args" ] = None
390391
@@ -520,85 +521,21 @@ async def eval_decorators(self, ast_ctx):
520521 code_str , code_list = ast_ctx .code_str , ast_ctx .code_list
521522 ast_ctx .code_str , ast_ctx .code_list = self .code_str , self .code_list
522523
523- decorator_chain_funcs = []
524-
524+ dec_funcs = []
525525 for dec in self .func_def .decorator_list :
526- # this should eventually handle:
527- # SomeClass('a','b').some_method('x','y')
528- if isinstance (dec , ast .Call ) and isinstance (dec .func , ast .Attribute ):
529- _LOGGER .info (
530- "Attribute as decorator (ignoring for now) %s %s %s" ,
531- dec .func ,
532- dec .func .attr ,
533- dec .func .value
534- )
535-
536- elif isinstance (dec , ast .Call ) and isinstance (dec .func , ast .Name ):
537- args = []
538- kwargs = {}
539- for arg in dec .args :
540- args .append (await ast_ctx .aeval (arg ))
541- for keyw in dec .keywords :
542- kwargs [keyw .arg ] = await ast_ctx .aeval (keyw .value )
526+ if isinstance (dec , ast .Call ) and isinstance (dec .func , ast .Name ) and dec .func .id in ALL_DECORATORS :
527+ args = [await ast_ctx .aeval (arg ) for arg in dec .args ]
528+ kwargs = {keyw .arg : await ast_ctx .aeval (keyw .value ) for keyw in dec .keywords }
543529 if len (kwargs ) == 0 :
544530 kwargs = None
545-
546- if dec .func .id in ast_ctx .global_sym_table :
547- _LOGGER .info (
548- "added %s to decorator_chain_funcs" ,
549- dec .func .id ,
550- )
551- decorator_chain_funcs .append (dec )
552- else :
553- self .decorators .append ([dec .func .id , args , kwargs ])
554- elif isinstance (dec , ast .Name ):
555- if dec .id in ast_ctx .global_sym_table :
556- decorator_chain_funcs .append (dec )
557- else :
558- self .decorators .append ([dec .id , None , None ])
531+ self .decorators .append ([dec .func .id , args , kwargs ])
532+ elif isinstance (dec , ast .Name ) and dec .id in ALL_DECORATORS :
533+ self .decorators .append ([dec .id , None , None ])
559534 else :
560- _LOGGER .error ("function %s has unexpected decorator type %s" , self .name , dec )
561-
562- actual_call = self .real_call
563-
564- try :
565- for dec in reversed (decorator_chain_funcs ):
566- if isinstance (dec , ast .Call ) and isinstance (dec .func , ast .Name ):
567- args = []
568- kwargs = {}
569- for arg in dec .args :
570- args .append (await ast_ctx .aeval (arg ))
571- for keyw in dec .keywords :
572- kwargs [keyw .arg ] = await ast_ctx .aeval (keyw .value )
573- if len (kwargs ) == 0 :
574- kwargs = {}
575- func_def = ast_ctx .global_sym_table [dec .func .id ]
576-
577- wrapper = await func_def .call (ast_ctx , * args , ** kwargs )
578- def make_actual_call_inner (actual_call ):
579- async def actual_call_inner (* args_tuple , ** kwargs ):
580- args = list (args_tuple )
581- if len (args ) > 0 and isinstance (args [0 ], AstEval ):
582- _LOGGER .info ('AstEval seen' )
583- args .pop (0 )
584- _LOGGER .info (actual_call )
585- return await actual_call (ast_ctx , * args , ** kwargs )
586- return actual_call_inner
587- actual_call = await wrapper (make_actual_call_inner (actual_call ))
588-
589- elif isinstance (dec , ast .Name ):
590- func_def = ast_ctx .global_sym_table [dec .id ]
591- actual_call = await func_def .call (ast_ctx , actual_call )
535+ dec_funcs .append (await ast_ctx .aeval (dec ))
592536
593- else :
594- _LOGGER .error ("function %s has unexpected global_sym_table decorator type %s" , self .name , dec )
595- except Exception as e :
596- _LOGGER .error (
597- "Something went wrong %s" ,
598- e
599- )
600-
601- self .perform_call = actual_call
537+ for func in reversed (dec_funcs ):
538+ self .call = await ast_ctx .call_func (func , None , self .call )
602539
603540 ast_ctx .code_str , ast_ctx .code_list = code_str , code_list
604541
@@ -680,13 +617,9 @@ async def try_aeval(self, ast_ctx, arg):
680617 ast_ctx .exception_long = ast_ctx .format_exc (err , arg .lineno , arg .col_offset )
681618
682619 async def call (self , ast_ctx , * args , ** kwargs ):
683- """Call the function with decorators"""
684- return await self .perform_call (ast_ctx , * args , ** kwargs )
685-
686- async def real_call (self , ast_ctx , * args , ** kwargs ):
687620 """Call the function with the given context and arguments."""
688621 _LOGGER .info (
689- 'in real_call of %s' ,
622+ 'in call of %s' ,
690623 self .name
691624 )
692625 sym_table = {}
0 commit comments