lifx-emulator 2.4.0__tar.gz → 3.0.1__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.
- lifx_emulator-3.0.1/CHANGELOG.md +27 -0
- lifx_emulator-3.0.1/PKG-INFO +102 -0
- lifx_emulator-3.0.1/README.md +74 -0
- {lifx_emulator-2.4.0 → lifx_emulator-3.0.1}/pyproject.toml +22 -82
- lifx_emulator-3.0.1/src/lifx_emulator_app/__init__.py +10 -0
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/__main__.py +2 -3
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/api/__init__.py +1 -1
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/api/app.py +3 -3
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/api/mappers/__init__.py +1 -1
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/api/mappers/device_mapper.py +1 -1
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/api/models.py +1 -2
- lifx_emulator-3.0.1/src/lifx_emulator_app/api/routers/__init__.py +11 -0
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/api/routers/devices.py +2 -2
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/api/routers/monitoring.py +1 -1
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/api/routers/scenarios.py +1 -1
- lifx_emulator-3.0.1/src/lifx_emulator_app/api/services/__init__.py +8 -0
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/api/services/device_service.py +3 -2
- lifx_emulator-3.0.1/tests/conftest.py +9 -0
- {lifx_emulator-2.4.0 → lifx_emulator-3.0.1}/tests/test_api.py +3 -4
- {lifx_emulator-2.4.0 → lifx_emulator-3.0.1}/tests/test_api_validation.py +1 -2
- {lifx_emulator-2.4.0 → lifx_emulator-3.0.1}/tests/test_cli.py +41 -42
- {lifx_emulator-2.4.0 → lifx_emulator-3.0.1}/tests/test_cli_validation.py +1 -2
- lifx_emulator-2.4.0/.github/workflows/ci.yml +0 -188
- lifx_emulator-2.4.0/.github/workflows/docs.yml +0 -111
- lifx_emulator-2.4.0/.pre-commit-config.yaml +0 -101
- lifx_emulator-2.4.0/CLAUDE.md +0 -957
- lifx_emulator-2.4.0/LICENSE +0 -35
- lifx_emulator-2.4.0/PKG-INFO +0 -107
- lifx_emulator-2.4.0/README.md +0 -79
- lifx_emulator-2.4.0/docs/advanced/device-management-api.md +0 -658
- lifx_emulator-2.4.0/docs/advanced/index.md +0 -145
- lifx_emulator-2.4.0/docs/advanced/scenario-api.md +0 -809
- lifx_emulator-2.4.0/docs/advanced/scenarios.md +0 -406
- lifx_emulator-2.4.0/docs/advanced/storage.md +0 -291
- lifx_emulator-2.4.0/docs/api/device.md +0 -489
- lifx_emulator-2.4.0/docs/api/factories.md +0 -340
- lifx_emulator-2.4.0/docs/api/index.md +0 -265
- lifx_emulator-2.4.0/docs/api/products.md +0 -539
- lifx_emulator-2.4.0/docs/api/protocol.md +0 -718
- lifx_emulator-2.4.0/docs/api/server.md +0 -437
- lifx_emulator-2.4.0/docs/api/storage.md +0 -680
- lifx_emulator-2.4.0/docs/architecture/device-state.md +0 -3
- lifx_emulator-2.4.0/docs/architecture/index.md +0 -76
- lifx_emulator-2.4.0/docs/architecture/overview.md +0 -373
- lifx_emulator-2.4.0/docs/architecture/packet-flow.md +0 -3
- lifx_emulator-2.4.0/docs/architecture/protocol.md +0 -3
- lifx_emulator-2.4.0/docs/assets/favicon.png +0 -1
- lifx_emulator-2.4.0/docs/changelog.md +0 -99
- lifx_emulator-2.4.0/docs/faq.md +0 -574
- lifx_emulator-2.4.0/docs/getting-started/cli.md +0 -483
- lifx_emulator-2.4.0/docs/getting-started/index.md +0 -83
- lifx_emulator-2.4.0/docs/getting-started/installation.md +0 -165
- lifx_emulator-2.4.0/docs/getting-started/quickstart.md +0 -182
- lifx_emulator-2.4.0/docs/guide/best-practices.md +0 -696
- lifx_emulator-2.4.0/docs/guide/device-types.md +0 -442
- lifx_emulator-2.4.0/docs/guide/framebuffers.md +0 -209
- lifx_emulator-2.4.0/docs/guide/index.md +0 -90
- lifx_emulator-2.4.0/docs/guide/integration-testing.md +0 -788
- lifx_emulator-2.4.0/docs/guide/products-and-specs.md +0 -229
- lifx_emulator-2.4.0/docs/guide/testing-scenarios.md +0 -673
- lifx_emulator-2.4.0/docs/guide/web-interface.md +0 -490
- lifx_emulator-2.4.0/docs/index.md +0 -169
- lifx_emulator-2.4.0/docs/reference/glossary.md +0 -352
- lifx_emulator-2.4.0/docs/reference/troubleshooting.md +0 -845
- lifx_emulator-2.4.0/docs/stylesheets/extra.css +0 -37
- lifx_emulator-2.4.0/docs/tutorials/01-first-device.md +0 -261
- lifx_emulator-2.4.0/docs/tutorials/02-basic.md +0 -345
- lifx_emulator-2.4.0/docs/tutorials/03-integration.md +0 -642
- lifx_emulator-2.4.0/docs/tutorials/04-advanced-scenarios.md +0 -583
- lifx_emulator-2.4.0/docs/tutorials/05-cicd.md +0 -696
- lifx_emulator-2.4.0/docs/tutorials/index.md +0 -108
- lifx_emulator-2.4.0/mkdocs.yml +0 -266
- lifx_emulator-2.4.0/renovate.json +0 -161
- lifx_emulator-2.4.0/src/lifx_emulator/__init__.py +0 -31
- lifx_emulator-2.4.0/src/lifx_emulator/api/routers/__init__.py +0 -11
- lifx_emulator-2.4.0/src/lifx_emulator/api/services/__init__.py +0 -8
- lifx_emulator-2.4.0/src/lifx_emulator/constants.py +0 -33
- lifx_emulator-2.4.0/src/lifx_emulator/devices/__init__.py +0 -37
- lifx_emulator-2.4.0/src/lifx_emulator/devices/device.py +0 -395
- lifx_emulator-2.4.0/src/lifx_emulator/devices/manager.py +0 -256
- lifx_emulator-2.4.0/src/lifx_emulator/devices/observers.py +0 -139
- lifx_emulator-2.4.0/src/lifx_emulator/devices/persistence.py +0 -308
- lifx_emulator-2.4.0/src/lifx_emulator/devices/state_restorer.py +0 -259
- lifx_emulator-2.4.0/src/lifx_emulator/devices/state_serializer.py +0 -157
- lifx_emulator-2.4.0/src/lifx_emulator/devices/states.py +0 -381
- lifx_emulator-2.4.0/src/lifx_emulator/factories/__init__.py +0 -39
- lifx_emulator-2.4.0/src/lifx_emulator/factories/builder.py +0 -375
- lifx_emulator-2.4.0/src/lifx_emulator/factories/default_config.py +0 -158
- lifx_emulator-2.4.0/src/lifx_emulator/factories/factory.py +0 -252
- lifx_emulator-2.4.0/src/lifx_emulator/factories/firmware_config.py +0 -77
- lifx_emulator-2.4.0/src/lifx_emulator/factories/serial_generator.py +0 -82
- lifx_emulator-2.4.0/src/lifx_emulator/handlers/__init__.py +0 -39
- lifx_emulator-2.4.0/src/lifx_emulator/handlers/base.py +0 -49
- lifx_emulator-2.4.0/src/lifx_emulator/handlers/device_handlers.py +0 -322
- lifx_emulator-2.4.0/src/lifx_emulator/handlers/light_handlers.py +0 -503
- lifx_emulator-2.4.0/src/lifx_emulator/handlers/multizone_handlers.py +0 -249
- lifx_emulator-2.4.0/src/lifx_emulator/handlers/registry.py +0 -110
- lifx_emulator-2.4.0/src/lifx_emulator/handlers/tile_handlers.py +0 -488
- lifx_emulator-2.4.0/src/lifx_emulator/products/__init__.py +0 -28
- lifx_emulator-2.4.0/src/lifx_emulator/products/generator.py +0 -1079
- lifx_emulator-2.4.0/src/lifx_emulator/products/registry.py +0 -1530
- lifx_emulator-2.4.0/src/lifx_emulator/products/specs.py +0 -284
- lifx_emulator-2.4.0/src/lifx_emulator/products/specs.yml +0 -386
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/__init__.py +0 -1
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/base.py +0 -446
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/const.py +0 -8
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/generator.py +0 -1384
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/header.py +0 -159
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/packets.py +0 -1351
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/protocol_types.py +0 -817
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/serializer.py +0 -379
- lifx_emulator-2.4.0/src/lifx_emulator/repositories/__init__.py +0 -22
- lifx_emulator-2.4.0/src/lifx_emulator/repositories/device_repository.py +0 -155
- lifx_emulator-2.4.0/src/lifx_emulator/repositories/storage_backend.py +0 -107
- lifx_emulator-2.4.0/src/lifx_emulator/scenarios/__init__.py +0 -22
- lifx_emulator-2.4.0/src/lifx_emulator/scenarios/manager.py +0 -322
- lifx_emulator-2.4.0/src/lifx_emulator/scenarios/models.py +0 -112
- lifx_emulator-2.4.0/src/lifx_emulator/scenarios/persistence.py +0 -241
- lifx_emulator-2.4.0/src/lifx_emulator/server.py +0 -464
- lifx_emulator-2.4.0/tests/conftest.py +0 -239
- lifx_emulator-2.4.0/tests/test_async_storage.py +0 -246
- lifx_emulator-2.4.0/tests/test_backwards_compatibility.py +0 -943
- lifx_emulator-2.4.0/tests/test_device.py +0 -541
- lifx_emulator-2.4.0/tests/test_device_edge_cases.py +0 -231
- lifx_emulator-2.4.0/tests/test_device_handlers_extended.py +0 -723
- lifx_emulator-2.4.0/tests/test_device_manager.py +0 -288
- lifx_emulator-2.4.0/tests/test_handler_registry.py +0 -103
- lifx_emulator-2.4.0/tests/test_integration.py +0 -463
- lifx_emulator-2.4.0/tests/test_light_handlers_extended.py +0 -788
- lifx_emulator-2.4.0/tests/test_multizone_handlers_extended.py +0 -560
- lifx_emulator-2.4.0/tests/test_observers.py +0 -164
- lifx_emulator-2.4.0/tests/test_products_generator.py +0 -1120
- lifx_emulator-2.4.0/tests/test_products_specs.py +0 -366
- lifx_emulator-2.4.0/tests/test_protocol_generator.py +0 -815
- lifx_emulator-2.4.0/tests/test_protocol_types_coverage.py +0 -118
- lifx_emulator-2.4.0/tests/test_repositories.py +0 -131
- lifx_emulator-2.4.0/tests/test_scenario_manager.py +0 -431
- lifx_emulator-2.4.0/tests/test_scenario_persistence.py +0 -271
- lifx_emulator-2.4.0/tests/test_serializer.py +0 -460
- lifx_emulator-2.4.0/tests/test_server.py +0 -545
- lifx_emulator-2.4.0/tests/test_state_restorer.py +0 -270
- lifx_emulator-2.4.0/tests/test_switch_devices.py +0 -335
- lifx_emulator-2.4.0/tests/test_tile_handlers_extended.py +0 -1265
- lifx_emulator-2.4.0/uv.lock +0 -1411
- {lifx_emulator-2.4.0 → lifx_emulator-3.0.1}/.gitignore +0 -0
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/api/templates/dashboard.html +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# CHANGELOG
|
|
2
|
+
|
|
3
|
+
<!-- version list -->
|
|
4
|
+
|
|
5
|
+
## v3.0.1 (2025-11-26)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- Adjust uv build for new monorepo layout
|
|
10
|
+
([`a0d5b7c`](https://github.com/Djelibeybi/lifx-emulator/commit/a0d5b7c1c1ab5659acc8554931f6c441654add05))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## v3.0.0 (2025-11-26)
|
|
14
|
+
|
|
15
|
+
### Refactoring
|
|
16
|
+
|
|
17
|
+
- Split into monorepo with separate library and CLI packages
|
|
18
|
+
([`402fe6e`](https://github.com/Djelibeybi/lifx-emulator/commit/402fe6e6c42e4fb730d076cd4dd0bfe7743b2c57))
|
|
19
|
+
|
|
20
|
+
### Breaking Changes
|
|
21
|
+
|
|
22
|
+
- The project is now split into two packages:
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## v2.4.0 (2025-11-26)
|
|
26
|
+
|
|
27
|
+
- Initial Release
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lifx-emulator
|
|
3
|
+
Version: 3.0.1
|
|
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.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Software Development :: Testing
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Requires-Dist: cyclopts>=4.2.0
|
|
23
|
+
Requires-Dist: fastapi>=0.115.0
|
|
24
|
+
Requires-Dist: lifx-emulator-core>=2.4.0
|
|
25
|
+
Requires-Dist: rich>=14.2.0
|
|
26
|
+
Requires-Dist: uvicorn>=0.34.0
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# lifx-emulator
|
|
30
|
+
|
|
31
|
+
Standalone LIFX device emulator with CLI and HTTP management API.
|
|
32
|
+
|
|
33
|
+
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.
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install lifx-emulator
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Start with default configuration (1 color light)
|
|
45
|
+
lifx-emulator
|
|
46
|
+
|
|
47
|
+
# Create multiple device types
|
|
48
|
+
lifx-emulator --color 2 --multizone 1 --tile 1
|
|
49
|
+
|
|
50
|
+
# Enable HTTP management API
|
|
51
|
+
lifx-emulator --api
|
|
52
|
+
|
|
53
|
+
# List available LIFX products
|
|
54
|
+
lifx-emulator list-products
|
|
55
|
+
|
|
56
|
+
# Create devices by product ID
|
|
57
|
+
lifx-emulator --product 27 --product 38 --product 55
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Features
|
|
61
|
+
|
|
62
|
+
- Command-line interface for quick emulator setup
|
|
63
|
+
- HTTP management API with web dashboard
|
|
64
|
+
- Real-time device monitoring and management
|
|
65
|
+
- Support for all LIFX device types (color, multizone, tile, infrared, HEV, switch)
|
|
66
|
+
- Persistent device state across restarts
|
|
67
|
+
- Testing scenarios for protocol edge cases
|
|
68
|
+
|
|
69
|
+
## HTTP Management API
|
|
70
|
+
|
|
71
|
+
Enable with `--api` to get:
|
|
72
|
+
|
|
73
|
+
- **Web Dashboard**: `http://localhost:8080` - Real-time monitoring UI
|
|
74
|
+
- **REST API**: Device management, statistics, and scenario control
|
|
75
|
+
- **OpenAPI Docs**: `http://localhost:8080/docs` - Interactive API documentation
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Start with API server
|
|
79
|
+
lifx-emulator --color 2 --api --api-port 9090
|
|
80
|
+
|
|
81
|
+
# Add a device via API
|
|
82
|
+
curl -X POST http://localhost:9090/api/devices \
|
|
83
|
+
-H "Content-Type: application/json" \
|
|
84
|
+
-d '{"product_id": 27}'
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Documentation
|
|
88
|
+
|
|
89
|
+
Full documentation is available at: **https://djelibeybi.github.io/lifx-emulator**
|
|
90
|
+
|
|
91
|
+
- [Installation Guide](https://djelibeybi.github.io/lifx-emulator/getting-started/installation/)
|
|
92
|
+
- [CLI Reference](https://djelibeybi.github.io/lifx-emulator/cli/cli-reference/)
|
|
93
|
+
- [Web Interface](https://djelibeybi.github.io/lifx-emulator/cli/web-interface/)
|
|
94
|
+
- [REST API](https://djelibeybi.github.io/lifx-emulator/cli/device-management-api/)
|
|
95
|
+
|
|
96
|
+
## Related Packages
|
|
97
|
+
|
|
98
|
+
- **[lifx-emulator-core](https://pypi.org/project/lifx-emulator-core/)**: Core library for embedding the emulator in your own projects
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
|
|
102
|
+
[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 = "
|
|
4
|
-
description = "LIFX Emulator
|
|
3
|
+
version = "3.0.1"
|
|
4
|
+
description = "Standalone LIFX Emulator with CLI and HTTP management API"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
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,7 +20,9 @@ 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",
|
|
@@ -29,66 +31,19 @@ classifiers = [
|
|
|
29
31
|
"Programming Language :: Python :: 3.12",
|
|
30
32
|
"Programming Language :: Python :: 3.13",
|
|
31
33
|
"Programming Language :: Python :: 3.14",
|
|
32
|
-
"Topic :: Software Development ::
|
|
33
|
-
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
34
|
+
"Topic :: Software Development :: Testing",
|
|
34
35
|
"Typing :: Typed"
|
|
35
36
|
]
|
|
36
37
|
|
|
37
38
|
[project.scripts]
|
|
38
|
-
lifx-emulator = "
|
|
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
|
-
]
|
|
39
|
+
lifx-emulator = "lifx_emulator_app.__main__:main"
|
|
56
40
|
|
|
57
41
|
[build-system]
|
|
58
42
|
requires = ["hatchling"]
|
|
59
43
|
build-backend = "hatchling.build"
|
|
60
44
|
|
|
61
45
|
[tool.hatch.build.targets.wheel]
|
|
62
|
-
packages = ["src/
|
|
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
|
-
|
|
46
|
+
packages = ["src/lifx_emulator_app"]
|
|
92
47
|
|
|
93
48
|
[tool.pyright]
|
|
94
49
|
typeCheckingMode = "standard"
|
|
@@ -102,43 +57,28 @@ pythonpath = ["src"]
|
|
|
102
57
|
python_files = ["test_*.py"]
|
|
103
58
|
python_classes = ["Test*"]
|
|
104
59
|
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
60
|
asyncio_mode = "auto"
|
|
115
61
|
asyncio_default_fixture_loop_scope = "function"
|
|
116
62
|
|
|
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
63
|
[tool.semantic_release]
|
|
64
|
+
commit_parser = "conventional-monorepo"
|
|
65
|
+
commit_message = """\
|
|
66
|
+
chore(release): lifx-emulator@{version}`
|
|
67
|
+
|
|
68
|
+
Automatically generated by python-semantic-release
|
|
69
|
+
"""
|
|
70
|
+
tag_format = "app-v{version}"
|
|
135
71
|
version_toml = ["pyproject.toml:project.version"]
|
|
136
72
|
build_command = """
|
|
137
73
|
uv lock --upgrade-package "$PACKAGE_NAME"
|
|
138
|
-
git add uv.lock
|
|
139
|
-
uv build
|
|
74
|
+
git add ../../uv.lock
|
|
75
|
+
uv build --package lifx-emulator --out-dir dist/
|
|
140
76
|
"""
|
|
141
77
|
|
|
78
|
+
[tool.semantic_release.commit_parser_options]
|
|
79
|
+
path_filters = ["."]
|
|
80
|
+
scope_prefix = "app-"
|
|
81
|
+
|
|
142
82
|
[tool.semantic_release.branches.main]
|
|
143
83
|
match = "main"
|
|
144
84
|
prerelease = false
|
|
@@ -161,7 +101,7 @@ exclude_commit_patterns = [
|
|
|
161
101
|
]
|
|
162
102
|
|
|
163
103
|
[tool.semantic_release.changelog.default_templates]
|
|
164
|
-
changelog_file = "
|
|
104
|
+
changelog_file = "CHANGELOG.md"
|
|
165
105
|
output_format = "md"
|
|
166
106
|
|
|
167
107
|
[tool.semantic_release.remote]
|
{lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/__main__.py
RENAMED
|
@@ -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
|
|
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))
|
{lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/api/__init__.py
RENAMED
|
@@ -10,7 +10,7 @@ of concerns.
|
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
# Import from new refactored structure
|
|
13
|
-
from
|
|
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
|
{lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/api/app.py
RENAMED
|
@@ -19,9 +19,9 @@ from fastapi.templating import Jinja2Templates
|
|
|
19
19
|
if TYPE_CHECKING:
|
|
20
20
|
from lifx_emulator.server import EmulatedLifxServer
|
|
21
21
|
|
|
22
|
-
from
|
|
23
|
-
from
|
|
24
|
-
from
|
|
22
|
+
from lifx_emulator_app.api.routers.devices import create_devices_router
|
|
23
|
+
from lifx_emulator_app.api.routers.monitoring import create_monitoring_router
|
|
24
|
+
from lifx_emulator_app.api.routers.scenarios import create_scenarios_router
|
|
25
25
|
|
|
26
26
|
logger = logging.getLogger(__name__)
|
|
27
27
|
|
|
@@ -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
|
|
10
|
+
from lifx_emulator_app.api.models import ColorHsbk, DeviceInfo
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class DeviceMapper:
|
{lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.0.1/src/lifx_emulator_app}/api/models.py
RENAMED
|
@@ -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
|
|
13
|
-
from
|
|
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
|
|
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
|
|
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
|
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
from fastapi.testclient import TestClient
|
|
5
|
-
|
|
6
|
-
from lifx_emulator.api import create_api_app
|
|
7
5
|
from lifx_emulator.devices.manager import DeviceManager
|
|
8
6
|
from lifx_emulator.factories import create_color_light, create_multizone_light
|
|
9
7
|
from lifx_emulator.repositories import DeviceRepository
|
|
10
8
|
from lifx_emulator.server import EmulatedLifxServer
|
|
9
|
+
from lifx_emulator_app.api import create_api_app
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
@pytest.fixture
|
|
@@ -725,7 +724,7 @@ class TestRunAPIServer:
|
|
|
725
724
|
"""Test that run_api_server creates uvicorn server with correct config."""
|
|
726
725
|
from unittest.mock import AsyncMock, Mock
|
|
727
726
|
|
|
728
|
-
from
|
|
727
|
+
from lifx_emulator_app.api.app import run_api_server
|
|
729
728
|
|
|
730
729
|
# Mock uvicorn components
|
|
731
730
|
mock_server_instance = Mock()
|
|
@@ -768,7 +767,7 @@ class TestRunAPIServer:
|
|
|
768
767
|
"""Test that run_api_server uses default host and port."""
|
|
769
768
|
from unittest.mock import AsyncMock, Mock
|
|
770
769
|
|
|
771
|
-
from
|
|
770
|
+
from lifx_emulator_app.api.app import run_api_server
|
|
772
771
|
|
|
773
772
|
# Mock uvicorn components
|
|
774
773
|
mock_server_instance = Mock()
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"""Tests for API input validation using Pydantic models."""
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
|
+
from lifx_emulator_app.api.models import ColorHsbk, DeviceCreateRequest
|
|
4
5
|
from pydantic import ValidationError
|
|
5
6
|
|
|
6
|
-
from lifx_emulator.api.models import ColorHsbk, DeviceCreateRequest
|
|
7
|
-
|
|
8
7
|
|
|
9
8
|
class TestDeviceCreateRequestValidation:
|
|
10
9
|
"""Test DeviceCreateRequest validation."""
|