diff --git a/custom_components/adaptive_lighting/__init__.py b/custom_components/adaptive_lighting/__init__.py index 39c900e4..dd1d0323 100644 --- a/custom_components/adaptive_lighting/__init__.py +++ b/custom_components/adaptive_lighting/__init__.py @@ -107,15 +107,14 @@ def _remove_orphan_lux_sensors( """Remove lux output sensors when lux_sensor is no longer configured.""" has_lux = bool( config_entry.options.get(CONF_LUX_SENSOR) - or config_entry.data.get(CONF_LUX_SENSOR) + or config_entry.data.get(CONF_LUX_SENSOR), ) if has_lux: return registry = er.async_get(hass) for entry in list(registry.entities.values()): - if ( - entry.config_entry_id == config_entry.entry_id - and any(entry.unique_id.endswith(s) for s in _LUX_CONDITIONAL_SUFFIXES) + if entry.config_entry_id == config_entry.entry_id and any( + entry.unique_id.endswith(s) for s in _LUX_CONDITIONAL_SUFFIXES ): _LOGGER.info( "Removing orphan lux sensor %s (lux_sensor no longer configured).", diff --git a/custom_components/adaptive_lighting/sensor.py b/custom_components/adaptive_lighting/sensor.py index d17ba755..9b995856 100644 --- a/custom_components/adaptive_lighting/sensor.py +++ b/custom_components/adaptive_lighting/sensor.py @@ -42,7 +42,7 @@ async def async_setup_entry( """Create the output sensors for this config entry.""" has_lux = bool( config_entry.options.get(CONF_LUX_SENSOR) - or config_entry.data.get(CONF_LUX_SENSOR) + or config_entry.data.get(CONF_LUX_SENSOR), ) entities = [ AdaptiveOutputSensor( diff --git a/custom_components/adaptive_lighting/switch.py b/custom_components/adaptive_lighting/switch.py index c86504d8..14474dad 100644 --- a/custom_components/adaptive_lighting/switch.py +++ b/custom_components/adaptive_lighting/switch.py @@ -849,7 +849,9 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity): self._lux_turned_off: set[str] = getattr(self, "_lux_turned_off", set()) self._last_lux_factor: float = 1.0 self._remove_lux_listener: CALLBACK_TYPE | None = getattr( - self, "_remove_lux_listener", None + self, + "_remove_lux_listener", + None, ) self._expand_light_groups() @@ -1090,7 +1092,8 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity): context = self.create_context("lux_change") self.hass.async_create_task( self._update_attrs_and_maybe_adapt_lights( - context=context, force=True, + context=context, + force=True, ), ) diff --git a/tests/test_config_flow.py b/tests/test_config_flow.py index 8728b120..fa677cbc 100644 --- a/tests/test_config_flow.py +++ b/tests/test_config_flow.py @@ -100,7 +100,9 @@ def _section_inner_keys(schema_section) -> set[str]: def test_options_schema_has_all_seven_sections_in_order() -> None: """R1: the options form returns the seven named sections in order.""" - schema = _build_options_schema({}, show_send_split_delay=False, show_target_lux=False) + schema = _build_options_schema( + {}, show_send_split_delay=False, show_target_lux=False + ) keys = [ k.schema if hasattr(k, "schema") else k for k in schema.schema # type: ignore[attr-defined] @@ -112,7 +114,9 @@ def test_each_section_contains_only_its_specified_fields() -> None: """R1 scenario 2: every field appears in exactly one section, matching the layout table. """ - schema = _build_options_schema({}, show_send_split_delay=True, show_target_lux=False) + schema = _build_options_schema( + {}, show_send_split_delay=True, show_target_lux=False + ) for marker in schema.schema: # type: ignore[attr-defined] section_id = marker.schema if hasattr(marker, "schema") else marker inner_fields = _section_inner_keys(schema.schema[marker]) # type: ignore[index] @@ -132,7 +136,9 @@ def test_each_section_contains_only_its_specified_fields() -> None: def test_send_split_delay_hidden_when_driver_false() -> None: """R2: send_split_delay is absent when separate_turn_on_commands=False.""" - schema = _build_options_schema({}, show_send_split_delay=False, show_target_lux=False) + schema = _build_options_schema( + {}, show_send_split_delay=False, show_target_lux=False + ) advanced_marker = next( m for m in schema.schema # type: ignore[attr-defined] @@ -144,7 +150,9 @@ def test_send_split_delay_hidden_when_driver_false() -> None: def test_send_split_delay_visible_when_driver_true() -> None: """R2: send_split_delay appears when separate_turn_on_commands=True.""" - schema = _build_options_schema({}, show_send_split_delay=True, show_target_lux=False) + schema = _build_options_schema( + {}, show_send_split_delay=True, show_target_lux=False + ) advanced_marker = next( m for m in schema.schema # type: ignore[attr-defined] @@ -161,7 +169,9 @@ def test_send_split_delay_visible_when_driver_true() -> None: def test_default_sunrise_and_sunset_entities() -> None: """R3: default entities point at the built-in sun.sun sensors.""" - schema = _build_options_schema({}, show_send_split_delay=False, show_target_lux=False) + schema = _build_options_schema( + {}, show_send_split_delay=False, show_target_lux=False + ) sun_marker = next( m for m in schema.schema # type: ignore[attr-defined] @@ -189,7 +199,9 @@ def test_sun_entity_selectors_are_strict_timestamp_sensors() -> None: """R3 + D14: both sun-event entity selectors filter by domain=sensor and device_class=timestamp. """ - schema = _build_options_schema({}, show_send_split_delay=False, show_target_lux=False) + schema = _build_options_schema( + {}, show_send_split_delay=False, show_target_lux=False + ) sun_marker = next( m for m in schema.schema # type: ignore[attr-defined] @@ -218,7 +230,9 @@ def test_sun_entity_selectors_are_strict_timestamp_sensors() -> None: def test_brightness_uses_slider_number_selector() -> None: """R5: brightness fields are NumberSelectors with slider mode, 1–100 %, step 1.""" - schema = _build_options_schema({}, show_send_split_delay=False, show_target_lux=False) + schema = _build_options_schema( + {}, show_send_split_delay=False, show_target_lux=False + ) daytime_marker = next( m for m in schema.schema # type: ignore[attr-defined] @@ -239,7 +253,9 @@ def test_brightness_uses_slider_number_selector() -> None: def test_color_temp_uses_box_number_selector() -> None: """R5: color-temp fields are NumberSelectors, 1000–10000 K, step 100.""" - schema = _build_options_schema({}, show_send_split_delay=False, show_target_lux=False) + schema = _build_options_schema( + {}, show_send_split_delay=False, show_target_lux=False + ) daytime_marker = next( m for m in schema.schema # type: ignore[attr-defined] @@ -259,7 +275,9 @@ def test_color_temp_uses_box_number_selector() -> None: def test_booleans_use_boolean_selector() -> None: """R5: every boolean field renders as a BooleanSelector.""" - schema = _build_options_schema({}, show_send_split_delay=True, show_target_lux=False) + schema = _build_options_schema( + {}, show_send_split_delay=True, show_target_lux=False + ) boolean_fields = { CONF_PREFER_RGB_COLOR, CONF_INTERCEPT, @@ -349,7 +367,9 @@ async def test_options_flow_renders_sectioned_schema(hass) -> None: def test_target_lux_hidden_when_no_sensor() -> None: """target_lux should not appear when lux_sensor is empty.""" - schema = _build_options_schema({}, show_send_split_delay=False, show_target_lux=False) + schema = _build_options_schema( + {}, show_send_split_delay=False, show_target_lux=False + ) lux_marker = next( m for m in schema.schema @@ -379,7 +399,9 @@ def test_target_lux_visible_when_sensor_set() -> None: def test_lux_sensor_selector_filters_to_illuminance() -> None: """lux_sensor entity selector should filter to device_class=illuminance.""" - schema = _build_options_schema({}, show_send_split_delay=False, show_target_lux=False) + schema = _build_options_schema( + {}, show_send_split_delay=False, show_target_lux=False + ) lux_marker = next( m for m in schema.schema @@ -465,7 +487,10 @@ def _full_section_payload() -> dict: # Omit lux_sensor entirely: an EntitySelector rejects an explicit "", # so the empty case is expressed by absence (the vol.Optional default). SECTION_AMBIENT_LUX: {}, - SECTION_LIGHT_CONTROL: {CONF_INTERCEPT: True, CONF_MULTI_LIGHT_INTERCEPT: False}, + SECTION_LIGHT_CONTROL: { + CONF_INTERCEPT: True, + CONF_MULTI_LIGHT_INTERCEPT: False, + }, SECTION_ADVANCED: { CONF_INTERVAL: 90, "transition": 45,