mirror of https://github.com/home-assistant/core
Enable strict typing of diagnostics (#83053)
* Enable strict typing of diagnostics * Reformat to avoid line break
This commit is contained in:
parent
fc93521e02
commit
bf7e50eb32
|
@ -92,6 +92,7 @@ homeassistant.components.device_tracker.*
|
||||||
homeassistant.components.devolo_home_control.*
|
homeassistant.components.devolo_home_control.*
|
||||||
homeassistant.components.devolo_home_network.*
|
homeassistant.components.devolo_home_network.*
|
||||||
homeassistant.components.dhcp.*
|
homeassistant.components.dhcp.*
|
||||||
|
homeassistant.components.diagnostics.*
|
||||||
homeassistant.components.dlna_dmr.*
|
homeassistant.components.dlna_dmr.*
|
||||||
homeassistant.components.dnsip.*
|
homeassistant.components.dnsip.*
|
||||||
homeassistant.components.dsmr.*
|
homeassistant.components.dsmr.*
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
"""The Diagnostics integration."""
|
"""The Diagnostics integration."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable, Coroutine
|
||||||
|
from dataclasses import dataclass, field
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
@ -31,9 +33,28 @@ __all__ = ["REDACTED", "async_redact_data"]
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DiagnosticsPlatformData:
|
||||||
|
"""Diagnostic platform data."""
|
||||||
|
|
||||||
|
config_entry_diagnostics: Callable[
|
||||||
|
[HomeAssistant, ConfigEntry], Coroutine[Any, Any, Any]
|
||||||
|
] | None
|
||||||
|
device_diagnostics: Callable[
|
||||||
|
[HomeAssistant, ConfigEntry, DeviceEntry], Coroutine[Any, Any, Any]
|
||||||
|
] | None
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DiagnosticsData:
|
||||||
|
"""Diagnostic data."""
|
||||||
|
|
||||||
|
platforms: dict[str, DiagnosticsPlatformData] = field(default_factory=dict)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
"""Set up Diagnostics from a config entry."""
|
"""Set up Diagnostics from a config entry."""
|
||||||
hass.data[DOMAIN] = {}
|
hass.data[DOMAIN] = DiagnosticsData()
|
||||||
|
|
||||||
await integration_platform.async_process_integration_platforms(
|
await integration_platform.async_process_integration_platforms(
|
||||||
hass, DOMAIN, _register_diagnostics_platform
|
hass, DOMAIN, _register_diagnostics_platform
|
||||||
|
@ -62,16 +83,13 @@ class DiagnosticsProtocol(Protocol):
|
||||||
|
|
||||||
async def _register_diagnostics_platform(
|
async def _register_diagnostics_platform(
|
||||||
hass: HomeAssistant, integration_domain: str, platform: DiagnosticsProtocol
|
hass: HomeAssistant, integration_domain: str, platform: DiagnosticsProtocol
|
||||||
):
|
) -> None:
|
||||||
"""Register a diagnostics platform."""
|
"""Register a diagnostics platform."""
|
||||||
hass.data[DOMAIN][integration_domain] = {
|
diagnostics_data: DiagnosticsData = hass.data[DOMAIN]
|
||||||
DiagnosticsType.CONFIG_ENTRY.value: getattr(
|
diagnostics_data.platforms[integration_domain] = DiagnosticsPlatformData(
|
||||||
platform, "async_get_config_entry_diagnostics", None
|
getattr(platform, "async_get_config_entry_diagnostics", None),
|
||||||
),
|
getattr(platform, "async_get_device_diagnostics", None),
|
||||||
DiagnosticsSubType.DEVICE.value: getattr(
|
)
|
||||||
platform, "async_get_device_diagnostics", None
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@websocket_api.require_admin
|
@websocket_api.require_admin
|
||||||
|
@ -79,18 +97,20 @@ async def _register_diagnostics_platform(
|
||||||
@callback
|
@callback
|
||||||
def handle_info(
|
def handle_info(
|
||||||
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict
|
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict
|
||||||
):
|
) -> None:
|
||||||
"""List all possible diagnostic handlers."""
|
"""List all possible diagnostic handlers."""
|
||||||
connection.send_result(
|
diagnostics_data: DiagnosticsData = hass.data[DOMAIN]
|
||||||
msg["id"],
|
result = [
|
||||||
[
|
{
|
||||||
{
|
"domain": domain,
|
||||||
"domain": domain,
|
"handlers": {
|
||||||
"handlers": {key: val is not None for key, val in info.items()},
|
DiagnosticsType.CONFIG_ENTRY: info.config_entry_diagnostics is not None,
|
||||||
}
|
DiagnosticsSubType.DEVICE: info.device_diagnostics is not None,
|
||||||
for domain, info in hass.data[DOMAIN].items()
|
},
|
||||||
],
|
}
|
||||||
)
|
for domain, info in diagnostics_data.platforms.items()
|
||||||
|
]
|
||||||
|
connection.send_result(msg["id"], result)
|
||||||
|
|
||||||
|
|
||||||
@websocket_api.require_admin
|
@websocket_api.require_admin
|
||||||
|
@ -103,11 +123,12 @@ def handle_info(
|
||||||
@callback
|
@callback
|
||||||
def handle_get(
|
def handle_get(
|
||||||
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict
|
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict
|
||||||
):
|
) -> None:
|
||||||
"""List all possible diagnostic handlers."""
|
"""List all diagnostic handlers for a domain."""
|
||||||
domain = msg["domain"]
|
domain = msg["domain"]
|
||||||
|
diagnostics_data: DiagnosticsData = hass.data[DOMAIN]
|
||||||
|
|
||||||
if (info := hass.data[DOMAIN].get(domain)) is None:
|
if (info := diagnostics_data.platforms.get(domain)) is None:
|
||||||
connection.send_error(
|
connection.send_error(
|
||||||
msg["id"], websocket_api.ERR_NOT_FOUND, "Domain not supported"
|
msg["id"], websocket_api.ERR_NOT_FOUND, "Domain not supported"
|
||||||
)
|
)
|
||||||
|
@ -117,7 +138,10 @@ def handle_get(
|
||||||
msg["id"],
|
msg["id"],
|
||||||
{
|
{
|
||||||
"domain": domain,
|
"domain": domain,
|
||||||
"handlers": {key: val is not None for key, val in info.items()},
|
"handlers": {
|
||||||
|
DiagnosticsType.CONFIG_ENTRY: info.config_entry_diagnostics is not None,
|
||||||
|
DiagnosticsSubType.DEVICE: info.device_diagnostics is not None,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -195,20 +219,21 @@ class DownloadDiagnosticsView(http.HomeAssistantView):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return web.Response(status=HTTPStatus.BAD_REQUEST)
|
return web.Response(status=HTTPStatus.BAD_REQUEST)
|
||||||
|
|
||||||
hass = request.app["hass"]
|
hass: HomeAssistant = request.app["hass"]
|
||||||
|
|
||||||
if (config_entry := hass.config_entries.async_get_entry(d_id)) is None:
|
if (config_entry := hass.config_entries.async_get_entry(d_id)) is None:
|
||||||
return web.Response(status=HTTPStatus.NOT_FOUND)
|
return web.Response(status=HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
if (info := hass.data[DOMAIN].get(config_entry.domain)) is None:
|
diagnostics_data: DiagnosticsData = hass.data[DOMAIN]
|
||||||
|
if (info := diagnostics_data.platforms.get(config_entry.domain)) is None:
|
||||||
return web.Response(status=HTTPStatus.NOT_FOUND)
|
return web.Response(status=HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
filename = f"{config_entry.domain}-{config_entry.entry_id}"
|
filename = f"{config_entry.domain}-{config_entry.entry_id}"
|
||||||
|
|
||||||
if sub_type is None:
|
if sub_type is None:
|
||||||
if info[d_type.value] is None:
|
if info.config_entry_diagnostics is None:
|
||||||
return web.Response(status=HTTPStatus.NOT_FOUND)
|
return web.Response(status=HTTPStatus.NOT_FOUND)
|
||||||
data = await info[d_type.value](hass, config_entry)
|
data = await info.config_entry_diagnostics(hass, config_entry)
|
||||||
filename = f"{d_type}-{filename}"
|
filename = f"{d_type}-{filename}"
|
||||||
return await _async_get_json_file_response(
|
return await _async_get_json_file_response(
|
||||||
hass, data, filename, config_entry.domain, d_type.value, d_id
|
hass, data, filename, config_entry.domain, d_type.value, d_id
|
||||||
|
@ -228,10 +253,10 @@ class DownloadDiagnosticsView(http.HomeAssistantView):
|
||||||
|
|
||||||
filename += f"-{device.name}-{device.id}"
|
filename += f"-{device.name}-{device.id}"
|
||||||
|
|
||||||
if info[sub_type.value] is None:
|
if info.device_diagnostics is None:
|
||||||
return web.Response(status=HTTPStatus.NOT_FOUND)
|
return web.Response(status=HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
data = await info[sub_type.value](hass, config_entry, device)
|
data = await info.device_diagnostics(hass, config_entry, device)
|
||||||
return await _async_get_json_file_response(
|
return await _async_get_json_file_response(
|
||||||
hass, data, filename, config_entry.domain, d_type, d_id, sub_type, sub_id
|
hass, data, filename, config_entry.domain, d_type, d_id, sub_type, sub_id
|
||||||
)
|
)
|
||||||
|
|
14
mypy.ini
14
mypy.ini
|
@ -673,6 +673,17 @@ disallow_untyped_defs = true
|
||||||
warn_return_any = true
|
warn_return_any = true
|
||||||
warn_unreachable = true
|
warn_unreachable = true
|
||||||
|
|
||||||
|
[mypy-homeassistant.components.diagnostics.*]
|
||||||
|
check_untyped_defs = true
|
||||||
|
disallow_incomplete_defs = true
|
||||||
|
disallow_subclassing_any = true
|
||||||
|
disallow_untyped_calls = true
|
||||||
|
disallow_untyped_decorators = true
|
||||||
|
disallow_untyped_defs = true
|
||||||
|
warn_return_any = true
|
||||||
|
warn_unreachable = true
|
||||||
|
no_implicit_reexport = true
|
||||||
|
|
||||||
[mypy-homeassistant.components.dlna_dmr.*]
|
[mypy-homeassistant.components.dlna_dmr.*]
|
||||||
check_untyped_defs = true
|
check_untyped_defs = true
|
||||||
disallow_incomplete_defs = true
|
disallow_incomplete_defs = true
|
||||||
|
@ -2848,9 +2859,6 @@ warn_unreachable = true
|
||||||
[mypy-homeassistant.components.application_credentials.*]
|
[mypy-homeassistant.components.application_credentials.*]
|
||||||
no_implicit_reexport = true
|
no_implicit_reexport = true
|
||||||
|
|
||||||
[mypy-homeassistant.components.diagnostics.*]
|
|
||||||
no_implicit_reexport = true
|
|
||||||
|
|
||||||
[mypy-homeassistant.components.spotify.*]
|
[mypy-homeassistant.components.spotify.*]
|
||||||
no_implicit_reexport = true
|
no_implicit_reexport = true
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue