Skip to content

Commit 028656f

Browse files
committed
add support for service blocking
1 parent beaf1b5 commit 028656f

File tree

3 files changed

+44
-21
lines changed

3 files changed

+44
-21
lines changed

custom_components/pyscript/function.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,18 @@ def service_has_service(cls, domain, name):
190190
async def service_call(cls, domain, name, **kwargs):
191191
"""Implement service.call()."""
192192
curr_task = asyncio.current_task()
193-
if "context" in kwargs and isinstance(kwargs["context"], Context):
194-
context = kwargs["context"]
195-
del kwargs["context"]
196-
else:
197-
context = cls.task2context.get(curr_task, None)
198-
199-
await cls.hass.services.async_call(domain, name, kwargs, context=context)
193+
hass_args = {}
194+
for keyword, typ, default in [
195+
("context", Context, cls.task2context.get(curr_task, None)),
196+
("blocking", bool, None),
197+
("limit", float, None),
198+
]:
199+
if keyword in kwargs and isinstance(kwargs[keyword], typ):
200+
hass_args[keyword] = kwargs.pop(keyword)
201+
elif default:
202+
hass_args[keyword] = default
203+
204+
await cls.hass.services.async_call(domain, name, kwargs, **hass_args)
200205

201206
@classmethod
202207
async def service_completions(cls, root):
@@ -255,15 +260,20 @@ def get(cls, name):
255260
def service_call_factory(domain, service):
256261
async def service_call(*args, **kwargs):
257262
curr_task = asyncio.current_task()
258-
if "context" in kwargs and isinstance(kwargs["context"], Context):
259-
context = kwargs["context"]
260-
del kwargs["context"]
261-
else:
262-
context = cls.task2context.get(curr_task, None)
263+
hass_args = {}
264+
for keyword, typ, default in [
265+
("context", Context, cls.task2context.get(curr_task, None)),
266+
("blocking", bool, None),
267+
("limit", float, None),
268+
]:
269+
if keyword in kwargs and isinstance(kwargs[keyword], typ):
270+
hass_args[keyword] = kwargs.pop(keyword)
271+
elif default:
272+
hass_args[keyword] = default
263273

264274
if len(args) != 0:
265275
raise (TypeError, f"service {domain}.{service} takes no positional arguments")
266-
await cls.hass.services.async_call(domain, service, kwargs, context=context)
276+
await cls.hass.services.async_call(domain, service, kwargs, **hass_args)
267277

268278
return service_call
269279

custom_components/pyscript/state.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -258,11 +258,16 @@ async def get(cls, var_name):
258258
def service_call_factory(domain, service, entity_id, params):
259259
async def service_call(*args, **kwargs):
260260
curr_task = asyncio.current_task()
261-
if "context" in kwargs and isinstance(kwargs["context"], Context):
262-
context = kwargs["context"]
263-
del kwargs["context"]
264-
else:
265-
context = Function.task2context.get(curr_task, None)
261+
hass_args = {}
262+
for keyword, typ, default in [
263+
("context", Context, Function.task2context.get(curr_task, None)),
264+
("blocking", bool, None),
265+
("limit", float, None),
266+
]:
267+
if keyword in kwargs and isinstance(kwargs[keyword], typ):
268+
hass_args[keyword] = kwargs.pop(keyword)
269+
elif default:
270+
hass_args[keyword] = default
266271

267272
kwargs["entity_id"] = entity_id
268273
if len(args) == 1 and len(params) == 1:
@@ -273,7 +278,7 @@ async def service_call(*args, **kwargs):
273278
kwargs[param_name] = args[0]
274279
elif len(args) != 0:
275280
raise TypeError(f"service {domain}.{service} takes no positional arguments")
276-
await cls.hass.services.async_call(domain, service, kwargs, context=context)
281+
await cls.hass.services.async_call(domain, service, kwargs, **hass_args)
277282

278283
return service_call
279284

docs/reference.rst

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ called by:
210210
211211
service.call("myservice", "flash_light", light_name="front", light_color="red")
212212
213+
When making a service call, either using the ``service.call`` function or the service name as the
214+
function, you can optionally pass the keyword argument ``blocking=True`` if you would like to wait
215+
for the service to finish execution before continuing execution in your function. You can also
216+
specify a timeout for a blocking service call using the ``limit=<number_of_seconds>`` parameters.
217+
213218
Firing events
214219
-------------
215220

@@ -691,8 +696,11 @@ or ``float()``). Attributes keep their native type.
691696
Service Calls
692697
^^^^^^^^^^^^^
693698

694-
``service.call(domain, name, **kwargs)``
695-
calls the service ``domain.name`` with the given keyword arguments as parameters.
699+
``service.call(domain, name, blocking=False, limit=10, **kwargs)``
700+
calls the service ``domain.name`` with the given keyword arguments as parameters. If ``blocking``
701+
is ``True``, pyscript will wait for the service to finish executing before continuing the current
702+
routine, or will wait a maximum of the number of seconds specified in the `limit` keyword
703+
argument.
696704
``service.has_service(domain, name)``
697705
returns whether the service ``domain.name`` exists.
698706

0 commit comments

Comments
 (0)