mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
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:
parent
a8b2c1edfa
commit
4b9bfe9a50
@ -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")
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user