refactor(devices): per-provider typed configs (phases 1-4)
Phase 1 — DeviceConfig hierarchy (device_config.py): - 17 @dataclass(frozen=True) subclasses (WLEDConfig, AdalightConfig, …) sharing BaseDeviceConfig; DeviceConfig = Union[all 17] - Device.to_config() in device_store.py: single flat→typed dispatch point Phase 2+3 — Typed provider signatures + call-site migration: - ProviderDeps(device_store) frozen dataclass in led_client.py - LEDDeviceProvider.create_client(config, *, deps) abstract signature - create_led_client(config, *, deps) factory dispatches via config.device_type - All 17 providers narrowed to their specific config type; drop kwargs.get() - GroupLEDClient.connect() uses device.to_config() + create_led_client() - wled_target_processor: replaced 21-field DeviceInfo unpacking with to_config() + dataclasses.replace(config, use_ddp=…) for DDP override - device_test_mode: build typed config via to_config() + ProviderDeps - Deleted DeviceInfo dataclass, _get_device_info(), _DEVICE_FIELD_DEFAULTS - TargetContext: replaced get_device_info callback with is_test_mode_active Phase 4 — Test migration: - 47-case test suite in tests/core/devices/test_device_config.py (100% coverage) - test_group_device.py TestGroupLEDClient migrated to GroupConfig + ProviderDeps - Removed legacy keyword-arg init path from GroupLEDClient
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from ledgrab.core.devices.device_config import GroupConfig
|
||||
from ledgrab.core.devices.led_client import ProviderDeps
|
||||
from ledgrab.storage.database import Database
|
||||
from ledgrab.storage.device_store import Device, DeviceStore
|
||||
|
||||
@@ -238,17 +240,22 @@ class TestGroupLEDClient:
|
||||
d3 = _create_device(store, "d3", 30)
|
||||
return store, [d1, d2, d3]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_connect_creates_children(self, mock_store):
|
||||
def _make_client(self, store, devices, mode="sequence"):
|
||||
from ledgrab.core.devices.group_client import GroupLEDClient
|
||||
|
||||
store, devices = mock_store
|
||||
client = GroupLEDClient(
|
||||
device_store=store,
|
||||
config = GroupConfig(
|
||||
device_id="test_group",
|
||||
group_mode="sequence",
|
||||
device_url="group://test_group",
|
||||
led_count=sum(d.led_count for d in devices),
|
||||
group_mode=mode,
|
||||
group_device_ids=[d.id for d in devices],
|
||||
)
|
||||
return GroupLEDClient(config=config, deps=ProviderDeps(device_store=store))
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_connect_creates_children(self, mock_store):
|
||||
store, devices = mock_store
|
||||
client = self._make_client(store, devices)
|
||||
await client.connect()
|
||||
assert client.is_connected
|
||||
assert client.device_led_count == 60 # 10+20+30
|
||||
@@ -257,15 +264,8 @@ class TestGroupLEDClient:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sequence_mode_slices(self, mock_store):
|
||||
from ledgrab.core.devices.group_client import GroupLEDClient
|
||||
|
||||
store, devices = mock_store
|
||||
client = GroupLEDClient(
|
||||
device_store=store,
|
||||
device_id="test_group",
|
||||
group_mode="sequence",
|
||||
group_device_ids=[d.id for d in devices],
|
||||
)
|
||||
client = self._make_client(store, devices)
|
||||
await client.connect()
|
||||
|
||||
# Capture what each child receives
|
||||
@@ -292,15 +292,8 @@ class TestGroupLEDClient:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_independent_mode_resamples(self, mock_store):
|
||||
from ledgrab.core.devices.group_client import GroupLEDClient
|
||||
|
||||
store, devices = mock_store
|
||||
client = GroupLEDClient(
|
||||
device_store=store,
|
||||
device_id="test_group",
|
||||
group_mode="independent",
|
||||
group_device_ids=[d.id for d in devices],
|
||||
)
|
||||
client = self._make_client(store, devices, mode="independent")
|
||||
await client.connect()
|
||||
|
||||
sent_pixels = []
|
||||
@@ -328,15 +321,8 @@ class TestGroupLEDClient:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_close_cleans_up(self, mock_store):
|
||||
from ledgrab.core.devices.group_client import GroupLEDClient
|
||||
|
||||
store, devices = mock_store
|
||||
client = GroupLEDClient(
|
||||
device_store=store,
|
||||
device_id="test_group",
|
||||
group_mode="sequence",
|
||||
group_device_ids=[d.id for d in devices],
|
||||
)
|
||||
client = self._make_client(store, devices)
|
||||
await client.connect()
|
||||
assert client.is_connected
|
||||
await client.close()
|
||||
@@ -345,15 +331,8 @@ class TestGroupLEDClient:
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_sequence_pads_short_pixels(self, mock_store):
|
||||
from ledgrab.core.devices.group_client import GroupLEDClient
|
||||
|
||||
store, devices = mock_store
|
||||
client = GroupLEDClient(
|
||||
device_store=store,
|
||||
device_id="test_group",
|
||||
group_mode="sequence",
|
||||
group_device_ids=[d.id for d in devices],
|
||||
)
|
||||
client = self._make_client(store, devices)
|
||||
await client.connect()
|
||||
|
||||
sent_pixels = []
|
||||
|
||||
Reference in New Issue
Block a user