mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-28 19:01:34 +00:00
Tooling: requirements_test.txt becomes the single source of backend CI dependencies; pyproject.toml configures ruff (E/F/B/I, E501 excluded by decision) and mypy strict for a grow-only allowlist of six pure modules (junction_limits annotated to pass). The 42 substantive ruff findings are fixed — the B023 loop-variable closures bind their variables as parameter defaults instead of hiding behind noqa, and every remaining noqa carries a reason (guarded by a test). Errors: const.ERROR_CODES / ERROR_CODE_FAMILIES formalise the stable contract; the scanner test proves every emitted code across BOTH paths (send_error literals; class attrs, literal and variable-passed MarkerControlError codes, f-string families) is registered and has a localized message — 22 missing backup.error.* keys added in all four languages. invalid_passage_fields / invalid_partition_opening_jamb_margin ship structured JSON details (legacy format read-compat for one beta), and _errText renders code-first: unknown codes localize, raw English messages go to the console. CI: the backend job lints with ruff, refuses a silently skipped HA harness (import + collect threshold), measures branch coverage over pure+harness, fails below the committed baseline and uploads coverage.xml. quality_scale: docs-troubleshooting/examples honestly done, test-coverage/strict-typing carry staged progress. User-Visible: yes Issue: #42
44 lines
1.5 KiB
Python
44 lines
1.5 KiB
Python
"""Public, manifest-gated JavaScript chunks for the Lovelace card."""
|
||
from __future__ import annotations
|
||
|
||
from pathlib import Path
|
||
|
||
from aiohttp import web
|
||
from homeassistant.components.http import HomeAssistantView
|
||
|
||
try:
|
||
from homeassistant.components.http import KEY_HASS
|
||
except ImportError: # pragma: no cover - old HA compatibility
|
||
KEY_HASS = "hass" # type: ignore[assignment]
|
||
|
||
from .const import FRONTEND_ASSETS_URL
|
||
from .frontend_asset_manifest import ASSET_CACHE_CONTROL, resolve_frontend_asset
|
||
|
||
_FRONTEND_ROOT = Path(__file__).parent / "frontend"
|
||
|
||
|
||
class HouseplanFrontendAssetView(HomeAssistantView):
|
||
"""Serve only generated chunks named by the current build manifest."""
|
||
|
||
url = f"{FRONTEND_ASSETS_URL}/{{filename}}"
|
||
name = "api:houseplan:frontend-asset"
|
||
requires_auth = False
|
||
|
||
async def get(self, request: web.Request, filename: str) -> web.StreamResponse:
|
||
hass = request.app[KEY_HASS]
|
||
path = await hass.async_add_executor_job(
|
||
resolve_frontend_asset, _FRONTEND_ROOT, filename
|
||
)
|
||
if path is None:
|
||
raise web.HTTPNotFound()
|
||
# Chunk names are content-hashed, so a served body can never change
|
||
# under its URL — immutable caching is safe and keeps a stale proxy
|
||
# from re-serving an old graph after an update (#353 К4).
|
||
return web.FileResponse(
|
||
path,
|
||
headers={
|
||
"Cache-Control": ASSET_CACHE_CONTROL,
|
||
"X-Content-Type-Options": "nosniff",
|
||
},
|
||
)
|