mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 09:47:13 +00:00
Make helpers.condition.* async
This commit is contained in:
parent
33a51623f8
commit
185bd6c28a
@ -20,15 +20,43 @@ import homeassistant.util.dt as dt_util
|
|||||||
from homeassistant.util.async import run_callback_threadsafe
|
from homeassistant.util.async import run_callback_threadsafe
|
||||||
|
|
||||||
FROM_CONFIG_FORMAT = '{}_from_config'
|
FROM_CONFIG_FORMAT = '{}_from_config'
|
||||||
|
ASYNC_FROM_CONFIG_FORMAT = 'async_{}_from_config'
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# PyLint does not like the use of _threaded_factory
|
||||||
|
# pylint: disable=invalid-name
|
||||||
|
|
||||||
def from_config(config: ConfigType, config_validation: bool=True):
|
|
||||||
"""Turn a condition configuration into a method."""
|
def _threaded_factory(async_factory):
|
||||||
factory = getattr(
|
"""Helper method to create threaded versions of async factories."""
|
||||||
sys.modules[__name__],
|
def factory(config, config_validation=True):
|
||||||
FROM_CONFIG_FORMAT.format(config.get(CONF_CONDITION)), None)
|
"""Threaded factory."""
|
||||||
|
async_check = async_factory(config, config_validation)
|
||||||
|
|
||||||
|
def condition_if(hass, variables=None):
|
||||||
|
"""Validate condition."""
|
||||||
|
return run_callback_threadsafe(
|
||||||
|
hass.loop, async_check, hass, variables,
|
||||||
|
).result()
|
||||||
|
|
||||||
|
return condition_if
|
||||||
|
|
||||||
|
return factory
|
||||||
|
|
||||||
|
|
||||||
|
def async_from_config(config: ConfigType, config_validation: bool=True):
|
||||||
|
"""Turn a condition configuration into a method.
|
||||||
|
|
||||||
|
Should be run on the event loop.
|
||||||
|
"""
|
||||||
|
for fmt in (ASYNC_FROM_CONFIG_FORMAT, FROM_CONFIG_FORMAT):
|
||||||
|
factory = getattr(
|
||||||
|
sys.modules[__name__],
|
||||||
|
fmt.format(config.get(CONF_CONDITION)), None)
|
||||||
|
|
||||||
|
if factory:
|
||||||
|
break
|
||||||
|
|
||||||
if factory is None:
|
if factory is None:
|
||||||
raise HomeAssistantError('Invalid condition "{}" specified {}'.format(
|
raise HomeAssistantError('Invalid condition "{}" specified {}'.format(
|
||||||
@ -37,49 +65,70 @@ def from_config(config: ConfigType, config_validation: bool=True):
|
|||||||
return factory(config, config_validation)
|
return factory(config, config_validation)
|
||||||
|
|
||||||
|
|
||||||
def and_from_config(config: ConfigType, config_validation: bool=True):
|
from_config = _threaded_factory(async_from_config)
|
||||||
|
|
||||||
|
|
||||||
|
def async_and_from_config(config: ConfigType, config_validation: bool=True):
|
||||||
"""Create multi condition matcher using 'AND'."""
|
"""Create multi condition matcher using 'AND'."""
|
||||||
if config_validation:
|
if config_validation:
|
||||||
config = cv.AND_CONDITION_SCHEMA(config)
|
config = cv.AND_CONDITION_SCHEMA(config)
|
||||||
checks = [from_config(entry, False) for entry in config['conditions']]
|
checks = None
|
||||||
|
|
||||||
def if_and_condition(hass: HomeAssistant,
|
def if_and_condition(hass: HomeAssistant,
|
||||||
variables=None) -> bool:
|
variables=None) -> bool:
|
||||||
"""Test and condition."""
|
"""Test and condition."""
|
||||||
for check in checks:
|
nonlocal checks
|
||||||
try:
|
|
||||||
|
if checks is None:
|
||||||
|
checks = [async_from_config(entry, False) for entry
|
||||||
|
in config['conditions']]
|
||||||
|
|
||||||
|
try:
|
||||||
|
for check in checks:
|
||||||
if not check(hass, variables):
|
if not check(hass, variables):
|
||||||
return False
|
return False
|
||||||
except Exception as ex: # pylint: disable=broad-except
|
except Exception as ex: # pylint: disable=broad-except
|
||||||
_LOGGER.warning('Error during and-condition: %s', ex)
|
_LOGGER.warning('Error during and-condition: %s', ex)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return if_and_condition
|
return if_and_condition
|
||||||
|
|
||||||
|
|
||||||
def or_from_config(config: ConfigType, config_validation: bool=True):
|
and_from_config = _threaded_factory(async_and_from_config)
|
||||||
|
|
||||||
|
|
||||||
|
def async_or_from_config(config: ConfigType, config_validation: bool=True):
|
||||||
"""Create multi condition matcher using 'OR'."""
|
"""Create multi condition matcher using 'OR'."""
|
||||||
if config_validation:
|
if config_validation:
|
||||||
config = cv.OR_CONDITION_SCHEMA(config)
|
config = cv.OR_CONDITION_SCHEMA(config)
|
||||||
checks = [from_config(entry, False) for entry in config['conditions']]
|
checks = None
|
||||||
|
|
||||||
def if_or_condition(hass: HomeAssistant,
|
def if_or_condition(hass: HomeAssistant,
|
||||||
variables=None) -> bool:
|
variables=None) -> bool:
|
||||||
"""Test and condition."""
|
"""Test and condition."""
|
||||||
for check in checks:
|
nonlocal checks
|
||||||
try:
|
|
||||||
|
if checks is None:
|
||||||
|
checks = [async_from_config(entry, False) for entry
|
||||||
|
in config['conditions']]
|
||||||
|
|
||||||
|
try:
|
||||||
|
for check in checks:
|
||||||
if check(hass, variables):
|
if check(hass, variables):
|
||||||
return True
|
return True
|
||||||
except Exception as ex: # pylint: disable=broad-except
|
except Exception as ex: # pylint: disable=broad-except
|
||||||
_LOGGER.warning('Error during or-condition: %s', ex)
|
_LOGGER.warning('Error during or-condition: %s', ex)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return if_or_condition
|
return if_or_condition
|
||||||
|
|
||||||
|
|
||||||
|
or_from_config = _threaded_factory(async_or_from_config)
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-many-arguments
|
# pylint: disable=too-many-arguments
|
||||||
def numeric_state(hass: HomeAssistant, entity, below=None, above=None,
|
def numeric_state(hass: HomeAssistant, entity, below=None, above=None,
|
||||||
value_template=None, variables=None):
|
value_template=None, variables=None):
|
||||||
@ -125,7 +174,7 @@ def async_numeric_state(hass: HomeAssistant, entity, below=None, above=None,
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def numeric_state_from_config(config, config_validation=True):
|
def async_numeric_state_from_config(config, config_validation=True):
|
||||||
"""Wrap action method with state based condition."""
|
"""Wrap action method with state based condition."""
|
||||||
if config_validation:
|
if config_validation:
|
||||||
config = cv.NUMERIC_STATE_CONDITION_SCHEMA(config)
|
config = cv.NUMERIC_STATE_CONDITION_SCHEMA(config)
|
||||||
@ -139,12 +188,15 @@ def numeric_state_from_config(config, config_validation=True):
|
|||||||
if value_template is not None:
|
if value_template is not None:
|
||||||
value_template.hass = hass
|
value_template.hass = hass
|
||||||
|
|
||||||
return numeric_state(hass, entity_id, below, above, value_template,
|
return async_numeric_state(
|
||||||
variables)
|
hass, entity_id, below, above, value_template, variables)
|
||||||
|
|
||||||
return if_numeric_state
|
return if_numeric_state
|
||||||
|
|
||||||
|
|
||||||
|
numeric_state_from_config = _threaded_factory(async_numeric_state_from_config)
|
||||||
|
|
||||||
|
|
||||||
def state(hass, entity, req_state, for_period=None):
|
def state(hass, entity, req_state, for_period=None):
|
||||||
"""Test if state matches requirements."""
|
"""Test if state matches requirements."""
|
||||||
if isinstance(entity, str):
|
if isinstance(entity, str):
|
||||||
@ -235,7 +287,7 @@ def async_template(hass, value_template, variables=None):
|
|||||||
return value.lower() == 'true'
|
return value.lower() == 'true'
|
||||||
|
|
||||||
|
|
||||||
def template_from_config(config, config_validation=True):
|
def async_template_from_config(config, config_validation=True):
|
||||||
"""Wrap action method with state based condition."""
|
"""Wrap action method with state based condition."""
|
||||||
if config_validation:
|
if config_validation:
|
||||||
config = cv.TEMPLATE_CONDITION_SCHEMA(config)
|
config = cv.TEMPLATE_CONDITION_SCHEMA(config)
|
||||||
@ -245,11 +297,14 @@ def template_from_config(config, config_validation=True):
|
|||||||
"""Validate template based if-condition."""
|
"""Validate template based if-condition."""
|
||||||
value_template.hass = hass
|
value_template.hass = hass
|
||||||
|
|
||||||
return template(hass, value_template, variables)
|
return async_template(hass, value_template, variables)
|
||||||
|
|
||||||
return template_if
|
return template_if
|
||||||
|
|
||||||
|
|
||||||
|
template_from_config = _threaded_factory(async_template_from_config)
|
||||||
|
|
||||||
|
|
||||||
def time(before=None, after=None, weekday=None):
|
def time(before=None, after=None, weekday=None):
|
||||||
"""Test if local time condition matches.
|
"""Test if local time condition matches.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user