mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 06:07:17 +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."""
|
"""Import logic for blueprint."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from contextlib import suppress
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
import html
|
import html
|
||||||
import re
|
import re
|
||||||
@ -28,6 +30,10 @@ GITHUB_FILE_PATTERN = re.compile(
|
|||||||
r"^https://github.com/(?P<repository>.+)/blob/(?P<path>.+)$"
|
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(
|
COMMUNITY_TOPIC_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
"slug": str,
|
"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:
|
async def fetch_blueprint_from_url(hass: HomeAssistant, url: str) -> ImportedBlueprint:
|
||||||
"""Get a blueprint from a url."""
|
"""Get a blueprint from a url."""
|
||||||
for func in (
|
for func in (
|
||||||
fetch_blueprint_from_community_post,
|
fetch_blueprint_from_community_post,
|
||||||
fetch_blueprint_from_github_url,
|
fetch_blueprint_from_github_url,
|
||||||
fetch_blueprint_from_github_gist_url,
|
fetch_blueprint_from_github_gist_url,
|
||||||
|
fetch_blueprint_from_website_url,
|
||||||
):
|
):
|
||||||
try:
|
with suppress(UnsupportedUrl):
|
||||||
imported_bp = await func(hass, url)
|
imported_bp = await func(hass, url)
|
||||||
imported_bp.blueprint.update_metadata(source_url=url)
|
imported_bp.blueprint.update_metadata(source_url=url)
|
||||||
return imported_bp
|
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.blueprint.inputs == snapshot
|
||||||
assert imported_blueprint.suggested_filename == "balloob/motion_light"
|
assert imported_blueprint.suggested_filename == "balloob/motion_light"
|
||||||
assert imported_blueprint.blueprint.metadata["source_url"] == url
|
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