lifx-async 4.3.0__tar.gz → 4.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. {lifx_async-4.3.0 → lifx_async-4.3.2}/.github/workflows/pr-automation.yml +2 -0
  2. {lifx_async-4.3.0 → lifx_async-4.3.2}/PKG-INFO +1 -1
  3. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/changelog.md +16 -0
  4. {lifx_async-4.3.0 → lifx_async-4.3.2}/pyproject.toml +1 -1
  5. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/devices/matrix.py +8 -8
  6. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/effects/base.py +10 -0
  7. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/effects/colorloop.py +9 -0
  8. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/effects/pulse.py +9 -0
  9. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_devices/test_matrix.py +22 -22
  10. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_effects/test_base.py +5 -0
  11. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_effects/test_colorloop.py +1 -0
  12. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_effects/test_integration.py +5 -0
  13. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_effects/test_models.py +5 -0
  14. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_effects/test_pulse.py +1 -0
  15. {lifx_async-4.3.0 → lifx_async-4.3.2}/uv.lock +1 -1
  16. {lifx_async-4.3.0 → lifx_async-4.3.2}/.claude/settings.json +0 -0
  17. {lifx_async-4.3.0 → lifx_async-4.3.2}/.github/dependabot.yml +0 -0
  18. {lifx_async-4.3.0 → lifx_async-4.3.2}/.github/labeler.yml +0 -0
  19. {lifx_async-4.3.0 → lifx_async-4.3.2}/.github/workflows/ci.yml +0 -0
  20. {lifx_async-4.3.0 → lifx_async-4.3.2}/.github/workflows/docs.yml +0 -0
  21. {lifx_async-4.3.0 → lifx_async-4.3.2}/.gitignore +0 -0
  22. {lifx_async-4.3.0 → lifx_async-4.3.2}/.pre-commit-config.yaml +0 -0
  23. {lifx_async-4.3.0 → lifx_async-4.3.2}/CLAUDE.md +0 -0
  24. {lifx_async-4.3.0 → lifx_async-4.3.2}/LICENSE +0 -0
  25. {lifx_async-4.3.0 → lifx_async-4.3.2}/README.md +0 -0
  26. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/api/colors.md +0 -0
  27. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/api/devices.md +0 -0
  28. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/api/effects.md +0 -0
  29. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/api/exceptions.md +0 -0
  30. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/api/high-level.md +0 -0
  31. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/api/index.md +0 -0
  32. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/api/network.md +0 -0
  33. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/api/protocol.md +0 -0
  34. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/api/themes.md +0 -0
  35. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/architecture/effects-architecture.md +0 -0
  36. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/architecture/overview.md +0 -0
  37. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/faq.md +0 -0
  38. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/getting-started/effects.md +0 -0
  39. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/getting-started/installation.md +0 -0
  40. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/getting-started/quickstart.md +0 -0
  41. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/getting-started/themes.md +0 -0
  42. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/index.md +0 -0
  43. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/migration/effect-api-changes.md +0 -0
  44. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/stylesheets/extra.css +0 -0
  45. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/user-guide/advanced-usage.md +0 -0
  46. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/user-guide/effects-custom.md +0 -0
  47. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/user-guide/effects-troubleshooting.md +0 -0
  48. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/user-guide/protocol-deep-dive.md +0 -0
  49. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/user-guide/themes.md +0 -0
  50. {lifx_async-4.3.0 → lifx_async-4.3.2}/docs/user-guide/troubleshooting.md +0 -0
  51. {lifx_async-4.3.0 → lifx_async-4.3.2}/examples/01_simple_discovery.py +0 -0
  52. {lifx_async-4.3.0 → lifx_async-4.3.2}/examples/02_simple_control.py +0 -0
  53. {lifx_async-4.3.0 → lifx_async-4.3.2}/examples/03_waveforms.py +0 -0
  54. {lifx_async-4.3.0 → lifx_async-4.3.2}/examples/04_logging.py +0 -0
  55. {lifx_async-4.3.0 → lifx_async-4.3.2}/examples/06_pulse_effect.py +0 -0
  56. {lifx_async-4.3.0 → lifx_async-4.3.2}/examples/07_colorloop_effect.py +0 -0
  57. {lifx_async-4.3.0 → lifx_async-4.3.2}/examples/08_custom_effect.py +0 -0
  58. {lifx_async-4.3.0 → lifx_async-4.3.2}/examples/09_background_effect.py +0 -0
  59. {lifx_async-4.3.0 → lifx_async-4.3.2}/examples/10_find_specific_devices.py +0 -0
  60. {lifx_async-4.3.0 → lifx_async-4.3.2}/examples/11_matrix_basic.py +0 -0
  61. {lifx_async-4.3.0 → lifx_async-4.3.2}/examples/12_matrix_effects.py +0 -0
  62. {lifx_async-4.3.0 → lifx_async-4.3.2}/examples/13_matrix_large.py +0 -0
  63. {lifx_async-4.3.0 → lifx_async-4.3.2}/mkdocs.yml +0 -0
  64. {lifx_async-4.3.0 → lifx_async-4.3.2}/renovate.json +0 -0
  65. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/__init__.py +0 -0
  66. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/api.py +0 -0
  67. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/color.py +0 -0
  68. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/const.py +0 -0
  69. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/devices/__init__.py +0 -0
  70. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/devices/base.py +0 -0
  71. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/devices/hev.py +0 -0
  72. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/devices/infrared.py +0 -0
  73. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/devices/light.py +0 -0
  74. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/devices/multizone.py +0 -0
  75. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/effects/__init__.py +0 -0
  76. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/effects/conductor.py +0 -0
  77. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/effects/const.py +0 -0
  78. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/effects/models.py +0 -0
  79. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/effects/state_manager.py +0 -0
  80. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/exceptions.py +0 -0
  81. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/network/__init__.py +0 -0
  82. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/network/connection.py +0 -0
  83. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/network/discovery.py +0 -0
  84. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/network/message.py +0 -0
  85. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/network/transport.py +0 -0
  86. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/products/__init__.py +0 -0
  87. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/products/generator.py +0 -0
  88. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/products/registry.py +0 -0
  89. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/protocol/__init__.py +0 -0
  90. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/protocol/base.py +0 -0
  91. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/protocol/generator.py +0 -0
  92. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/protocol/header.py +0 -0
  93. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/protocol/models.py +0 -0
  94. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/protocol/packets.py +0 -0
  95. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/protocol/protocol_types.py +0 -0
  96. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/protocol/serializer.py +0 -0
  97. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/py.typed +0 -0
  98. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/theme/__init__.py +0 -0
  99. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/theme/canvas.py +0 -0
  100. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/theme/generators.py +0 -0
  101. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/theme/library.py +0 -0
  102. {lifx_async-4.3.0 → lifx_async-4.3.2}/src/lifx/theme/theme.py +0 -0
  103. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/__init__.py +0 -0
  104. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/conftest.py +0 -0
  105. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_api/__init__.py +0 -0
  106. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_api/test_api_apply_theme.py +0 -0
  107. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_api/test_api_batch_errors.py +0 -0
  108. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_api/test_api_batch_operations.py +0 -0
  109. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_api/test_api_discovery.py +0 -0
  110. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_api/test_api_organization.py +0 -0
  111. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_color.py +0 -0
  112. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_devices/__init__.py +0 -0
  113. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_devices/conftest.py +0 -0
  114. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_devices/test_base.py +0 -0
  115. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_devices/test_hev.py +0 -0
  116. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_devices/test_infrared.py +0 -0
  117. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_devices/test_light.py +0 -0
  118. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_devices/test_mac_address.py +0 -0
  119. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_devices/test_multizone.py +0 -0
  120. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_effects/__init__.py +0 -0
  121. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_effects/test_capability_filtering.py +0 -0
  122. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_effects/test_state_manager.py +0 -0
  123. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_network/__init__.py +0 -0
  124. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_network/test_concurrent_requests.py +0 -0
  125. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_network/test_connection.py +0 -0
  126. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_network/test_discovery_devices.py +0 -0
  127. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_network/test_discovery_errors.py +0 -0
  128. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_network/test_message.py +0 -0
  129. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_network/test_message_advanced.py +0 -0
  130. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_network/test_transport.py +0 -0
  131. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_products/test_product_generator.py +0 -0
  132. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_products/test_registry.py +0 -0
  133. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_protocol/test_generated.py +0 -0
  134. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_protocol/test_header.py +0 -0
  135. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_protocol/test_protocol_generator.py +0 -0
  136. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_protocol/test_serializer.py +0 -0
  137. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_theme/__init__.py +0 -0
  138. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_theme/conftest.py +0 -0
  139. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_theme/test_apply_theme.py +0 -0
  140. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_theme/test_canvas.py +0 -0
  141. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_theme/test_generators.py +0 -0
  142. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_theme/test_library.py +0 -0
  143. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_theme/test_theme.py +0 -0
  144. {lifx_async-4.3.0 → lifx_async-4.3.2}/tests/test_utils.py +0 -0
@@ -71,6 +71,8 @@ jobs:
71
71
  docs
72
72
  ci
73
73
  deps
74
+ effects
75
+ themes
74
76
  requireScope: false
75
77
  subjectPattern: ^(?![A-Z]).+$
76
78
  subjectPatternError: |
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lifx-async
3
- Version: 4.3.0
3
+ Version: 4.3.2
4
4
  Summary: A modern, type-safe, async Python library for controlling LIFX lights
5
5
  Author-email: Avi Miller <me@dje.li>
6
6
  Maintainer-email: Avi Miller <me@dje.li>
@@ -2,6 +2,22 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v4.3.2 (2025-11-22)
6
+
7
+ ### Bug Fixes
8
+
9
+ - **effects**: Add name property to LIFXEffect and subclasses
10
+ ([`deb8a54`](https://github.com/Djelibeybi/lifx-async/commit/deb8a54f674d2d4cd9b8dce519dc6ca8678e048a))
11
+
12
+
13
+ ## v4.3.1 (2025-11-22)
14
+
15
+ ### Bug Fixes
16
+
17
+ - Actually rename the matrix methods
18
+ ([`061aaa7`](https://github.com/Djelibeybi/lifx-async/commit/061aaa7c1931b2fc606363d5acc14ec7fa1b039b))
19
+
20
+
5
21
  ## v4.3.0 (2025-11-22)
6
22
 
7
23
  ### Features
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lifx-async"
3
- version = "4.3.0"
3
+ version = "4.3.2"
4
4
  description = "A modern, type-safe, async Python library for controlling LIFX lights"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -683,17 +683,17 @@ class MatrixLight(Light):
683
683
  colors=colors,
684
684
  )
685
685
 
686
- async def get_tile_effect(self) -> MatrixEffect:
687
- """Get current running tile effect.
686
+ async def get_effect(self) -> MatrixEffect:
687
+ """Get current running matrix effect.
688
688
 
689
689
  Returns:
690
690
  MatrixEffect describing the current effect state
691
691
 
692
692
  Example:
693
- >>> effect = await matrix.get_tile_effect()
693
+ >>> effect = await matrix.get_effect()
694
694
  >>> print(f"Effect type: {effect.effect_type}")
695
695
  """
696
- _LOGGER.debug("Getting tile effect for %s", self.label or self.serial)
696
+ _LOGGER.debug("Getting matrix effect for %s", self.label or self.serial)
697
697
 
698
698
  response: packets.Tile.StateEffect = await self.connection.request(
699
699
  packets.Tile.GetEffect()
@@ -720,7 +720,7 @@ class MatrixLight(Light):
720
720
  self._tile_effect = effect
721
721
  return effect
722
722
 
723
- async def set_tile_effect(
723
+ async def set_effect(
724
724
  self,
725
725
  effect_type: FirmwareEffect,
726
726
  speed: int = 3000,
@@ -730,7 +730,7 @@ class MatrixLight(Light):
730
730
  cloud_saturation_min: int = 0,
731
731
  cloud_saturation_max: int = 0,
732
732
  ) -> None:
733
- """Set tile effect with configuration.
733
+ """Set matrix effect with configuration.
734
734
 
735
735
  Args:
736
736
  effect_type: Type of effect (OFF, MORPH, FLAME, SKY)
@@ -749,14 +749,14 @@ class MatrixLight(Light):
749
749
  ... HSBK(120, 1.0, 1.0, 3500), # Green
750
750
  ... HSBK(240, 1.0, 1.0, 3500), # Blue
751
751
  ... ]
752
- >>> await matrix.set_tile_effect(
752
+ >>> await matrix.set_effect(
753
753
  ... effect_type=FirmwareEffect.MORPH,
754
754
  ... speed=5000,
755
755
  ... palette=rainbow,
756
756
  ... )
757
757
  """
758
758
  _LOGGER.debug(
759
- "Setting tile effect %s (speed=%d) for %s",
759
+ "Setting matrix effect %s (speed=%d) for %s",
760
760
  effect_type,
761
761
  speed,
762
762
  self.label or self.serial,
@@ -59,6 +59,16 @@ class LIFXEffect(ABC):
59
59
  self.conductor: Conductor | None = None
60
60
  self.participants: list[Light] = []
61
61
 
62
+ @property
63
+ @abstractmethod
64
+ def name(self) -> str:
65
+ """Return the name of the effect.
66
+
67
+ Returns:
68
+ The effect name as a string
69
+ """
70
+ raise NotImplementedError("Subclasses must implement name property")
71
+
62
72
  async def async_perform(self, participants: list[Light]) -> None:
63
73
  """Perform common setup and play the effect.
64
74
 
@@ -127,6 +127,15 @@ class EffectColorloop(LIFXEffect):
127
127
  self._running = False
128
128
  self._stop_event = asyncio.Event()
129
129
 
130
+ @property
131
+ def name(self) -> str:
132
+ """Return the name of the effect.
133
+
134
+ Returns:
135
+ The effect name 'colorloop'
136
+ """
137
+ return "colorloop"
138
+
130
139
  async def async_play(self) -> None:
131
140
  """Execute the colorloop effect continuously."""
132
141
  self._running = True
@@ -136,6 +136,15 @@ class EffectPulse(LIFXEffect):
136
136
  if self.cycles < 1:
137
137
  raise ValueError(f"Cycles must be 1 or higher, got {self.cycles}")
138
138
 
139
+ @property
140
+ def name(self) -> str:
141
+ """Return the name of the effect.
142
+
143
+ Returns:
144
+ The effect name 'pulse'
145
+ """
146
+ return "pulse"
147
+
139
148
  async def async_play(self) -> None:
140
149
  """Execute the pulse effect on all participants."""
141
150
  # Determine colors for each light
@@ -186,11 +186,11 @@ class TestMatrixLight:
186
186
  assert colors[0].saturation > 0.9
187
187
  assert colors[0].brightness > 0.9
188
188
 
189
- async def test_get_tile_effect(self, emulator_devices) -> None:
189
+ async def test_get_effect(self, emulator_devices) -> None:
190
190
  """Test getting current tile effect."""
191
191
  matrix = emulator_devices[6]
192
192
  async with matrix:
193
- effect = await matrix.get_tile_effect()
193
+ effect = await matrix.get_effect()
194
194
 
195
195
  assert isinstance(effect, MatrixEffect)
196
196
  assert isinstance(effect.effect_type, FirmwareEffect)
@@ -204,14 +204,14 @@ class TestMatrixLight:
204
204
  matrix = emulator_devices[6]
205
205
  async with matrix:
206
206
  # Fetch tile effect
207
- effect = await matrix.get_tile_effect()
207
+ effect = await matrix.get_effect()
208
208
 
209
209
  # Should be cached in property
210
210
  assert matrix.tile_effect is not None
211
211
  assert isinstance(matrix.tile_effect, MatrixEffect)
212
212
  assert matrix.tile_effect == effect
213
213
 
214
- async def test_set_tile_effect_morph(self, emulator_devices) -> None:
214
+ async def test_set_effect_morph(self, emulator_devices) -> None:
215
215
  """Test setting MORPH effect."""
216
216
  matrix = emulator_devices[6]
217
217
  async with matrix:
@@ -223,18 +223,18 @@ class TestMatrixLight:
223
223
  HSBK(240, 1.0, 1.0, 3500), # Blue
224
224
  ]
225
225
 
226
- await matrix.set_tile_effect(
226
+ await matrix.set_effect(
227
227
  effect_type=FirmwareEffect.MORPH,
228
228
  speed=5000,
229
229
  palette=rainbow,
230
230
  )
231
231
 
232
232
  # Verify effect was set
233
- effect = await matrix.get_tile_effect()
233
+ effect = await matrix.get_effect()
234
234
  assert effect.effect_type == FirmwareEffect.MORPH
235
235
  assert len(effect.palette) == 4
236
236
 
237
- async def test_set_tile_effect_flame(self, emulator_devices) -> None:
237
+ async def test_set_effect_flame(self, emulator_devices) -> None:
238
238
  """Test setting FLAME effect."""
239
239
  matrix = emulator_devices[6]
240
240
  async with matrix:
@@ -246,17 +246,17 @@ class TestMatrixLight:
246
246
  HSBK.from_rgb(255, 215, 0), # Gold
247
247
  ]
248
248
 
249
- await matrix.set_tile_effect(
249
+ await matrix.set_effect(
250
250
  effect_type=FirmwareEffect.FLAME,
251
251
  speed=3000,
252
252
  palette=fire_palette,
253
253
  )
254
254
 
255
255
  # Verify effect was set
256
- effect = await matrix.get_tile_effect()
256
+ effect = await matrix.get_effect()
257
257
  assert effect.effect_type == FirmwareEffect.FLAME
258
258
 
259
- async def test_set_tile_effect_sky_sunrise(self, ceiling_device) -> None:
259
+ async def test_set_effect_sky_sunrise(self, ceiling_device) -> None:
260
260
  """Test setting SKY effect with SUNRISE.
261
261
 
262
262
  SKY effects are only supported on LIFX Ceiling devices
@@ -265,18 +265,18 @@ class TestMatrixLight:
265
265
  """
266
266
  matrix = ceiling_device
267
267
  async with matrix:
268
- await matrix.set_tile_effect(
268
+ await matrix.set_effect(
269
269
  effect_type=FirmwareEffect.SKY,
270
270
  speed=2000,
271
271
  sky_type=TileEffectSkyType.SUNRISE,
272
272
  )
273
273
 
274
274
  # Verify effect was set
275
- effect = await matrix.get_tile_effect()
275
+ effect = await matrix.get_effect()
276
276
  assert effect.effect_type == FirmwareEffect.SKY
277
277
  assert effect.sky_type == TileEffectSkyType.SUNRISE
278
278
 
279
- async def test_set_tile_effect_sky_sunset(self, ceiling_device) -> None:
279
+ async def test_set_effect_sky_sunset(self, ceiling_device) -> None:
280
280
  """Test setting SKY effect with SUNSET.
281
281
 
282
282
  SKY effects are only supported on LIFX Ceiling devices
@@ -285,18 +285,18 @@ class TestMatrixLight:
285
285
  """
286
286
  matrix = ceiling_device
287
287
  async with matrix:
288
- await matrix.set_tile_effect(
288
+ await matrix.set_effect(
289
289
  effect_type=FirmwareEffect.SKY,
290
290
  speed=2000,
291
291
  sky_type=TileEffectSkyType.SUNSET,
292
292
  )
293
293
 
294
294
  # Verify effect was set
295
- effect = await matrix.get_tile_effect()
295
+ effect = await matrix.get_effect()
296
296
  assert effect.effect_type == FirmwareEffect.SKY
297
297
  assert effect.sky_type == TileEffectSkyType.SUNSET
298
298
 
299
- async def test_set_tile_effect_sky_clouds(self, ceiling_device) -> None:
299
+ async def test_set_effect_sky_clouds(self, ceiling_device) -> None:
300
300
  """Test setting SKY effect with CLOUDS and saturation parameters.
301
301
 
302
302
  SKY effects are only supported on LIFX Ceiling devices
@@ -305,7 +305,7 @@ class TestMatrixLight:
305
305
  """
306
306
  matrix = ceiling_device
307
307
  async with matrix:
308
- await matrix.set_tile_effect(
308
+ await matrix.set_effect(
309
309
  effect_type=FirmwareEffect.SKY,
310
310
  speed=4000,
311
311
  sky_type=TileEffectSkyType.CLOUDS,
@@ -314,30 +314,30 @@ class TestMatrixLight:
314
314
  )
315
315
 
316
316
  # Verify effect was set
317
- effect = await matrix.get_tile_effect()
317
+ effect = await matrix.get_effect()
318
318
  assert effect.effect_type == FirmwareEffect.SKY
319
319
  assert effect.sky_type == TileEffectSkyType.CLOUDS
320
320
  assert effect.cloud_saturation_min == 50
321
321
  assert effect.cloud_saturation_max == 200
322
322
 
323
- async def test_set_tile_effect_off(self, emulator_devices) -> None:
323
+ async def test_set_effect_off(self, emulator_devices) -> None:
324
324
  """Test turning off tile effect."""
325
325
  matrix = emulator_devices[6]
326
326
  async with matrix:
327
327
  # First set an effect
328
- await matrix.set_tile_effect(
328
+ await matrix.set_effect(
329
329
  effect_type=FirmwareEffect.MORPH,
330
330
  speed=3000,
331
331
  )
332
332
 
333
333
  # Then turn it off
334
- await matrix.set_tile_effect(
334
+ await matrix.set_effect(
335
335
  effect_type=FirmwareEffect.OFF,
336
336
  speed=0,
337
337
  )
338
338
 
339
339
  # Verify effect was turned off
340
- effect = await matrix.get_tile_effect()
340
+ effect = await matrix.get_effect()
341
341
  assert effect.effect_type == FirmwareEffect.OFF
342
342
 
343
343
  async def test_get64_large_tile(self, ceiling_device) -> None:
@@ -13,6 +13,11 @@ from lifx.effects.const import DEFAULT_BRIGHTNESS
13
13
  class ConcreteEffect(LIFXEffect):
14
14
  """Concrete implementation for testing abstract base class."""
15
15
 
16
+ @property
17
+ def name(self) -> str:
18
+ """Return the name of the effect."""
19
+ return "test"
20
+
16
21
  async def async_play(self) -> None:
17
22
  """Minimal implementation for testing."""
18
23
  pass
@@ -14,6 +14,7 @@ def test_colorloop_default_parameters():
14
14
  """Test EffectColorloop with default parameters."""
15
15
  effect = EffectColorloop()
16
16
 
17
+ assert effect.name == "colorloop"
17
18
  assert effect.period == 60
18
19
  assert effect.change == 20
19
20
  assert effect.spread == 30
@@ -392,6 +392,11 @@ async def test_conductor_exception_during_async_perform():
392
392
 
393
393
  # Create a custom effect that raises exception during async_perform
394
394
  class FailingEffect(LIFXEffect):
395
+ @property
396
+ def name(self) -> str:
397
+ """Return the name of the effect."""
398
+ return "failing"
399
+
395
400
  async def async_play(self):
396
401
  raise RuntimeError("Effect failed during execution")
397
402
 
@@ -10,6 +10,11 @@ from lifx.effects.models import PreState, RunningEffect
10
10
  class DummyEffect(LIFXEffect):
11
11
  """Dummy effect for testing."""
12
12
 
13
+ @property
14
+ def name(self) -> str:
15
+ """Return the name of the effect."""
16
+ return "dummy"
17
+
13
18
  async def async_play(self) -> None:
14
19
  """Dummy play method."""
15
20
  pass
@@ -14,6 +14,7 @@ def test_pulse_default_mode():
14
14
  """Test EffectPulse with default mode (blink)."""
15
15
  effect = EffectPulse()
16
16
 
17
+ assert effect.name == "pulse"
17
18
  assert effect.mode == "blink"
18
19
  assert effect.period == 1.0
19
20
  assert effect.cycles == 1
@@ -432,7 +432,7 @@ wheels = [
432
432
 
433
433
  [[package]]
434
434
  name = "lifx-async"
435
- version = "4.3.0"
435
+ version = "4.3.2"
436
436
  source = { editable = "." }
437
437
 
438
438
  [package.dev-dependencies]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes