From d33a96fd048fd15f57174fd75a32e924ae6b1507 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Wed, 23 Sep 2020 12:59:58 +0200 Subject: [PATCH] simplify validation --- .../adaptive_lighting/__init__.py | 46 ------------------- .../adaptive_lighting/config_flow.py | 5 +- custom_components/adaptive_lighting/const.py | 16 +++---- custom_components/adaptive_lighting/switch.py | 26 +++++------ 4 files changed, 22 insertions(+), 71 deletions(-) diff --git a/custom_components/adaptive_lighting/__init__.py b/custom_components/adaptive_lighting/__init__.py index 3c83bab2..20121f85 100755 --- a/custom_components/adaptive_lighting/__init__.py +++ b/custom_components/adaptive_lighting/__init__.py @@ -28,7 +28,6 @@ Technical notes: I had to make a lot of assumptions when writing this app """ import asyncio import logging -import voluptuous as vol from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry from .const import DOMAIN, UNDO_UPDATE_LISTENER @@ -37,51 +36,6 @@ _LOGGER = logging.getLogger(__name__) PLATFORMS = ["switch"] -# _SCHEMA = { -# vol.Optional(CONF_LIGHTS, default=DEFAULT_LIGHTS): cv.entity_ids, -# vol.Optional( -# CONF_DISABLE_BRIGHTNESS_ADJUST, -# default=DEFAULT_DISABLE_BRIGHTNESS_ADJUST, -# ): cv.boolean, -# vol.Optional(CONF_DISABLE_ENTITY): cv.entity_id, -# vol.Optional(CONF_DISABLE_STATE): vol.All(cv.ensure_list, [cv.string]), -# vol.Optional( -# CONF_INITIAL_TRANSITION, default=DEFAULT_INITIAL_TRANSITION -# ): VALID_TRANSITION, -# vol.Optional(CONF_INTERVAL, default=DEFAULT_INTERVAL): cv.time_period, -# vol.Optional(CONF_MAX_BRIGHTNESS, default=DEFAULT_MAX_BRIGHTNESS): vol.All( -# vol.Coerce(int), vol.Range(min=1, max=100) -# ), -# vol.Optional(CONF_MAX_COLOR_TEMP, default=DEFAULT_MAX_COLOR_TEMP): vol.All( -# vol.Coerce(int), vol.Range(min=1000, max=10000) -# ), -# vol.Optional(CONF_MIN_BRIGHTNESS, default=DEFAULT_MIN_BRIGHTNESS): vol.All( -# vol.Coerce(int), vol.Range(min=1, max=100) -# ), -# vol.Optional(CONF_MIN_COLOR_TEMP, default=DEFAULT_MIN_COLOR_TEMP): vol.All( -# vol.Coerce(int), vol.Range(min=1000, max=10000) -# ), -# vol.Optional(CONF_ONLY_ONCE, default=DEFAULT_ONLY_ONCE): cv.boolean, -# vol.Optional(CONF_SLEEP_BRIGHTNESS, default=DEFAULT_SLEEP_BRIGHTNESS): vol.All( -# vol.Coerce(int), vol.Range(min=1, max=100) -# ), -# vol.Optional(CONF_SLEEP_COLOR_TEMP, default=DEFAULT_SLEEP_COLOR_TEMP): vol.All( -# vol.Coerce(int), vol.Range(min=1000, max=10000) -# ), -# vol.Optional(CONF_SLEEP_ENTITY): cv.entity_id, -# vol.Optional(CONF_SLEEP_STATE): vol.All(cv.ensure_list, [cv.string]), -# vol.Optional(CONF_SUNRISE_OFFSET, default=DEFAULT_SUNRISE_OFFSET): cv.time_period, -# vol.Optional(CONF_SUNRISE_TIME): cv.time, -# vol.Optional(CONF_SUNSET_OFFSET, default=DEFAULT_SUNSET_OFFSET): cv.time_period, -# vol.Optional(CONF_SUNSET_TIME): cv.time, -# vol.Optional(CONF_TRANSITION, default=DEFAULT_TRANSITION): VALID_TRANSITION, -# } -# CONFIG_SCHEMA = vol.Schema( -# {DOMAIN: vol.All(vol.Schema(_SCHEMA))}, -# extra=vol.ALLOW_EXTRA, -# ) - - async def async_setup(hass, config): """Import integration from config.""" diff --git a/custom_components/adaptive_lighting/config_flow.py b/custom_components/adaptive_lighting/config_flow.py index 3136b697..7e417869 100644 --- a/custom_components/adaptive_lighting/config_flow.py +++ b/custom_components/adaptive_lighting/config_flow.py @@ -45,7 +45,7 @@ from .const import ( DEFAULT_TRANSITION, DOMAIN, FAKE_NONE, - VALIDATION, + EXTRA_VALIDATION, ) _LOGGER = logging.getLogger(__name__) @@ -89,7 +89,8 @@ class OptionsFlowHandler(config_entries.OptionsFlow): """Handle options flow.""" errors = {} if user_input is not None: - for key, validate in VALIDATION: + for key, validate in EXTRA_VALIDATION: + # these are unserializable validators try: value = user_input.get(key) if value == FAKE_NONE: diff --git a/custom_components/adaptive_lighting/const.py b/custom_components/adaptive_lighting/const.py index c07a9af6..5f03f698 100644 --- a/custom_components/adaptive_lighting/const.py +++ b/custom_components/adaptive_lighting/const.py @@ -34,16 +34,16 @@ CONF_SUNSET_TIME = "sunset_time" CONF_TRANSITION, DEFAULT_TRANSITION = "transition", 60 UNDO_UPDATE_LISTENER = "undo_update_listener" -FAKE_NONE = "None" +FAKE_NONE = "None" # TODO: use `from homeassistant.const import ENTITY_MATCH_NONE`? -VALIDATION = [ # these validators cannot be serialized - (CONF_SUNRISE_TIME, cv.time), - (CONF_SUNSET_TIME, cv.time), - (CONF_SUNRISE_OFFSET, cv.time_period), - (CONF_SUNSET_OFFSET, cv.time_period), - (CONF_INTERVAL, cv.time_period), +EXTRA_VALIDATION = [ # these validators cannot be serialized (CONF_DISABLE_ENTITY, cv.entity_id), - (CONF_SLEEP_ENTITY, cv.entity_id), (CONF_DISABLE_STATE, vol.All(cv.ensure_list_csv, [cv.string])), + (CONF_INTERVAL, cv.time_period), + (CONF_SLEEP_ENTITY, cv.entity_id), (CONF_SLEEP_STATE, vol.All(cv.ensure_list_csv, [cv.string])), + (CONF_SUNRISE_OFFSET, cv.time_period), + (CONF_SUNRISE_TIME, cv.time), + (CONF_SUNSET_OFFSET, cv.time_period), + (CONF_SUNSET_TIME, cv.time), ] diff --git a/custom_components/adaptive_lighting/switch.py b/custom_components/adaptive_lighting/switch.py index 378880d9..40ef889c 100755 --- a/custom_components/adaptive_lighting/switch.py +++ b/custom_components/adaptive_lighting/switch.py @@ -3,12 +3,10 @@ import asyncio import bisect +from copy import deepcopy import logging from datetime import timedelta -import voluptuous as vol - -import homeassistant.helpers.config_validation as cv import homeassistant.util.dt as dt_util from homeassistant.components.light import ( ATTR_BRIGHTNESS_PCT, @@ -87,7 +85,7 @@ from .const import ( ICON, SUN_EVENT_MIDNIGHT, SUN_EVENT_NOON, - VALIDATION, + EXTRA_VALIDATION, ) _SUPPORT_OPTS = { @@ -130,7 +128,15 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity): self._entity_id = f"switch.{DOMAIN}_{slugify(name)}" self._icon = ICON - opts = config_entry.options + opts = { + key: value if value != FAKE_NONE else None + for key, value in config_entry.options.items() + } + for key, validate in EXTRA_VALIDATION: # Fix the types of the inputs + value = opts.get(key) + if value is not None: + opts[key] = validate(value) + self._lights = opts.get(CONF_LIGHTS, DEFAULT_LIGHTS) self._disable_brightness_adjust = opts.get( CONF_DISABLE_BRIGHTNESS_ADJUST, DEFAULT_DISABLE_BRIGHTNESS_ADJUST @@ -160,16 +166,6 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity): self._sunset_time = opts.get(CONF_SUNSET_TIME) self._transition = opts.get(CONF_TRANSITION, DEFAULT_TRANSITION) - for name, validate in VALIDATION: - name = f"_{name}" - attr = getattr(self, name) - if attr is not None and attr != FAKE_NONE: - setattr(self, name, validate(attr)) - elif attr == FAKE_NONE: - # FIX: Can't use `None` in OptionsFlow. For reasons I do - # not understand, I cannot save an option that is empty. - setattr(self, name, None) - # Initialize attributes that will be set in self._update_attrs self._percent = None self._brightness = None