@@ -54,7 +54,6 @@ def init(cls, hass):
5454 "task.executor" : cls .task_executor ,
5555 "event.fire" : cls .event_fire ,
5656 "task.sleep" : cls .async_sleep ,
57- "task.unique" : cls .task_unique ,
5857 "service.call" : cls .service_call ,
5958 "service.has_service" : cls .service_has_service ,
6059 }
@@ -66,6 +65,7 @@ def init(cls, hass):
6665 "log.info" : lambda ast_ctx : ast_ctx .get_logger ().info ,
6766 "log.warning" : lambda ast_ctx : ast_ctx .get_logger ().warning ,
6867 "print" : lambda ast_ctx : ast_ctx .get_logger ().debug ,
68+ "task.unique" : lambda ast_ctx : cls .task_unique_factory (ast_ctx ),
6969 }
7070 )
7171
@@ -101,30 +101,36 @@ async def event_fire(cls, event_type, **kwargs):
101101 cls .hass .bus .async_fire (event_type , kwargs )
102102
103103 @classmethod
104- async def task_unique (cls , name , kill_me = False ):
105- """Implement task.unique()."""
106- if name in cls .unique_name2task :
107- if kill_me :
108- #
109- # it seems we can't cancel ourselves, so we
110- # tell the repeaer task to cancel us
111- #
112- Function .task_cancel (asyncio .current_task ())
113- # wait to be canceled
114- await asyncio .sleep (100000 )
115- else :
116- task = cls .unique_name2task [name ]
117- if task in cls .our_tasks :
118- # only cancel tasks if they are ones we started
119- try :
120- task .cancel ()
121- await task
122- except asyncio .CancelledError :
123- pass
124- task = asyncio .current_task ()
125- if task in cls .our_tasks :
126- cls .unique_name2task [name ] = task
127- cls .unique_task2name [task ] = name
104+ def task_unique_factory (cls , ctx ):
105+ """Define and return task.unique() for this context."""
106+
107+ async def task_unique (name , kill_me = False ):
108+ """Implement task.unique()."""
109+ name = f"{ ctx .get_global_ctx_name ()} .{ name } "
110+ if name in cls .unique_name2task :
111+ if kill_me :
112+ #
113+ # it seems we can't cancel ourselves, so we
114+ # tell the repeaer task to cancel us
115+ #
116+ Function .task_cancel (asyncio .current_task ())
117+ # wait to be canceled
118+ await asyncio .sleep (100000 )
119+ else :
120+ task = cls .unique_name2task [name ]
121+ if task in cls .our_tasks :
122+ # only cancel tasks if they are ones we started
123+ try :
124+ task .cancel ()
125+ await task
126+ except asyncio .CancelledError :
127+ pass
128+ task = asyncio .current_task ()
129+ if task in cls .our_tasks :
130+ cls .unique_name2task [name ] = task
131+ cls .unique_task2name [task ] = name
132+
133+ return task_unique
128134
129135 @classmethod
130136 async def task_executor (cls , func , * args , ** kwargs ):
@@ -134,8 +140,9 @@ async def task_executor(cls, func, *args, **kwargs):
134140 return await cls .hass .async_add_executor_job (functools .partial (func , ** kwargs ), * args )
135141
136142 @classmethod
137- def unique_name_used (cls , name ):
143+ def unique_name_used (cls , ctx , name ):
138144 """Return whether the current unique name is in use."""
145+ name = f"{ ctx .get_global_ctx_name ()} .{ name } "
139146 return name in cls .unique_name2task
140147
141148 @classmethod
0 commit comments