From 126cdc18c88b73831d65d28267290923cf1101b9 Mon Sep 17 00:00:00 2001 From: Avi Miller Date: Mon, 19 Dec 2022 16:10:30 +1100 Subject: [PATCH] feat: add new Stardust theme from LIFX app v4.13.0 Also more type and test fixes Signed-off-by: Avi Miller --- src/aiolifx_themes/themes.py | 44 +++++++++++++++++++++++------------- tests/test_theme.py | 14 ++++++++++-- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/aiolifx_themes/themes.py b/src/aiolifx_themes/themes.py index fd38535..d6524c9 100644 --- a/src/aiolifx_themes/themes.py +++ b/src/aiolifx_themes/themes.py @@ -2,13 +2,14 @@ from __future__ import annotations import asyncio -from collections.abc import AsyncGenerator, Coroutine, Iterator +from collections.abc import Coroutine, Iterator from functools import partial import math import random -from typing import NamedTuple +from typing import Any, NamedTuple from aiolifx.aiolifx import Light +from aiolifx.message import Message from .util import AwaitAioLIFX, is_multizone, single_zone, supports_extended_multizone @@ -240,7 +241,7 @@ def shuffled(self) -> Theme: new_theme = Theme() colors = list(self._colors) random.shuffle(colors) - new_theme._colors = colors + new_theme._colors = colors # pylint: disable=protected-access return new_theme def ensure_color(self) -> None: @@ -259,7 +260,7 @@ def __init__(self) -> None: @property def themes(self) -> list[str]: """Returns a list of names of the themes in the library.""" - return [name for name in self._palettes.keys()] + return [name for name in self._palettes] def get_theme(self, theme_name: str) -> Theme: """Returns the named theme from the library or a blank theme.""" @@ -322,23 +323,28 @@ async def paint_multizone( ) ) - async def paint_legacy_multizone( + def paint_legacy_multizone( self, light: Light, colors: list[tuple[int, int, int, int]], duration: int = 0 - ) -> AsyncGenerator[Coroutine, None]: # type: ignore + ) -> list[Coroutine[Any, Any, Message]]: """Paint each zone individually on a legacy multizone light.""" + coros = [] for index, color in enumerate(colors): apply = 1 if (index == len(colors) - 1) else 0 - yield AwaitAioLIFX().wait( - partial( - light.set_color_zones, - index, - index, - color, - apply=apply, - duration=int(duration), + coros.append( + AwaitAioLIFX().wait( + partial( + light.set_color_zones, + index, + index, + color, + apply=apply, + duration=int(duration), + ) ) ) + return list(coros) + async def paint( self, theme: Theme, lights: list[Light], duration: float = 0.25 ) -> None: @@ -367,10 +373,10 @@ async def paint( tasks.append(self.paint_multizone(light, colors, duration)) else: # send multiple set_color_zones messages to paint the theme. - async for task in self.paint_legacy_multizone( + for coro in self.paint_legacy_multizone( light, colors, duration=duration ): - tasks.append(task) + tasks.append(coro) await asyncio.gather(*tasks, return_exceptions=True) @@ -709,6 +715,12 @@ def colors(self) -> list[tuple[tuple[int, int], ThemeColor]]: {"hue": 49.0, "saturation": 1.0, "brightness": 0.5, "kelvin": 3500}, {"hue": 198.0, "saturation": 1.0, "brightness": 0.5, "kelvin": 3500}, ], + "stardust": [ + {"hue": 0.0, "saturation": 0.0, "brightness": 0.902, "kelvin": 6500}, + {"hue": 209.0, "saturation": 0.5, "brightness": 0.902, "kelvin": 3500}, + {"hue": 0.0, "saturation": 0.0, "brightness": 0.902, "kelvin": 6497}, + {"hue": 260.0, "saturation": 0.3, "brightness": 0.902, "kelvin": 3500}, + ], "thanksgiving": [ {"hue": 50.0, "saturation": 0.81, "brightness": 0.7757, "kelvin": 3500}, {"hue": 35.0, "saturation": 0.81, "brightness": 0.7757, "kelvin": 3500}, diff --git a/tests/test_theme.py b/tests/test_theme.py index b1b735b..3a7e230 100644 --- a/tests/test_theme.py +++ b/tests/test_theme.py @@ -115,9 +115,9 @@ def test_theme_library() -> None: """Test the theme librarian.""" library = ThemeLibrary() themes = library.themes - assert len(themes) == 41 + assert len(themes) == 42 - for theme_name in ["exciting", "intense", "autumn"]: + for theme_name in ["exciting", "intense", "autumn", "stardust"]: theme_colors = library.get_theme_colors(theme_name) assert [color.as_dict() for color in theme_colors] == LIFX_APP_THEMES[ theme_name @@ -153,8 +153,18 @@ async def test_theme_painter() -> None: for light in lights: if light.product == 38: + # only send a single set_extended_color_zone packet assert len(light.set_extended_color_zones.calls) == 1 elif light.product == 31: + # send a packet for each zone assert len(light.set_color_zones.calls) == light.zones_count + # packets in the sequence have apply=0 so they accumulate + assert ( + light.set_color_zones.calls[round(light.zones_count / 2)][1]["apply"] + == 0 + ) + # the last packet has apply=1 set to trigger the paint + assert light.set_color_zones.calls[light.zones_count - 1][1]["apply"] == 1 elif light.product == 22: + # single zone bulbs get one packet too assert len(light.set_color.calls) == 1