Refactored to new global json saving and loading (#10677)

* Refactored to new global json saving and loading

* Fixed emulated_hue tests

* Removed unnecassary error handling

* Added missing newline

* Remove unused imports

* Fixed linting error

* Moved _load_json wrapper out of the config class
This commit is contained in:
Markus Nigbur 2017-11-20 04:47:55 +01:00 committed by Paulus Schoutsen
parent 7695ca2c8b
commit a83e741dc7
15 changed files with 73 additions and 348 deletions

2
.gitignore vendored
View file

@ -96,4 +96,4 @@ docs/build
desktop.ini desktop.ini
/home-assistant.pyproj /home-assistant.pyproj
/home-assistant.sln /home-assistant.sln
/.vs/home-assistant/v14 /.vs/*

View file

@ -5,7 +5,6 @@ For more details about this component, please refer to the documentation at
https://home-assistant.io/components/axis/ https://home-assistant.io/components/axis/
""" """
import json
import logging import logging
import os import os
@ -22,6 +21,7 @@ from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import discovery from homeassistant.helpers import discovery
from homeassistant.helpers.dispatcher import dispatcher_send from homeassistant.helpers.dispatcher import dispatcher_send
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.util.json import load_json, save_json
REQUIREMENTS = ['axis==14'] REQUIREMENTS = ['axis==14']
@ -103,9 +103,9 @@ def request_configuration(hass, config, name, host, serialnumber):
return False return False
if setup_device(hass, config, device_config): if setup_device(hass, config, device_config):
config_file = _read_config(hass) config_file = load_json(hass.config.path(CONFIG_FILE))
config_file[serialnumber] = dict(device_config) config_file[serialnumber] = dict(device_config)
_write_config(hass, config_file) save_json(hass.config.path(CONFIG_FILE), config_file)
configurator.request_done(request_id) configurator.request_done(request_id)
else: else:
configurator.notify_errors(request_id, configurator.notify_errors(request_id,
@ -163,7 +163,7 @@ def setup(hass, config):
serialnumber = discovery_info['properties']['macaddress'] serialnumber = discovery_info['properties']['macaddress']
if serialnumber not in AXIS_DEVICES: if serialnumber not in AXIS_DEVICES:
config_file = _read_config(hass) config_file = load_json(hass.config.path(CONFIG_FILE))
if serialnumber in config_file: if serialnumber in config_file:
# Device config previously saved to file # Device config previously saved to file
try: try:
@ -274,25 +274,6 @@ def setup_device(hass, config, device_config):
return True return True
def _read_config(hass):
"""Read Axis config."""
path = hass.config.path(CONFIG_FILE)
if not os.path.isfile(path):
return {}
with open(path) as f_handle:
# Guard against empty file
return json.loads(f_handle.read() or '{}')
def _write_config(hass, config):
"""Write Axis config."""
data = json.dumps(config)
with open(hass.config.path(CONFIG_FILE), 'w', encoding='utf-8') as outfile:
outfile.write(data)
class AxisDeviceEvent(Entity): class AxisDeviceEvent(Entity):
"""Representation of a Axis device event.""" """Representation of a Axis device event."""

View file

@ -14,6 +14,7 @@ import homeassistant.helpers.config_validation as cv
from homeassistant.helpers import discovery from homeassistant.helpers import discovery
from homeassistant.const import CONF_API_KEY from homeassistant.const import CONF_API_KEY
from homeassistant.util import Throttle from homeassistant.util import Throttle
from homeassistant.util.json import save_json
REQUIREMENTS = ['python-ecobee-api==0.0.10'] REQUIREMENTS = ['python-ecobee-api==0.0.10']
@ -110,12 +111,10 @@ def setup(hass, config):
if 'ecobee' in _CONFIGURING: if 'ecobee' in _CONFIGURING:
return return
from pyecobee import config_from_file
# Create ecobee.conf if it doesn't exist # Create ecobee.conf if it doesn't exist
if not os.path.isfile(hass.config.path(ECOBEE_CONFIG_FILE)): if not os.path.isfile(hass.config.path(ECOBEE_CONFIG_FILE)):
jsonconfig = {"API_KEY": config[DOMAIN].get(CONF_API_KEY)} jsonconfig = {"API_KEY": config[DOMAIN].get(CONF_API_KEY)}
config_from_file(hass.config.path(ECOBEE_CONFIG_FILE), jsonconfig) save_json(hass.config.path(ECOBEE_CONFIG_FILE), jsonconfig)
NETWORK = EcobeeData(hass.config.path(ECOBEE_CONFIG_FILE)) NETWORK = EcobeeData(hass.config.path(ECOBEE_CONFIG_FILE))

View file

@ -5,7 +5,6 @@ For more details about this component, please refer to the documentation at
https://home-assistant.io/components/emulated_hue/ https://home-assistant.io/components/emulated_hue/
""" """
import asyncio import asyncio
import json
import logging import logging
import voluptuous as vol import voluptuous as vol
@ -16,8 +15,10 @@ from homeassistant.const import (
) )
from homeassistant.components.http import REQUIREMENTS # NOQA from homeassistant.components.http import REQUIREMENTS # NOQA
from homeassistant.components.http import HomeAssistantWSGI from homeassistant.components.http import HomeAssistantWSGI
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.deprecation import get_deprecated from homeassistant.helpers.deprecation import get_deprecated
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.util.json import load_json, save_json
from .hue_api import ( from .hue_api import (
HueUsernameView, HueAllLightsStateView, HueOneLightStateView, HueUsernameView, HueAllLightsStateView, HueOneLightStateView,
HueOneLightChangeView) HueOneLightChangeView)
@ -187,7 +188,7 @@ class Config(object):
return entity_id return entity_id
if self.numbers is None: if self.numbers is None:
self.numbers = self._load_numbers_json() self.numbers = _load_json(self.hass.config.path(NUMBERS_FILE))
# Google Home # Google Home
for number, ent_id in self.numbers.items(): for number, ent_id in self.numbers.items():
@ -198,7 +199,7 @@ class Config(object):
if self.numbers: if self.numbers:
number = str(max(int(k) for k in self.numbers) + 1) number = str(max(int(k) for k in self.numbers) + 1)
self.numbers[number] = entity_id self.numbers[number] = entity_id
self._save_numbers_json() save_json(self.hass.config.path(NUMBERS_FILE), self.numbers)
return number return number
def number_to_entity_id(self, number): def number_to_entity_id(self, number):
@ -207,7 +208,7 @@ class Config(object):
return number return number
if self.numbers is None: if self.numbers is None:
self.numbers = self._load_numbers_json() self.numbers = _load_json(self.hass.config.path(NUMBERS_FILE))
# Google Home # Google Home
assert isinstance(number, str) assert isinstance(number, str)
@ -244,25 +245,11 @@ class Config(object):
return is_default_exposed or expose return is_default_exposed or expose
def _load_numbers_json(self):
"""Set up helper method to load numbers json."""
try:
with open(self.hass.config.path(NUMBERS_FILE),
encoding='utf-8') as fil:
return json.loads(fil.read())
except (OSError, ValueError) as err:
# OSError if file not found or unaccessible/no permissions
# ValueError if could not parse JSON
if not isinstance(err, FileNotFoundError):
_LOGGER.warning("Failed to open %s: %s", NUMBERS_FILE, err)
return {}
def _save_numbers_json(self): def _load_json(filename):
"""Set up helper method to save numbers json.""" """Wrapper, because we actually want to handle invalid json."""
try: try:
with open(self.hass.config.path(NUMBERS_FILE), 'w', return load_json(filename)
encoding='utf-8') as fil: except HomeAssistantError:
fil.write(json.dumps(self.numbers)) pass
except OSError as err: return {}
# OSError if file write permissions
_LOGGER.warning("Failed to write %s: %s", NUMBERS_FILE, err)

View file

@ -4,9 +4,7 @@ Support for Insteon fans via local hub control.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
https://home-assistant.io/components/fan.insteon_local/ https://home-assistant.io/components/fan.insteon_local/
""" """
import json
import logging import logging
import os
from datetime import timedelta from datetime import timedelta
from homeassistant.components.fan import ( from homeassistant.components.fan import (
@ -14,6 +12,7 @@ from homeassistant.components.fan import (
SUPPORT_SET_SPEED, FanEntity) SUPPORT_SET_SPEED, FanEntity)
from homeassistant.helpers.entity import ToggleEntity from homeassistant.helpers.entity import ToggleEntity
import homeassistant.util as util import homeassistant.util as util
from homeassistant.util.json import load_json, save_json
_CONFIGURING = {} _CONFIGURING = {}
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -33,7 +32,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Insteon local fan platform.""" """Set up the Insteon local fan platform."""
insteonhub = hass.data['insteon_local'] insteonhub = hass.data['insteon_local']
conf_fans = config_from_file(hass.config.path(INSTEON_LOCAL_FANS_CONF)) conf_fans = load_json(hass.config.path(INSTEON_LOCAL_FANS_CONF))
if conf_fans: if conf_fans:
for device_id in conf_fans: for device_id in conf_fans:
setup_fan(device_id, conf_fans[device_id], insteonhub, hass, setup_fan(device_id, conf_fans[device_id], insteonhub, hass,
@ -88,44 +87,16 @@ def setup_fan(device_id, name, insteonhub, hass, add_devices_callback):
configurator.request_done(request_id) configurator.request_done(request_id)
_LOGGER.info("Device configuration done!") _LOGGER.info("Device configuration done!")
conf_fans = config_from_file(hass.config.path(INSTEON_LOCAL_FANS_CONF)) conf_fans = load_json(hass.config.path(INSTEON_LOCAL_FANS_CONF))
if device_id not in conf_fans: if device_id not in conf_fans:
conf_fans[device_id] = name conf_fans[device_id] = name
if not config_from_file( save_json(hass.config.path(INSTEON_LOCAL_FANS_CONF), conf_fans)
hass.config.path(INSTEON_LOCAL_FANS_CONF),
conf_fans):
_LOGGER.error("Failed to save configuration file")
device = insteonhub.fan(device_id) device = insteonhub.fan(device_id)
add_devices_callback([InsteonLocalFanDevice(device, name)]) add_devices_callback([InsteonLocalFanDevice(device, name)])
def config_from_file(filename, config=None):
"""Small configuration file management function."""
if config:
# We're writing configuration
try:
with open(filename, 'w') as fdesc:
fdesc.write(json.dumps(config))
except IOError as error:
_LOGGER.error('Saving config file failed: %s', error)
return False
return True
else:
# We're reading config
if os.path.isfile(filename):
try:
with open(filename, 'r') as fdesc:
return json.loads(fdesc.read())
except IOError as error:
_LOGGER.error("Reading configuration file failed: %s", error)
# This won't work yet
return False
else:
return {}
class InsteonLocalFanDevice(FanEntity): class InsteonLocalFanDevice(FanEntity):
"""An abstract Class for an Insteon node.""" """An abstract Class for an Insteon node."""

View file

@ -5,26 +5,21 @@ For more details about this component, please refer to the documentation at
https://home-assistant.io/ecosystem/ios/ https://home-assistant.io/ecosystem/ios/
""" """
import asyncio import asyncio
import os
import json
import logging import logging
import datetime import datetime
import voluptuous as vol import voluptuous as vol
# from voluptuous.humanize import humanize_error # from voluptuous.humanize import humanize_error
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import discovery
from homeassistant.core import callback
from homeassistant.components.http import HomeAssistantView from homeassistant.components.http import HomeAssistantView
from homeassistant.remote import JSONEncoder
from homeassistant.const import (HTTP_INTERNAL_SERVER_ERROR, from homeassistant.const import (HTTP_INTERNAL_SERVER_ERROR,
HTTP_BAD_REQUEST) HTTP_BAD_REQUEST)
from homeassistant.core import callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import discovery
from homeassistant.util.json import load_json, save_json
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -174,36 +169,6 @@ CONFIG_FILE = {ATTR_DEVICES: {}}
CONFIG_FILE_PATH = "" CONFIG_FILE_PATH = ""
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
def _save_config(filename, config):
"""Save configuration."""
try:
with open(filename, 'w') as fdesc:
fdesc.write(json.dumps(config, cls=JSONEncoder))
except (IOError, TypeError) as error:
_LOGGER.error("Saving config file failed: %s", error)
return False
return True
def devices_with_push(): def devices_with_push():
"""Return a dictionary of push enabled targets.""" """Return a dictionary of push enabled targets."""
targets = {} targets = {}
@ -244,7 +209,7 @@ def setup(hass, config):
CONFIG_FILE_PATH = hass.config.path(CONFIGURATION_FILE) CONFIG_FILE_PATH = hass.config.path(CONFIGURATION_FILE)
CONFIG_FILE = _load_config(CONFIG_FILE_PATH) CONFIG_FILE = load_json(CONFIG_FILE_PATH)
if CONFIG_FILE == {}: if CONFIG_FILE == {}:
CONFIG_FILE[ATTR_DEVICES] = {} CONFIG_FILE[ATTR_DEVICES] = {}
@ -305,7 +270,9 @@ class iOSIdentifyDeviceView(HomeAssistantView):
CONFIG_FILE[ATTR_DEVICES][name] = data CONFIG_FILE[ATTR_DEVICES][name] = data
if not _save_config(CONFIG_FILE_PATH, CONFIG_FILE): try:
save_json(CONFIG_FILE_PATH, CONFIG_FILE)
except HomeAssistantError:
return self.json_message("Error saving device.", return self.json_message("Error saving device.",
HTTP_INTERNAL_SERVER_ERROR) HTTP_INTERNAL_SERVER_ERROR)

View file

@ -4,14 +4,14 @@ Support for Insteon dimmers via local hub control.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
https://home-assistant.io/components/light.insteon_local/ https://home-assistant.io/components/light.insteon_local/
""" """
import json
import logging import logging
import os
from datetime import timedelta from datetime import timedelta
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, Light) ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, Light)
import homeassistant.util as util import homeassistant.util as util
from homeassistant.util.json import load_json, save_json
_CONFIGURING = {} _CONFIGURING = {}
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -31,7 +31,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Insteon local light platform.""" """Set up the Insteon local light platform."""
insteonhub = hass.data['insteon_local'] insteonhub = hass.data['insteon_local']
conf_lights = config_from_file(hass.config.path(INSTEON_LOCAL_LIGHTS_CONF)) conf_lights = load_json(hass.config.path(INSTEON_LOCAL_LIGHTS_CONF))
if conf_lights: if conf_lights:
for device_id in conf_lights: for device_id in conf_lights:
setup_light(device_id, conf_lights[device_id], insteonhub, hass, setup_light(device_id, conf_lights[device_id], insteonhub, hass,
@ -85,44 +85,16 @@ def setup_light(device_id, name, insteonhub, hass, add_devices_callback):
configurator.request_done(request_id) configurator.request_done(request_id)
_LOGGER.debug("Device configuration done") _LOGGER.debug("Device configuration done")
conf_lights = config_from_file(hass.config.path(INSTEON_LOCAL_LIGHTS_CONF)) conf_lights = load_json(hass.config.path(INSTEON_LOCAL_LIGHTS_CONF))
if device_id not in conf_lights: if device_id not in conf_lights:
conf_lights[device_id] = name conf_lights[device_id] = name
if not config_from_file( save_json(hass.config.path(INSTEON_LOCAL_LIGHTS_CONF), conf_lights)
hass.config.path(INSTEON_LOCAL_LIGHTS_CONF),
conf_lights):
_LOGGER.error("Failed to save configuration file")
device = insteonhub.dimmer(device_id) device = insteonhub.dimmer(device_id)
add_devices_callback([InsteonLocalDimmerDevice(device, name)]) add_devices_callback([InsteonLocalDimmerDevice(device, name)])
def config_from_file(filename, config=None):
"""Small configuration file management function."""
if config:
# We're writing configuration
try:
with open(filename, 'w') as fdesc:
fdesc.write(json.dumps(config))
except IOError as error:
_LOGGER.error("Saving config file failed: %s", error)
return False
return True
else:
# We're reading config
if os.path.isfile(filename):
try:
with open(filename, 'r') as fdesc:
return json.loads(fdesc.read())
except IOError as error:
_LOGGER.error("Reading configuration file failed: %s", error)
# This won't work yet
return False
else:
return {}
class InsteonLocalDimmerDevice(Light): class InsteonLocalDimmerDevice(Light):
"""An abstract Class for an Insteon node.""" """An abstract Class for an Insteon node."""

View file

@ -5,8 +5,6 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/media_player.braviatv/ https://home-assistant.io/components/media_player.braviatv/
""" """
import logging import logging
import os
import json
import re import re
import voluptuous as vol import voluptuous as vol
@ -18,6 +16,7 @@ from homeassistant.components.media_player import (
PLATFORM_SCHEMA) PLATFORM_SCHEMA)
from homeassistant.const import (CONF_HOST, CONF_NAME, STATE_OFF, STATE_ON) from homeassistant.const import (CONF_HOST, CONF_NAME, STATE_OFF, STATE_ON)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.util.json import load_json, save_json
REQUIREMENTS = [ REQUIREMENTS = [
'https://github.com/aparraga/braviarc/archive/0.3.7.zip' 'https://github.com/aparraga/braviarc/archive/0.3.7.zip'
@ -61,38 +60,6 @@ def _get_mac_address(ip_address):
return None return None
def _config_from_file(filename, config=None):
"""Create the configuration from a file."""
if config:
# We're writing configuration
bravia_config = _config_from_file(filename)
if bravia_config is None:
bravia_config = {}
new_config = bravia_config.copy()
new_config.update(config)
try:
with open(filename, 'w') as fdesc:
fdesc.write(json.dumps(new_config))
except IOError as error:
_LOGGER.error("Saving config file failed: %s", error)
return False
return True
else:
# We're reading config
if os.path.isfile(filename):
try:
with open(filename, 'r') as fdesc:
return json.loads(fdesc.read())
except ValueError as error:
return {}
except IOError as error:
_LOGGER.error("Reading config file failed: %s", error)
# This won't work yet
return False
else:
return {}
# pylint: disable=unused-argument # pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Sony Bravia TV platform.""" """Set up the Sony Bravia TV platform."""
@ -102,7 +69,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
return return
pin = None pin = None
bravia_config = _config_from_file(hass.config.path(BRAVIA_CONFIG_FILE)) bravia_config = load_json(hass.config.path(BRAVIA_CONFIG_FILE))
while bravia_config: while bravia_config:
# Set up a configured TV # Set up a configured TV
host_ip, host_config = bravia_config.popitem() host_ip, host_config = bravia_config.popitem()
@ -136,10 +103,9 @@ def setup_bravia(config, pin, hass, add_devices):
_LOGGER.info("Discovery configuration done") _LOGGER.info("Discovery configuration done")
# Save config # Save config
if not _config_from_file( save_json(
hass.config.path(BRAVIA_CONFIG_FILE), hass.config.path(BRAVIA_CONFIG_FILE),
{host: {'pin': pin, 'host': host, 'mac': mac}}): {host: {'pin': pin, 'host': host, 'mac': mac}})
_LOGGER.error("Failed to save configuration file")
add_devices([BraviaTVDevice(host, mac, name, pin)]) add_devices([BraviaTVDevice(host, mac, name, pin)])

View file

@ -6,7 +6,6 @@ https://home-assistant.io/components/media_player.gpmdp/
""" """
import logging import logging
import json import json
import os
import socket import socket
import time import time
@ -19,6 +18,7 @@ from homeassistant.components.media_player import (
from homeassistant.const import ( from homeassistant.const import (
STATE_PLAYING, STATE_PAUSED, STATE_OFF, CONF_HOST, CONF_PORT, CONF_NAME) STATE_PLAYING, STATE_PAUSED, STATE_OFF, CONF_HOST, CONF_PORT, CONF_NAME)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.util.json import load_json, save_json
REQUIREMENTS = ['websocket-client==0.37.0'] REQUIREMENTS = ['websocket-client==0.37.0']
@ -86,8 +86,7 @@ def request_configuration(hass, config, url, add_devices_callback):
continue continue
setup_gpmdp(hass, config, code, setup_gpmdp(hass, config, code,
add_devices_callback) add_devices_callback)
_save_config(hass.config.path(GPMDP_CONFIG_FILE), save_json(hass.config.path(GPMDP_CONFIG_FILE), {"CODE": code})
{"CODE": code})
websocket.send(json.dumps({'namespace': 'connect', websocket.send(json.dumps({'namespace': 'connect',
'method': 'connect', 'method': 'connect',
'arguments': ['Home Assistant', code]})) 'arguments': ['Home Assistant', code]}))
@ -122,39 +121,9 @@ def setup_gpmdp(hass, config, code, add_devices):
add_devices([GPMDP(name, url, code)], True) add_devices([GPMDP(name, url, code)], True)
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
def _save_config(filename, config):
"""Save configuration."""
try:
with open(filename, 'w') as fdesc:
fdesc.write(json.dumps(config, indent=4, sort_keys=True))
except (IOError, TypeError) as error:
_LOGGER.error("Saving configuration file failed: %s", error)
return False
return True
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the GPMDP platform.""" """Set up the GPMDP platform."""
codeconfig = _load_config(hass.config.path(GPMDP_CONFIG_FILE)) codeconfig = load_json(hass.config.path(GPMDP_CONFIG_FILE))
if codeconfig: if codeconfig:
code = codeconfig.get('CODE') code = codeconfig.get('CODE')
elif discovery_info is not None: elif discovery_info is not None:

View file

@ -121,13 +121,12 @@ def setup_plexserver(
_LOGGER.info("Discovery configuration done") _LOGGER.info("Discovery configuration done")
# Save config # Save config
if not save_json( save_json(
hass.config.path(PLEX_CONFIG_FILE), {host: { hass.config.path(PLEX_CONFIG_FILE), {host: {
'token': token, 'token': token,
'ssl': has_ssl, 'ssl': has_ssl,
'verify': verify_ssl, 'verify': verify_ssl,
}}): }})
_LOGGER.error("Failed to save configuration file")
_LOGGER.info('Connected to: %s://%s', http_prefix, host) _LOGGER.info('Connected to: %s://%s', http_prefix, host)

View file

@ -5,7 +5,6 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/notify.matrix/ https://home-assistant.io/components/notify.matrix/
""" """
import logging import logging
import json
import os import os
from urllib.parse import urlparse from urllib.parse import urlparse
@ -15,6 +14,7 @@ import homeassistant.helpers.config_validation as cv
from homeassistant.components.notify import (ATTR_TARGET, PLATFORM_SCHEMA, from homeassistant.components.notify import (ATTR_TARGET, PLATFORM_SCHEMA,
BaseNotificationService) BaseNotificationService)
from homeassistant.const import CONF_USERNAME, CONF_PASSWORD, CONF_VERIFY_SSL from homeassistant.const import CONF_USERNAME, CONF_PASSWORD, CONF_VERIFY_SSL
from homeassistant.util.json import load_json, save_json
REQUIREMENTS = ['matrix-client==0.0.6'] REQUIREMENTS = ['matrix-client==0.0.6']
@ -82,8 +82,7 @@ class MatrixNotificationService(BaseNotificationService):
return {} return {}
try: try:
with open(self.session_filepath) as handle: data = load_json(self.session_filepath)
data = json.load(handle)
auth_tokens = {} auth_tokens = {}
for mx_id, token in data.items(): for mx_id, token in data.items():
@ -101,16 +100,7 @@ class MatrixNotificationService(BaseNotificationService):
"""Store authentication token to session and persistent storage.""" """Store authentication token to session and persistent storage."""
self.auth_tokens[self.mx_id] = token self.auth_tokens[self.mx_id] = token
try: save_json(self.session_filepath, self.auth_tokens)
with open(self.session_filepath, 'w') as handle:
handle.write(json.dumps(self.auth_tokens))
# Not saving the tokens to disk should not stop the client, we can just
# login using the password every time.
except (OSError, IOError, PermissionError) as ex:
_LOGGER.warning(
"Storing authentication tokens to file '%s' failed: %s",
self.session_filepath, str(ex))
def login(self): def login(self):
"""Login to the matrix homeserver and return the client instance.""" """Login to the matrix homeserver and return the client instance."""

View file

@ -5,7 +5,6 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.fitbit/ https://home-assistant.io/components/sensor.fitbit/
""" """
import os import os
import json
import logging import logging
import datetime import datetime
import time import time
@ -19,6 +18,8 @@ from homeassistant.const import ATTR_ATTRIBUTION
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.helpers.icon import icon_for_battery_level from homeassistant.helpers.icon import icon_for_battery_level
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.util.json import load_json, save_json
REQUIREMENTS = ['fitbit==0.3.0'] REQUIREMENTS = ['fitbit==0.3.0']
@ -147,31 +148,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
}) })
def config_from_file(filename, config=None):
"""Small configuration file management function."""
if config:
# We"re writing configuration
try:
with open(filename, 'w') as fdesc:
fdesc.write(json.dumps(config))
except IOError as error:
_LOGGER.error("Saving config file failed: %s", error)
return False
return config
else:
# We"re reading config
if os.path.isfile(filename):
try:
with open(filename, 'r') as fdesc:
return json.loads(fdesc.read())
except IOError as error:
_LOGGER.error("Reading config file failed: %s", error)
# This won"t work yet
return False
else:
return {}
def request_app_setup(hass, config, add_devices, config_path, def request_app_setup(hass, config, add_devices, config_path,
discovery_info=None): discovery_info=None):
"""Assist user with configuring the Fitbit dev application.""" """Assist user with configuring the Fitbit dev application."""
@ -182,7 +158,7 @@ def request_app_setup(hass, config, add_devices, config_path,
"""Handle configuration updates.""" """Handle configuration updates."""
config_path = hass.config.path(FITBIT_CONFIG_FILE) config_path = hass.config.path(FITBIT_CONFIG_FILE)
if os.path.isfile(config_path): if os.path.isfile(config_path):
config_file = config_from_file(config_path) config_file = load_json(config_path)
if config_file == DEFAULT_CONFIG: if config_file == DEFAULT_CONFIG:
error_msg = ("You didn't correctly modify fitbit.conf", error_msg = ("You didn't correctly modify fitbit.conf",
" please try again") " please try again")
@ -242,13 +218,13 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Fitbit sensor.""" """Set up the Fitbit sensor."""
config_path = hass.config.path(FITBIT_CONFIG_FILE) config_path = hass.config.path(FITBIT_CONFIG_FILE)
if os.path.isfile(config_path): if os.path.isfile(config_path):
config_file = config_from_file(config_path) config_file = load_json(config_path)
if config_file == DEFAULT_CONFIG: if config_file == DEFAULT_CONFIG:
request_app_setup( request_app_setup(
hass, config, add_devices, config_path, discovery_info=None) hass, config, add_devices, config_path, discovery_info=None)
return False return False
else: else:
config_file = config_from_file(config_path, DEFAULT_CONFIG) config_file = save_json(config_path, DEFAULT_CONFIG)
request_app_setup( request_app_setup(
hass, config, add_devices, config_path, discovery_info=None) hass, config, add_devices, config_path, discovery_info=None)
return False return False
@ -384,9 +360,7 @@ class FitbitAuthCallbackView(HomeAssistantView):
ATTR_CLIENT_SECRET: self.oauth.client_secret, ATTR_CLIENT_SECRET: self.oauth.client_secret,
ATTR_LAST_SAVED_AT: int(time.time()) ATTR_LAST_SAVED_AT: int(time.time())
} }
if not config_from_file(hass.config.path(FITBIT_CONFIG_FILE), save_json(hass.config.path(FITBIT_CONFIG_FILE), config_contents)
config_contents):
_LOGGER.error("Failed to save config file")
hass.async_add_job(setup_platform, hass, self.config, self.add_devices) hass.async_add_job(setup_platform, hass, self.config, self.add_devices)
@ -513,5 +487,4 @@ class FitbitSensor(Entity):
ATTR_CLIENT_SECRET: self.client.client.client_secret, ATTR_CLIENT_SECRET: self.client.client.client_secret,
ATTR_LAST_SAVED_AT: int(time.time()) ATTR_LAST_SAVED_AT: int(time.time())
} }
if not config_from_file(self.config_path, config_contents): save_json(self.config_path, config_contents)
_LOGGER.error("Failed to save config file")

View file

@ -4,9 +4,7 @@ Support for monitoring an SABnzbd NZB client.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.sabnzbd/ https://home-assistant.io/components/sensor.sabnzbd/
""" """
import os
import logging import logging
import json
from datetime import timedelta from datetime import timedelta
import voluptuous as vol import voluptuous as vol
@ -17,6 +15,7 @@ from homeassistant.const import (
CONF_SSL) CONF_SSL)
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.util import Throttle from homeassistant.util import Throttle
from homeassistant.util.json import load_json, save_json
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['https://github.com/jamespcole/home-assistant-nzb-clients/' REQUIREMENTS = ['https://github.com/jamespcole/home-assistant-nzb-clients/'
@ -104,9 +103,9 @@ def request_configuration(host, name, hass, config, add_devices, sab_api):
def success(): def success():
"""Set up was successful.""" """Set up was successful."""
conf = _read_config(hass) conf = load_json(hass.config.path(CONFIG_FILE))
conf[host] = {'api_key': api_key} conf[host] = {'api_key': api_key}
_write_config(hass, conf) save_json(hass.config.path(CONFIG_FILE), conf)
req_config = _CONFIGURING.pop(host) req_config = _CONFIGURING.pop(host)
hass.async_add_job(configurator.request_done, req_config) hass.async_add_job(configurator.request_done, req_config)
@ -144,7 +143,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
api_key = config.get(CONF_API_KEY) api_key = config.get(CONF_API_KEY)
if not api_key: if not api_key:
conf = _read_config(hass) conf = load_json(hass.config.path(CONFIG_FILE))
if conf.get(base_url, {}).get('api_key'): if conf.get(base_url, {}).get('api_key'):
api_key = conf[base_url]['api_key'] api_key = conf[base_url]['api_key']
@ -214,22 +213,3 @@ class SabnzbdSensor(Entity):
self._state = self.sabnzb_client.queue.get('diskspace1') self._state = self.sabnzb_client.queue.get('diskspace1')
else: else:
self._state = 'Unknown' self._state = 'Unknown'
def _read_config(hass):
"""Read SABnzbd config."""
path = hass.config.path(CONFIG_FILE)
if not os.path.isfile(path):
return {}
with open(path) as f_handle:
# Guard against empty file
return json.loads(f_handle.read() or '{}')
def _write_config(hass, config):
"""Write SABnzbd config."""
data = json.dumps(config)
with open(hass.config.path(CONFIG_FILE), 'w', encoding='utf-8') as outfile:
outfile.write(data)

View file

@ -4,13 +4,12 @@ Support for Insteon switch devices via local hub support.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
https://home-assistant.io/components/switch.insteon_local/ https://home-assistant.io/components/switch.insteon_local/
""" """
import json
import logging import logging
import os
from datetime import timedelta from datetime import timedelta
from homeassistant.components.switch import SwitchDevice from homeassistant.components.switch import SwitchDevice
import homeassistant.util as util import homeassistant.util as util
from homeassistant.util.json import load_json, save_json
_CONFIGURING = {} _CONFIGURING = {}
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -28,8 +27,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the Insteon local switch platform.""" """Set up the Insteon local switch platform."""
insteonhub = hass.data['insteon_local'] insteonhub = hass.data['insteon_local']
conf_switches = config_from_file(hass.config.path( conf_switches = load_json(hass.config.path(INSTEON_LOCAL_SWITCH_CONF))
INSTEON_LOCAL_SWITCH_CONF))
if conf_switches: if conf_switches:
for device_id in conf_switches: for device_id in conf_switches:
setup_switch( setup_switch(
@ -82,43 +80,16 @@ def setup_switch(device_id, name, insteonhub, hass, add_devices_callback):
configurator.request_done(request_id) configurator.request_done(request_id)
_LOGGER.info("Device configuration done") _LOGGER.info("Device configuration done")
conf_switch = config_from_file(hass.config.path(INSTEON_LOCAL_SWITCH_CONF)) conf_switch = load_json(hass.config.path(INSTEON_LOCAL_SWITCH_CONF))
if device_id not in conf_switch: if device_id not in conf_switch:
conf_switch[device_id] = name conf_switch[device_id] = name
if not config_from_file( save_json(hass.config.path(INSTEON_LOCAL_SWITCH_CONF), conf_switch)
hass.config.path(INSTEON_LOCAL_SWITCH_CONF), conf_switch):
_LOGGER.error("Failed to save configuration file")
device = insteonhub.switch(device_id) device = insteonhub.switch(device_id)
add_devices_callback([InsteonLocalSwitchDevice(device, name)]) add_devices_callback([InsteonLocalSwitchDevice(device, name)])
def config_from_file(filename, config=None):
"""Small configuration file management function."""
if config:
# We're writing configuration
try:
with open(filename, 'w') as fdesc:
fdesc.write(json.dumps(config))
except IOError as error:
_LOGGER.error("Saving configuration file failed: %s", error)
return False
return True
else:
# We're reading config
if os.path.isfile(filename):
try:
with open(filename, 'r') as fdesc:
return json.loads(fdesc.read())
except IOError as error:
_LOGGER.error("Reading config file failed: %s", error)
# This won't work yet
return False
else:
return {}
class InsteonLocalSwitchDevice(SwitchDevice): class InsteonLocalSwitchDevice(SwitchDevice):
"""An abstract Class for an Insteon node.""" """An abstract Class for an Insteon node."""

View file

@ -15,7 +15,7 @@ def test_config_google_home_entity_id_to_number():
mop = mock_open(read_data=json.dumps({'1': 'light.test2'})) mop = mock_open(read_data=json.dumps({'1': 'light.test2'}))
handle = mop() handle = mop()
with patch('homeassistant.components.emulated_hue.open', mop, create=True): with patch('homeassistant.util.json.open', mop, create=True):
number = conf.entity_id_to_number('light.test') number = conf.entity_id_to_number('light.test')
assert number == '2' assert number == '2'
assert handle.write.call_count == 1 assert handle.write.call_count == 1
@ -45,7 +45,7 @@ def test_config_google_home_entity_id_to_number_altered():
mop = mock_open(read_data=json.dumps({'21': 'light.test2'})) mop = mock_open(read_data=json.dumps({'21': 'light.test2'}))
handle = mop() handle = mop()
with patch('homeassistant.components.emulated_hue.open', mop, create=True): with patch('homeassistant.util.json.open', mop, create=True):
number = conf.entity_id_to_number('light.test') number = conf.entity_id_to_number('light.test')
assert number == '22' assert number == '22'
assert handle.write.call_count == 1 assert handle.write.call_count == 1
@ -75,7 +75,7 @@ def test_config_google_home_entity_id_to_number_empty():
mop = mock_open(read_data='') mop = mock_open(read_data='')
handle = mop() handle = mop()
with patch('homeassistant.components.emulated_hue.open', mop, create=True): with patch('homeassistant.util.json.open', mop, create=True):
number = conf.entity_id_to_number('light.test') number = conf.entity_id_to_number('light.test')
assert number == '1' assert number == '1'
assert handle.write.call_count == 1 assert handle.write.call_count == 1