Add support for dynamic frontend panels

This commit is contained in:
Paulus Schoutsen 2016-07-16 22:32:25 -07:00
parent 35a57e1385
commit 22b4aebeb3
21 changed files with 197 additions and 119 deletions

View file

@ -1,37 +1,112 @@
"""Handle the frontend for Home Assistant.""" """Handle the frontend for Home Assistant."""
import logging
import os import os
from homeassistant.const import EVENT_HOMEASSISTANT_START
from homeassistant.components import api from homeassistant.components import api
from homeassistant.components.http import HomeAssistantView from homeassistant.components.http import HomeAssistantView
from . import version, mdi_version from .version import FINGERPRINTS
DOMAIN = 'frontend' DOMAIN = 'frontend'
DEPENDENCIES = ['api'] DEPENDENCIES = ['api']
PANELS = {}
URL_PANEL_COMPONENT = '/frontend/panels/{}.html'
URL_PANEL_COMPONENT_FP = '/frontend/panels/{}-{}.html'
STATIC_PATH = os.path.join(os.path.dirname(__file__), 'www_static')
_LOGGER = logging.getLogger(__name__)
def register_built_in_panel(hass, component_name, title=None, icon=None,
url_name=None, config=None):
"""Register a built-in panel."""
path = 'panels/ha-panel-{}.html'.format(component_name)
register_panel(hass, component_name, os.path.join(STATIC_PATH, path),
FINGERPRINTS[path], title, icon, url_name, config)
def register_panel(hass, component_name, path, md5, title=None, icon=None,
url_name=None, config=None):
"""Register a panel for the frontend.
component_name: name of the web component
path: path to the HTML of the web component
md5: the md5 hash of the web component (for versioning)
title: title to show in the sidebar (optional)
icon: icon to show next to title in sidebar (optional)
url_name: name to use in the url (defaults to component_name)
config: config to be passed into the web component
Warning: this API will probably change. Use at own risk.
"""
if url_name is None:
url_name = component_name
if url_name in PANELS:
_LOGGER.warning('Overwriting component %s', url_name)
if not os.path.isfile(path):
_LOGGER.warning('Panel %s component does not exist: %s',
component_name, path)
data = {
'url_name': url_name,
'component_name': component_name,
}
if title:
data['title'] = title
if icon:
data['icon'] = icon
if config is not None:
data['config'] = config
if hass.wsgi.development:
data['url'] = ('/static/home-assistant-polymer/panels/'
'{0}/ha-panel-{0}.html'.format(component_name))
else:
url = URL_PANEL_COMPONENT.format(component_name)
fprinted_url = URL_PANEL_COMPONENT_FP.format(component_name, md5)
hass.wsgi.register_static_path(url, path)
data['url'] = fprinted_url
PANELS[url_name] = data
# TODO register /<component_name> to index view.
def setup(hass, config): def setup(hass, config):
"""Setup serving the frontend.""" """Setup serving the frontend."""
hass.wsgi.register_view(IndexView)
hass.wsgi.register_view(BootstrapView) hass.wsgi.register_view(BootstrapView)
www_static_path = os.path.join(os.path.dirname(__file__), 'www_static')
if hass.wsgi.development: if hass.wsgi.development:
sw_path = "home-assistant-polymer/build/service_worker.js" sw_path = "home-assistant-polymer/build/service_worker.js"
else: else:
sw_path = "service_worker.js" sw_path = "service_worker.js"
hass.wsgi.register_static_path( hass.wsgi.register_static_path("/service_worker.js",
"/service_worker.js", os.path.join(STATIC_PATH, sw_path), 0)
os.path.join(www_static_path, sw_path), hass.wsgi.register_static_path("/robots.txt",
0 os.path.join(STATIC_PATH, "robots.txt"))
) hass.wsgi.register_static_path("/static", STATIC_PATH)
hass.wsgi.register_static_path(
"/robots.txt",
os.path.join(www_static_path, "robots.txt")
)
hass.wsgi.register_static_path("/static", www_static_path)
hass.wsgi.register_static_path("/local", hass.config.path('www')) hass.wsgi.register_static_path("/local", hass.config.path('www'))
register_built_in_panel(hass, 'map', 'Map', 'mdi:account-location')
for panel in ('dev-event', 'dev-info', 'dev-service', 'dev-state',
'dev-template'):
register_built_in_panel(hass, panel)
def register_frontend_index(event):
"""Register the frontend index urls.
Done when Home Assistant is started so that all panels are known.
"""
hass.wsgi.register_view(IndexView(
hass, ['/{}'.format(name) for name in PANELS]))
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, register_frontend_index)
return True return True
@ -48,6 +123,7 @@ class BootstrapView(HomeAssistantView):
'states': self.hass.states.all(), 'states': self.hass.states.all(),
'events': api.events_json(self.hass), 'events': api.events_json(self.hass),
'services': api.services_json(self.hass), 'services': api.services_json(self.hass),
'panels': PANELS,
}) })
@ -57,16 +133,15 @@ class IndexView(HomeAssistantView):
url = '/' url = '/'
name = "frontend:index" name = "frontend:index"
requires_auth = False requires_auth = False
extra_urls = ['/logbook', '/history', '/map', '/devService', '/devState', extra_urls = ['/states', '/states/<entity:entity_id>']
'/devEvent', '/devInfo', '/devTemplate',
'/states', '/states/<entity:entity_id>']
def __init__(self, hass): def __init__(self, hass, extra_urls):
"""Initialize the frontend view.""" """Initialize the frontend view."""
super().__init__(hass) super().__init__(hass)
from jinja2 import FileSystemLoader, Environment from jinja2 import FileSystemLoader, Environment
self.extra_urls = self.extra_urls + extra_urls
self.templates = Environment( self.templates = Environment(
loader=FileSystemLoader( loader=FileSystemLoader(
os.path.join(os.path.dirname(__file__), 'templates/') os.path.join(os.path.dirname(__file__), 'templates/')
@ -76,32 +151,24 @@ class IndexView(HomeAssistantView):
def get(self, request, entity_id=None): def get(self, request, entity_id=None):
"""Serve the index view.""" """Serve the index view."""
if self.hass.wsgi.development: if self.hass.wsgi.development:
core_url = '/static/home-assistant-polymer/build/_core_compiled.js' core_url = '/static/home-assistant-polymer/build/core.js'
ui_url = '/static/home-assistant-polymer/src/home-assistant.html' ui_url = '/static/home-assistant-polymer/src/home-assistant.html'
map_url = ('/static/home-assistant-polymer/src/layouts/'
'partial-map.html')
dev_url = ('/static/home-assistant-polymer/src/entry-points/'
'dev-tools.html')
else: else:
core_url = '/static/core-{}.js'.format(version.CORE) core_url = '/static/core-{}.js'.format(
ui_url = '/static/frontend-{}.html'.format(version.UI) FINGERPRINTS['core.js'])
map_url = '/static/partial-map-{}.html'.format(version.MAP) ui_url = '/static/frontend-{}.html'.format(
dev_url = '/static/dev-tools-{}.html'.format(version.DEV) FINGERPRINTS['frontend.html'])
# auto login if no password was set # auto login if no password was set
if self.hass.config.api.api_password is None: no_auth = 'false' if self.hass.config.api.api_password else 'true'
auth = 'true'
else:
auth = 'false'
icons_url = '/static/mdi-{}.html'.format(mdi_version.VERSION)
icons_url = '/static/mdi-{}.html'.format(FINGERPRINTS['mdi.html'])
template = self.templates.get_template('index.html') template = self.templates.get_template('index.html')
# pylint is wrong # pylint is wrong
# pylint: disable=no-member # pylint: disable=no-member
resp = template.render( resp = template.render(
core_url=core_url, ui_url=ui_url, map_url=map_url, auth=auth, core_url=core_url, ui_url=ui_url, no_auth=no_auth,
dev_url=dev_url, icons_url=icons_url, icons=mdi_version.VERSION) icons_url=icons_url, icons=FINGERPRINTS['mdi.html'])
return self.Response(resp, mimetype='text/html') return self.Response(resp, mimetype='text/html')

View file

@ -1,2 +0,0 @@
"""DO NOT MODIFY. Auto-generated by update_mdi script."""
VERSION = "758957b7ea989d6beca60e218ea7f7dd"

View file

@ -5,14 +5,14 @@
<title>Home Assistant</title> <title>Home Assistant</title>
<link rel='manifest' href='/static/manifest.json'> <link rel='manifest' href='/static/manifest.json'>
<link rel='icon' href='/static/favicon.ico'> <link rel='icon' href='/static/icons/favicon.ico'>
<link rel='apple-touch-icon' sizes='180x180' <link rel='apple-touch-icon' sizes='180x180'
href='/static/favicon-apple-180x180.png'> href='/static/icons/favicon-apple-180x180.png'>
<meta name='apple-mobile-web-app-capable' content='yes'> <meta name='apple-mobile-web-app-capable' content='yes'>
<meta name="msapplication-square70x70logo" content="/static/tile-win-70x70.png"/> <meta name="msapplication-square70x70logo" content="/static/icons/tile-win-70x70.png"/>
<meta name="msapplication-square150x150logo" content="/static/tile-win-150x150.png"/> <meta name="msapplication-square150x150logo" content="/static/icons/tile-win-150x150.png"/>
<meta name="msapplication-wide310x150logo" content="/static/tile-win-310x150.png"/> <meta name="msapplication-wide310x150logo" content="/static/icons/tile-win-310x150.png"/>
<meta name="msapplication-square310x310logo" content="/static/tile-win-310x310.png"/> <meta name="msapplication-square310x310logo" content="/static/icons/tile-win-310x310.png"/>
<meta name="msapplication-TileColor" content="#3fbbf4ff"/> <meta name="msapplication-TileColor" content="#3fbbf4ff"/>
<meta name='mobile-web-app-capable' content='yes'> <meta name='mobile-web-app-capable' content='yes'>
<meta name='viewport' content='width=device-width, user-scalable=no'> <meta name='viewport' content='width=device-width, user-scalable=no'>
@ -65,16 +65,12 @@
.getElementById('ha-init-skeleton') .getElementById('ha-init-skeleton')
.classList.add('error'); .classList.add('error');
}; };
window.noAuth = {{ auth }}; window.noAuth = {{ no_auth }};
window.deferredLoading = {
map: '{{ map_url }}',
dev: '{{ dev_url }}',
};
</script> </script>
</head> </head>
<body fullbleed> <body fullbleed>
<div id='ha-init-skeleton'> <div id='ha-init-skeleton'>
<img src='/static/favicon-192x192.png' height='192'> <img src='/static/icons/favicon-192x192.png' height='192'>
<paper-spinner active></paper-spinner> <paper-spinner active></paper-spinner>
Home Assistant had trouble<br>connecting to the server.<br><br><a href='/'>TRY AGAIN</a> Home Assistant had trouble<br>connecting to the server.<br><br><a href='/'>TRY AGAIN</a>
</div> </div>

View file

@ -1,5 +1,24 @@
<<<<<<< HEAD
"""DO NOT MODIFY. Auto-generated by build_frontend script.""" """DO NOT MODIFY. Auto-generated by build_frontend script."""
CORE = "7d80cc0e4dea6bc20fa2889be0b3cd15" CORE = "7d80cc0e4dea6bc20fa2889be0b3cd15"
UI = "805f8dda70419b26daabc8e8f625127f" UI = "805f8dda70419b26daabc8e8f625127f"
MAP = "c922306de24140afd14f857f927bf8f0" MAP = "c922306de24140afd14f857f927bf8f0"
DEV = "b7079ac3121b95b9856e5603a6d8a263" DEV = "b7079ac3121b95b9856e5603a6d8a263"
=======
"""DO NOT MODIFY. Auto-generated by script/fingerprint_frontend."""
FINGERPRINTS = {
"core.js": "4783ccdb2f15d3a63fcab9be411629b7",
"frontend.html": "6c50bcdd8c8b7d840bc2cdef02e9ee39",
"mdi.html": "a7fa9237b7da93951076b4fe26cb8cd2",
"panels/ha-panel-dev-event.html": "f1f47bf3f0e305f855a99dd1ee788045",
"panels/ha-panel-dev-info.html": "50a7817f60675feef3e4c9aa9a043fe1",
"panels/ha-panel-dev-service.html": "d507e0018faf73d58a1fdeb2a0368505",
"panels/ha-panel-dev-state.html": "6a4418826419f235fd9fcc5e952e858c",
"panels/ha-panel-dev-template.html": "cc8917fdad5a4fc81cc1d4104ea0d2dc",
"panels/ha-panel-history.html": "999ecb591df76d6a4aba1fe84e04baf1",
"panels/ha-panel-iframe.html": "f4aaaf31321cd8bfb57755c24af7fc31",
"panels/ha-panel-logbook.html": "6dde7050246875774ec9fce60df05442",
"panels/ha-panel-map.html": "d2cf412d52f43431307bbc2e216be9c9"
}
>>>>>>> Add support for dynamic frontend panels

View file

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Before After
Before After

View file

@ -7,22 +7,22 @@
"background_color": "#FFFFFF", "background_color": "#FFFFFF",
"icons": [ "icons": [
{ {
"src": "/static/favicon-192x192.png", "src": "/static/icons/favicon-192x192.png",
"sizes": "192x192", "sizes": "192x192",
"type": "image/png" "type": "image/png"
}, },
{ {
"src": "/static/favicon-384x384.png", "src": "/static/icons/favicon-384x384.png",
"sizes": "384x384", "sizes": "384x384",
"type": "image/png" "type": "image/png"
}, },
{ {
"src": "/static/favicon-512x512.png", "src": "/static/icons/favicon-512x512.png",
"sizes": "512x512", "sizes": "512x512",
"type": "image/png" "type": "image/png"
}, },
{ {
"src": "/static/favicon-1024x1024.png", "src": "/static/icons/favicon-1024x1024.png",
"sizes": "1024x1024", "sizes": "1024x1024",
"type": "image/png" "type": "image/png"
} }

View file

@ -11,6 +11,7 @@ from itertools import groupby
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from homeassistant.components import recorder, script from homeassistant.components import recorder, script
from homeassistant.components.frontend import register_built_in_panel
from homeassistant.components.http import HomeAssistantView from homeassistant.components.http import HomeAssistantView
DOMAIN = 'history' DOMAIN = 'history'
@ -153,6 +154,7 @@ def setup(hass, config):
"""Setup the history hooks.""" """Setup the history hooks."""
hass.wsgi.register_view(Last5StatesView) hass.wsgi.register_view(Last5StatesView)
hass.wsgi.register_view(HistoryPeriodView) hass.wsgi.register_view(HistoryPeriodView)
register_built_in_panel(hass, 'history', 'History', 'mdi:poll-box')
return True return True

View file

@ -14,6 +14,7 @@ import voluptuous as vol
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from homeassistant.components import recorder, sun from homeassistant.components import recorder, sun
from homeassistant.components.frontend import register_built_in_panel
from homeassistant.components.http import HomeAssistantView from homeassistant.components.http import HomeAssistantView
from homeassistant.const import (EVENT_HOMEASSISTANT_START, from homeassistant.const import (EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP, EVENT_STATE_CHANGED, EVENT_HOMEASSISTANT_STOP, EVENT_STATE_CHANGED,
@ -24,7 +25,7 @@ from homeassistant.helpers import template
from homeassistant.helpers.entity import split_entity_id from homeassistant.helpers.entity import split_entity_id
DOMAIN = "logbook" DOMAIN = "logbook"
DEPENDENCIES = ['recorder', 'http'] DEPENDENCIES = ['recorder', 'frontend']
URL_LOGBOOK = re.compile(r'/api/logbook(?:/(?P<date>\d{4}-\d{1,2}-\d{1,2})|)') URL_LOGBOOK = re.compile(r'/api/logbook(?:/(?P<date>\d{4}-\d{1,2}-\d{1,2})|)')
@ -75,6 +76,9 @@ def setup(hass, config):
hass.wsgi.register_view(LogbookView) hass.wsgi.register_view(LogbookView)
register_built_in_panel(hass, 'logbook', 'Logbook',
'mdi:format-list-bulleted-type')
hass.services.register(DOMAIN, 'log', log_message, hass.services.register(DOMAIN, 'log', log_message,
schema=LOG_MESSAGE_SCHEMA) schema=LOG_MESSAGE_SCHEMA)
return True return True

View file

@ -2,36 +2,21 @@
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
cd homeassistant/components/frontend/www_static/home-assistant-polymer cd homeassistant/components/frontend/www_static
rm -rf core.js* frontend.html* webcomponents-lite.min.js* panels
cd home-assistant-polymer
npm run clean
npm run frontend_prod npm run frontend_prod
cp bower_components/webcomponentsjs/webcomponents-lite.min.js .. cp bower_components/webcomponentsjs/webcomponents-lite.min.js ..
cp build/frontend.html .. cp -r build/* ..
gzip build/frontend.html -c -k -9 > ../frontend.html.gz
cp build/partial-map.html ..
gzip build/partial-map.html -c -k -9 > ../partial-map.html.gz
cp build/dev-tools.html ..
gzip build/dev-tools.html -c -k -9 > ../dev-tools.html.gz
cp build/_core_compiled.js ../core.js
gzip build/_core_compiled.js -c -k -9 > ../core.js.gz
node script/sw-precache.js node script/sw-precache.js
cp build/service_worker.js .. cp build/service_worker.js ..
gzip build/service_worker.js -c -k -9 > ../service_worker.js.gz
cd ..
gzip -f -k -9 *.html *.js ./panels/*.html
# Generate the MD5 hash of the new frontend # Generate the MD5 hash of the new frontend
cd ../.. cd ../../../..
echo '"""DO NOT MODIFY. Auto-generated by build_frontend script."""' > version.py script/fingerprint_frontend.py
if [ $(command -v md5) ]; then
echo 'CORE = "'`md5 -q www_static/core.js`'"' >> version.py
echo 'UI = "'`md5 -q www_static/frontend.html`'"' >> version.py
echo 'MAP = "'`md5 -q www_static/partial-map.html`'"' >> version.py
echo 'DEV = "'`md5 -q www_static/dev-tools.html`'"' >> version.py
elif [ $(command -v md5sum) ]; then
echo 'CORE = "'`md5sum www_static/core.js | cut -c-32`'"' >> version.py
echo 'UI = "'`md5sum www_static/frontend.html | cut -c-32`'"' >> version.py
echo 'MAP = "'`md5sum www_static/partial-map.html | cut -c-32`'"' >> version.py
echo 'DEV = "'`md5sum www_static/dev-tools.html | cut -c-32`'"' >> version.py
else
echo 'Could not find an MD5 utility'
fi

37
script/fingerprint_frontend.py Executable file
View file

@ -0,0 +1,37 @@
#!/usr/bin/env python3
from collections import OrderedDict
import glob
import hashlib
import json
fingerprint_file = 'homeassistant/components/frontend/version.py'
base_dir = 'homeassistant/components/frontend/www_static/'
def fingerprint():
"""Fingerprint the frontend files."""
files = (glob.glob(base_dir + '**/*.html') +
glob.glob(base_dir + '*.html') +
glob.glob(base_dir + 'core.js'))
md5s = OrderedDict()
for fil in sorted(files):
name = fil[len(base_dir):]
with open(fil) as fp:
md5 = hashlib.md5(fp.read().encode('utf-8')).hexdigest()
md5s[name] = md5
template = """\"\"\"DO NOT MODIFY. Auto-generated by script/fingerprint_frontend.\"\"\"
FINGERPRINTS = {}
"""
result = template.format(json.dumps(md5s, indent=4))
with open(fingerprint_file, 'w') as fp:
fp.write(result)
if __name__ == '__main__':
fingerprint()

View file

@ -1,38 +1,24 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""Download the latest Polymer v1 iconset for materialdesignicons.com.""" """Download the latest Polymer v1 iconset for materialdesignicons.com."""
import hashlib
import gzip import gzip
import os import os
import re import re
import requests import requests
import sys import sys
from fingerprint_frontend import fingerprint
GETTING_STARTED_URL = ('https://raw.githubusercontent.com/Templarian/' GETTING_STARTED_URL = ('https://raw.githubusercontent.com/Templarian/'
'MaterialDesign/master/site/getting-started.savvy') 'MaterialDesign/master/site/getting-started.savvy')
DOWNLOAD_LINK = re.compile(r'(/api/download/polymer/v1/([A-Z0-9-]{36}))') DOWNLOAD_LINK = re.compile(r'(/api/download/polymer/v1/([A-Z0-9-]{36}))')
START_ICONSET = '<iron-iconset-svg' START_ICONSET = '<iron-iconset-svg'
CUR_VERSION = re.compile(r'VERSION = "([A-Za-z0-9]{32})"')
OUTPUT_BASE = os.path.join('homeassistant', 'components', 'frontend') OUTPUT_BASE = os.path.join('homeassistant', 'components', 'frontend')
VERSION_OUTPUT = os.path.join(OUTPUT_BASE, 'mdi_version.py')
ICONSET_OUTPUT = os.path.join(OUTPUT_BASE, 'www_static', 'mdi.html') ICONSET_OUTPUT = os.path.join(OUTPUT_BASE, 'www_static', 'mdi.html')
ICONSET_OUTPUT_GZ = os.path.join(OUTPUT_BASE, 'www_static', 'mdi.html.gz') ICONSET_OUTPUT_GZ = os.path.join(OUTPUT_BASE, 'www_static', 'mdi.html.gz')
def get_local_version():
"""Parse the local version."""
try:
with open(VERSION_OUTPUT) as inp:
for line in inp:
match = CUR_VERSION.search(line)
if match:
return match.group(1)
except FileNotFoundError:
return False
return False
def get_remote_version(): def get_remote_version():
"""Get current version and download link.""" """Get current version and download link."""
gs_page = requests.get(GETTING_STARTED_URL).text gs_page = requests.get(GETTING_STARTED_URL).text
@ -43,10 +29,7 @@ def get_remote_version():
print("Unable to find download link") print("Unable to find download link")
sys.exit() sys.exit()
url = 'https://materialdesignicons.com' + mdi_download.group(1) return 'https://materialdesignicons.com' + mdi_download.group(1)
version = mdi_download.group(2).replace('-', '')
return version, url
def clean_component(source): def clean_component(source):
@ -54,7 +37,7 @@ def clean_component(source):
return source[source.index(START_ICONSET):] return source[source.index(START_ICONSET):]
def write_component(version, source): def write_component(source):
"""Write component.""" """Write component."""
with open(ICONSET_OUTPUT, 'w') as outp: with open(ICONSET_OUTPUT, 'w') as outp:
print('Writing icons to', ICONSET_OUTPUT) print('Writing icons to', ICONSET_OUTPUT)
@ -64,12 +47,6 @@ def write_component(version, source):
print('Writing icons gz to', ICONSET_OUTPUT_GZ) print('Writing icons gz to', ICONSET_OUTPUT_GZ)
outp.write(source.encode('utf-8')) outp.write(source.encode('utf-8'))
with open(VERSION_OUTPUT, 'w') as outp:
print('Generating version file', VERSION_OUTPUT)
outp.write(
'"""DO NOT MODIFY. Auto-generated by update_mdi script."""\n')
outp.write('VERSION = "{}"\n'.format(version))
def main(): def main():
"""Main section of the script.""" """Main section of the script."""
@ -79,19 +56,11 @@ def main():
print("materialdesignicons.com icon updater") print("materialdesignicons.com icon updater")
local_version = get_local_version() remote_url = get_remote_version()
# The remote version is not reliable.
_, remote_url = get_remote_version()
source = clean_component(requests.get(remote_url).text) source = clean_component(requests.get(remote_url).text)
new_version = hashlib.md5(source.encode('utf-8')).hexdigest() write_component(source)
fingerprint()
if local_version == new_version:
print('Already on the latest version.')
sys.exit()
write_component(new_version, source)
print('Updated to latest version') print('Updated to latest version')
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -7,7 +7,7 @@ import unittest
import requests import requests
import homeassistant.bootstrap as bootstrap import homeassistant.bootstrap as bootstrap
import homeassistant.components.http as http from homeassistant.components import frontend, http
from homeassistant.const import HTTP_HEADER_HA_AUTH from homeassistant.const import HTTP_HEADER_HA_AUTH
from tests.common import get_test_instance_port, get_test_home_assistant from tests.common import get_test_instance_port, get_test_home_assistant
@ -48,6 +48,7 @@ def setUpModule(): # pylint: disable=invalid-name
def tearDownModule(): # pylint: disable=invalid-name def tearDownModule(): # pylint: disable=invalid-name
"""Stop everything that was started.""" """Stop everything that was started."""
hass.stop() hass.stop()
frontend.PANELS = {}
class TestFrontend(unittest.TestCase): class TestFrontend(unittest.TestCase):