mirror of
https://github.com/home-assistant/core
synced 2024-10-04 19:43:00 +00:00
Move recorder services to services.py (#71249)
This commit is contained in:
parent
0580803b7d
commit
e1be6dd34f
|
@ -188,6 +188,7 @@ homeassistant.components.recorder.pool
|
|||
homeassistant.components.recorder.purge
|
||||
homeassistant.components.recorder.repack
|
||||
homeassistant.components.recorder.run_history
|
||||
homeassistant.components.recorder.services
|
||||
homeassistant.components.recorder.statistics
|
||||
homeassistant.components.recorder.system_health
|
||||
homeassistant.components.recorder.tasks
|
||||
|
|
|
@ -7,7 +7,7 @@ from typing import Any
|
|||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import CONF_EXCLUDE, EVENT_STATE_CHANGED
|
||||
from homeassistant.core import HomeAssistant, ServiceCall, callback
|
||||
from homeassistant.core import HomeAssistant
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.entityfilter import (
|
||||
INCLUDE_EXCLUDE_BASE_FILTER_SCHEMA,
|
||||
|
@ -17,15 +17,11 @@ from homeassistant.helpers.entityfilter import (
|
|||
from homeassistant.helpers.integration_platform import (
|
||||
async_process_integration_platforms,
|
||||
)
|
||||
from homeassistant.helpers.service import async_extract_entity_ids
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
from . import history, statistics, websocket_api
|
||||
from .const import (
|
||||
ATTR_APPLY_FILTER,
|
||||
ATTR_KEEP_DAYS,
|
||||
ATTR_REPACK,
|
||||
CONF_DB_INTEGRITY_CHECK,
|
||||
DATA_INSTANCE,
|
||||
DOMAIN,
|
||||
|
@ -33,39 +29,12 @@ from .const import (
|
|||
SQLITE_URL_PREFIX,
|
||||
)
|
||||
from .core import Recorder
|
||||
from .services import async_register_services
|
||||
from .tasks import AddRecorderPlatformTask
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
SERVICE_PURGE = "purge"
|
||||
SERVICE_PURGE_ENTITIES = "purge_entities"
|
||||
SERVICE_ENABLE = "enable"
|
||||
SERVICE_DISABLE = "disable"
|
||||
|
||||
|
||||
SERVICE_PURGE_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(ATTR_KEEP_DAYS): cv.positive_int,
|
||||
vol.Optional(ATTR_REPACK, default=False): cv.boolean,
|
||||
vol.Optional(ATTR_APPLY_FILTER, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
|
||||
ATTR_DOMAINS = "domains"
|
||||
ATTR_ENTITY_GLOBS = "entity_globs"
|
||||
|
||||
SERVICE_PURGE_ENTITIES_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(ATTR_DOMAINS, default=[]): vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(ATTR_ENTITY_GLOBS, default=[]): vol.All(
|
||||
cv.ensure_list, [cv.string]
|
||||
),
|
||||
}
|
||||
).extend(cv.ENTITY_SERVICE_FIELDS)
|
||||
SERVICE_ENABLE_SCHEMA = vol.Schema({})
|
||||
SERVICE_DISABLE_SCHEMA = vol.Schema({})
|
||||
|
||||
DEFAULT_URL = "sqlite:///{hass_config_path}"
|
||||
DEFAULT_DB_FILE = "home-assistant_v2.db"
|
||||
DEFAULT_DB_INTEGRITY_CHECK = True
|
||||
|
@ -196,7 +165,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||
instance.async_initialize()
|
||||
instance.async_register()
|
||||
instance.start()
|
||||
_async_register_services(hass, instance)
|
||||
async_register_services(hass, instance)
|
||||
history.async_setup(hass)
|
||||
statistics.async_setup(hass)
|
||||
websocket_api.async_setup(hass)
|
||||
|
@ -211,51 +180,3 @@ async def _process_recorder_platform(
|
|||
"""Process a recorder platform."""
|
||||
instance: Recorder = hass.data[DATA_INSTANCE]
|
||||
instance.queue.put(AddRecorderPlatformTask(domain, platform))
|
||||
|
||||
|
||||
@callback
|
||||
def _async_register_services(hass: HomeAssistant, instance: Recorder) -> None:
|
||||
"""Register recorder services."""
|
||||
|
||||
async def async_handle_purge_service(service: ServiceCall) -> None:
|
||||
"""Handle calls to the purge service."""
|
||||
instance.do_adhoc_purge(**service.data)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_PURGE, async_handle_purge_service, schema=SERVICE_PURGE_SCHEMA
|
||||
)
|
||||
|
||||
async def async_handle_purge_entities_service(service: ServiceCall) -> None:
|
||||
"""Handle calls to the purge entities service."""
|
||||
entity_ids = await async_extract_entity_ids(hass, service)
|
||||
domains = service.data.get(ATTR_DOMAINS, [])
|
||||
entity_globs = service.data.get(ATTR_ENTITY_GLOBS, [])
|
||||
|
||||
instance.do_adhoc_purge_entities(entity_ids, domains, entity_globs)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_PURGE_ENTITIES,
|
||||
async_handle_purge_entities_service,
|
||||
schema=SERVICE_PURGE_ENTITIES_SCHEMA,
|
||||
)
|
||||
|
||||
async def async_handle_enable_service(service: ServiceCall) -> None:
|
||||
instance.set_enable(True)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_ENABLE,
|
||||
async_handle_enable_service,
|
||||
schema=SERVICE_ENABLE_SCHEMA,
|
||||
)
|
||||
|
||||
async def async_handle_disable_service(service: ServiceCall) -> None:
|
||||
instance.set_enable(False)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_DISABLE,
|
||||
async_handle_disable_service,
|
||||
schema=SERVICE_DISABLE_SCHEMA,
|
||||
)
|
||||
|
|
106
homeassistant/components/recorder/services.py
Normal file
106
homeassistant/components/recorder/services.py
Normal file
|
@ -0,0 +1,106 @@
|
|||
"""Support for recorder services."""
|
||||
from __future__ import annotations
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.core import HomeAssistant, ServiceCall, callback
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.service import async_extract_entity_ids
|
||||
|
||||
from .const import ATTR_APPLY_FILTER, ATTR_KEEP_DAYS, ATTR_REPACK, DOMAIN
|
||||
from .core import Recorder
|
||||
|
||||
SERVICE_PURGE = "purge"
|
||||
SERVICE_PURGE_ENTITIES = "purge_entities"
|
||||
SERVICE_ENABLE = "enable"
|
||||
SERVICE_DISABLE = "disable"
|
||||
|
||||
|
||||
SERVICE_PURGE_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(ATTR_KEEP_DAYS): cv.positive_int,
|
||||
vol.Optional(ATTR_REPACK, default=False): cv.boolean,
|
||||
vol.Optional(ATTR_APPLY_FILTER, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
|
||||
ATTR_DOMAINS = "domains"
|
||||
ATTR_ENTITY_GLOBS = "entity_globs"
|
||||
|
||||
SERVICE_PURGE_ENTITIES_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(ATTR_DOMAINS, default=[]): vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(ATTR_ENTITY_GLOBS, default=[]): vol.All(
|
||||
cv.ensure_list, [cv.string]
|
||||
),
|
||||
}
|
||||
).extend(cv.ENTITY_SERVICE_FIELDS)
|
||||
|
||||
SERVICE_ENABLE_SCHEMA = vol.Schema({})
|
||||
SERVICE_DISABLE_SCHEMA = vol.Schema({})
|
||||
|
||||
|
||||
@callback
|
||||
def _async_register_purge_service(hass: HomeAssistant, instance: Recorder) -> None:
|
||||
async def async_handle_purge_service(service: ServiceCall) -> None:
|
||||
"""Handle calls to the purge service."""
|
||||
instance.do_adhoc_purge(**service.data)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_PURGE, async_handle_purge_service, schema=SERVICE_PURGE_SCHEMA
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def _async_register_purge_entities_service(
|
||||
hass: HomeAssistant, instance: Recorder
|
||||
) -> None:
|
||||
async def async_handle_purge_entities_service(service: ServiceCall) -> None:
|
||||
"""Handle calls to the purge entities service."""
|
||||
entity_ids = await async_extract_entity_ids(hass, service)
|
||||
domains = service.data.get(ATTR_DOMAINS, [])
|
||||
entity_globs = service.data.get(ATTR_ENTITY_GLOBS, [])
|
||||
|
||||
instance.do_adhoc_purge_entities(entity_ids, domains, entity_globs)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_PURGE_ENTITIES,
|
||||
async_handle_purge_entities_service,
|
||||
schema=SERVICE_PURGE_ENTITIES_SCHEMA,
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def _async_register_enable_service(hass: HomeAssistant, instance: Recorder) -> None:
|
||||
async def async_handle_enable_service(service: ServiceCall) -> None:
|
||||
instance.set_enable(True)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_ENABLE,
|
||||
async_handle_enable_service,
|
||||
schema=SERVICE_ENABLE_SCHEMA,
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def _async_register_disable_service(hass: HomeAssistant, instance: Recorder) -> None:
|
||||
async def async_handle_disable_service(service: ServiceCall) -> None:
|
||||
instance.set_enable(False)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_DISABLE,
|
||||
async_handle_disable_service,
|
||||
schema=SERVICE_DISABLE_SCHEMA,
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def async_register_services(hass: HomeAssistant, instance: Recorder) -> None:
|
||||
"""Register recorder services."""
|
||||
_async_register_purge_service(hass, instance)
|
||||
_async_register_purge_entities_service(hass, instance)
|
||||
_async_register_enable_service(hass, instance)
|
||||
_async_register_disable_service(hass, instance)
|
11
mypy.ini
11
mypy.ini
|
@ -1831,6 +1831,17 @@ no_implicit_optional = true
|
|||
warn_return_any = true
|
||||
warn_unreachable = true
|
||||
|
||||
[mypy-homeassistant.components.recorder.services]
|
||||
check_untyped_defs = true
|
||||
disallow_incomplete_defs = true
|
||||
disallow_subclassing_any = true
|
||||
disallow_untyped_calls = true
|
||||
disallow_untyped_decorators = true
|
||||
disallow_untyped_defs = true
|
||||
no_implicit_optional = true
|
||||
warn_return_any = true
|
||||
warn_unreachable = true
|
||||
|
||||
[mypy-homeassistant.components.recorder.statistics]
|
||||
check_untyped_defs = true
|
||||
disallow_incomplete_defs = true
|
||||
|
|
|
@ -20,10 +20,6 @@ from homeassistant.components.recorder import (
|
|||
CONF_DB_URL,
|
||||
CONFIG_SCHEMA,
|
||||
DOMAIN,
|
||||
SERVICE_DISABLE,
|
||||
SERVICE_ENABLE,
|
||||
SERVICE_PURGE,
|
||||
SERVICE_PURGE_ENTITIES,
|
||||
SQLITE_URL_PREFIX,
|
||||
Recorder,
|
||||
get_instance,
|
||||
|
@ -38,6 +34,12 @@ from homeassistant.components.recorder.models import (
|
|||
StatisticsRuns,
|
||||
process_timestamp,
|
||||
)
|
||||
from homeassistant.components.recorder.services import (
|
||||
SERVICE_DISABLE,
|
||||
SERVICE_ENABLE,
|
||||
SERVICE_PURGE,
|
||||
SERVICE_PURGE_ENTITIES,
|
||||
)
|
||||
from homeassistant.components.recorder.util import session_scope
|
||||
from homeassistant.const import (
|
||||
EVENT_HOMEASSISTANT_FINAL_WRITE,
|
||||
|
|
|
@ -19,6 +19,10 @@ from homeassistant.components.recorder.models import (
|
|||
StatisticsShortTerm,
|
||||
)
|
||||
from homeassistant.components.recorder.purge import purge_old_data
|
||||
from homeassistant.components.recorder.services import (
|
||||
SERVICE_PURGE,
|
||||
SERVICE_PURGE_ENTITIES,
|
||||
)
|
||||
from homeassistant.components.recorder.tasks import PurgeTask
|
||||
from homeassistant.components.recorder.util import session_scope
|
||||
from homeassistant.const import EVENT_STATE_CHANGED, STATE_ON
|
||||
|
@ -133,9 +137,7 @@ async def test_purge_old_states_encouters_database_corruption(
|
|||
"homeassistant.components.recorder.purge.purge_old_data",
|
||||
side_effect=sqlite3_exception,
|
||||
):
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, {"keep_days": 0}
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, {"keep_days": 0})
|
||||
await hass.async_block_till_done()
|
||||
await async_wait_recording_done(hass)
|
||||
|
||||
|
@ -169,9 +171,7 @@ async def test_purge_old_states_encounters_temporary_mysql_error(
|
|||
), patch.object(
|
||||
instance.engine.dialect, "name", "mysql"
|
||||
):
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, {"keep_days": 0}
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, {"keep_days": 0})
|
||||
await hass.async_block_till_done()
|
||||
await async_wait_recording_done(hass)
|
||||
await async_wait_recording_done(hass)
|
||||
|
@ -197,9 +197,7 @@ async def test_purge_old_states_encounters_operational_error(
|
|||
"homeassistant.components.recorder.purge._purge_old_recorder_runs",
|
||||
side_effect=exception,
|
||||
):
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, {"keep_days": 0}
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, {"keep_days": 0})
|
||||
await hass.async_block_till_done()
|
||||
await async_wait_recording_done(hass)
|
||||
await async_wait_recording_done(hass)
|
||||
|
@ -452,9 +450,7 @@ async def test_purge_edge_case(
|
|||
events = session.query(Events).filter(Events.event_type == "EVENT_TEST_PURGE")
|
||||
assert events.count() == 1
|
||||
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, service_data
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, service_data)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await async_recorder_block_till_done(hass)
|
||||
|
@ -722,9 +718,7 @@ async def test_purge_filtered_states(
|
|||
assert events_keep.count() == 1
|
||||
|
||||
# Normal purge doesn't remove excluded entities
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, service_data
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, service_data)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await async_recorder_block_till_done(hass)
|
||||
|
@ -742,9 +736,7 @@ async def test_purge_filtered_states(
|
|||
|
||||
# Test with 'apply_filter' = True
|
||||
service_data["apply_filter"] = True
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, service_data
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, service_data)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await async_recorder_block_till_done(hass)
|
||||
|
@ -780,9 +772,7 @@ async def test_purge_filtered_states(
|
|||
assert session.query(StateAttributes).count() == 11
|
||||
|
||||
# Do it again to make sure nothing changes
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, service_data
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, service_data)
|
||||
await async_recorder_block_till_done(hass)
|
||||
await async_wait_purge_done(hass)
|
||||
|
||||
|
@ -794,9 +784,7 @@ async def test_purge_filtered_states(
|
|||
assert session.query(StateAttributes).count() == 11
|
||||
|
||||
service_data = {"keep_days": 0}
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, service_data
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, service_data)
|
||||
await async_recorder_block_till_done(hass)
|
||||
await async_wait_purge_done(hass)
|
||||
|
||||
|
@ -844,9 +832,7 @@ async def test_purge_filtered_states_to_empty(
|
|||
|
||||
# Test with 'apply_filter' = True
|
||||
service_data["apply_filter"] = True
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, service_data
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, service_data)
|
||||
await async_recorder_block_till_done(hass)
|
||||
await async_wait_purge_done(hass)
|
||||
|
||||
|
@ -858,9 +844,7 @@ async def test_purge_filtered_states_to_empty(
|
|||
|
||||
# Do it again to make sure nothing changes
|
||||
# Why do we do this? Should we check the end result?
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, service_data
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, service_data)
|
||||
await async_recorder_block_till_done(hass)
|
||||
await async_wait_purge_done(hass)
|
||||
|
||||
|
@ -914,9 +898,7 @@ async def test_purge_without_state_attributes_filtered_states_to_empty(
|
|||
|
||||
# Test with 'apply_filter' = True
|
||||
service_data["apply_filter"] = True
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, service_data
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, service_data)
|
||||
await async_recorder_block_till_done(hass)
|
||||
await async_wait_purge_done(hass)
|
||||
|
||||
|
@ -928,9 +910,7 @@ async def test_purge_without_state_attributes_filtered_states_to_empty(
|
|||
|
||||
# Do it again to make sure nothing changes
|
||||
# Why do we do this? Should we check the end result?
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, service_data
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, service_data)
|
||||
await async_recorder_block_till_done(hass)
|
||||
await async_wait_purge_done(hass)
|
||||
|
||||
|
@ -985,9 +965,7 @@ async def test_purge_filtered_events(
|
|||
assert states.count() == 10
|
||||
|
||||
# Normal purge doesn't remove excluded events
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, service_data
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, service_data)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await async_recorder_block_till_done(hass)
|
||||
|
@ -1005,9 +983,7 @@ async def test_purge_filtered_events(
|
|||
|
||||
# Test with 'apply_filter' = True
|
||||
service_data["apply_filter"] = True
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, service_data
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, service_data)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await async_recorder_block_till_done(hass)
|
||||
|
@ -1105,9 +1081,7 @@ async def test_purge_filtered_events_state_changed(
|
|||
assert events_purge.count() == 60
|
||||
assert states.count() == 63
|
||||
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE, service_data
|
||||
)
|
||||
await hass.services.async_call(recorder.DOMAIN, SERVICE_PURGE, service_data)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await async_recorder_block_till_done(hass)
|
||||
|
@ -1146,7 +1120,7 @@ async def test_purge_entities(
|
|||
}
|
||||
|
||||
await hass.services.async_call(
|
||||
recorder.DOMAIN, recorder.SERVICE_PURGE_ENTITIES, service_data
|
||||
recorder.DOMAIN, SERVICE_PURGE_ENTITIES, service_data
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
|
Loading…
Reference in a new issue