lifx-emulator 2.4.0__tar.gz → 3.1.0__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 (148) hide show
  1. lifx_emulator-3.1.0/CHANGELOG.md +43 -0
  2. lifx_emulator-3.1.0/PKG-INFO +103 -0
  3. lifx_emulator-3.1.0/README.md +74 -0
  4. {lifx_emulator-2.4.0 → lifx_emulator-3.1.0}/pyproject.toml +25 -84
  5. lifx_emulator-3.1.0/src/lifx_emulator_app/__init__.py +10 -0
  6. {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/__main__.py +2 -3
  7. {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/__init__.py +1 -1
  8. {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/app.py +9 -4
  9. {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/mappers/__init__.py +1 -1
  10. {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/mappers/device_mapper.py +1 -1
  11. {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/models.py +1 -2
  12. lifx_emulator-3.1.0/src/lifx_emulator_app/api/routers/__init__.py +11 -0
  13. {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/routers/devices.py +2 -2
  14. {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/routers/monitoring.py +1 -1
  15. {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/routers/scenarios.py +1 -1
  16. lifx_emulator-3.1.0/src/lifx_emulator_app/api/services/__init__.py +8 -0
  17. {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/services/device_service.py +3 -2
  18. lifx_emulator-3.1.0/src/lifx_emulator_app/api/static/dashboard.js +588 -0
  19. lifx_emulator-3.1.0/src/lifx_emulator_app/api/templates/dashboard.html +357 -0
  20. lifx_emulator-3.1.0/tests/conftest.py +9 -0
  21. {lifx_emulator-2.4.0 → lifx_emulator-3.1.0}/tests/test_api.py +3 -4
  22. {lifx_emulator-2.4.0 → lifx_emulator-3.1.0}/tests/test_api_validation.py +1 -2
  23. {lifx_emulator-2.4.0 → lifx_emulator-3.1.0}/tests/test_cli.py +41 -42
  24. {lifx_emulator-2.4.0 → lifx_emulator-3.1.0}/tests/test_cli_validation.py +1 -2
  25. lifx_emulator-2.4.0/.github/workflows/ci.yml +0 -188
  26. lifx_emulator-2.4.0/.github/workflows/docs.yml +0 -111
  27. lifx_emulator-2.4.0/.pre-commit-config.yaml +0 -101
  28. lifx_emulator-2.4.0/CLAUDE.md +0 -957
  29. lifx_emulator-2.4.0/LICENSE +0 -35
  30. lifx_emulator-2.4.0/PKG-INFO +0 -107
  31. lifx_emulator-2.4.0/README.md +0 -79
  32. lifx_emulator-2.4.0/docs/advanced/device-management-api.md +0 -658
  33. lifx_emulator-2.4.0/docs/advanced/index.md +0 -145
  34. lifx_emulator-2.4.0/docs/advanced/scenario-api.md +0 -809
  35. lifx_emulator-2.4.0/docs/advanced/scenarios.md +0 -406
  36. lifx_emulator-2.4.0/docs/advanced/storage.md +0 -291
  37. lifx_emulator-2.4.0/docs/api/device.md +0 -489
  38. lifx_emulator-2.4.0/docs/api/factories.md +0 -340
  39. lifx_emulator-2.4.0/docs/api/index.md +0 -265
  40. lifx_emulator-2.4.0/docs/api/products.md +0 -539
  41. lifx_emulator-2.4.0/docs/api/protocol.md +0 -718
  42. lifx_emulator-2.4.0/docs/api/server.md +0 -437
  43. lifx_emulator-2.4.0/docs/api/storage.md +0 -680
  44. lifx_emulator-2.4.0/docs/architecture/device-state.md +0 -3
  45. lifx_emulator-2.4.0/docs/architecture/index.md +0 -76
  46. lifx_emulator-2.4.0/docs/architecture/overview.md +0 -373
  47. lifx_emulator-2.4.0/docs/architecture/packet-flow.md +0 -3
  48. lifx_emulator-2.4.0/docs/architecture/protocol.md +0 -3
  49. lifx_emulator-2.4.0/docs/assets/favicon.png +0 -1
  50. lifx_emulator-2.4.0/docs/changelog.md +0 -99
  51. lifx_emulator-2.4.0/docs/faq.md +0 -574
  52. lifx_emulator-2.4.0/docs/getting-started/cli.md +0 -483
  53. lifx_emulator-2.4.0/docs/getting-started/index.md +0 -83
  54. lifx_emulator-2.4.0/docs/getting-started/installation.md +0 -165
  55. lifx_emulator-2.4.0/docs/getting-started/quickstart.md +0 -182
  56. lifx_emulator-2.4.0/docs/guide/best-practices.md +0 -696
  57. lifx_emulator-2.4.0/docs/guide/device-types.md +0 -442
  58. lifx_emulator-2.4.0/docs/guide/framebuffers.md +0 -209
  59. lifx_emulator-2.4.0/docs/guide/index.md +0 -90
  60. lifx_emulator-2.4.0/docs/guide/integration-testing.md +0 -788
  61. lifx_emulator-2.4.0/docs/guide/products-and-specs.md +0 -229
  62. lifx_emulator-2.4.0/docs/guide/testing-scenarios.md +0 -673
  63. lifx_emulator-2.4.0/docs/guide/web-interface.md +0 -490
  64. lifx_emulator-2.4.0/docs/index.md +0 -169
  65. lifx_emulator-2.4.0/docs/reference/glossary.md +0 -352
  66. lifx_emulator-2.4.0/docs/reference/troubleshooting.md +0 -845
  67. lifx_emulator-2.4.0/docs/stylesheets/extra.css +0 -37
  68. lifx_emulator-2.4.0/docs/tutorials/01-first-device.md +0 -261
  69. lifx_emulator-2.4.0/docs/tutorials/02-basic.md +0 -345
  70. lifx_emulator-2.4.0/docs/tutorials/03-integration.md +0 -642
  71. lifx_emulator-2.4.0/docs/tutorials/04-advanced-scenarios.md +0 -583
  72. lifx_emulator-2.4.0/docs/tutorials/05-cicd.md +0 -696
  73. lifx_emulator-2.4.0/docs/tutorials/index.md +0 -108
  74. lifx_emulator-2.4.0/mkdocs.yml +0 -266
  75. lifx_emulator-2.4.0/renovate.json +0 -161
  76. lifx_emulator-2.4.0/src/lifx_emulator/__init__.py +0 -31
  77. lifx_emulator-2.4.0/src/lifx_emulator/api/routers/__init__.py +0 -11
  78. lifx_emulator-2.4.0/src/lifx_emulator/api/services/__init__.py +0 -8
  79. lifx_emulator-2.4.0/src/lifx_emulator/api/templates/dashboard.html +0 -899
  80. lifx_emulator-2.4.0/src/lifx_emulator/constants.py +0 -33
  81. lifx_emulator-2.4.0/src/lifx_emulator/devices/__init__.py +0 -37
  82. lifx_emulator-2.4.0/src/lifx_emulator/devices/device.py +0 -395
  83. lifx_emulator-2.4.0/src/lifx_emulator/devices/manager.py +0 -256
  84. lifx_emulator-2.4.0/src/lifx_emulator/devices/observers.py +0 -139
  85. lifx_emulator-2.4.0/src/lifx_emulator/devices/persistence.py +0 -308
  86. lifx_emulator-2.4.0/src/lifx_emulator/devices/state_restorer.py +0 -259
  87. lifx_emulator-2.4.0/src/lifx_emulator/devices/state_serializer.py +0 -157
  88. lifx_emulator-2.4.0/src/lifx_emulator/devices/states.py +0 -381
  89. lifx_emulator-2.4.0/src/lifx_emulator/factories/__init__.py +0 -39
  90. lifx_emulator-2.4.0/src/lifx_emulator/factories/builder.py +0 -375
  91. lifx_emulator-2.4.0/src/lifx_emulator/factories/default_config.py +0 -158
  92. lifx_emulator-2.4.0/src/lifx_emulator/factories/factory.py +0 -252
  93. lifx_emulator-2.4.0/src/lifx_emulator/factories/firmware_config.py +0 -77
  94. lifx_emulator-2.4.0/src/lifx_emulator/factories/serial_generator.py +0 -82
  95. lifx_emulator-2.4.0/src/lifx_emulator/handlers/__init__.py +0 -39
  96. lifx_emulator-2.4.0/src/lifx_emulator/handlers/base.py +0 -49
  97. lifx_emulator-2.4.0/src/lifx_emulator/handlers/device_handlers.py +0 -322
  98. lifx_emulator-2.4.0/src/lifx_emulator/handlers/light_handlers.py +0 -503
  99. lifx_emulator-2.4.0/src/lifx_emulator/handlers/multizone_handlers.py +0 -249
  100. lifx_emulator-2.4.0/src/lifx_emulator/handlers/registry.py +0 -110
  101. lifx_emulator-2.4.0/src/lifx_emulator/handlers/tile_handlers.py +0 -488
  102. lifx_emulator-2.4.0/src/lifx_emulator/products/__init__.py +0 -28
  103. lifx_emulator-2.4.0/src/lifx_emulator/products/generator.py +0 -1079
  104. lifx_emulator-2.4.0/src/lifx_emulator/products/registry.py +0 -1530
  105. lifx_emulator-2.4.0/src/lifx_emulator/products/specs.py +0 -284
  106. lifx_emulator-2.4.0/src/lifx_emulator/products/specs.yml +0 -386
  107. lifx_emulator-2.4.0/src/lifx_emulator/protocol/__init__.py +0 -1
  108. lifx_emulator-2.4.0/src/lifx_emulator/protocol/base.py +0 -446
  109. lifx_emulator-2.4.0/src/lifx_emulator/protocol/const.py +0 -8
  110. lifx_emulator-2.4.0/src/lifx_emulator/protocol/generator.py +0 -1384
  111. lifx_emulator-2.4.0/src/lifx_emulator/protocol/header.py +0 -159
  112. lifx_emulator-2.4.0/src/lifx_emulator/protocol/packets.py +0 -1351
  113. lifx_emulator-2.4.0/src/lifx_emulator/protocol/protocol_types.py +0 -817
  114. lifx_emulator-2.4.0/src/lifx_emulator/protocol/serializer.py +0 -379
  115. lifx_emulator-2.4.0/src/lifx_emulator/repositories/__init__.py +0 -22
  116. lifx_emulator-2.4.0/src/lifx_emulator/repositories/device_repository.py +0 -155
  117. lifx_emulator-2.4.0/src/lifx_emulator/repositories/storage_backend.py +0 -107
  118. lifx_emulator-2.4.0/src/lifx_emulator/scenarios/__init__.py +0 -22
  119. lifx_emulator-2.4.0/src/lifx_emulator/scenarios/manager.py +0 -322
  120. lifx_emulator-2.4.0/src/lifx_emulator/scenarios/models.py +0 -112
  121. lifx_emulator-2.4.0/src/lifx_emulator/scenarios/persistence.py +0 -241
  122. lifx_emulator-2.4.0/src/lifx_emulator/server.py +0 -464
  123. lifx_emulator-2.4.0/tests/conftest.py +0 -239
  124. lifx_emulator-2.4.0/tests/test_async_storage.py +0 -246
  125. lifx_emulator-2.4.0/tests/test_backwards_compatibility.py +0 -943
  126. lifx_emulator-2.4.0/tests/test_device.py +0 -541
  127. lifx_emulator-2.4.0/tests/test_device_edge_cases.py +0 -231
  128. lifx_emulator-2.4.0/tests/test_device_handlers_extended.py +0 -723
  129. lifx_emulator-2.4.0/tests/test_device_manager.py +0 -288
  130. lifx_emulator-2.4.0/tests/test_handler_registry.py +0 -103
  131. lifx_emulator-2.4.0/tests/test_integration.py +0 -463
  132. lifx_emulator-2.4.0/tests/test_light_handlers_extended.py +0 -788
  133. lifx_emulator-2.4.0/tests/test_multizone_handlers_extended.py +0 -560
  134. lifx_emulator-2.4.0/tests/test_observers.py +0 -164
  135. lifx_emulator-2.4.0/tests/test_products_generator.py +0 -1120
  136. lifx_emulator-2.4.0/tests/test_products_specs.py +0 -366
  137. lifx_emulator-2.4.0/tests/test_protocol_generator.py +0 -815
  138. lifx_emulator-2.4.0/tests/test_protocol_types_coverage.py +0 -118
  139. lifx_emulator-2.4.0/tests/test_repositories.py +0 -131
  140. lifx_emulator-2.4.0/tests/test_scenario_manager.py +0 -431
  141. lifx_emulator-2.4.0/tests/test_scenario_persistence.py +0 -271
  142. lifx_emulator-2.4.0/tests/test_serializer.py +0 -460
  143. lifx_emulator-2.4.0/tests/test_server.py +0 -545
  144. lifx_emulator-2.4.0/tests/test_state_restorer.py +0 -270
  145. lifx_emulator-2.4.0/tests/test_switch_devices.py +0 -335
  146. lifx_emulator-2.4.0/tests/test_tile_handlers_extended.py +0 -1265
  147. lifx_emulator-2.4.0/uv.lock +0 -1411
  148. {lifx_emulator-2.4.0 → lifx_emulator-3.1.0}/.gitignore +0 -0
@@ -0,0 +1,43 @@
1
+ # CHANGELOG
2
+
3
+ <!-- version list -->
4
+
5
+ ## v3.1.0 (2026-01-11)
6
+
7
+ ### Features
8
+
9
+ - Add Python 3.10 support
10
+ ([`c19eee5`](https://github.com/Djelibeybi/lifx-emulator/commit/c19eee5181fc3e0e3b4ef9fc3e6d47308dce7a0f))
11
+
12
+
13
+ ## v3.0.2 (2025-12-24)
14
+
15
+ ### Bug Fixes
16
+
17
+ - **api**: Eliminate XSS vulnerabilities and extract dashboard JavaScript
18
+ ([`8302a09`](https://github.com/Djelibeybi/lifx-emulator/commit/8302a0947b326e73f6c2f15de85986a464a307ad))
19
+
20
+
21
+ ## v3.0.1 (2025-11-26)
22
+
23
+ ### Bug Fixes
24
+
25
+ - Adjust uv build for new monorepo layout
26
+ ([`a0d5b7c`](https://github.com/Djelibeybi/lifx-emulator/commit/a0d5b7c1c1ab5659acc8554931f6c441654add05))
27
+
28
+
29
+ ## v3.0.0 (2025-11-26)
30
+
31
+ ### Refactoring
32
+
33
+ - Split into monorepo with separate library and CLI packages
34
+ ([`402fe6e`](https://github.com/Djelibeybi/lifx-emulator/commit/402fe6e6c42e4fb730d076cd4dd0bfe7743b2c57))
35
+
36
+ ### Breaking Changes
37
+
38
+ - The project is now split into two packages:
39
+
40
+
41
+ ## v2.4.0 (2025-11-26)
42
+
43
+ - Initial Release
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.4
2
+ Name: lifx-emulator
3
+ Version: 3.1.0
4
+ Summary: Standalone LIFX Emulator with CLI and HTTP management API
5
+ Author-email: Avi Miller <me@dje.li>
6
+ Maintainer-email: Avi Miller <me@dje.li>
7
+ License-Expression: UPL-1.0
8
+ Classifier: Environment :: Console
9
+ Classifier: Framework :: AsyncIO
10
+ Classifier: Framework :: FastAPI
11
+ Classifier: Framework :: Pytest
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Natural Language :: English
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Software Development :: Testing
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: cyclopts>=4.2.0
24
+ Requires-Dist: fastapi>=0.115.0
25
+ Requires-Dist: lifx-emulator-core>=2.4.0
26
+ Requires-Dist: rich>=14.2.0
27
+ Requires-Dist: uvicorn>=0.34.0
28
+ Description-Content-Type: text/markdown
29
+
30
+ # lifx-emulator
31
+
32
+ Standalone LIFX device emulator with CLI and HTTP management API.
33
+
34
+ This package provides a ready-to-run emulator for testing LIFX LAN protocol libraries. It includes a command-line interface and an optional HTTP API for runtime device management.
35
+
36
+ ## Installation
37
+
38
+ ```bash
39
+ pip install lifx-emulator
40
+ ```
41
+
42
+ ## Quick Start
43
+
44
+ ```bash
45
+ # Start with default configuration (1 color light)
46
+ lifx-emulator
47
+
48
+ # Create multiple device types
49
+ lifx-emulator --color 2 --multizone 1 --tile 1
50
+
51
+ # Enable HTTP management API
52
+ lifx-emulator --api
53
+
54
+ # List available LIFX products
55
+ lifx-emulator list-products
56
+
57
+ # Create devices by product ID
58
+ lifx-emulator --product 27 --product 38 --product 55
59
+ ```
60
+
61
+ ## Features
62
+
63
+ - Command-line interface for quick emulator setup
64
+ - HTTP management API with web dashboard
65
+ - Real-time device monitoring and management
66
+ - Support for all LIFX device types (color, multizone, tile, infrared, HEV, switch)
67
+ - Persistent device state across restarts
68
+ - Testing scenarios for protocol edge cases
69
+
70
+ ## HTTP Management API
71
+
72
+ Enable with `--api` to get:
73
+
74
+ - **Web Dashboard**: `http://localhost:8080` - Real-time monitoring UI
75
+ - **REST API**: Device management, statistics, and scenario control
76
+ - **OpenAPI Docs**: `http://localhost:8080/docs` - Interactive API documentation
77
+
78
+ ```bash
79
+ # Start with API server
80
+ lifx-emulator --color 2 --api --api-port 9090
81
+
82
+ # Add a device via API
83
+ curl -X POST http://localhost:9090/api/devices \
84
+ -H "Content-Type: application/json" \
85
+ -d '{"product_id": 27}'
86
+ ```
87
+
88
+ ## Documentation
89
+
90
+ Full documentation is available at: **https://djelibeybi.github.io/lifx-emulator**
91
+
92
+ - [Installation Guide](https://djelibeybi.github.io/lifx-emulator/getting-started/installation/)
93
+ - [CLI Reference](https://djelibeybi.github.io/lifx-emulator/cli/cli-reference/)
94
+ - [Web Interface](https://djelibeybi.github.io/lifx-emulator/cli/web-interface/)
95
+ - [REST API](https://djelibeybi.github.io/lifx-emulator/cli/device-management-api/)
96
+
97
+ ## Related Packages
98
+
99
+ - **[lifx-emulator-core](https://pypi.org/project/lifx-emulator-core/)**: Core library for embedding the emulator in your own projects
100
+
101
+ ## License
102
+
103
+ [UPL-1.0](https://opensource.org/licenses/UPL)
@@ -0,0 +1,74 @@
1
+ # lifx-emulator
2
+
3
+ Standalone LIFX device emulator with CLI and HTTP management API.
4
+
5
+ This package provides a ready-to-run emulator for testing LIFX LAN protocol libraries. It includes a command-line interface and an optional HTTP API for runtime device management.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pip install lifx-emulator
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```bash
16
+ # Start with default configuration (1 color light)
17
+ lifx-emulator
18
+
19
+ # Create multiple device types
20
+ lifx-emulator --color 2 --multizone 1 --tile 1
21
+
22
+ # Enable HTTP management API
23
+ lifx-emulator --api
24
+
25
+ # List available LIFX products
26
+ lifx-emulator list-products
27
+
28
+ # Create devices by product ID
29
+ lifx-emulator --product 27 --product 38 --product 55
30
+ ```
31
+
32
+ ## Features
33
+
34
+ - Command-line interface for quick emulator setup
35
+ - HTTP management API with web dashboard
36
+ - Real-time device monitoring and management
37
+ - Support for all LIFX device types (color, multizone, tile, infrared, HEV, switch)
38
+ - Persistent device state across restarts
39
+ - Testing scenarios for protocol edge cases
40
+
41
+ ## HTTP Management API
42
+
43
+ Enable with `--api` to get:
44
+
45
+ - **Web Dashboard**: `http://localhost:8080` - Real-time monitoring UI
46
+ - **REST API**: Device management, statistics, and scenario control
47
+ - **OpenAPI Docs**: `http://localhost:8080/docs` - Interactive API documentation
48
+
49
+ ```bash
50
+ # Start with API server
51
+ lifx-emulator --color 2 --api --api-port 9090
52
+
53
+ # Add a device via API
54
+ curl -X POST http://localhost:9090/api/devices \
55
+ -H "Content-Type: application/json" \
56
+ -d '{"product_id": 27}'
57
+ ```
58
+
59
+ ## Documentation
60
+
61
+ Full documentation is available at: **https://djelibeybi.github.io/lifx-emulator**
62
+
63
+ - [Installation Guide](https://djelibeybi.github.io/lifx-emulator/getting-started/installation/)
64
+ - [CLI Reference](https://djelibeybi.github.io/lifx-emulator/cli/cli-reference/)
65
+ - [Web Interface](https://djelibeybi.github.io/lifx-emulator/cli/web-interface/)
66
+ - [REST API](https://djelibeybi.github.io/lifx-emulator/cli/device-management-api/)
67
+
68
+ ## Related Packages
69
+
70
+ - **[lifx-emulator-core](https://pypi.org/project/lifx-emulator-core/)**: Core library for embedding the emulator in your own projects
71
+
72
+ ## License
73
+
74
+ [UPL-1.0](https://opensource.org/licenses/UPL)
@@ -1,13 +1,13 @@
1
1
  [project]
2
2
  name = "lifx-emulator"
3
- version = "2.4.0"
4
- description = "LIFX Emulator for testing LIFX LAN protocol libraries"
3
+ version = "3.1.0"
4
+ description = "Standalone LIFX Emulator with CLI and HTTP management API"
5
5
  readme = "README.md"
6
- requires-python = ">=3.11"
6
+ requires-python = ">=3.10"
7
7
  dependencies = [
8
+ "lifx-emulator-core>=2.4.0",
8
9
  "cyclopts>=4.2.0",
9
10
  "fastapi>=0.115.0",
10
- "pyyaml>=6.0.3",
11
11
  "rich>=14.2.0",
12
12
  "uvicorn>=0.34.0",
13
13
  ]
@@ -20,79 +20,35 @@ maintainers = [
20
20
  {name = "Avi Miller", email = "me@dje.li"}
21
21
  ]
22
22
  classifiers = [
23
+ "Environment :: Console",
23
24
  "Framework :: AsyncIO",
25
+ "Framework :: FastAPI",
24
26
  "Framework :: Pytest",
25
27
  "Intended Audience :: Developers",
26
28
  "Natural Language :: English",
27
29
  "Operating System :: OS Independent",
30
+ "Programming Language :: Python :: 3.10",
28
31
  "Programming Language :: Python :: 3.11",
29
32
  "Programming Language :: Python :: 3.12",
30
33
  "Programming Language :: Python :: 3.13",
31
34
  "Programming Language :: Python :: 3.14",
32
- "Topic :: Software Development :: Libraries",
33
- "Topic :: Software Development :: Libraries :: Python Modules",
35
+ "Topic :: Software Development :: Testing",
34
36
  "Typing :: Typed"
35
37
  ]
36
38
 
37
39
  [project.scripts]
38
- lifx-emulator = "lifx_emulator.__main__:main"
39
-
40
- [dependency-groups]
41
- dev = [
42
- "hatchling>=1.27.0",
43
- "httpx>=0.28.0",
44
- "pyright>=1.1.407",
45
- "pytest>=8.4.2",
46
- "pytest-asyncio>=0.24.0",
47
- "pytest-cov>=7.0.0",
48
- "pytest-sugar>=1.1.1",
49
- "ruff>=0.14.2",
50
- "mkdocs>=1.6.0",
51
- "mkdocs-material>=9.6.0",
52
- "mkdocstrings[python]>=0.27.0",
53
- "mkdocs-git-revision-date-localized-plugin>=1.4.0",
54
- "mkdocs-llmstxt>=0.3.0",
55
- ]
40
+ lifx-emulator = "lifx_emulator_app.__main__:main"
56
41
 
57
42
  [build-system]
58
43
  requires = ["hatchling"]
59
44
  build-backend = "hatchling.build"
60
45
 
61
46
  [tool.hatch.build.targets.wheel]
62
- packages = ["src/lifx_emulator"]
63
-
64
- [tool.ruff]
65
- line-length = 88
66
- indent-width = 4
67
- target-version = "py311"
68
-
69
- [tool.ruff.format]
70
- quote-style = "double"
71
- indent-style = "space"
72
- docstring-code-format = true
73
- docstring-code-line-length = "dynamic"
74
-
75
- [tool.ruff.lint]
76
- select = ["E", "F", "I", "N", "W", "UP"]
77
- ignore = []
78
-
79
- # Complexity and code quality limits
80
- [tool.ruff.lint.mccabe]
81
- max-complexity = 10
82
-
83
- [tool.ruff.lint.pylint]
84
- max-args = 5
85
- max-branches = 12
86
- max-statements = 50
87
-
88
- [tool.ruff.lint.per-file-ignores]
89
- "src/lifx_emulator/protocol/generator.py" = ["E501"]
90
- "src/lifx_emulator/protocol/packets.py" = ["E501"]
91
-
47
+ packages = ["src/lifx_emulator_app"]
92
48
 
93
49
  [tool.pyright]
94
50
  typeCheckingMode = "standard"
95
- pythonVersion = "3.11"
51
+ pythonVersion = "3.10"
96
52
  include = ["src"]
97
53
  exclude = ["**/__pycache__"]
98
54
 
@@ -102,43 +58,28 @@ pythonpath = ["src"]
102
58
  python_files = ["test_*.py"]
103
59
  python_classes = ["Test*"]
104
60
  python_functions = ["test_*"]
105
- addopts = """\
106
- -v
107
- -Wdefault
108
- --cov=lifx_emulator
109
- --cov-branch
110
- --cov-report=xml
111
- --cov-report=term-missing:skip-covered
112
- --junitxml=junit.xml -o junit_family=legacy
113
- """
114
61
  asyncio_mode = "auto"
115
62
  asyncio_default_fixture_loop_scope = "function"
116
63
 
117
- [tool.coverage.run]
118
- omit = [
119
- "src/lifx_emulator/protocol/generator.py",
120
- "src/lifx_emulator/protocol/protocol_types.py",
121
- "src/lifx_emulator/products/generator.py",
122
- "src/lifx_emulator/products/registry.py",
123
- ]
124
-
125
- [tool.coverage.report]
126
- exclude_lines = [
127
- "pragma: no cover",
128
- "@overload",
129
- "if TYPE_CHECKING",
130
- "raise NotImplementedError",
131
- 'if __name__ == "__main__":',
132
- ]
133
-
134
64
  [tool.semantic_release]
65
+ commit_parser = "conventional-monorepo"
66
+ commit_message = """\
67
+ chore(release): lifx-emulator@{version}
68
+
69
+ Automatically generated by python-semantic-release
70
+ """
71
+ tag_format = "app-v{version}"
135
72
  version_toml = ["pyproject.toml:project.version"]
136
73
  build_command = """
137
74
  uv lock --upgrade-package "$PACKAGE_NAME"
138
- git add uv.lock
139
- uv build
75
+ git add ../../uv.lock
76
+ uv build --package lifx-emulator --out-dir dist/
140
77
  """
141
78
 
79
+ [tool.semantic_release.commit_parser_options]
80
+ path_filters = ["."]
81
+ scope_prefix = "app-"
82
+
142
83
  [tool.semantic_release.branches.main]
143
84
  match = "main"
144
85
  prerelease = false
@@ -161,7 +102,7 @@ exclude_commit_patterns = [
161
102
  ]
162
103
 
163
104
  [tool.semantic_release.changelog.default_templates]
164
- changelog_file = "docs/changelog.md"
105
+ changelog_file = "CHANGELOG.md"
165
106
  output_format = "md"
166
107
 
167
108
  [tool.semantic_release.remote]
@@ -0,0 +1,10 @@
1
+ """LIFX Emulator Application
2
+
3
+ Standalone CLI and HTTP management API for the LIFX Emulator.
4
+ """
5
+
6
+ from importlib.metadata import version as get_version
7
+
8
+ __version__ = get_version("lifx-emulator")
9
+
10
+ __all__ = ["__version__"]
@@ -6,8 +6,6 @@ import signal
6
6
  from typing import Annotated
7
7
 
8
8
  import cyclopts
9
- from rich.logging import RichHandler
10
-
11
9
  from lifx_emulator.constants import LIFX_UDP_PORT
12
10
  from lifx_emulator.devices import (
13
11
  DEFAULT_STORAGE_DIR,
@@ -28,6 +26,7 @@ from lifx_emulator.products.registry import get_registry
28
26
  from lifx_emulator.repositories import DeviceRepository
29
27
  from lifx_emulator.scenarios import ScenarioPersistenceAsyncFile
30
28
  from lifx_emulator.server import EmulatedLifxServer
29
+ from rich.logging import RichHandler
31
30
 
32
31
  app = cyclopts.App(
33
32
  name="lifx-emulator",
@@ -529,7 +528,7 @@ async def run(
529
528
  # Start API server if enabled
530
529
  api_task = None
531
530
  if api:
532
- from lifx_emulator.api import run_api_server
531
+ from lifx_emulator_app.api import run_api_server
533
532
 
534
533
  logger.info("Starting HTTP API server on http://%s:%s", api_host, api_port)
535
534
  api_task = asyncio.create_task(run_api_server(server, api_host, api_port))
@@ -10,7 +10,7 @@ of concerns.
10
10
  """
11
11
 
12
12
  # Import from new refactored structure
13
- from lifx_emulator.api.app import create_api_app, run_api_server
13
+ from lifx_emulator_app.api.app import create_api_app, run_api_server
14
14
 
15
15
  # Note: HTML_UI remains in the old lifx_emulator/api.py file temporarily
16
16
  # TODO: Phase 1.1d - extract HTML template to separate file
@@ -14,19 +14,21 @@ from typing import TYPE_CHECKING
14
14
 
15
15
  from fastapi import FastAPI, Request
16
16
  from fastapi.responses import HTMLResponse
17
+ from fastapi.staticfiles import StaticFiles
17
18
  from fastapi.templating import Jinja2Templates
18
19
 
19
20
  if TYPE_CHECKING:
20
21
  from lifx_emulator.server import EmulatedLifxServer
21
22
 
22
- from lifx_emulator.api.routers.devices import create_devices_router
23
- from lifx_emulator.api.routers.monitoring import create_monitoring_router
24
- from lifx_emulator.api.routers.scenarios import create_scenarios_router
23
+ from lifx_emulator_app.api.routers.devices import create_devices_router
24
+ from lifx_emulator_app.api.routers.monitoring import create_monitoring_router
25
+ from lifx_emulator_app.api.routers.scenarios import create_scenarios_router
25
26
 
26
27
  logger = logging.getLogger(__name__)
27
28
 
28
- # Template directory for web UI
29
+ # Asset directories for web UI
29
30
  TEMPLATES_DIR = Path(__file__).parent / "templates"
31
+ STATIC_DIR = Path(__file__).parent / "static"
30
32
  templates = Jinja2Templates(directory=str(TEMPLATES_DIR))
31
33
 
32
34
 
@@ -102,6 +104,9 @@ The API is organized into three main routers:
102
104
  """Serve embedded web UI dashboard."""
103
105
  return templates.TemplateResponse(request, "dashboard.html")
104
106
 
107
+ # Mount static files for JS/CSS assets (cached by browsers)
108
+ app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")
109
+
105
110
  # Include routers with server dependency injection
106
111
  monitoring_router = create_monitoring_router(server)
107
112
  devices_router = create_devices_router(server)
@@ -1,5 +1,5 @@
1
1
  """Mappers for converting domain models to API models."""
2
2
 
3
- from lifx_emulator.api.mappers.device_mapper import DeviceMapper
3
+ from lifx_emulator_app.api.mappers.device_mapper import DeviceMapper
4
4
 
5
5
  __all__ = ["DeviceMapper"]
@@ -7,7 +7,7 @@ from typing import TYPE_CHECKING
7
7
  if TYPE_CHECKING:
8
8
  from lifx_emulator.devices import EmulatedLifxDevice
9
9
 
10
- from lifx_emulator.api.models import ColorHsbk, DeviceInfo
10
+ from lifx_emulator_app.api.models import ColorHsbk, DeviceInfo
11
11
 
12
12
 
13
13
  class DeviceMapper:
@@ -1,9 +1,8 @@
1
1
  """Pydantic models for API requests and responses."""
2
2
 
3
- from pydantic import BaseModel, Field, field_validator
4
-
5
3
  # Import shared domain models
6
4
  from lifx_emulator.scenarios import ScenarioConfig
5
+ from pydantic import BaseModel, Field, field_validator
7
6
 
8
7
 
9
8
  class DeviceCreateRequest(BaseModel):
@@ -0,0 +1,11 @@
1
+ """API routers for LIFX emulator endpoints."""
2
+
3
+ from lifx_emulator_app.api.routers.devices import create_devices_router
4
+ from lifx_emulator_app.api.routers.monitoring import create_monitoring_router
5
+ from lifx_emulator_app.api.routers.scenarios import create_scenarios_router
6
+
7
+ __all__ = [
8
+ "create_monitoring_router",
9
+ "create_devices_router",
10
+ "create_scenarios_router",
11
+ ]
@@ -9,8 +9,8 @@ from fastapi import APIRouter, HTTPException
9
9
  if TYPE_CHECKING:
10
10
  from lifx_emulator.server import EmulatedLifxServer
11
11
 
12
- from lifx_emulator.api.models import DeviceCreateRequest, DeviceInfo
13
- from lifx_emulator.api.services.device_service import (
12
+ from lifx_emulator_app.api.models import DeviceCreateRequest, DeviceInfo
13
+ from lifx_emulator_app.api.services.device_service import (
14
14
  DeviceAlreadyExistsError,
15
15
  DeviceCreationError,
16
16
  DeviceNotFoundError,
@@ -9,7 +9,7 @@ from fastapi import APIRouter
9
9
  if TYPE_CHECKING:
10
10
  from lifx_emulator.server import EmulatedLifxServer
11
11
 
12
- from lifx_emulator.api.models import ActivityEvent, ServerStats
12
+ from lifx_emulator_app.api.models import ActivityEvent, ServerStats
13
13
 
14
14
 
15
15
  def create_monitoring_router(server: EmulatedLifxServer) -> APIRouter:
@@ -9,7 +9,7 @@ from fastapi import APIRouter, HTTPException
9
9
  if TYPE_CHECKING:
10
10
  from lifx_emulator.server import EmulatedLifxServer
11
11
 
12
- from lifx_emulator.api.models import ScenarioConfig, ScenarioResponse
12
+ from lifx_emulator_app.api.models import ScenarioConfig, ScenarioResponse
13
13
 
14
14
 
15
15
  def _validate_device_serial(serial: str) -> bool:
@@ -0,0 +1,8 @@
1
+ """Business logic services for API endpoints."""
2
+
3
+ from lifx_emulator_app.api.services.device_service import DeviceService
4
+
5
+ # TODO: Create ScenarioService (Phase 1.1b completion)
6
+ # from lifx_emulator_app.api.services.scenario_service import ScenarioService
7
+
8
+ __all__ = ["DeviceService"]
@@ -13,10 +13,11 @@ from typing import TYPE_CHECKING
13
13
  if TYPE_CHECKING:
14
14
  from lifx_emulator.server import EmulatedLifxServer
15
15
 
16
- from lifx_emulator.api.mappers import DeviceMapper
17
- from lifx_emulator.api.models import DeviceCreateRequest, DeviceInfo
18
16
  from lifx_emulator.factories import create_device
19
17
 
18
+ from lifx_emulator_app.api.mappers import DeviceMapper
19
+ from lifx_emulator_app.api.models import DeviceCreateRequest, DeviceInfo
20
+
20
21
  logger = logging.getLogger(__name__)
21
22
 
22
23