diff --git a/hassio/addons/addon.py b/hassio/addons/addon.py index cb47ce7cc..8e118a12e 100644 --- a/hassio/addons/addon.py +++ b/hassio/addons/addon.py @@ -137,6 +137,7 @@ class Addon(object): """Return if auto update is enable.""" if ATTR_AUTO_UPDATE in self.data.user.get(self._id, {}): return self.data.user[self._id][ATTR_AUTO_UPDATE] + return None @auto_update.setter def auto_update(self, value): @@ -159,6 +160,7 @@ class Addon(object): """Return a API token for this add-on.""" if self.is_installed: return self.data.user[self._id][ATTR_UUID] + return None @property def description(self): @@ -333,7 +335,7 @@ class Addon(object): def audio_input(self): """Return ALSA config for input or None.""" if not self.with_audio: - return + return None setting = self.config.audio_input if self.is_installed and ATTR_AUDIO_INPUT in self.data.user[self._id]: diff --git a/hassio/addons/validate.py b/hassio/addons/validate.py index a0001d289..ae40c067c 100644 --- a/hassio/addons/validate.py +++ b/hassio/addons/validate.py @@ -219,6 +219,7 @@ def validate_options(raw_schema): # pylint: disable=no-value-for-parameter +# pylint: disable=inconsistent-return-statements def _single_validate(typ, value, key): """Validate a single element.""" # if required argument diff --git a/hassio/api/__init__.py b/hassio/api/__init__.py index 269fbfd6f..3f7d0fde2 100644 --- a/hassio/api/__init__.py +++ b/hassio/api/__init__.py @@ -79,6 +79,8 @@ class RestAPI(object): '/homeassistant/api/{path:.+}', api_hass.api) self.webapp.router.add_get( '/homeassistant/api/{path:.+}', api_hass.api) + self.webapp.router.add_get( + '/homeassistant/api', api_hass.api) def register_addons(self, addons): """Register homeassistant function.""" diff --git a/hassio/api/addons.py b/hassio/api/addons.py index bdb4512ee..f5f7232b6 100644 --- a/hassio/api/addons.py +++ b/hassio/api/addons.py @@ -57,7 +57,7 @@ class APIAddons(object): """Return a simplified device list.""" dev_list = addon.devices if not dev_list: - return + return None return [row.split(':')[0] for row in dev_list] @api_process diff --git a/hassio/api/homeassistant.py b/hassio/api/homeassistant.py index a455956c2..7f9c74f87 100644 --- a/hassio/api/homeassistant.py +++ b/hassio/api/homeassistant.py @@ -46,9 +46,9 @@ class APIHomeAssistant(object): self.loop = loop self.homeassistant = homeassistant - async def homeassistant_proxy(self, path, request): + async def homeassistant_proxy(self, path, request, timeout=300): """Return a client request with proxy origin for Home-Assistant.""" - url = "{}/api/{}".format(self.homeassistant.api_url, path) + url = f"{self.homeassistant.api_url}/api/{path}" try: data = None @@ -57,7 +57,7 @@ class APIHomeAssistant(object): self.homeassistant.websession, request.method.lower()) # read data - with async_timeout.timeout(10, loop=self.loop): + with async_timeout.timeout(30, loop=self.loop): data = await request.read() if data: @@ -72,7 +72,7 @@ class APIHomeAssistant(object): headers = None client = await method( - url, data=data, headers=headers, timeout=300 + url, data=data, headers=headers, timeout=timeout ) return client @@ -172,11 +172,41 @@ class APIHomeAssistant(object): async def api(self, request): """Proxy API request to Home-Assistant.""" - path = request.match_info.get('path') + path = request.match_info.get('path', '') + _LOGGER.info("Proxy /api/%s request", path) - client = await self.homeassistant_proxy(path, request) - return web.Response( - body=await client.read(), - status=client.status, - content_type=client.content_type - ) + # API stream + if path.startswith("stream"): + client = await self.homeassistant_proxy( + path, request, timeout=None) + + response = web.StreamResponse() + response.content_type = request.headers.get(CONTENT_TYPE) + try: + await response.prepare(request) + while True: + data = await client.content.read(10) + if not data: + await response.write_eof() + break + response.write(data) + + except aiohttp.ClientError: + await response.write_eof() + + except asyncio.TimeoutError: + pass + + finally: + client.close() + + # Normal request + else: + client = await self.homeassistant_proxy(path, request) + + data = await client.read() + return web.Response( + body=data, + status=client.status, + content_type=client.content_type + ) diff --git a/hassio/dock/addon.py b/hassio/dock/addon.py index fa9b075e5..141be97df 100644 --- a/hassio/dock/addon.py +++ b/hassio/dock/addon.py @@ -25,6 +25,7 @@ class DockerAddon(DockerInterface): config, loop, api, image=addon.image, timeout=addon.timeout) self.addon = addon + # pylint: disable=inconsistent-return-statements def process_metadata(self, metadata, force=False): """Use addon data instead meta data with legacy.""" if not self.addon.legacy: @@ -50,6 +51,7 @@ class DockerAddon(DockerInterface): """Return the IPC namespace.""" if self.addon.host_ipc: return 'host' + return None @property def hostname(self): @@ -114,6 +116,7 @@ class DockerAddon(DockerInterface): return [ "apparmor:unconfined", ] + return None @property def tmpfs(self): diff --git a/hassio/dock/homeassistant.py b/hassio/dock/homeassistant.py index 09a2d8918..2037f7364 100644 --- a/hassio/dock/homeassistant.py +++ b/hassio/dock/homeassistant.py @@ -27,7 +27,7 @@ class DockerHomeAssistant(DockerInterface): def devices(self): """Create list of special device to map into docker.""" if not self.data.devices: - return + return None devices = [] for device in self.data.devices: @@ -41,7 +41,7 @@ class DockerHomeAssistant(DockerInterface): Need run inside executor. """ if self._is_running(): - return + return False # cleanup self._stop() diff --git a/hassio/hardware.py b/hassio/hardware.py index d8ba8eb82..a97774eea 100644 --- a/hassio/hardware.py +++ b/hassio/hardware.py @@ -70,7 +70,7 @@ class Hardware(object): devices = devices_file.read() except OSError as err: _LOGGER.error("Can't read asound data -> %s", err) - return + return None audio_list = {} @@ -110,12 +110,12 @@ class Hardware(object): stats = stat_file.read() except OSError as err: _LOGGER.error("Can't read stat data -> %s", err) - return + return None # parse stat file found = RE_BOOT_TIME.search(stats) if not found: _LOGGER.error("Can't found last boot time!") - return + return None return datetime.utcfromtimestamp(int(found.group(1))) diff --git a/hassio/validate.py b/hassio/validate.py index f0507c531..71688d5ae 100644 --- a/hassio/validate.py +++ b/hassio/validate.py @@ -29,11 +29,12 @@ def validate_timezone(timezone): return timezone +# pylint: disable=inconsistent-return-statements def convert_to_docker_ports(data): """Convert data into docker port list.""" # dynamic ports if data is None: - return + return None # single port if isinstance(data, int):