lifx-async 4.3.7__tar.gz → 4.3.8__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.7 → lifx_async-4.3.8}/PKG-INFO +1 -1
  2. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/changelog.md +8 -0
  3. {lifx_async-4.3.7 → lifx_async-4.3.8}/pyproject.toml +1 -1
  4. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/devices/base.py +0 -2
  5. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/network/connection.py +4 -2
  6. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_network/test_connection.py +7 -8
  7. {lifx_async-4.3.7 → lifx_async-4.3.8}/uv.lock +1 -1
  8. {lifx_async-4.3.7 → lifx_async-4.3.8}/.claude/settings.json +0 -0
  9. {lifx_async-4.3.7 → lifx_async-4.3.8}/.github/dependabot.yml +0 -0
  10. {lifx_async-4.3.7 → lifx_async-4.3.8}/.github/labeler.yml +0 -0
  11. {lifx_async-4.3.7 → lifx_async-4.3.8}/.github/workflows/ci.yml +0 -0
  12. {lifx_async-4.3.7 → lifx_async-4.3.8}/.github/workflows/docs.yml +0 -0
  13. {lifx_async-4.3.7 → lifx_async-4.3.8}/.github/workflows/pr-automation.yml +0 -0
  14. {lifx_async-4.3.7 → lifx_async-4.3.8}/.gitignore +0 -0
  15. {lifx_async-4.3.7 → lifx_async-4.3.8}/.pre-commit-config.yaml +0 -0
  16. {lifx_async-4.3.7 → lifx_async-4.3.8}/CLAUDE.md +0 -0
  17. {lifx_async-4.3.7 → lifx_async-4.3.8}/LICENSE +0 -0
  18. {lifx_async-4.3.7 → lifx_async-4.3.8}/README.md +0 -0
  19. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/api/colors.md +0 -0
  20. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/api/devices.md +0 -0
  21. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/api/effects.md +0 -0
  22. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/api/exceptions.md +0 -0
  23. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/api/high-level.md +0 -0
  24. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/api/index.md +0 -0
  25. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/api/network.md +0 -0
  26. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/api/protocol.md +0 -0
  27. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/api/themes.md +0 -0
  28. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/architecture/effects-architecture.md +0 -0
  29. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/architecture/overview.md +0 -0
  30. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/faq.md +0 -0
  31. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/getting-started/effects.md +0 -0
  32. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/getting-started/installation.md +0 -0
  33. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/getting-started/quickstart.md +0 -0
  34. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/getting-started/themes.md +0 -0
  35. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/index.md +0 -0
  36. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/migration/effect-api-changes.md +0 -0
  37. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/stylesheets/extra.css +0 -0
  38. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/user-guide/advanced-usage.md +0 -0
  39. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/user-guide/effects-custom.md +0 -0
  40. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/user-guide/effects-troubleshooting.md +0 -0
  41. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/user-guide/protocol-deep-dive.md +0 -0
  42. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/user-guide/themes.md +0 -0
  43. {lifx_async-4.3.7 → lifx_async-4.3.8}/docs/user-guide/troubleshooting.md +0 -0
  44. {lifx_async-4.3.7 → lifx_async-4.3.8}/examples/01_simple_discovery.py +0 -0
  45. {lifx_async-4.3.7 → lifx_async-4.3.8}/examples/02_simple_control.py +0 -0
  46. {lifx_async-4.3.7 → lifx_async-4.3.8}/examples/03_waveforms.py +0 -0
  47. {lifx_async-4.3.7 → lifx_async-4.3.8}/examples/04_logging.py +0 -0
  48. {lifx_async-4.3.7 → lifx_async-4.3.8}/examples/06_pulse_effect.py +0 -0
  49. {lifx_async-4.3.7 → lifx_async-4.3.8}/examples/07_colorloop_effect.py +0 -0
  50. {lifx_async-4.3.7 → lifx_async-4.3.8}/examples/08_custom_effect.py +0 -0
  51. {lifx_async-4.3.7 → lifx_async-4.3.8}/examples/09_background_effect.py +0 -0
  52. {lifx_async-4.3.7 → lifx_async-4.3.8}/examples/10_find_specific_devices.py +0 -0
  53. {lifx_async-4.3.7 → lifx_async-4.3.8}/examples/11_matrix_basic.py +0 -0
  54. {lifx_async-4.3.7 → lifx_async-4.3.8}/examples/12_matrix_effects.py +0 -0
  55. {lifx_async-4.3.7 → lifx_async-4.3.8}/examples/13_matrix_large.py +0 -0
  56. {lifx_async-4.3.7 → lifx_async-4.3.8}/mkdocs.yml +0 -0
  57. {lifx_async-4.3.7 → lifx_async-4.3.8}/renovate.json +0 -0
  58. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/__init__.py +0 -0
  59. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/api.py +0 -0
  60. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/color.py +0 -0
  61. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/const.py +0 -0
  62. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/devices/__init__.py +0 -0
  63. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/devices/hev.py +0 -0
  64. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/devices/infrared.py +0 -0
  65. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/devices/light.py +0 -0
  66. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/devices/matrix.py +0 -0
  67. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/devices/multizone.py +0 -0
  68. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/effects/__init__.py +0 -0
  69. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/effects/base.py +0 -0
  70. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/effects/colorloop.py +0 -0
  71. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/effects/conductor.py +0 -0
  72. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/effects/const.py +0 -0
  73. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/effects/models.py +0 -0
  74. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/effects/pulse.py +0 -0
  75. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/effects/state_manager.py +0 -0
  76. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/exceptions.py +0 -0
  77. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/network/__init__.py +0 -0
  78. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/network/discovery.py +0 -0
  79. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/network/message.py +0 -0
  80. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/network/transport.py +0 -0
  81. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/products/__init__.py +0 -0
  82. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/products/generator.py +0 -0
  83. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/products/registry.py +0 -0
  84. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/protocol/__init__.py +0 -0
  85. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/protocol/base.py +0 -0
  86. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/protocol/generator.py +0 -0
  87. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/protocol/header.py +0 -0
  88. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/protocol/models.py +0 -0
  89. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/protocol/packets.py +0 -0
  90. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/protocol/protocol_types.py +0 -0
  91. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/protocol/serializer.py +0 -0
  92. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/py.typed +0 -0
  93. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/theme/__init__.py +0 -0
  94. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/theme/canvas.py +0 -0
  95. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/theme/generators.py +0 -0
  96. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/theme/library.py +0 -0
  97. {lifx_async-4.3.7 → lifx_async-4.3.8}/src/lifx/theme/theme.py +0 -0
  98. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/__init__.py +0 -0
  99. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/conftest.py +0 -0
  100. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_api/__init__.py +0 -0
  101. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_api/test_api_apply_theme.py +0 -0
  102. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_api/test_api_batch_errors.py +0 -0
  103. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_api/test_api_batch_operations.py +0 -0
  104. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_api/test_api_discovery.py +0 -0
  105. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_api/test_api_organization.py +0 -0
  106. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_color.py +0 -0
  107. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_devices/__init__.py +0 -0
  108. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_devices/conftest.py +0 -0
  109. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_devices/test_base.py +0 -0
  110. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_devices/test_hev.py +0 -0
  111. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_devices/test_infrared.py +0 -0
  112. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_devices/test_light.py +0 -0
  113. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_devices/test_mac_address.py +0 -0
  114. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_devices/test_matrix.py +0 -0
  115. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_devices/test_multizone.py +0 -0
  116. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_effects/__init__.py +0 -0
  117. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_effects/test_base.py +0 -0
  118. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_effects/test_capability_filtering.py +0 -0
  119. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_effects/test_colorloop.py +0 -0
  120. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_effects/test_integration.py +0 -0
  121. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_effects/test_models.py +0 -0
  122. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_effects/test_pulse.py +0 -0
  123. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_effects/test_state_manager.py +0 -0
  124. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_network/__init__.py +0 -0
  125. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_network/test_concurrent_requests.py +0 -0
  126. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_network/test_discovery_devices.py +0 -0
  127. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_network/test_discovery_errors.py +0 -0
  128. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_network/test_message.py +0 -0
  129. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_network/test_message_advanced.py +0 -0
  130. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_network/test_transport.py +0 -0
  131. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_products/test_product_generator.py +0 -0
  132. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_products/test_registry.py +0 -0
  133. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_protocol/test_generated.py +0 -0
  134. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_protocol/test_header.py +0 -0
  135. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_protocol/test_protocol_generator.py +0 -0
  136. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_protocol/test_serializer.py +0 -0
  137. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_theme/__init__.py +0 -0
  138. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_theme/conftest.py +0 -0
  139. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_theme/test_apply_theme.py +0 -0
  140. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_theme/test_canvas.py +0 -0
  141. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_theme/test_generators.py +0 -0
  142. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_theme/test_library.py +0 -0
  143. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_theme/test_theme.py +0 -0
  144. {lifx_async-4.3.7 → lifx_async-4.3.8}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lifx-async
3
- Version: 4.3.7
3
+ Version: 4.3.8
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,14 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v4.3.8 (2025-11-25)
6
+
7
+ ### Bug Fixes
8
+
9
+ - **network**: Raise exception on StateUnhandled instead of returning False
10
+ ([`5ca3e8a`](https://github.com/Djelibeybi/lifx-async/commit/5ca3e8abcde0ec0eefe77645aeb0a2e63b18418c))
11
+
12
+
5
13
  ## v4.3.7 (2025-11-25)
6
14
 
7
15
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lifx-async"
3
- version = "4.3.7"
3
+ version = "4.3.8"
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"
@@ -166,8 +166,6 @@ class Device:
166
166
  raise LifxUnsupportedCommandError(
167
167
  f"Device does not support packet type {response.unhandled_type}"
168
168
  )
169
- if response is False:
170
- raise LifxUnsupportedCommandError("Device does not support this command")
171
169
 
172
170
  def __init__(
173
171
  self,
@@ -22,6 +22,7 @@ from lifx.exceptions import (
22
22
  LifxConnectionError,
23
23
  LifxProtocolError,
24
24
  LifxTimeoutError,
25
+ LifxUnsupportedCommandError,
25
26
  )
26
27
  from lifx.network.message import create_message, parse_message
27
28
  from lifx.network.transport import UdpTransport
@@ -722,8 +723,9 @@ class DeviceConnection:
722
723
 
723
724
  # Check for StateUnhandled - return False to indicate unsupported
724
725
  if header.pkt_type == _STATE_UNHANDLED_PKT_TYPE:
725
- yield False
726
- return
726
+ raise LifxUnsupportedCommandError(
727
+ "Device does not support this command"
728
+ )
727
729
 
728
730
  # ACK received successfully
729
731
  yield True
@@ -572,11 +572,12 @@ class TestStateUnhandledResponses:
572
572
  assert response.unhandled_type == packets.Light.GetColor.PKT_TYPE
573
573
 
574
574
  @pytest.mark.emulator
575
- async def test_set_color_returns_false_for_switch(self, switch_device) -> None:
576
- """Test SetColor to a Switch device returns False.
575
+ async def test_set_color_raises_for_switch(self, switch_device) -> None:
576
+ """Test SetColor to a Switch device raises LifxUnsupportedCommandError.
577
577
 
578
578
  Switch devices don't support Light commands, so SetColor should
579
- return False (indicating StateUnhandled) instead of True (ACK).
579
+ raise LifxUnsupportedCommandError. We don't return False, because
580
+ that means the Acknowledgement timed out.
580
581
  """
581
582
  from lifx.color import HSBK
582
583
  from lifx.protocol import packets
@@ -589,8 +590,6 @@ class TestStateUnhandledResponses:
589
590
  duration=0,
590
591
  )
591
592
 
592
- # Send SetColor to a Switch - should return False (StateUnhandled)
593
- result = await switch_device.request(set_packet)
594
-
595
- # Should return False, not True or raise an exception
596
- assert result is False
593
+ with pytest.raises(LifxUnsupportedCommandError):
594
+ # Send SetColor to a Switch, should raise LifxUnsupportedCommandError
595
+ await switch_device.request(set_packet)
@@ -432,7 +432,7 @@ wheels = [
432
432
 
433
433
  [[package]]
434
434
  name = "lifx-async"
435
- version = "4.3.7"
435
+ version = "4.3.8"
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