Skip to content

Commit

Permalink
Upgrade aiohttp to 1.1.5 (home-assistant#4213)
Browse files Browse the repository at this point in the history
  • Loading branch information
lwis authored and balloob committed Nov 25, 2016
1 parent febe16d commit 95b439f
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 90 deletions.
70 changes: 44 additions & 26 deletions homeassistant/components/frontend/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from aiohttp import web

from homeassistant.core import callback
from homeassistant.const import EVENT_HOMEASSISTANT_START, HTTP_NOT_FOUND
from homeassistant.const import HTTP_NOT_FOUND
from homeassistant.components import api, group
from homeassistant.components.http import HomeAssistantView
from .version import FINGERPRINTS
Expand All @@ -18,7 +18,6 @@
URL_PANEL_COMPONENT = '/frontend/panels/{}.html'
URL_PANEL_COMPONENT_FP = '/frontend/panels/{}-{}.html'
STATIC_PATH = os.path.join(os.path.dirname(__file__), 'www_static')
PANELS = {}
MANIFEST_JSON = {
"background_color": "#FFFFFF",
"description": "Open-source home automation platform running on Python 3.",
Expand All @@ -32,6 +31,16 @@
"theme_color": "#03A9F4"
}

for size in (192, 384, 512, 1024):
MANIFEST_JSON['icons'].append({
"src": "/static/icons/favicon-{}x{}.png".format(size, size),
"sizes": "{}x{}".format(size, size),
"type": "image/png"
})

DATA_PANELS = 'frontend_panels'
DATA_INDEX_VIEW = 'frontend_index_view'

# To keep track we don't register a component twice (gives a warning)
_REGISTERED_COMPONENTS = set()
_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -68,10 +77,14 @@ def register_panel(hass, component_name, path, md5=None, sidebar_title=None,
Warning: this API will probably change. Use at own risk.
"""
panels = hass.data.get(DATA_PANELS)
if panels is None:
panels = hass.data[DATA_PANELS] = {}

if url_path is None:
url_path = component_name

if url_path in PANELS:
if url_path in panels:
_LOGGER.warning('Overwriting component %s', url_path)
if not os.path.isfile(path):
_LOGGER.error('Panel %s component does not exist: %s',
Expand Down Expand Up @@ -106,7 +119,15 @@ def register_panel(hass, component_name, path, md5=None, sidebar_title=None,
fprinted_url = URL_PANEL_COMPONENT_FP.format(component_name, md5)
data['url'] = fprinted_url

PANELS[url_path] = data
panels[url_path] = data

# Register index view for this route if IndexView already loaded
# Otherwise it will be done during setup.
index_view = hass.data.get(DATA_INDEX_VIEW)

if index_view:
hass.http.app.router.add_route('get', '/{}'.format(url_path),
index_view.get)


def add_manifest_json_key(key, val):
Expand Down Expand Up @@ -134,29 +155,24 @@ def setup(hass, config):
if os.path.isdir(local):
hass.http.register_static_path("/local", local)

index_view = hass.data[DATA_INDEX_VIEW] = IndexView(hass)
hass.http.register_view(index_view)

# Components have registered panels before frontend got setup.
# Now register their urls.
if DATA_PANELS in hass.data:
for url_path in hass.data[DATA_PANELS]:
hass.http.app.router.add_route('get', '/{}'.format(url_path),
index_view.get)
else:
hass.data[DATA_PANELS] = {}

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.http.register_view(IndexView(
hass, ['/{}'.format(name) for name in PANELS]))

hass.bus.listen_once(EVENT_HOMEASSISTANT_START, register_frontend_index)

for size in (192, 384, 512, 1024):
MANIFEST_JSON['icons'].append({
"src": "/static/icons/favicon-{}x{}.png".format(size, size),
"sizes": "{}x{}".format(size, size),
"type": "image/png"
})

return True


Expand All @@ -174,7 +190,7 @@ def get(self, request):
'states': self.hass.states.async_all(),
'events': api.async_events_json(self.hass),
'services': api.async_services_json(self.hass),
'panels': PANELS,
'panels': self.hass.data[DATA_PANELS],
})


Expand All @@ -186,13 +202,12 @@ class IndexView(HomeAssistantView):
requires_auth = False
extra_urls = ['/states', '/states/{entity_id}']

def __init__(self, hass, extra_urls):
def __init__(self, hass):
"""Initialize the frontend view."""
super().__init__(hass)

from jinja2 import FileSystemLoader, Environment

self.extra_urls = self.extra_urls + extra_urls
self.templates = Environment(
loader=FileSystemLoader(
os.path.join(os.path.dirname(__file__), 'templates/')
Expand Down Expand Up @@ -223,7 +238,10 @@ def get(self, request, entity_id=None):
else:
panel = request.path.split('/')[1]

panel_url = PANELS[panel]['url'] if panel != 'states' else ''
if panel == 'states':
panel_url = ''
else:
panel_url = self.hass.data[DATA_PANELS][panel]['url']

no_auth = 'true'
if self.hass.config.api.api_password:
Expand All @@ -244,7 +262,7 @@ def get(self, request, entity_id=None):
resp = template.render(
core_url=core_url, ui_url=ui_url, no_auth=no_auth,
icons_url=icons_url, icons=FINGERPRINTS['mdi.html'],
panel_url=panel_url, panels=PANELS)
panel_url=panel_url, panels=self.hass.data[DATA_PANELS])

return web.Response(text=resp, content_type='text/html')

Expand Down
58 changes: 28 additions & 30 deletions homeassistant/components/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from aiohttp.file_sender import FileSender
from aiohttp.web_exceptions import (
HTTPUnauthorized, HTTPMovedPermanently, HTTPNotModified)
from aiohttp.web_urldispatcher import StaticRoute
from aiohttp.web_urldispatcher import StaticResource

from homeassistant.core import is_callback
import homeassistant.remote as rem
Expand All @@ -33,7 +33,7 @@
from homeassistant.components import persistent_notification

DOMAIN = 'http'
REQUIREMENTS = ('aiohttp_cors==0.4.0',)
REQUIREMENTS = ('aiohttp_cors==0.5.0',)

CONF_API_PASSWORD = 'api_password'
CONF_SERVER_HOST = 'server_host'
Expand Down Expand Up @@ -212,40 +212,41 @@ def send(self, request, filepath):
file_size = st.st_size

resp.content_length = file_size
resp.set_tcp_cork(True)
try:
with filepath.open('rb') as f:
yield from self._sendfile(request, resp, f, file_size)

finally:
resp.set_tcp_nodelay(True)
with filepath.open('rb') as f:
yield from self._sendfile(request, resp, f, file_size)

return resp


_GZIP_FILE_SENDER = GzipFileSender()


class HAStaticRoute(StaticRoute):
"""StaticRoute with support for fingerprinting."""
@asyncio.coroutine
def staticresource_enhancer(app, handler):
"""Enhance StaticResourceHandler.
Adds gzip encoding and fingerprinting matching.
"""
inst = getattr(handler, '__self__', None)
if not isinstance(inst, StaticResource):
return handler

def __init__(self, prefix, path):
"""Initialize a static route with gzip and cache busting support."""
super().__init__(None, prefix, path)
self._file_sender = _GZIP_FILE_SENDER
# pylint: disable=protected-access
inst._file_sender = _GZIP_FILE_SENDER

def match(self, path):
"""Match path to filename."""
if not path.startswith(self._prefix):
return None
@asyncio.coroutine
def middleware_handler(request):
"""Strip out fingerprints from resource names."""
fingerprinted = _FINGERPRINT.match(request.match_info['filename'])

# Extra sauce to remove fingerprinted resource names
filename = path[self._prefix_len:]
fingerprinted = _FINGERPRINT.match(filename)
if fingerprinted:
filename = '{}.{}'.format(*fingerprinted.groups())
request.match_info['filename'] = \
'{}.{}'.format(*fingerprinted.groups())

resp = yield from handler(request)
return resp

return {'filename': filename}
return middleware_handler


class HomeAssistantWSGI(object):
Expand All @@ -257,7 +258,8 @@ def __init__(self, hass, development, api_password, ssl_certificate,
"""Initialize the WSGI Home Assistant server."""
import aiohttp_cors

self.app = web.Application(loop=hass.loop)
self.app = web.Application(middlewares=[staticresource_enhancer],
loop=hass.loop)
self.hass = hass
self.development = development
self.api_password = api_password
Expand Down Expand Up @@ -318,11 +320,7 @@ def register_static_path(self, url_root, path, cache_length=31):
Specify optional cache length of asset in days.
"""
if os.path.isdir(path):
assert url_root.startswith('/')
if not url_root.endswith('/'):
url_root += '/'
route = HAStaticRoute(url_root, path)
self.app.router.register_route(route)
self.app.router.add_static(url_root, path)
return

filepath = Path(path)
Expand Down
6 changes: 3 additions & 3 deletions requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ pip>=7.0.0
jinja2>=2.8
voluptuous==0.9.2
typing>=3,<4
aiohttp==1.0.5
async_timeout==1.0.0
aiohttp==1.1.5
async_timeout==1.1.0

# homeassistant.components.nuimo_controller
--only-binary=all git+https://github.com/getSenic/nuimo-linux-python#nuimo==1.0.0
Expand All @@ -31,7 +31,7 @@ SoCo==0.12
TwitterAPI==2.4.2

# homeassistant.components.http
aiohttp_cors==0.4.0
aiohttp_cors==0.5.0

# homeassistant.components.apcupsd
apcaccess==0.0.4
Expand Down
2 changes: 1 addition & 1 deletion requirements_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pytest>=2.9.2
pytest-aiohttp>=0.1.3
pytest-asyncio>=0.5.0
pytest-cov>=2.3.1
pytest-timeout>=1.0.0
pytest-timeout>=1.2.0
pytest-catchlog>=1.2.2
requests_mock>=1.0
mock-open>=1.3.1
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
'jinja2>=2.8',
'voluptuous==0.9.2',
'typing>=3,<4',
'aiohttp==1.0.5',
'async_timeout==1.0.0',
'aiohttp==1.1.5',
'async_timeout==1.1.0',
]

setup(
Expand Down
10 changes: 5 additions & 5 deletions tests/components/media_player/test_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,13 +245,17 @@ def setUp(self):
"""Setup things to be run when tests are started."""
self.hass = get_test_home_assistant()

setup_component(self.hass, http.DOMAIN, {
assert setup_component(self.hass, http.DOMAIN, {
http.DOMAIN: {
http.CONF_SERVER_PORT: SERVER_PORT,
http.CONF_API_PASSWORD: API_PASSWORD,
},
})

assert setup_component(
self.hass, mp.DOMAIN,
{'media_player': {'platform': 'demo'}})

self.hass.start()

def tearDown(self):
Expand Down Expand Up @@ -287,10 +291,6 @@ def close(self):

self.hass._websession = MockWebsession()

self.hass.block_till_done()
assert setup_component(
self.hass, mp.DOMAIN,
{'media_player': {'platform': 'demo'}})
assert self.hass.states.is_state(entity_id, 'playing')
state = self.hass.states.get(entity_id)
req = requests.get(HTTP_BASE_URL +
Expand Down
36 changes: 19 additions & 17 deletions tests/components/test_google.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def test_setup_component(self, mock_do_auth):
self.assertTrue(setup_component(self.hass, 'google', config))

def test_get_calendar_info(self):
"""Test getting the calendar info."""
calendar = {
'id': 'qwertyuiopasdfghjklzxcvbnm@import.calendar.google.com',
'etag': '"3584134138943410"',
Expand Down Expand Up @@ -61,21 +62,22 @@ def test_get_calendar_info(self):
})

def test_found_calendar(self):
calendar = {
'id': 'qwertyuiopasdfghjklzxcvbnm@import.calendar.google.com',
'etag': '"3584134138943410"',
'timeZone': 'UTC',
'accessRole': 'reader',
'foregroundColor': '#000000',
'selected': True,
'kind': 'calendar#calendarListEntry',
'backgroundColor': '#16a765',
'description': 'Test Calendar',
'summary': 'We are, we are, a... Test Calendar',
'colorId': '8',
'defaultReminders': [],
'track': True
}
"""Test when a calendar is found."""
# calendar = {
# 'id': 'qwertyuiopasdfghjklzxcvbnm@import.calendar.google.com',
# 'etag': '"3584134138943410"',
# 'timeZone': 'UTC',
# 'accessRole': 'reader',
# 'foregroundColor': '#000000',
# 'selected': True,
# 'kind': 'calendar#calendarListEntry',
# 'backgroundColor': '#16a765',
# 'description': 'Test Calendar',
# 'summary': 'We are, we are, a... Test Calendar',
# 'colorId': '8',
# 'defaultReminders': [],
# 'track': True
# }

# self.assertIsInstance(self.hass.data[google.DATA_INDEX], dict)
# self.assertEquals(self.hass.data[google.DATA_INDEX], {})
Expand All @@ -84,8 +86,8 @@ def test_found_calendar(self):
self.hass.config.path(google.TOKEN_FILE))
self.assertTrue(google.setup_services(self.hass, True,
calendar_service))
self.hass.services.call('google', 'found_calendar', calendar,
blocking=True)
# self.hass.services.call('google', 'found_calendar', calendar,
# blocking=True)

# TODO: Fix this
# self.assertTrue(self.hass.data[google.DATA_INDEX]
Expand Down
Loading

0 comments on commit 95b439f

Please sign in to comment.