Skip to content

Commit 62f0156

Browse files
committed
adds task.create(), task.cancel() and task.wait() per #112
1 parent 8fe16fe commit 62f0156

File tree

3 files changed

+54
-9
lines changed

3 files changed

+54
-9
lines changed

custom_components/pyscript/eval.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,10 @@ async def call(self, ast_ctx, *args, **kwargs):
726726
"""Call the EvalFunc function."""
727727
return await self.func.call(ast_ctx, *args, **kwargs)
728728

729+
def get_name(self):
730+
"""Return the function name."""
731+
return self.func.get_name()
732+
729733
def __del__(self):
730734
"""On deletion, stop any triggers for this function."""
731735
self.func.trigger_stop()
@@ -756,6 +760,10 @@ async def call(self, ast_ctx, *args, **kwargs):
756760
"""Call the EvalFunc function."""
757761
return await self.eval_func_var.call(ast_ctx, *args, **kwargs)
758762

763+
def get_name(self):
764+
"""Return the function name."""
765+
return self.eval_func_var.get_name()
766+
759767
async def __call__(self, *args, **kwargs):
760768
"""Call the EvalFunc function using our saved ast ctx."""
761769
return await self.eval_func_var.call(self.ast_ctx, *args, **kwargs)

custom_components/pyscript/function.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,11 @@ def init(cls, hass):
6363
cls.hass = hass
6464
cls.functions.update(
6565
{
66-
"task.executor": cls.task_executor,
6766
"event.fire": cls.event_fire,
68-
"task.sleep": cls.async_sleep,
6967
"service.call": cls.service_call,
7068
"service.has_service": cls.service_has_service,
69+
"task.executor": cls.task_executor,
70+
"task.sleep": cls.async_sleep,
7171
}
7272
)
7373
cls.ast_functions.update(
@@ -187,11 +187,7 @@ async def task_unique(name, kill_me=False):
187187
await asyncio.sleep(100000)
188188
elif task != curr_task and task in cls.our_tasks:
189189
# only cancel tasks if they are ones we started
190-
try:
191-
task.cancel()
192-
await task
193-
except asyncio.CancelledError:
194-
pass
190+
Function.reaper_cancel(task)
195191
if curr_task in cls.our_tasks:
196192
if name in cls.unique_name2task:
197193
task = cls.unique_name2task[name]
@@ -325,7 +321,7 @@ async def run_coro(cls, coro):
325321
try:
326322
task = asyncio.current_task()
327323
cls.our_tasks.add(task)
328-
await coro
324+
return await coro
329325
except asyncio.CancelledError:
330326
raise
331327
except Exception:

custom_components/pyscript/trigger.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import homeassistant.helpers.sun as sun
1515

1616
from .const import LOGGER_PATH
17-
from .eval import AstEval
17+
from .eval import AstEval, EvalFuncVar, EvalFuncVarAstCtx
1818
from .event import Event
1919
from .function import Function
2020
from .mqtt import Mqtt
@@ -133,11 +133,52 @@ async def wait_until_call(*arg, **kw):
133133

134134
return wait_until_call
135135

136+
def user_task_create_factory(ast_ctx):
137+
"""Return wapper to call to astFunction with the ast context."""
138+
139+
async def user_task_create(func, *args, **kwargs):
140+
"""Implement task.create()."""
141+
142+
async def func_call(func, new_ast_ctx, *args, **kwargs):
143+
"""Call user function inside task.create()."""
144+
ret = await func.call(new_ast_ctx, *args, **kwargs)
145+
if new_ast_ctx.get_exception_obj():
146+
new_ast_ctx.get_logger().error(new_ast_ctx.get_exception_long())
147+
return ret
148+
149+
if not isinstance(func, (EvalFuncVar, EvalFuncVarAstCtx)):
150+
raise TypeError("function is not callable by task.create()")
151+
152+
new_ast_ctx = AstEval(
153+
f"{ast_ctx.get_global_ctx_name()}.{func.get_name()}", ast_ctx.get_global_ctx()
154+
)
155+
Function.install_ast_funcs(new_ast_ctx)
156+
return Function.create_task(func_call(func, new_ast_ctx, *args, **kwargs))
157+
158+
return user_task_create
159+
136160
ast_funcs = {
137161
"task.wait_until": wait_until_factory,
162+
"task.create": user_task_create_factory,
138163
}
139164
Function.register_ast(ast_funcs)
140165

166+
def user_task_cancel(task):
167+
"""Implement task.cancel()."""
168+
if not isinstance(task, asyncio.Task):
169+
raise TypeError(f"{task} is not of type asyncio.Task")
170+
Function.reaper_cancel(task)
171+
172+
async def user_task_wait(aws):
173+
"""Implement task.wait()."""
174+
return await asyncio.wait(aws)
175+
176+
funcs = {
177+
"task.cancel": user_task_cancel,
178+
"task.wait": user_task_wait,
179+
}
180+
Function.register(funcs)
181+
141182
for i in range(0, 7):
142183
cls.dow2int[locale.nl_langinfo(getattr(locale, f"ABDAY_{i + 1}")).lower()] = i
143184
cls.dow2int[locale.nl_langinfo(getattr(locale, f"DAY_{i + 1}")).lower()] = i

0 commit comments

Comments
 (0)