Expose supported brands via API (#75074)

This commit is contained in:
Paulus Schoutsen 2022-07-12 13:49:54 -07:00 committed by GitHub
parent b54fe14a10
commit 41ec8cd354
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 142 additions and 2 deletions

View File

@ -21,7 +21,7 @@ repos:
- --skip="./.*,*.csv,*.json"
- --quiet-level=2
exclude_types: [csv, json]
exclude: ^tests/fixtures/
exclude: ^tests/fixtures/|homeassistant/generated/
- repo: https://github.com/PyCQA/flake8
rev: 4.0.1
hooks:

View File

@ -22,6 +22,7 @@ from homeassistant.exceptions import (
TemplateError,
Unauthorized,
)
from homeassistant.generated import supported_brands
from homeassistant.helpers import config_validation as cv, entity, template
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.event import (
@ -68,6 +69,7 @@ def async_register_commands(
async_reg(hass, handle_unsubscribe_events)
async_reg(hass, handle_validate_config)
async_reg(hass, handle_subscribe_entities)
async_reg(hass, handle_supported_brands)
def pong_message(iden: int) -> dict[str, Any]:
@ -691,3 +693,25 @@ async def handle_validate_config(
result[key] = {"valid": True, "error": None}
connection.send_result(msg["id"], result)
@decorators.websocket_command(
{
vol.Required("type"): "supported_brands",
}
)
@decorators.async_response
async def handle_supported_brands(
hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any]
) -> None:
"""Handle supported brands command."""
data = {}
for integration in await asyncio.gather(
*[
async_get_integration(hass, integration)
for integration in supported_brands.HAS_SUPPORTED_BRANDS
]
):
data[integration.domain] = integration.manifest["supported_brands"]
connection.send_result(msg["id"], data)

View File

@ -0,0 +1,15 @@
"""Automatically generated by hassfest.
To update, run python3 -m script.hassfest
"""
# fmt: off
HAS_SUPPORTED_BRANDS = (
"denonavr",
"hunterdouglas_powerview",
"motion_blinds",
"overkiz",
"renault",
"wemo"
)

View File

@ -20,6 +20,7 @@ from . import (
requirements,
services,
ssdp,
supported_brands,
translations,
usb,
zeroconf,
@ -39,6 +40,7 @@ INTEGRATION_PLUGINS = [
requirements,
services,
ssdp,
supported_brands,
translations,
usb,
zeroconf,

View File

@ -112,6 +112,11 @@ class Integration:
"""List of dependencies."""
return self.manifest.get("dependencies", [])
@property
def supported_brands(self) -> dict[str]:
"""Return dict of supported brands."""
return self.manifest.get("supported_brands", {})
@property
def integration_type(self) -> str:
"""Get integration_type."""

View File

@ -0,0 +1,55 @@
"""Generate supported_brands data."""
from __future__ import annotations
import json
from .model import Config, Integration
BASE = """
\"\"\"Automatically generated by hassfest.
To update, run python3 -m script.hassfest
\"\"\"
# fmt: off
HAS_SUPPORTED_BRANDS = ({})
""".strip()
def generate_and_validate(integrations: dict[str, Integration], config: Config) -> str:
"""Validate and generate supported_brands data."""
brands = [
domain
for domain, integration in sorted(integrations.items())
if integration.supported_brands
]
return BASE.format(json.dumps(brands, indent=4)[1:-1])
def validate(integrations: dict[str, Integration], config: Config) -> None:
"""Validate supported_brands data."""
supported_brands_path = config.root / "homeassistant/generated/supported_brands.py"
config.cache["supported_brands"] = content = generate_and_validate(
integrations, config
)
if config.specific_integrations:
return
if supported_brands_path.read_text(encoding="utf-8").strip() != content:
config.add_error(
"supported_brands",
"File supported_brands.py is not up to date. Run python3 -m script.hassfest",
fixable=True,
)
def generate(integrations: dict[str, Integration], config: Config):
"""Generate supported_brands data."""
supported_brands_path = config.root / "homeassistant/generated/supported_brands.py"
supported_brands_path.write_text(
f"{config.cache['supported_brands']}\n", encoding="utf-8"
)

View File

@ -22,7 +22,13 @@ from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.loader import async_get_integration
from homeassistant.setup import DATA_SETUP_TIME, async_setup_component
from tests.common import MockEntity, MockEntityPlatform, async_mock_service
from tests.common import (
MockEntity,
MockEntityPlatform,
MockModule,
async_mock_service,
mock_integration,
)
STATE_KEY_SHORT_NAMES = {
"entity_id": "e",
@ -1749,3 +1755,36 @@ async def test_validate_config_invalid(websocket_client, key, config, error):
assert msg["type"] == const.TYPE_RESULT
assert msg["success"]
assert msg["result"] == {key: {"valid": False, "error": error}}
async def test_supported_brands(hass, websocket_client):
"""Test supported brands."""
mock_integration(
hass,
MockModule("test", partial_manifest={"supported_brands": {"hello": "World"}}),
)
mock_integration(
hass,
MockModule(
"abcd", partial_manifest={"supported_brands": {"something": "Something"}}
),
)
with patch(
"homeassistant.generated.supported_brands.HAS_SUPPORTED_BRANDS",
("abcd", "test"),
):
await websocket_client.send_json({"id": 7, "type": "supported_brands"})
msg = await websocket_client.receive_json()
assert msg["id"] == 7
assert msg["type"] == const.TYPE_RESULT
assert msg["success"]
assert msg["result"] == {
"abcd": {
"something": "Something",
},
"test": {
"hello": "World",
},
}