diff --git a/homeassistant/components/notify/html5.py b/homeassistant/components/notify/html5.py
index a05c061c515..2314722a2ab 100644
--- a/homeassistant/components/notify/html5.py
+++ b/homeassistant/components/notify/html5.py
@@ -8,7 +8,6 @@ import asyncio
import datetime
import json
import logging
-import os
import time
import uuid
@@ -16,6 +15,8 @@ from aiohttp.hdrs import AUTHORIZATION
import voluptuous as vol
from voluptuous.humanize import humanize_error
+from homeassistant.util.json import load_json, save_json
+from homeassistant.exceptions import HomeAssistantError
from homeassistant.components.frontend import add_manifest_json_key
from homeassistant.components.http import HomeAssistantView
from homeassistant.components.notify import (
@@ -125,21 +126,11 @@ def get_service(hass, config, discovery_info=None):
def _load_config(filename):
"""Load configuration."""
- if not os.path.isfile(filename):
- return {}
-
try:
- with open(filename, 'r') as fdesc:
- inp = fdesc.read()
-
- # In case empty file
- if not inp:
- return {}
-
- return json.loads(inp)
- except (IOError, ValueError) as error:
- _LOGGER.error("Reading config file %s failed: %s", filename, error)
- return None
+ return load_json(filename)
+ except HomeAssistantError:
+ pass
+ return {}
class JSONBytesDecoder(json.JSONEncoder):
@@ -153,18 +144,6 @@ class JSONBytesDecoder(json.JSONEncoder):
return json.JSONEncoder.default(self, obj)
-def _save_config(filename, config):
- """Save configuration."""
- try:
- with open(filename, 'w') as fdesc:
- fdesc.write(json.dumps(
- config, cls=JSONBytesDecoder, indent=4, sort_keys=True))
- except (IOError, TypeError) as error:
- _LOGGER.error("Saving configuration file failed: %s", error)
- return False
- return True
-
-
class HTML5PushRegistrationView(HomeAssistantView):
"""Accepts push registrations from a browser."""
@@ -194,7 +173,7 @@ class HTML5PushRegistrationView(HomeAssistantView):
self.registrations[name] = data
- if not _save_config(self.json_path, self.registrations):
+ if not save_json(self.json_path, self.registrations):
return self.json_message(
'Error saving registration.', HTTP_INTERNAL_SERVER_ERROR)
@@ -223,7 +202,7 @@ class HTML5PushRegistrationView(HomeAssistantView):
reg = self.registrations.pop(found)
- if not _save_config(self.json_path, self.registrations):
+ if not save_json(self.json_path, self.registrations):
self.registrations[found] = reg
return self.json_message(
'Error saving registration.', HTTP_INTERNAL_SERVER_ERROR)
@@ -411,8 +390,8 @@ class HTML5NotificationService(BaseNotificationService):
if response.status_code == 410:
_LOGGER.info("Notification channel has expired")
reg = self.registrations.pop(target)
- if not _save_config(self.registrations_json_path,
- self.registrations):
+ if not save_json(self.registrations_json_path,
+ self.registrations):
self.registrations[target] = reg
_LOGGER.error("Error saving registration")
else:
diff --git a/tests/components/notify/test_html5.py b/tests/components/notify/test_html5.py
index 2c39cc5dbd7..c3998b6db64 100644
--- a/tests/components/notify/test_html5.py
+++ b/tests/components/notify/test_html5.py
@@ -57,24 +57,13 @@ class TestHtml5Notify(object):
m = mock_open()
with patch(
- 'homeassistant.components.notify.html5.open', m, create=True
+ 'homeassistant.util.json.open',
+ m, create=True
):
service = html5.get_service(hass, {})
assert service is not None
- def test_get_service_with_bad_json(self):
- """Test ."""
- hass = MagicMock()
-
- m = mock_open(read_data='I am not JSON')
- with patch(
- 'homeassistant.components.notify.html5.open', m, create=True
- ):
- service = html5.get_service(hass, {})
-
- assert service is None
-
@patch('pywebpush.WebPusher')
def test_sending_message(self, mock_wp):
"""Test sending message."""
@@ -86,7 +75,8 @@ class TestHtml5Notify(object):
m = mock_open(read_data=json.dumps(data))
with patch(
- 'homeassistant.components.notify.html5.open', m, create=True
+ 'homeassistant.util.json.open',
+ m, create=True
):
service = html5.get_service(hass, {'gcm_sender_id': '100'})
@@ -120,7 +110,8 @@ class TestHtml5Notify(object):
m = mock_open()
with patch(
- 'homeassistant.components.notify.html5.open', m, create=True
+ 'homeassistant.util.json.open',
+ m, create=True
):
hass.config.path.return_value = 'file.conf'
service = html5.get_service(hass, {})
@@ -158,7 +149,8 @@ class TestHtml5Notify(object):
m = mock_open()
with patch(
- 'homeassistant.components.notify.html5.open', m, create=True
+ 'homeassistant.util.json.open',
+ m, create=True
):
hass.config.path.return_value = 'file.conf'
service = html5.get_service(hass, {})
@@ -193,7 +185,8 @@ class TestHtml5Notify(object):
m = mock_open()
with patch(
- 'homeassistant.components.notify.html5.open', m, create=True
+ 'homeassistant.util.json.open',
+ m, create=True
):
hass.config.path.return_value = 'file.conf'
service = html5.get_service(hass, {})
@@ -222,7 +215,7 @@ class TestHtml5Notify(object):
}))
assert resp.status == 400
- with patch('homeassistant.components.notify.html5._save_config',
+ with patch('homeassistant.components.notify.html5.save_json',
return_value=False):
# resp = view.post(Request(builder.get_environ()))
resp = yield from client.post(REGISTER_URL, data=json.dumps({
@@ -243,14 +236,12 @@ class TestHtml5Notify(object):
}
m = mock_open(read_data=json.dumps(config))
-
- with patch('homeassistant.components.notify.html5.open', m,
- create=True):
+ with patch(
+ 'homeassistant.util.json.open',
+ m, create=True
+ ):
hass.config.path.return_value = 'file.conf'
-
- with patch('homeassistant.components.notify.html5.os.path.isfile',
- return_value=True):
- service = html5.get_service(hass, {})
+ service = html5.get_service(hass, {})
assert service is not None
@@ -291,12 +282,11 @@ class TestHtml5Notify(object):
m = mock_open(read_data=json.dumps(config))
with patch(
- 'homeassistant.components.notify.html5.open', m, create=True
+ 'homeassistant.util.json.open',
+ m, create=True
):
hass.config.path.return_value = 'file.conf'
- with patch('homeassistant.components.notify.html5.os.path.isfile',
- return_value=True):
- service = html5.get_service(hass, {})
+ service = html5.get_service(hass, {})
assert service is not None
@@ -324,7 +314,7 @@ class TestHtml5Notify(object):
@asyncio.coroutine
def test_unregistering_device_view_handles_json_safe_error(
- self, loop, test_client):
+ self, loop, test_client):
"""Test that the HTML unregister view handles JSON write errors."""
hass = MagicMock()
@@ -335,12 +325,11 @@ class TestHtml5Notify(object):
m = mock_open(read_data=json.dumps(config))
with patch(
- 'homeassistant.components.notify.html5.open', m, create=True
+ 'homeassistant.util.json.open',
+ m, create=True
):
hass.config.path.return_value = 'file.conf'
- with patch('homeassistant.components.notify.html5.os.path.isfile',
- return_value=True):
- service = html5.get_service(hass, {})
+ service = html5.get_service(hass, {})
assert service is not None
@@ -357,7 +346,7 @@ class TestHtml5Notify(object):
client = yield from test_client(app)
hass.http.is_banned_ip.return_value = False
- with patch('homeassistant.components.notify.html5._save_config',
+ with patch('homeassistant.components.notify.html5.save_json',
return_value=False):
resp = yield from client.delete(REGISTER_URL, data=json.dumps({
'subscription': SUBSCRIPTION_1['subscription'],
@@ -375,7 +364,8 @@ class TestHtml5Notify(object):
m = mock_open()
with patch(
- 'homeassistant.components.notify.html5.open', m, create=True
+ 'homeassistant.util.json.open',
+ m, create=True
):
hass.config.path.return_value = 'file.conf'
service = html5.get_service(hass, {})
@@ -406,17 +396,16 @@ class TestHtml5Notify(object):
hass = MagicMock()
data = {
- 'device': SUBSCRIPTION_1,
+ 'device': SUBSCRIPTION_1
}
m = mock_open(read_data=json.dumps(data))
with patch(
- 'homeassistant.components.notify.html5.open', m, create=True
+ 'homeassistant.util.json.open',
+ m, create=True
):
hass.config.path.return_value = 'file.conf'
- with patch('homeassistant.components.notify.html5.os.path.isfile',
- return_value=True):
- service = html5.get_service(hass, {'gcm_sender_id': '100'})
+ service = html5.get_service(hass, {'gcm_sender_id': '100'})
assert service is not None