Support importing Blueprints from the Home Assistant websites (#95340)

* Support importing Blueprints from the Home Assistant websites

* Improve test coverage
This commit is contained in:
Franck Nijhof 2023-06-27 18:40:53 +02:00 committed by GitHub
parent a8b2c1edfa
commit 4b9bfe9a50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 4 deletions

View File

@ -1,6 +1,8 @@
"""Import logic for blueprint."""
from __future__ import annotations
from contextlib import suppress
from dataclasses import dataclass
import html
import re
@ -28,6 +30,10 @@ GITHUB_FILE_PATTERN = re.compile(
r"^https://github.com/(?P<repository>.+)/blob/(?P<path>.+)$"
)
WEBSITE_PATTERN = re.compile(
r"^https://(?P<subdomain>[a-z0-9-]+)\.home-assistant\.io/(?P<path>.+).yaml$"
)
COMMUNITY_TOPIC_SCHEMA = vol.Schema(
{
"slug": str,
@ -219,18 +225,37 @@ async def fetch_blueprint_from_github_gist_url(
)
async def fetch_blueprint_from_website_url(
hass: HomeAssistant, url: str
) -> ImportedBlueprint:
"""Get a blueprint from our website."""
if (WEBSITE_PATTERN.match(url)) is None:
raise UnsupportedUrl("Not a Home Assistant website URL")
session = aiohttp_client.async_get_clientsession(hass)
resp = await session.get(url, raise_for_status=True)
raw_yaml = await resp.text()
data = yaml.parse_yaml(raw_yaml)
assert isinstance(data, dict)
blueprint = Blueprint(data)
parsed_import_url = yarl.URL(url)
suggested_filename = f"homeassistant/{parsed_import_url.parts[-1][:-5]}"
return ImportedBlueprint(suggested_filename, raw_yaml, blueprint)
async def fetch_blueprint_from_url(hass: HomeAssistant, url: str) -> ImportedBlueprint:
"""Get a blueprint from a url."""
for func in (
fetch_blueprint_from_community_post,
fetch_blueprint_from_github_url,
fetch_blueprint_from_github_gist_url,
fetch_blueprint_from_website_url,
):
try:
with suppress(UnsupportedUrl):
imported_bp = await func(hass, url)
imported_bp.blueprint.update_metadata(source_url=url)
return imported_bp
except UnsupportedUrl:
pass
raise HomeAssistantError("Unsupported url")
raise HomeAssistantError("Unsupported URL")

View File

@ -162,3 +162,30 @@ async def test_fetch_blueprint_from_github_gist_url(
assert imported_blueprint.blueprint.inputs == snapshot
assert imported_blueprint.suggested_filename == "balloob/motion_light"
assert imported_blueprint.blueprint.metadata["source_url"] == url
async def test_fetch_blueprint_from_website_url(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test fetching blueprint from url."""
aioclient_mock.get(
"https://www.home-assistant.io/blueprints/awesome.yaml",
text=Path(
hass.config.path("blueprints/automation/test_event_service.yaml")
).read_text(),
)
url = "https://www.home-assistant.io/blueprints/awesome.yaml"
imported_blueprint = await importer.fetch_blueprint_from_url(hass, url)
assert isinstance(imported_blueprint, importer.ImportedBlueprint)
assert imported_blueprint.blueprint.domain == "automation"
assert imported_blueprint.suggested_filename == "homeassistant/awesome"
assert imported_blueprint.blueprint.metadata["source_url"] == url
async def test_fetch_blueprint_from_unsupported_url(hass: HomeAssistant) -> None:
"""Test fetching blueprint from an unsupported URL."""
url = "https://example.com/unsupported.yaml"
with pytest.raises(HomeAssistantError, match=r"^Unsupported URL$"):
await importer.fetch_blueprint_from_url(hass, url)