refactor: rename project to LedGrab, split HA integration into separate repo
Lint & Test / test (push) Successful in 1m56s
Lint & Test / test (push) Successful in 1m56s
- Rename Python package: wled_controller -> ledgrab - Rename env var prefix: WLED_ -> LEDGRAB_ (with auto-migration for old vars) - Rename localStorage key: wled_api_key -> ledgrab_api_key (with migration) - Rename HA integration domain: wled_screen_controller -> ledgrab - Update all imports, build scripts, Docker, installer, config, docs - Remove HA integration (moved to ledgrab-haos-integration repo) - Remove hacs.json (belongs in HA repo now) - Add startup warning for users with old WLED_ env vars - All tests pass (715/715), ruff clean, tsc clean, frontend builds
This commit is contained in:
@@ -2,12 +2,12 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from wled_controller.core.filters.filter_instance import FilterInstance
|
||||
from wled_controller.storage.audio_processing_template_store import AudioProcessingTemplateStore
|
||||
from wled_controller.storage.database import Database
|
||||
from ledgrab.core.filters.filter_instance import FilterInstance
|
||||
from ledgrab.storage.audio_processing_template_store import AudioProcessingTemplateStore
|
||||
from ledgrab.storage.database import Database
|
||||
|
||||
# Ensure all built-in audio filters are registered
|
||||
import wled_controller.core.audio.filters # noqa: F401
|
||||
import ledgrab.core.audio.filters # noqa: F401
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from wled_controller.storage.audio_source import CaptureAudioSource, ProcessedAudioSource
|
||||
from wled_controller.storage.audio_source_store import AudioSourceStore, ResolvedAudioSource
|
||||
from wled_controller.storage.database import Database
|
||||
from ledgrab.storage.audio_source import CaptureAudioSource, ProcessedAudioSource
|
||||
from ledgrab.storage.audio_source_store import AudioSourceStore, ResolvedAudioSource
|
||||
from ledgrab.storage.database import Database
|
||||
|
||||
# Ensure audio filter registration for any template-related code
|
||||
import wled_controller.core.audio.filters # noqa: F401
|
||||
import ledgrab.core.audio.filters # noqa: F401
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from wled_controller.storage.automation import (
|
||||
from ledgrab.storage.automation import (
|
||||
ApplicationRule,
|
||||
Automation,
|
||||
DisplayStateRule,
|
||||
@@ -13,7 +13,7 @@ from wled_controller.storage.automation import (
|
||||
TimeOfDayRule,
|
||||
WebhookRule,
|
||||
)
|
||||
from wled_controller.storage.automation_store import AutomationStore
|
||||
from ledgrab.storage.automation_store import AutomationStore
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -268,7 +268,7 @@ class TestAutomationNameUniqueness:
|
||||
|
||||
class TestAutomationPersistence:
|
||||
def test_persist_and_reload(self, tmp_path):
|
||||
from wled_controller.storage.database import Database
|
||||
from ledgrab.storage.database import Database
|
||||
|
||||
db = Database(tmp_path / "auto_persist.db")
|
||||
s1 = AutomationStore(db)
|
||||
|
||||
@@ -7,7 +7,7 @@ from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from wled_controller.storage.base_store import BaseJsonStore, EntityNotFoundError
|
||||
from ledgrab.storage.base_store import BaseJsonStore, EntityNotFoundError
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -45,6 +45,7 @@ class _TestStore(BaseJsonStore[_Item]):
|
||||
|
||||
class _LegacyStore(BaseJsonStore[_Item]):
|
||||
"""Store that supports legacy JSON keys for migration testing."""
|
||||
|
||||
_json_key = "items_v2"
|
||||
_entity_name = "Item"
|
||||
_legacy_json_keys = ["items_v1", "old_items"]
|
||||
|
||||
@@ -4,7 +4,7 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
|
||||
import pytest
|
||||
|
||||
from wled_controller.storage.device_store import Device, DeviceStore
|
||||
from ledgrab.storage.device_store import Device, DeviceStore
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -14,7 +14,8 @@ from wled_controller.storage.device_store import Device, DeviceStore
|
||||
|
||||
@pytest.fixture
|
||||
def tmp_db(tmp_path):
|
||||
from wled_controller.storage.database import Database
|
||||
from ledgrab.storage.database import Database
|
||||
|
||||
db = Database(tmp_path / "test.db")
|
||||
yield db
|
||||
db.close()
|
||||
@@ -95,8 +96,13 @@ class TestDeviceModel:
|
||||
|
||||
def test_to_dict_includes_non_defaults(self):
|
||||
d = Device(
|
||||
device_id="d", name="D", url="http://x", led_count=10,
|
||||
rgbw=True, tags=["a"], software_brightness=100,
|
||||
device_id="d",
|
||||
name="D",
|
||||
url="http://x",
|
||||
led_count=10,
|
||||
rgbw=True,
|
||||
tags=["a"],
|
||||
software_brightness=100,
|
||||
)
|
||||
data = d.to_dict()
|
||||
assert data["rgbw"] is True
|
||||
@@ -243,7 +249,8 @@ class TestDeviceNameUniqueness:
|
||||
|
||||
class TestDevicePersistence:
|
||||
def test_persistence_across_instances(self, tmp_path):
|
||||
from wled_controller.storage.database import Database
|
||||
from ledgrab.storage.database import Database
|
||||
|
||||
db = Database(tmp_path / "persist.db")
|
||||
s1 = DeviceStore(db)
|
||||
d = s1.create_device(name="Persist", url="http://p", led_count=77)
|
||||
@@ -256,7 +263,8 @@ class TestDevicePersistence:
|
||||
db.close()
|
||||
|
||||
def test_update_persists(self, tmp_path):
|
||||
from wled_controller.storage.database import Database
|
||||
from ledgrab.storage.database import Database
|
||||
|
||||
db = Database(tmp_path / "persist2.db")
|
||||
s1 = DeviceStore(db)
|
||||
d = s1.create_device(name="Before", url="http://x", led_count=10)
|
||||
@@ -274,7 +282,8 @@ class TestDevicePersistence:
|
||||
|
||||
class TestDeviceThreadSafety:
|
||||
def test_concurrent_creates(self, tmp_path):
|
||||
from wled_controller.storage.database import Database
|
||||
from ledgrab.storage.database import Database
|
||||
|
||||
db = Database(tmp_path / "conc.db")
|
||||
s = DeviceStore(db)
|
||||
errors = []
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from wled_controller.storage.base_store import EntityNotFoundError
|
||||
from wled_controller.storage.game_integration import EventMapping, GameIntegrationConfig
|
||||
from wled_controller.storage.game_integration_store import GameIntegrationStore
|
||||
from ledgrab.storage.base_store import EntityNotFoundError
|
||||
from ledgrab.storage.game_integration import EventMapping, GameIntegrationConfig
|
||||
from ledgrab.storage.game_integration_store import GameIntegrationStore
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from wled_controller.storage.output_target import OutputTarget
|
||||
from wled_controller.storage.output_target_store import OutputTargetStore
|
||||
from wled_controller.storage.wled_output_target import WledOutputTarget
|
||||
from ledgrab.storage.output_target import OutputTarget
|
||||
from ledgrab.storage.output_target_store import OutputTargetStore
|
||||
from ledgrab.storage.wled_output_target import WledOutputTarget
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -168,7 +168,7 @@ class TestOutputTargetQueries:
|
||||
|
||||
class TestOutputTargetPersistence:
|
||||
def test_persist_and_reload(self, tmp_path):
|
||||
from wled_controller.storage.database import Database
|
||||
from ledgrab.storage.database import Database
|
||||
|
||||
db_path = str(tmp_path / "ot_persist.db")
|
||||
db = Database(db_path)
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from wled_controller.storage.sync_clock import SyncClock
|
||||
from wled_controller.storage.sync_clock_store import SyncClockStore
|
||||
from ledgrab.storage.sync_clock import SyncClock
|
||||
from ledgrab.storage.sync_clock_store import SyncClockStore
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -54,9 +54,7 @@ class TestSyncClockStoreCRUD:
|
||||
assert store.count() == 1
|
||||
|
||||
def test_create_clock_with_options(self, store):
|
||||
c = store.create_clock(
|
||||
name="Fast", speed=5.0, description="speedy", tags=["anim"]
|
||||
)
|
||||
c = store.create_clock(name="Fast", speed=5.0, description="speedy", tags=["anim"])
|
||||
assert c.speed == 5.0
|
||||
assert c.description == "speedy"
|
||||
assert c.tags == ["anim"]
|
||||
@@ -149,7 +147,8 @@ class TestSyncClockNameUniqueness:
|
||||
|
||||
class TestSyncClockPersistence:
|
||||
def test_persist_and_reload(self, tmp_path):
|
||||
from wled_controller.storage.database import Database
|
||||
from ledgrab.storage.database import Database
|
||||
|
||||
db = Database(tmp_path / "sc_persist.db")
|
||||
s1 = SyncClockStore(db)
|
||||
c = s1.create_clock(name="Persist", speed=2.5)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import pytest
|
||||
|
||||
from wled_controller.storage.value_source import (
|
||||
from ledgrab.storage.value_source import (
|
||||
AdaptiveValueSource,
|
||||
AnimatedValueSource,
|
||||
AudioValueSource,
|
||||
@@ -10,7 +10,7 @@ from wled_controller.storage.value_source import (
|
||||
StaticValueSource,
|
||||
ValueSource,
|
||||
)
|
||||
from wled_controller.storage.value_source_store import ValueSourceStore
|
||||
from ledgrab.storage.value_source_store import ValueSourceStore
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -149,8 +149,10 @@ class TestValueSourceStoreCRUD:
|
||||
|
||||
def test_create_animated(self, store):
|
||||
s = store.create_source(
|
||||
name="A1", source_type="animated",
|
||||
waveform="sawtooth", speed=20.0,
|
||||
name="A1",
|
||||
source_type="animated",
|
||||
waveform="sawtooth",
|
||||
speed=20.0,
|
||||
)
|
||||
assert isinstance(s, AnimatedValueSource)
|
||||
assert s.waveform == "sawtooth"
|
||||
@@ -158,8 +160,10 @@ class TestValueSourceStoreCRUD:
|
||||
|
||||
def test_create_audio(self, store):
|
||||
s = store.create_source(
|
||||
name="Au1", source_type="audio",
|
||||
audio_source_id="as_1", mode="beat",
|
||||
name="Au1",
|
||||
source_type="audio",
|
||||
audio_source_id="as_1",
|
||||
mode="beat",
|
||||
)
|
||||
assert isinstance(s, AudioValueSource)
|
||||
assert s.mode == "beat"
|
||||
@@ -170,7 +174,9 @@ class TestValueSourceStoreCRUD:
|
||||
{"time": "20:00", "value": 1.0},
|
||||
]
|
||||
s = store.create_source(
|
||||
name="AT", source_type="adaptive_time", schedule=schedule,
|
||||
name="AT",
|
||||
source_type="adaptive_time",
|
||||
schedule=schedule,
|
||||
)
|
||||
assert isinstance(s, AdaptiveValueSource)
|
||||
assert len(s.schedule) == 2
|
||||
@@ -178,14 +184,18 @@ class TestValueSourceStoreCRUD:
|
||||
def test_create_adaptive_time_insufficient_schedule(self, store):
|
||||
with pytest.raises(ValueError, match="at least 2 points"):
|
||||
store.create_source(
|
||||
name="Bad", source_type="adaptive_time",
|
||||
name="Bad",
|
||||
source_type="adaptive_time",
|
||||
schedule=[{"time": "12:00", "value": 0.5}],
|
||||
)
|
||||
|
||||
def test_create_daylight(self, store):
|
||||
s = store.create_source(
|
||||
name="DL", source_type="daylight",
|
||||
speed=2.0, use_real_time=True, latitude=48.0,
|
||||
name="DL",
|
||||
source_type="daylight",
|
||||
speed=2.0,
|
||||
use_real_time=True,
|
||||
latitude=48.0,
|
||||
)
|
||||
assert isinstance(s, DaylightValueSource)
|
||||
assert s.use_real_time is True
|
||||
@@ -247,7 +257,8 @@ class TestValueSourceNameUniqueness:
|
||||
|
||||
class TestValueSourcePersistence:
|
||||
def test_persist_and_reload(self, tmp_path):
|
||||
from wled_controller.storage.database import Database
|
||||
from ledgrab.storage.database import Database
|
||||
|
||||
db = Database(tmp_path / "vs_persist.db")
|
||||
s1 = ValueSourceStore(db)
|
||||
src = s1.create_source("Persist", "static", value=0.42)
|
||||
|
||||
Reference in New Issue
Block a user