From b3b4f7468dd2c236f008e412664f22b66711f856 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 5 Jun 2018 10:50:16 -0400 Subject: [PATCH] Further cleanup frontend (#14805) * Remove registering panels * Remove unused image * Lint --- homeassistant/components/frontend/__init__.py | 196 ++++-------------- .../www_static/images/logo_tellduslive.png | Bin 7796 -> 0 bytes tests/components/test_frontend.py | 11 +- 3 files changed, 39 insertions(+), 168 deletions(-) delete mode 100644 homeassistant/components/frontend/www_static/images/logo_tellduslive.png diff --git a/homeassistant/components/frontend/__init__.py b/homeassistant/components/frontend/__init__.py index 5dad77f64ce..3f2f9ded22a 100644 --- a/homeassistant/components/frontend/__init__.py +++ b/homeassistant/components/frontend/__init__.py @@ -5,7 +5,6 @@ For more details about this component, please refer to the documentation at https://home-assistant.io/components/frontend/ """ import asyncio -import hashlib import json import logging import os @@ -30,8 +29,6 @@ REQUIREMENTS = ['home-assistant-frontend==20180603.0'] DOMAIN = 'frontend' DEPENDENCIES = ['api', 'websocket_api', 'http', 'system_log'] -URL_PANEL_COMPONENT_FP = '/frontend/panels/{}-{}.html' - CONF_THEMES = 'themes' CONF_EXTRA_HTML_URL = 'extra_html_url' CONF_EXTRA_HTML_URL_ES5 = 'extra_html_url_es5' @@ -101,7 +98,7 @@ SCHEMA_GET_PANELS = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({ }) -class AbstractPanel: +class Panel: """Abstract class for panels.""" # Name of the webcomponent @@ -113,44 +110,12 @@ class AbstractPanel: # Title to show in the sidebar (optional) sidebar_title = None - # Url to the webcomponent (depending on JS version) - webcomponent_url_es5 = None - webcomponent_url_latest = None - # Url to show the panel in the frontend frontend_url_path = None # Config to pass to the webcomponent config = None - @asyncio.coroutine - def async_register(self, hass): - """Register panel with HASS.""" - panels = hass.data.get(DATA_PANELS) - if panels is None: - panels = hass.data[DATA_PANELS] = {} - - if self.frontend_url_path in panels: - _LOGGER.warning("Overwriting component %s", self.frontend_url_path) - - if DATA_FINALIZE_PANEL in hass.data: - yield from hass.data[DATA_FINALIZE_PANEL](self) - - panels[self.frontend_url_path] = self - - @callback - def async_register_index_routes(self, router, index_view): - """Register routes for panel to be served by index view.""" - router.add_route( - 'get', '/{}'.format(self.frontend_url_path), index_view.get) - router.add_route( - 'get', '/{}/{{extra:.+}}'.format(self.frontend_url_path), - index_view.get) - - -class BuiltInPanel(AbstractPanel): - """Panel that is part of hass_frontend.""" - def __init__(self, component_name, sidebar_title, sidebar_icon, frontend_url_path, config): """Initialize a built-in panel.""" @@ -160,6 +125,16 @@ class BuiltInPanel(AbstractPanel): self.frontend_url_path = frontend_url_path or component_name self.config = config + @callback + def async_register_index_routes(self, router, index_view): + """Register routes for panel to be served by index view.""" + router.add_route( + 'get', '/{}'.format(self.frontend_url_path), index_view.get) + router.add_route( + 'get', '/{}/{{extra:.+}}'.format(self.frontend_url_path), + index_view.get) + + @callback def to_response(self, hass, request): """Panel as dictionary.""" return { @@ -171,95 +146,25 @@ class BuiltInPanel(AbstractPanel): } -class ExternalPanel(AbstractPanel): - """Panel that is added by a custom component.""" - - REGISTERED_COMPONENTS = set() - - def __init__(self, component_name, path, md5, sidebar_title, sidebar_icon, - frontend_url_path, config): - """Initialize an external panel.""" - self.component_name = component_name - self.path = path - self.md5 = md5 - self.sidebar_title = sidebar_title - self.sidebar_icon = sidebar_icon - self.frontend_url_path = frontend_url_path or component_name - self.config = config - - @asyncio.coroutine - def async_finalize(self, hass, frontend_repository_path): - """Finalize this panel for usage. - - frontend_repository_path is set, will be prepended to path of built-in - components. - """ - try: - if self.md5 is None: - self.md5 = yield from hass.async_add_job( - _fingerprint, self.path) - except OSError: - _LOGGER.error('Cannot find or access %s at %s', - self.component_name, self.path) - hass.data[DATA_PANELS].pop(self.frontend_url_path) - return - - self.webcomponent_url_es5 = self.webcomponent_url_latest = \ - URL_PANEL_COMPONENT_FP.format(self.component_name, self.md5) - - if self.component_name not in self.REGISTERED_COMPONENTS: - hass.http.register_static_path( - self.webcomponent_url_latest, self.path, - # if path is None, we're in prod mode, so cache static assets - frontend_repository_path is None) - self.REGISTERED_COMPONENTS.add(self.component_name) - - def to_response(self, hass, request): - """Panel as dictionary.""" - result = { - 'component_name': self.component_name, - 'icon': self.sidebar_icon, - 'title': self.sidebar_title, - 'url_path': self.frontend_url_path, - 'config': self.config, - } - if _is_latest(hass.data[DATA_JS_VERSION], request): - result['url'] = self.webcomponent_url_latest - else: - result['url'] = self.webcomponent_url_es5 - return result - - @bind_hass -@asyncio.coroutine -def async_register_built_in_panel(hass, component_name, sidebar_title=None, - sidebar_icon=None, frontend_url_path=None, - config=None): +async def async_register_built_in_panel(hass, component_name, + sidebar_title=None, sidebar_icon=None, + frontend_url_path=None, config=None): """Register a built-in panel.""" - panel = BuiltInPanel(component_name, sidebar_title, sidebar_icon, - frontend_url_path, config) - yield from panel.async_register(hass) + panel = Panel(component_name, sidebar_title, sidebar_icon, + frontend_url_path, config) + panels = hass.data.get(DATA_PANELS) + if panels is None: + panels = hass.data[DATA_PANELS] = {} -@bind_hass -@asyncio.coroutine -def async_register_panel(hass, component_name, path, md5=None, - sidebar_title=None, sidebar_icon=None, - frontend_url_path=None, config=None): - """Register a panel for the frontend. + if panel.frontend_url_path in panels: + _LOGGER.warning("Overwriting component %s", panel.frontend_url_path) - component_name: name of the web component - path: path to the HTML of the web component - (required unless url is provided) - md5: the md5 hash of the web component (for versioning in URL, optional) - sidebar_title: title to show in the sidebar (optional) - sidebar_icon: icon to show next to title in sidebar (optional) - url_path: name to use in the URL (defaults to component_name) - config: config to be passed into the web component - """ - panel = ExternalPanel(component_name, path, md5, sidebar_title, - sidebar_icon, frontend_url_path, config) - yield from panel.async_register(hass) + if DATA_FINALIZE_PANEL in hass.data: + hass.data[DATA_FINALIZE_PANEL](panel) + + panels[panel.frontend_url_path] = panel @bind_hass @@ -278,11 +183,10 @@ def add_manifest_json_key(key, val): MANIFEST_JSON[key] = val -@asyncio.coroutine -def async_setup(hass, config): +async def async_setup(hass, config): """Set up the serving of the frontend.""" if list(hass.auth.async_auth_providers): - client = yield from hass.auth.async_create_client( + client = await hass.auth.async_create_client( 'Home Assistant Frontend', redirect_uris=['/'], no_secret=True, @@ -331,24 +235,22 @@ def async_setup(hass, config): index_view = IndexView(repo_path, js_version, client) hass.http.register_view(index_view) - async def finalize_panel(panel): + @callback + def async_finalize_panel(panel): """Finalize setup of a panel.""" - if hasattr(panel, 'async_finalize'): - await panel.async_finalize(hass, repo_path) panel.async_register_index_routes(hass.http.app.router, index_view) - yield from asyncio.wait([ + await asyncio.wait([ async_register_built_in_panel(hass, panel) for panel in ('dev-event', 'dev-info', 'dev-service', 'dev-state', 'dev-template', 'dev-mqtt', 'kiosk')], loop=hass.loop) - hass.data[DATA_FINALIZE_PANEL] = finalize_panel + hass.data[DATA_FINALIZE_PANEL] = async_finalize_panel # Finalize registration of panels that registered before frontend was setup # This includes the built-in panels from line above. - yield from asyncio.wait( - [finalize_panel(panel) for panel in hass.data[DATA_PANELS].values()], - loop=hass.loop) + for panel in hass.data[DATA_PANELS].values(): + async_finalize_panel(panel) if DATA_EXTRA_HTML_URL not in hass.data: hass.data[DATA_EXTRA_HTML_URL] = set() @@ -456,38 +358,23 @@ class IndexView(HomeAssistantView): return tpl - @asyncio.coroutine - def get(self, request, extra=None): + async def get(self, request, extra=None): """Serve the index view.""" hass = request.app['hass'] latest = self.repo_path is not None or \ _is_latest(self.js_option, request) - if request.path == '/': - panel = 'states' - else: - panel = request.path.split('/')[1] - - if panel == 'states': - panel_url = '' - elif latest: - panel_url = hass.data[DATA_PANELS][panel].webcomponent_url_latest - else: - panel_url = hass.data[DATA_PANELS][panel].webcomponent_url_es5 - no_auth = '1' if hass.config.api.api_password and not request[KEY_AUTHENTICATED]: # do not try to auto connect on load no_auth = '0' - template = yield from hass.async_add_job(self.get_template, latest) + template = await hass.async_add_job(self.get_template, latest) extra_key = DATA_EXTRA_HTML_URL if latest else DATA_EXTRA_HTML_URL_ES5 template_params = dict( no_auth=no_auth, - panel_url=panel_url, - panels=hass.data[DATA_PANELS], theme_color=MANIFEST_JSON['theme_color'], extra_urls=hass.data[extra_key], ) @@ -506,7 +393,7 @@ class ManifestJSONView(HomeAssistantView): url = '/manifest.json' name = 'manifestjson' - @asyncio.coroutine + @callback def get(self, request): # pylint: disable=no-self-use """Return the manifest.json.""" msg = json.dumps(MANIFEST_JSON, sort_keys=True) @@ -537,23 +424,16 @@ class TranslationsView(HomeAssistantView): url = '/api/translations/{language}' name = 'api:translations' - @asyncio.coroutine - def get(self, request, language): + async def get(self, request, language): """Return translations.""" hass = request.app['hass'] - resources = yield from async_get_translations(hass, language) + resources = await async_get_translations(hass, language) return self.json({ 'resources': resources, }) -def _fingerprint(path): - """Fingerprint a file.""" - with open(path) as fil: - return hashlib.md5(fil.read().encode('utf-8')).hexdigest() - - def _is_latest(js_option, request): """ Return whether we should serve latest untranspiled code. diff --git a/homeassistant/components/frontend/www_static/images/logo_tellduslive.png b/homeassistant/components/frontend/www_static/images/logo_tellduslive.png deleted file mode 100644 index 7ea78f8ef3aad4d3cd982835c797693a68264c00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7796 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 diff --git a/tests/components/test_frontend.py b/tests/components/test_frontend.py index 657497b868b..2f83d923e2b 100644 --- a/tests/components/test_frontend.py +++ b/tests/components/test_frontend.py @@ -8,7 +8,7 @@ import pytest from homeassistant.setup import async_setup_component from homeassistant.components.frontend import ( DOMAIN, CONF_JS_VERSION, CONF_THEMES, CONF_EXTRA_HTML_URL, - CONF_EXTRA_HTML_URL_ES5, DATA_PANELS) + CONF_EXTRA_HTML_URL_ES5) from homeassistant.components import websocket_api as wapi @@ -183,15 +183,6 @@ def test_extra_urls_es5(mock_http_client_with_urls): assert text.find('href="https://domain.com/my_extra_url_es5.html"') >= 0 -@asyncio.coroutine -def test_panel_without_path(hass): - """Test panel registration without file path.""" - yield from hass.components.frontend.async_register_panel( - 'test_component', 'nonexistant_file') - yield from async_setup_component(hass, 'frontend', {}) - assert 'test_component' not in hass.data[DATA_PANELS] - - async def test_get_panels(hass, hass_ws_client): """Test get_panels command.""" await async_setup_component(hass, 'frontend')