Developer Documentation¶
Practical guide for developers working on the lifx-emulator codebase
Welcome¶
This section provides developer-focused documentation for navigating and contributing to the lifx-emulator project. Whether you're fixing a bug, adding a feature, or just exploring the codebase, this guide will help you get oriented quickly.
Quick Links¶
Essential Reading¶
- Code Navigation Guide - Navigate the codebase efficiently
- Architecture Overview - Understand system design
- Architecture Decisions - Design rationale and ADRs
- Testing Guide - Writing and running tests
Quick Start¶
- Installation - Set up your development environment
- Best Practices - Code quality standards
Understanding the Architecture¶
Before diving into development, understand the system design:
- Architecture Overview - System layers and component interaction
- Architecture Decisions - 15 ADRs explaining design choices
- Packet Flow - How packets are processed
- Protocol Details - Binary protocol implementation
- Device State - State management internals
This Development section focuses on navigating and modifying the codebase, not architectural theory.
Code Navigation Guide¶
Purpose: Help you find your way around the codebase quickly
What's inside: - Package structure and file organization (13.6k LOC core library) - Entry points and main exports - Layer architecture (Network → Domain → Repository → Persistence) - Common code paths and module dependencies - Quick command reference for development
When to use: - First time exploring the codebase - Looking for where specific functionality lives - Understanding how modules relate to each other - Finding test files or documentation
Read the Code Navigation Guide →
Getting Started as a Developer¶
1. Environment Setup¶
# Clone repository
git clone https://github.com/Djelibeybi/lifx-emulator.git
cd lifx-emulator
# Install dependencies (uses uv package manager)
uv sync
# Activate virtual environment
source .venv/bin/activate
# Verify installation
pytest --version
pyright --version
ruff --version
2. Run Tests¶
# Run all tests (764 tests)
pytest
# Run with coverage report
pytest --cov=lifx_emulator --cov=lifx_emulator_app --cov-report=html
# Run specific module tests
pytest packages/lifx-emulator-core/tests/test_device.py -v
# Run specific test
pytest packages/lifx-emulator-core/tests/test_device.py::test_process_packet -v
3. Code Quality Checks¶
# Lint and auto-fix
ruff check --fix .
# Type checking
pyright
# Run all quality checks (mimics CI)
ruff check . && pyright && pytest
4. Run the Emulator¶
# As module
python -m lifx_emulator_app
# As installed command
lifx-emulator --api --verbose
# With custom devices
lifx-emulator --color 2 --multizone 1 --tile 1 --api
5. Build Documentation¶
# Serve locally (live reload)
uv run mkdocs serve
# Build static site
uv run mkdocs build
# View at http://localhost:8000
Development Workflow¶
Adding a New Feature¶
- Understand the architecture
- Read Architecture Decisions for context
- Review Architecture Overview for data flow
-
Check Code Navigation for file locations
-
Write tests first (TDD approach)
- Add test cases in appropriate
tests/directory - Ensure 95% coverage (minimum 80%)
-
Run
pytest -vto verify tests fail -
Implement the feature
- Follow existing patterns and layer boundaries
- Keep functions under 10 complexity (McCabe)
- Add type hints for all public APIs
-
Update docstrings
-
Verify code quality
-
Update documentation
- Add/update docstrings
- Update relevant markdown docs
-
Add examples if public API changed
-
Submit pull request
- Use conventional commits (feat:, fix:, docs:, etc.)
- Reference related issues
- Ensure CI passes
Fixing a Bug¶
- Reproduce the bug
- Write a failing test case
-
Verify it fails:
pytest -v -
Locate the issue
- Use Code Navigation to find relevant code
- Check Packet Flow for data flow
-
Add debug logging if needed
-
Fix the bug
- Make minimal changes
- Avoid scope creep
-
Maintain backwards compatibility
-
Verify the fix
-
Submit pull request
- Use
fix:prefix in commit message - Explain root cause in PR description
- Reference issue number
Refactoring Code¶
- Establish test coverage
- Ensure affected code has >95% coverage
-
Add tests if needed:
pytest --cov=lifx_emulator.module -
Plan the refactoring
- Review Architecture Decisions
- Don't violate established patterns
-
Consider backwards compatibility
-
Refactor incrementally
- Small, focused changes
- Run tests after each change
-
Keep commits atomic
-
Verify no regressions
-
Update documentation
- Revise docstrings
- Update architecture docs if needed
Code Quality Standards¶
Test Coverage¶
- Target: 95% coverage
- Minimum: 80% (enforced by CI)
- Check:
pytest --cov --cov-report=term-missing
Code Complexity¶
- Max McCabe complexity: 10 per function
- Max arguments: 5 per function
- Max branches: 12 per function
- Max statements: 50 per function
- Check:
ruff check .(enforced automatically)
Type Checking¶
- Standard: Pyright standard mode
- Target: Python 3.11+
- Check:
pyright
Formatting¶
- Tool: Ruff formatter
- Line length: 88 characters
- Quote style: Double quotes
- Indent: 4 spaces
- Check:
ruff format --check . - Fix:
ruff format .
Import Organization¶
- Order: stdlib → third-party → local
- Tool: Ruff import sorter
- Check:
ruff check --select I . - Fix:
ruff check --select I --fix .
Common Development Tasks¶
Regenerating Auto-Generated Code¶
Protocol packets (DO NOT EDIT protocol/packets.py):
Product registry (DO NOT EDIT products/registry.py):
python -m lifx_emulator.products.generator
# Downloads products.json from LIFX GitHub
# Regenerates registry.py with all 137+ products
# Updates specs.yml templates for new products
Adding a New Packet Type¶
-
Regenerate protocol (if LIFX added new packet type):
-
Create handler function in appropriate handler module:
-
Register handler in
handlers/registry.py: -
Add tests in
tests/test_handlers.py:
Adding a New Device Type¶
-
Add product to specs.yml (if needed):
-
Create factory function in
factories/factory.py: -
Add to
__init__.pyexports: -
Add CLI argument in
__main__.py: -
Add tests:
Debugging Tips¶
Enable Verbose Logging¶
Inspect Device State¶
import asyncio
from lifx_emulator import create_color_light
device = create_color_light()
print(device.state) # Pretty-prints all state
Test Single Packet¶
from lifx_emulator.protocol.packets import Light
from lifx_emulator.protocol.header import LifxHeader
packet = Light.Get()
header = LifxHeader(
target=bytes.fromhex("d073d5000001") + b"\x00\x00",
source=12345,
sequence=1,
pkt_type=Light.Get.PKT_TYPE,
)
responses = device.process_packet(packet, header, ("127.0.0.1", 56700))
print(responses)
Profile Performance¶
# Using pytest with profiling
pytest --profile
# Using cProfile
python -m cProfile -s cumtime -m lifx_emulator_app
Check Coverage Gaps¶
CI/CD Pipeline¶
Automated Checks (GitHub Actions)¶
Every pull request runs: 1. Ruff lint check - Code quality and formatting 2. Pyright type check - Type safety validation 3. Pytest with coverage - All 764 tests, 95% coverage target 4. Multi-version testing - Python 3.11, 3.12, 3.13, 3.14 5. Documentation build - Ensures docs compile
All checks must pass before merge.
Building Standalone Binaries¶
The project uses PyApp to create standalone executables that bundle Python and all dependencies into a single binary. Binaries are built automatically on release, but you can build them locally for testing.
Prerequisites:
# Install Rust (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Build locally:
# Clone PyApp
git clone --depth 1 --branch v0.26.0 https://github.com/ofek/pyapp pyapp
# Build with environment variables
cd pyapp
PYAPP_PROJECT_NAME=lifx-emulator \
PYAPP_PROJECT_VERSION=4.1.0 \
PYAPP_PYTHON_VERSION=3.12 \
PYAPP_EXEC_SPEC=lifx_emulator_app.__main__:main \
cargo build --release
# Binary is at target/release/pyapp
mv target/release/pyapp ../lifx-emulator
chmod +x ../lifx-emulator
Optional: Embed Python distribution (larger binary, no download on first run):
Cross-compile for other platforms:
# Add target (example: macOS ARM64)
rustup target add aarch64-apple-darwin
# Build for that target
CARGO_BUILD_TARGET=aarch64-apple-darwin cargo build --release
Supported platforms (built automatically on release):
| Platform | Target | Binary Name |
|---|---|---|
| Linux x86_64 | x86_64-unknown-linux-gnu |
lifx-emulator-linux-x86_64 |
| macOS Intel | x86_64-apple-darwin |
lifx-emulator-macos-x86_64 |
| macOS ARM | aarch64-apple-darwin |
lifx-emulator-macos-arm64 |
| Windows x86_64 | x86_64-pc-windows-msvc |
lifx-emulator-windows-x86_64.exe |
See PyApp documentation for advanced configuration options.
Semantic Release¶
The project uses semantic-release with conventional commits:
feat:→ Minor version bump (1.x.0)fix:→ Patch version bump (1.0.x)BREAKING CHANGE:→ Major version bump (x.0.0)docs:,chore:,ci:→ No version bump
Commit message format:
Examples:
feat(core): add HEV device support
Implements HEV Clean device emulation with duration tracking.
Closes #123
fix(api): correct scenario merging precedence
Device-specific scenarios now correctly override type scenarios.
docs(guide): add scenario API examples
Project Structure Quick Reference¶
lifx-emulator/
├── packages/
│ ├── lifx-emulator-core/ # Core library (13.6k LOC)
│ │ ├── src/lifx_emulator/
│ │ │ ├── devices/ # Device lifecycle, state, persistence
│ │ │ ├── scenarios/ # Test scenario management
│ │ │ ├── protocol/ # LIFX binary protocol
│ │ │ ├── handlers/ # Packet type handlers
│ │ │ ├── products/ # Product registry
│ │ │ ├── factories/ # Device creation
│ │ │ ├── repositories/ # Storage abstraction
│ │ │ └── server.py # UDP server
│ │ └── tests/ # Core library tests
│ │
│ └── lifx-emulator/ # Standalone app (1.6k LOC)
│ ├── src/lifx_emulator_app/
│ │ ├── __main__.py # CLI entry point
│ │ └── api/ # HTTP API (FastAPI)
│ └── tests/ # App/API tests
│
├── docs/ # MkDocs documentation
│ ├── development/ # This section
│ ├── architecture/ # System design
│ ├── guide/ # User guides
│ ├── library/ # Library API reference
│ ├── cli/ # CLI/API documentation
│ └── tutorials/ # Step-by-step tutorials
│
├── pyproject.toml # Workspace config (uv)
├── mkdocs.yml # Documentation config
└── README.md # Project overview
Resources¶
Internal Documentation¶
External Resources¶
- LIFX LAN Protocol Docs
- LIFX Products JSON
- Python Type Hints
- asyncio Documentation
- Pytest Documentation
- FastAPI Documentation
Tools Documentation¶
- uv Package Manager
- Ruff Linter
- Pyright Type Checker
- PyApp Binary Builder
- MkDocs
- Conventional Commits
Getting Help¶
Contribution Guidelines¶
For detailed contribution information: - Code of conduct: Follow respectful collaboration practices - How to submit issues: Use GitHub Issues with clear descriptions - Pull request process: Use conventional commits, ensure CI passes - Development setup: See Getting Started above
Questions and Discussion¶
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Next Steps¶
- First time here? Start with Code Navigation
- Planning a feature? Read Architecture Decisions
- Need to understand data flow? Check Packet Flow
- Ready to code? Review the Getting Started section above
Happy coding! 🚀