omni-pca/pyproject.toml
Ryan Malloy df8b6128ea HA test harness + docker dev stack — both proven green
Pytest harness (in-process HA + MockPanel)
==========================================
pyproject.toml — bumps requires-python to 3.14.2 to align with HA 2026.5.x
which is what pytest-homeassistant-custom-component pins. Dev group 'ha'
pulls the harness; .python-version updated to 3.14.

src/omni_pca/mock_panel.py — Thermostat (6) and Button (3) RequestProperties
handlers added (previous commit). Without these the HA coordinator's
discovery walk produced empty thermostat/button dicts.

custom_components/omni_pca/services.py — fix CONF_ENTRY_ID import: HA
exports it as ATTR_CONFIG_ENTRY_ID, not CONF_ENTRY_ID. Aliased on import.

tests/conftest.py — re-enables sockets globally (the HA harness installs
pytest_socket which otherwise blocks our network e2e tests).

tests/ha_integration/ — new directory with full HA boot harness:
  conftest.py:
    - autouse enable_custom_integrations so HA loads our component
    - autouse expected_lingering_tasks=True (background event listener)
    - autouse _short_scan_interval (1s instead of 30s for fast tests)
    - panel fixture: MockPanel on a random localhost port for each test
    - configured_panel fixture: builds a MockConfigEntry, runs setup,
      yields, then unloads on teardown so the coordinator's reader task
      and OmniClient socket close cleanly (otherwise verify_cleanup hangs)
  test_setup.py — 12 tests:
    - integration loads + system_info populated
    - alarm_control_panel/light/switch/climate/button/event/binary_sensor
      entities materialise per platform
    - unload_entry tears down cleanly
    - turning a light on via HA service updates the mock state
    - arming via HA service with the right code transitions the area
    - arming with wrong code keeps the area disarmed and surfaces error

Total: 351 passed, 1 skipped (PCA fixture). Ruff clean across src/ tests/
custom_components/. The 12 HA integration tests run in <1s end-to-end —
they boot HA in-process, drive the config flow, exercise services, and
verify state mutations on the mock side.

Docker dev stack (manual smoke / screenshots)
=============================================
dev/docker-compose.yml — HA 2026.5 container + MockPanel sidecar.
dev/run_mock_panel.py — long-running mock with a populated state
  (5 zones, 4 units, 2 areas, 2 thermostats, 3 buttons, codes 1234/5678).
dev/Makefile — make dev-up / dev-logs / dev-down / dev-mock / dev-reset.
dev/README.md — onboarding walkthrough (host=host.docker.internal,
  port=14369, controller_key=000102030405060708090a0b0c0d0e0f).

.gitignore — adds ha-config/ so the persisted HA state from the dev
stack doesn't get committed.
2026-05-10 15:37:48 -06:00

86 lines
2.3 KiB
TOML

[project]
name = "omni-pca"
version = "2026.5.10"
description = "Async Python client for HAI/Leviton Omni-Link II home automation panels (Omni Pro II, Omni IIe, Omni LTe, Lumina)."
readme = "README.md"
license = { text = "MIT" }
authors = [{ name = "Ryan Malloy", email = "ryan@supported.systems" }]
requires-python = ">=3.14.2"
keywords = ["hai", "leviton", "omni", "home-automation", "omni-link", "home-assistant"]
classifiers = [
"Development Status :: 3 - Alpha",
"Framework :: AsyncIO",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Home Automation",
]
dependencies = [
"cryptography>=44.0.0",
]
[project.optional-dependencies]
cli = ["rich>=13.9.0", "typer>=0.15.0"]
[project.scripts]
omni-pca = "omni_pca.__main__:main"
[project.urls]
Repository = "https://github.com/rsp2k/omni-pca"
[build-system]
requires = ["uv_build>=0.11.8,<0.12.0"]
build-backend = "uv_build"
[dependency-groups]
dev = [
"pytest>=8.3.0",
"pytest-asyncio>=0.25.0",
"pytest-cov>=6.0.0",
"ruff>=0.13.0",
"mypy>=1.18.0",
]
# Optional group for testing the HA custom_component end-to-end. Pulls in
# the full Home Assistant test harness; requires Python 3.14.2+. The repo's
# .python-version pins to 3.14 for development; install with:
# uv sync --group ha
ha = [
"pytest-homeassistant-custom-component>=0.13.330",
]
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
addopts = ["-ra", "--strict-markers", "--strict-config"]
markers = [
"slow: tests that take more than ~1s",
"live: tests that require a real panel (skipped by default)",
]
[tool.ruff]
line-length = 100
target-version = "py312"
src = ["src", "tests", "custom_components"]
[tool.ruff.lint]
select = [
"E", "F", "W",
"I", "N", "UP", "B", "A", "C4", "PT", "SIM", "RUF",
]
ignore = ["E501"]
[tool.ruff.lint.per-file-ignores]
"tests/*" = ["N802", "N803", "PT011"]
[tool.mypy]
python_version = "3.12"
strict = true
warn_unused_configs = true
warn_redundant_casts = true
warn_unused_ignores = true
disallow_untyped_defs = true
no_implicit_reexport = true