mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
Add max_exceeded log level option to automations & scripts (#39448)
This commit is contained in:
parent
603707aa85
commit
4486251382
@ -39,6 +39,7 @@ from homeassistant.helpers.script import (
|
|||||||
ATTR_MAX,
|
ATTR_MAX,
|
||||||
ATTR_MODE,
|
ATTR_MODE,
|
||||||
CONF_MAX,
|
CONF_MAX,
|
||||||
|
CONF_MAX_EXCEEDED,
|
||||||
SCRIPT_MODE_SINGLE,
|
SCRIPT_MODE_SINGLE,
|
||||||
Script,
|
Script,
|
||||||
make_script_schema,
|
make_script_schema,
|
||||||
@ -515,6 +516,7 @@ async def _async_process_config(hass, config, component):
|
|||||||
running_description="automation actions",
|
running_description="automation actions",
|
||||||
script_mode=config_block[CONF_MODE],
|
script_mode=config_block[CONF_MODE],
|
||||||
max_runs=config_block[CONF_MAX],
|
max_runs=config_block[CONF_MAX],
|
||||||
|
max_exceeded=config_block[CONF_MAX_EXCEEDED],
|
||||||
logger=_LOGGER,
|
logger=_LOGGER,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ from homeassistant.helpers.script import (
|
|||||||
ATTR_MAX,
|
ATTR_MAX,
|
||||||
ATTR_MODE,
|
ATTR_MODE,
|
||||||
CONF_MAX,
|
CONF_MAX,
|
||||||
|
CONF_MAX_EXCEEDED,
|
||||||
SCRIPT_MODE_SINGLE,
|
SCRIPT_MODE_SINGLE,
|
||||||
Script,
|
Script,
|
||||||
make_script_schema,
|
make_script_schema,
|
||||||
@ -260,6 +261,7 @@ class ScriptEntity(ToggleEntity):
|
|||||||
change_listener=self.async_change_listener,
|
change_listener=self.async_change_listener,
|
||||||
script_mode=cfg[CONF_MODE],
|
script_mode=cfg[CONF_MODE],
|
||||||
max_runs=cfg[CONF_MAX],
|
max_runs=cfg[CONF_MAX],
|
||||||
|
max_exceeded=cfg[CONF_MAX_EXCEEDED],
|
||||||
logger=logging.getLogger(f"{__name__}.{object_id}"),
|
logger=logging.getLogger(f"{__name__}.{object_id}"),
|
||||||
)
|
)
|
||||||
self._changed = asyncio.Event()
|
self._changed = asyncio.Event()
|
||||||
|
@ -24,6 +24,7 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from homeassistant import exceptions
|
from homeassistant import exceptions
|
||||||
import homeassistant.components.device_automation as device_automation
|
import homeassistant.components.device_automation as device_automation
|
||||||
|
from homeassistant.components.logger import LOGSEVERITY
|
||||||
import homeassistant.components.scene as scene
|
import homeassistant.components.scene as scene
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
@ -88,6 +89,10 @@ DEFAULT_SCRIPT_MODE = SCRIPT_MODE_SINGLE
|
|||||||
CONF_MAX = "max"
|
CONF_MAX = "max"
|
||||||
DEFAULT_MAX = 10
|
DEFAULT_MAX = 10
|
||||||
|
|
||||||
|
CONF_MAX_EXCEEDED = "max_exceeded"
|
||||||
|
_MAX_EXCEEDED_CHOICES = list(LOGSEVERITY) + ["SILENT"]
|
||||||
|
DEFAULT_MAX_EXCEEDED = "WARNING"
|
||||||
|
|
||||||
ATTR_CUR = "current"
|
ATTR_CUR = "current"
|
||||||
ATTR_MAX = "max"
|
ATTR_MAX = "max"
|
||||||
ATTR_MODE = "mode"
|
ATTR_MODE = "mode"
|
||||||
@ -113,6 +118,9 @@ def make_script_schema(schema, default_script_mode, extra=vol.PREVENT_EXTRA):
|
|||||||
vol.Optional(CONF_MAX, default=DEFAULT_MAX): vol.All(
|
vol.Optional(CONF_MAX, default=DEFAULT_MAX): vol.All(
|
||||||
vol.Coerce(int), vol.Range(min=2)
|
vol.Coerce(int), vol.Range(min=2)
|
||||||
),
|
),
|
||||||
|
vol.Optional(CONF_MAX_EXCEEDED, default=DEFAULT_MAX_EXCEEDED): vol.All(
|
||||||
|
vol.Upper, vol.In(_MAX_EXCEEDED_CHOICES)
|
||||||
|
),
|
||||||
},
|
},
|
||||||
extra=extra,
|
extra=extra,
|
||||||
)
|
)
|
||||||
@ -710,6 +718,7 @@ class Script:
|
|||||||
change_listener: Optional[Callable[..., Any]] = None,
|
change_listener: Optional[Callable[..., Any]] = None,
|
||||||
script_mode: str = DEFAULT_SCRIPT_MODE,
|
script_mode: str = DEFAULT_SCRIPT_MODE,
|
||||||
max_runs: int = DEFAULT_MAX,
|
max_runs: int = DEFAULT_MAX,
|
||||||
|
max_exceeded: str = DEFAULT_MAX_EXCEEDED,
|
||||||
logger: Optional[logging.Logger] = None,
|
logger: Optional[logging.Logger] = None,
|
||||||
log_exceptions: bool = True,
|
log_exceptions: bool = True,
|
||||||
top_level: bool = True,
|
top_level: bool = True,
|
||||||
@ -743,6 +752,7 @@ class Script:
|
|||||||
|
|
||||||
self._runs: List[_ScriptRun] = []
|
self._runs: List[_ScriptRun] = []
|
||||||
self.max_runs = max_runs
|
self.max_runs = max_runs
|
||||||
|
self._max_exceeded = max_exceeded
|
||||||
if script_mode == SCRIPT_MODE_QUEUED:
|
if script_mode == SCRIPT_MODE_QUEUED:
|
||||||
self._queue_lck = asyncio.Lock()
|
self._queue_lck = asyncio.Lock()
|
||||||
self._config_cache: Dict[Set[Tuple], Callable[..., bool]] = {}
|
self._config_cache: Dict[Set[Tuple], Callable[..., bool]] = {}
|
||||||
@ -871,13 +881,18 @@ class Script:
|
|||||||
|
|
||||||
if self.is_running:
|
if self.is_running:
|
||||||
if self.script_mode == SCRIPT_MODE_SINGLE:
|
if self.script_mode == SCRIPT_MODE_SINGLE:
|
||||||
self._log("Already running", level=logging.WARNING)
|
if self._max_exceeded != "SILENT":
|
||||||
|
self._log("Already running", level=LOGSEVERITY[self._max_exceeded])
|
||||||
return
|
return
|
||||||
if self.script_mode == SCRIPT_MODE_RESTART:
|
if self.script_mode == SCRIPT_MODE_RESTART:
|
||||||
self._log("Restarting")
|
self._log("Restarting")
|
||||||
await self.async_stop(update_state=False)
|
await self.async_stop(update_state=False)
|
||||||
elif len(self._runs) == self.max_runs:
|
elif len(self._runs) == self.max_runs:
|
||||||
self._log("Maximum number of runs exceeded", level=logging.WARNING)
|
if self._max_exceeded != "SILENT":
|
||||||
|
self._log(
|
||||||
|
"Maximum number of runs exceeded",
|
||||||
|
level=LOGSEVERITY[self._max_exceeded],
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# If this is a top level Script then make a copy of the variables in case they
|
# If this is a top level Script then make a copy of the variables in case they
|
||||||
|
@ -1419,6 +1419,60 @@ async def test_script_mode_single(hass, caplog):
|
|||||||
assert events[1].data["value"] == 2
|
assert events[1].data["value"] == 2
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("max_exceeded", [None, "WARNING", "INFO", "ERROR", "SILENT"])
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"script_mode,max_runs", [("single", 1), ("parallel", 2), ("queued", 2)]
|
||||||
|
)
|
||||||
|
async def test_max_exceeded(hass, caplog, max_exceeded, script_mode, max_runs):
|
||||||
|
"""Test max_exceeded option."""
|
||||||
|
sequence = cv.SCRIPT_SCHEMA(
|
||||||
|
{"wait_template": "{{ states.switch.test.state == 'off' }}"}
|
||||||
|
)
|
||||||
|
if max_exceeded is None:
|
||||||
|
script_obj = script.Script(
|
||||||
|
hass,
|
||||||
|
sequence,
|
||||||
|
"Test Name",
|
||||||
|
"test_domain",
|
||||||
|
script_mode=script_mode,
|
||||||
|
max_runs=max_runs,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
script_obj = script.Script(
|
||||||
|
hass,
|
||||||
|
sequence,
|
||||||
|
"Test Name",
|
||||||
|
"test_domain",
|
||||||
|
script_mode=script_mode,
|
||||||
|
max_runs=max_runs,
|
||||||
|
max_exceeded=max_exceeded,
|
||||||
|
)
|
||||||
|
hass.states.async_set("switch.test", "on")
|
||||||
|
for _ in range(max_runs + 1):
|
||||||
|
hass.async_create_task(script_obj.async_run(context=Context()))
|
||||||
|
hass.states.async_set("switch.test", "off")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
if max_exceeded is None:
|
||||||
|
max_exceeded = "WARNING"
|
||||||
|
if max_exceeded == "SILENT":
|
||||||
|
assert not any(
|
||||||
|
any(
|
||||||
|
message in rec.message
|
||||||
|
for message in ("Already running", "Maximum number of runs exceeded")
|
||||||
|
)
|
||||||
|
for rec in caplog.records
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
assert any(
|
||||||
|
rec.levelname == max_exceeded
|
||||||
|
and any(
|
||||||
|
message in rec.message
|
||||||
|
for message in ("Already running", "Maximum number of runs exceeded")
|
||||||
|
)
|
||||||
|
for rec in caplog.records
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"script_mode,messages,last_events",
|
"script_mode,messages,last_events",
|
||||||
[("restart", ["Restarting"], [2]), ("parallel", [], [2, 2])],
|
[("restart", ["Restarting"], [2]), ("parallel", [], [2, 2])],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user