fix: resolve all 153 ruff lint errors for CI
Some checks failed
Lint & Test / test (push) Failing after 9s

Auto-fixed 138 unused imports and f-string issues. Manually fixed:
ambiguous variable names (l→layer), availability-check imports using
importlib.util.find_spec, unused Color import, ImagePool forward ref
via TYPE_CHECKING, multi-statement semicolons, and E402 suppression.
This commit is contained in:
2026-03-22 01:29:26 +03:00
parent f2871319cb
commit 7380b33b9b
79 changed files with 73 additions and 146 deletions

View File

@@ -4,7 +4,7 @@ Uses a registry dict instead of individual module-level globals.
All getter function signatures remain unchanged for FastAPI Depends() compatibility. All getter function signatures remain unchanged for FastAPI Depends() compatibility.
""" """
from typing import Any, Dict, Type, TypeVar from typing import Any, Dict, TypeVar
from wled_controller.core.processing.processor_manager import ProcessorManager from wled_controller.core.processing.processor_manager import ProcessorManager
from wled_controller.storage import DeviceStore from wled_controller.storage import DeviceStore

View File

@@ -3,16 +3,14 @@
import asyncio import asyncio
import base64 import base64
import io import io
import secrets
import threading import threading
import time import time
from typing import Callable, List, Optional from typing import Callable, Optional
import numpy as np import numpy as np
from PIL import Image from PIL import Image
from starlette.websockets import WebSocket from starlette.websockets import WebSocket
from wled_controller.config import get_config
from wled_controller.core.filters import FilterRegistry, ImagePool from wled_controller.core.filters import FilterRegistry, ImagePool
from wled_controller.utils import get_logger from wled_controller.utils import get_logger

View File

@@ -1,7 +1,6 @@
"""Audio capture template and engine routes.""" """Audio capture template and engine routes."""
import asyncio import asyncio
import json
from fastapi import APIRouter, HTTPException, Depends, Query from fastapi import APIRouter, HTTPException, Depends, Query
from starlette.websockets import WebSocket, WebSocketDisconnect from starlette.websockets import WebSocket, WebSocketDisconnect

View File

@@ -2,10 +2,8 @@
import asyncio import asyncio
import json as _json import json as _json
import time as _time
import uuid as _uuid import uuid as _uuid
import numpy as np
from fastapi import APIRouter, HTTPException, Depends, Query, WebSocket, WebSocketDisconnect from fastapi import APIRouter, HTTPException, Depends, Query, WebSocket, WebSocketDisconnect
from wled_controller.api.auth import AuthRequired from wled_controller.api.auth import AuthRequired

View File

@@ -32,11 +32,10 @@ from wled_controller.api.schemas.devices import (
) )
from wled_controller.core.capture.calibration import ( from wled_controller.core.capture.calibration import (
calibration_from_dict, calibration_from_dict,
calibration_to_dict,
) )
from wled_controller.core.capture.screen_capture import get_available_displays from wled_controller.core.capture.screen_capture import get_available_displays
from wled_controller.core.processing.processor_manager import ProcessorManager from wled_controller.core.processing.processor_manager import ProcessorManager
from wled_controller.storage.color_strip_source import AdvancedPictureColorStripSource, ApiInputColorStripSource, CompositeColorStripSource, NotificationColorStripSource, PictureColorStripSource, ProcessedColorStripSource from wled_controller.storage.color_strip_source import AdvancedPictureColorStripSource, ApiInputColorStripSource, CompositeColorStripSource, NotificationColorStripSource, PictureColorStripSource
from wled_controller.storage.color_strip_store import ColorStripStore from wled_controller.storage.color_strip_store import ColorStripStore
from wled_controller.storage.picture_source import ProcessedPictureSource, ScreenCapturePictureSource from wled_controller.storage.picture_source import ProcessedPictureSource, ScreenCapturePictureSource
from wled_controller.storage.picture_source_store import PictureSourceStore from wled_controller.storage.picture_source_store import PictureSourceStore
@@ -136,7 +135,7 @@ def _extract_css_kwargs(data) -> dict:
else: else:
kwargs["calibration"] = None kwargs["calibration"] = None
kwargs["stops"] = [s.model_dump() for s in data.stops] if data.stops is not None else None kwargs["stops"] = [s.model_dump() for s in data.stops] if data.stops is not None else None
kwargs["layers"] = [l.model_dump() for l in data.layers] if data.layers is not None else None kwargs["layers"] = [layer.model_dump() for layer in data.layers] if data.layers is not None else None
kwargs["zones"] = [z.model_dump() for z in data.zones] if data.zones is not None else None kwargs["zones"] = [z.model_dump() for z in data.zones] if data.zones is not None else None
kwargs["animation"] = data.animation.model_dump() if data.animation else None kwargs["animation"] = data.animation.model_dump() if data.animation else None
return kwargs return kwargs
@@ -870,7 +869,7 @@ async def test_color_strip_ws(
meta["border_width"] = cal.border_width meta["border_width"] = cal.border_width
if is_composite and hasattr(source, "layers"): if is_composite and hasattr(source, "layers"):
# Send layer info for composite preview # Send layer info for composite preview
enabled_layers = [l for l in source.layers if l.get("enabled", True)] enabled_layers = [layer for layer in source.layers if layer.get("enabled", True)]
layer_infos = [] # [{name, id, is_notification, has_brightness, ...}, ...] layer_infos = [] # [{name, id, is_notification, has_brightness, ...}, ...]
for layer in enabled_layers: for layer in enabled_layers:
info = {"id": layer["source_id"], "name": layer.get("source_id", "?"), info = {"id": layer["source_id"], "name": layer.get("source_id", "?"),

View File

@@ -32,7 +32,6 @@ from wled_controller.core.processing.processor_manager import ProcessorManager
from wled_controller.storage import DeviceStore from wled_controller.storage import DeviceStore
from wled_controller.storage.output_target_store import OutputTargetStore from wled_controller.storage.output_target_store import OutputTargetStore
from wled_controller.utils import get_logger from wled_controller.utils import get_logger
from wled_controller.storage.base_store import EntityNotFoundError
logger = get_logger(__name__) logger = get_logger(__name__)

View File

@@ -3,7 +3,6 @@
import asyncio import asyncio
from fastapi import APIRouter, HTTPException, Depends from fastapi import APIRouter, HTTPException, Depends
from fastapi import Query as QueryParam
from wled_controller.api.auth import AuthRequired from wled_controller.api.auth import AuthRequired
from wled_controller.api.dependencies import ( from wled_controller.api.dependencies import (

View File

@@ -3,15 +3,12 @@
Extracted from output_targets.py to keep files under 800 lines. Extracted from output_targets.py to keep files under 800 lines.
""" """
import asyncio
from fastapi import APIRouter, HTTPException, Depends, Query, WebSocket, WebSocketDisconnect from fastapi import APIRouter, HTTPException, Depends, Query, WebSocket, WebSocketDisconnect
from wled_controller.api.auth import AuthRequired from wled_controller.api.auth import AuthRequired
from wled_controller.api.dependencies import ( from wled_controller.api.dependencies import (
fire_entity_event,
get_color_strip_store, get_color_strip_store,
get_device_store,
get_output_target_store, get_output_target_store,
get_picture_source_store, get_picture_source_store,
get_processor_manager, get_processor_manager,

View File

@@ -306,7 +306,7 @@ async def test_kc_target_ws(
# Load stores # Load stores
target_store_inst: OutputTargetStore = get_output_target_store() target_store_inst: OutputTargetStore = get_output_target_store()
source_store_inst: PictureSourceStore = get_picture_source_store() source_store_inst: PictureSourceStore = get_picture_source_store()
template_store_inst: TemplateStore = get_template_store() get_template_store()
pattern_store_inst: PatternTemplateStore = get_pattern_template_store() pattern_store_inst: PatternTemplateStore = get_pattern_template_store()
processor_manager_inst: ProcessorManager = get_processor_manager() processor_manager_inst: ProcessorManager = get_processor_manager()
device_store_inst: DeviceStore = get_device_store() device_store_inst: DeviceStore = get_device_store()

View File

@@ -55,7 +55,7 @@ logger = get_logger(__name__)
psutil.cpu_percent(interval=None) psutil.cpu_percent(interval=None)
# GPU monitoring (initialized once in utils.gpu, shared with metrics_history) # GPU monitoring (initialized once in utils.gpu, shared with metrics_history)
from wled_controller.utils.gpu import nvml_available as _nvml_available, nvml as _nvml, nvml_handle as _nvml_handle from wled_controller.utils.gpu import nvml_available as _nvml_available, nvml as _nvml, nvml_handle as _nvml_handle # noqa: E402
def _get_cpu_name() -> str | None: def _get_cpu_name() -> str | None:

View File

@@ -1,7 +1,7 @@
"""Shared schemas used across multiple route modules.""" """Shared schemas used across multiple route modules."""
from datetime import datetime from datetime import datetime
from typing import Dict, List, Optional from typing import Dict, Optional
from pydantic import BaseModel, Field from pydantic import BaseModel, Field

View File

@@ -141,7 +141,6 @@ class AudioAnalyzer:
Returns: Returns:
AudioAnalysis with spectrum, RMS, beat, etc. AudioAnalysis with spectrum, RMS, beat, etc.
""" """
chunk_size = self._chunk_size
alpha = self._smoothing_alpha alpha = self._smoothing_alpha
one_minus_alpha = 1.0 - alpha one_minus_alpha = 1.0 - alpha

View File

@@ -16,8 +16,6 @@ from typing import Any, Dict, List, Optional, Tuple
from wled_controller.core.audio.analysis import ( from wled_controller.core.audio.analysis import (
AudioAnalysis, AudioAnalysis,
AudioAnalyzer, AudioAnalyzer,
DEFAULT_CHUNK_SIZE,
DEFAULT_SAMPLE_RATE,
) )
from wled_controller.core.audio.base import AudioCaptureStreamBase from wled_controller.core.audio.base import AudioCaptureStreamBase
from wled_controller.core.audio.factory import AudioEngineRegistry from wled_controller.core.audio.factory import AudioEngineRegistry

View File

@@ -3,7 +3,7 @@
import asyncio import asyncio
import re import re
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import Dict, List, Optional, Set from typing import Dict, Optional, Set
from wled_controller.core.automations.platform_detector import PlatformDetector from wled_controller.core.automations.platform_detector import PlatformDetector
from wled_controller.storage.automation import ( from wled_controller.storage.automation import (

View File

@@ -1,7 +1,7 @@
"""Calibration system for mapping screen pixels to LED positions.""" """Calibration system for mapping screen pixels to LED positions."""
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Dict, List, Literal, Optional, Set, Tuple from typing import Dict, List, Literal, Set, Tuple
import numpy as np import numpy as np

View File

@@ -1,7 +1,7 @@
"""Screen capture functionality using mss library.""" """Screen capture functionality using mss library."""
from dataclasses import dataclass from dataclasses import dataclass
from typing import Dict, List from typing import List
import mss import mss
import numpy as np import numpy as np

View File

@@ -4,9 +4,8 @@ import colorsys
import logging import logging
import sys import sys
import threading import threading
import time
import tkinter as tk import tkinter as tk
from typing import Dict, List, Optional, Tuple from typing import Dict, List, Optional
from wled_controller.core.capture.calibration import CalibrationConfig from wled_controller.core.capture.calibration import CalibrationConfig
from wled_controller.core.capture_engines.base import DisplayInfo from wled_controller.core.capture_engines.base import DisplayInfo

View File

@@ -4,7 +4,6 @@ import sys
import time import time
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
import numpy as np
from wled_controller.core.capture_engines.base import ( from wled_controller.core.capture_engines.base import (
CaptureEngine, CaptureEngine,
@@ -145,9 +144,9 @@ class BetterCamEngine(CaptureEngine):
if sys.platform != "win32": if sys.platform != "win32":
return False return False
try: try:
import bettercam import importlib.util
return True return importlib.util.find_spec("bettercam") is not None
except ImportError: except (ImportError, ModuleNotFoundError, ValueError):
return False return False
@classmethod @classmethod

View File

@@ -14,7 +14,6 @@ import threading
import time import time
from typing import Any, Dict, List, Optional, Set from typing import Any, Dict, List, Optional, Set
import numpy as np
from wled_controller.core.capture_engines.base import ( from wled_controller.core.capture_engines.base import (
CaptureEngine, CaptureEngine,

View File

@@ -74,7 +74,6 @@ class DemoCaptureStream(CaptureStream):
hue = ((self._angle + rotation) / (2.0 * np.pi)) % 1.0 hue = ((self._angle + rotation) / (2.0 * np.pi)) % 1.0
# Saturation: full # Saturation: full
sat = 1.0
# Value: bright at centre, fading toward edges # Value: bright at centre, fading toward edges
max_r = float(self._radius.max()) or 1.0 max_r = float(self._radius.max()) or 1.0

View File

@@ -4,7 +4,6 @@ import sys
import time import time
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
import numpy as np
from wled_controller.core.capture_engines.base import ( from wled_controller.core.capture_engines.base import (
CaptureEngine, CaptureEngine,
@@ -145,9 +144,9 @@ class DXcamEngine(CaptureEngine):
if sys.platform != "win32": if sys.platform != "win32":
return False return False
try: try:
import dxcam import importlib.util
return True return importlib.util.find_spec("dxcam") is not None
except ImportError: except (ImportError, ModuleNotFoundError, ValueError):
return False return False
@classmethod @classmethod

View File

@@ -91,9 +91,9 @@ class MSSEngine(CaptureEngine):
@classmethod @classmethod
def is_available(cls) -> bool: def is_available(cls) -> bool:
try: try:
import mss import importlib.util
return True return importlib.util.find_spec("mss") is not None
except ImportError: except (ImportError, ModuleNotFoundError, ValueError):
return False return False
@classmethod @classmethod

View File

@@ -5,7 +5,6 @@ import sys
import threading import threading
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
import numpy as np
from wled_controller.core.capture_engines.base import ( from wled_controller.core.capture_engines.base import (
CaptureEngine, CaptureEngine,
@@ -220,9 +219,9 @@ class WGCEngine(CaptureEngine):
pass pass
try: try:
import windows_capture import importlib.util
return True return importlib.util.find_spec("windows_capture") is not None
except ImportError: except (ImportError, ModuleNotFoundError, ValueError):
return False return False
@classmethod @classmethod

View File

@@ -2,7 +2,7 @@
import asyncio import asyncio
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import List, Optional, Tuple from typing import Optional, Tuple
import numpy as np import numpy as np

View File

@@ -1,7 +1,6 @@
"""Razer Chroma SDK LED client — controls Razer RGB peripherals via REST API.""" """Razer Chroma SDK LED client — controls Razer RGB peripherals via REST API."""
import asyncio import asyncio
import json
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import List, Optional, Tuple, Union from typing import List, Optional, Tuple, Union

View File

@@ -1,6 +1,5 @@
"""Razer Chroma SDK device provider — control Razer RGB peripherals.""" """Razer Chroma SDK device provider — control Razer RGB peripherals."""
from datetime import datetime, timezone
from typing import List from typing import List
from wled_controller.core.devices.led_client import ( from wled_controller.core.devices.led_client import (

View File

@@ -7,7 +7,7 @@ from typing import List, Optional, Tuple, Union
import numpy as np import numpy as np
from wled_controller.core.devices.led_client import LEDClient, DeviceHealth from wled_controller.core.devices.led_client import LEDClient
from wled_controller.utils import get_logger from wled_controller.utils import get_logger
logger = get_logger(__name__) logger = get_logger(__name__)

View File

@@ -1,6 +1,5 @@
"""ESP-NOW device provider — ultra-low-latency LED control via ESP32 gateway.""" """ESP-NOW device provider — ultra-low-latency LED control via ESP32 gateway."""
from datetime import datetime, timezone
from typing import List from typing import List
from wled_controller.core.devices.led_client import ( from wled_controller.core.devices.led_client import (

View File

@@ -1,6 +1,5 @@
"""SteelSeries GameSense LED client — controls SteelSeries RGB peripherals via REST API.""" """SteelSeries GameSense LED client — controls SteelSeries RGB peripherals via REST API."""
import asyncio
import json import json
import os import os
import platform import platform

View File

@@ -1,6 +1,5 @@
"""SteelSeries GameSense device provider — control SteelSeries RGB peripherals.""" """SteelSeries GameSense device provider — control SteelSeries RGB peripherals."""
from datetime import datetime, timezone
from typing import List from typing import List
from wled_controller.core.devices.led_client import ( from wled_controller.core.devices.led_client import (

View File

@@ -1,7 +1,6 @@
"""Philips Hue device provider — entertainment streaming to Hue lights.""" """Philips Hue device provider — entertainment streaming to Hue lights."""
import asyncio import asyncio
from datetime import datetime, timezone
from typing import List, Tuple from typing import List, Tuple
from wled_controller.core.devices.led_client import ( from wled_controller.core.devices.led_client import (

View File

@@ -1,7 +1,7 @@
"""Abstract base class for LED device communication clients and provider registry.""" """Abstract base class for LED device communication clients and provider registry."""
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from dataclasses import dataclass, field from dataclasses import dataclass
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import Dict, List, Optional, Tuple, Union from typing import Dict, List, Optional, Tuple, Union

View File

@@ -1,7 +1,7 @@
"""MQTT LED client — publishes pixel data to an MQTT topic.""" """MQTT LED client — publishes pixel data to an MQTT topic."""
import json import json
from typing import List, Optional, Tuple, Union from typing import List, Tuple, Union
import numpy as np import numpy as np

View File

@@ -1,7 +1,6 @@
"""MQTT device provider — factory, validation, health checks.""" """MQTT device provider — factory, validation, health checks."""
from datetime import datetime from typing import List
from typing import List, Optional, Tuple
from wled_controller.core.devices.led_client import ( from wled_controller.core.devices.led_client import (
DeviceHealth, DeviceHealth,
@@ -11,7 +10,6 @@ from wled_controller.core.devices.led_client import (
) )
from wled_controller.core.devices.mqtt_client import ( from wled_controller.core.devices.mqtt_client import (
MQTTLEDClient, MQTTLEDClient,
get_mqtt_service,
parse_mqtt_url, parse_mqtt_url,
) )
from wled_controller.utils import get_logger from wled_controller.utils import get_logger

View File

@@ -5,7 +5,7 @@ import socket
import struct import struct
import threading import threading
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import Any, Dict, List, Optional, Tuple, Union from typing import Any, List, Optional, Tuple, Union
import numpy as np import numpy as np
@@ -165,7 +165,6 @@ class OpenRGBLEDClient(LEDClient):
def _connect_sync(self) -> Tuple[Any, Any]: def _connect_sync(self) -> Tuple[Any, Any]:
"""Synchronous connect — runs in thread pool.""" """Synchronous connect — runs in thread pool."""
from openrgb import OpenRGBClient from openrgb import OpenRGBClient
from openrgb.utils import DeviceType
client = OpenRGBClient(self._host, self._port, name="WLED Controller") client = OpenRGBClient(self._host, self._port, name="WLED Controller")
devices = client.devices devices = client.devices

View File

@@ -1,7 +1,7 @@
"""OpenRGB device provider — factory, validation, health checks, discovery.""" """OpenRGB device provider — factory, validation, health checks, discovery."""
import asyncio import asyncio
from typing import List, Optional, Tuple from typing import List, Tuple
from wled_controller.core.devices.led_client import ( from wled_controller.core.devices.led_client import (
DeviceHealth, DeviceHealth,

View File

@@ -12,7 +12,6 @@ import numpy as np
from wled_controller.core.devices.led_client import ( from wled_controller.core.devices.led_client import (
DeviceHealth, DeviceHealth,
DiscoveredDevice, DiscoveredDevice,
LEDClient,
LEDDeviceProvider, LEDDeviceProvider,
) )
from wled_controller.utils import get_logger from wled_controller.utils import get_logger

View File

@@ -94,7 +94,7 @@ class SPIClient(LEDClient):
def _connect_rpi_ws281x(self): def _connect_rpi_ws281x(self):
"""Connect via rpi_ws281x library (GPIO PWM/DMA).""" """Connect via rpi_ws281x library (GPIO PWM/DMA)."""
try: try:
from rpi_ws281x import PixelStrip, Color from rpi_ws281x import PixelStrip
except ImportError: except ImportError:
raise RuntimeError( raise RuntimeError(
"rpi_ws281x is required for GPIO LED control: " "rpi_ws281x is required for GPIO LED control: "
@@ -254,8 +254,10 @@ class SPIClient(LEDClient):
else: else:
# GPIO — check if we can import rpi_ws281x # GPIO — check if we can import rpi_ws281x
try: try:
import rpi_ws281x import importlib.util
if importlib.util.find_spec("rpi_ws281x") is not None:
return DeviceHealth(online=True, latency_ms=0.0, last_checked=datetime.now(timezone.utc)) return DeviceHealth(online=True, latency_ms=0.0, last_checked=datetime.now(timezone.utc))
raise ImportError("rpi_ws281x not found")
except ImportError: except ImportError:
return DeviceHealth( return DeviceHealth(
online=False, online=False,

View File

@@ -1,7 +1,6 @@
"""SPI Direct device provider — Raspberry Pi GPIO/SPI direct LED strip control.""" """SPI Direct device provider — Raspberry Pi GPIO/SPI direct LED strip control."""
import platform import platform
from datetime import datetime, timezone
from typing import List from typing import List
from wled_controller.core.devices.led_client import ( from wled_controller.core.devices.led_client import (

View File

@@ -1,6 +1,5 @@
"""USB HID LED device provider — control RGB peripherals via USB HID.""" """USB HID LED device provider — control RGB peripherals via USB HID."""
from datetime import datetime, timezone
from typing import List from typing import List
from wled_controller.core.devices.led_client import ( from wled_controller.core.devices.led_client import (

View File

@@ -134,7 +134,7 @@ class WLEDClient(LEDClient):
except Exception as e: except Exception as e:
logger.warning(f"Could not configure device for DDP: {e}") logger.warning(f"Could not configure device for DDP: {e}")
logger.info(f"DDP protocol enabled for pixel data transmission (RGB mode)") logger.info("DDP protocol enabled for pixel data transmission (RGB mode)")
self._connected = True self._connected = True
@@ -381,7 +381,7 @@ class WLEDClient(LEDClient):
# Note: brightness already applied by processor loop (_cached_brightness) # Note: brightness already applied by processor loop (_cached_brightness)
logger.debug(f"Sending {len(pixels)} LEDs via DDP") logger.debug(f"Sending {len(pixels)} LEDs via DDP")
self._ddp_client.send_pixels_numpy(pixels) self._ddp_client.send_pixels_numpy(pixels)
logger.debug(f"Successfully sent pixel colors via DDP") logger.debug("Successfully sent pixel colors via DDP")
return True return True
except Exception as e: except Exception as e:
@@ -430,7 +430,7 @@ class WLEDClient(LEDClient):
logger.debug(f"Payload size: ~{len(str(payload))} bytes") logger.debug(f"Payload size: ~{len(str(payload))} bytes")
await self._request("POST", "/json/state", json_data=payload) await self._request("POST", "/json/state", json_data=payload)
logger.debug(f"Successfully sent pixel colors via HTTP") logger.debug("Successfully sent pixel colors via HTTP")
return True return True
except Exception as e: except Exception as e:

View File

@@ -9,7 +9,7 @@ from wled_controller.core.devices.led_client import (
LEDClient, LEDClient,
LEDDeviceProvider, LEDDeviceProvider,
) )
from wled_controller.core.devices.ws_client import WSLEDClient, parse_ws_url from wled_controller.core.devices.ws_client import WSLEDClient
from wled_controller.utils import get_logger from wled_controller.utils import get_logger
logger = get_logger(__name__) logger = get_logger(__name__)

View File

@@ -1,6 +1,6 @@
"""Auto-crop postprocessing filter.""" """Auto-crop postprocessing filter."""
from typing import Any, Dict, List, Optional from typing import List, Optional
import numpy as np import numpy as np

View File

@@ -1,11 +1,16 @@
"""Base classes for the postprocessing filter system.""" """Base classes for the postprocessing filter system."""
from __future__ import annotations
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from dataclasses import dataclass, field from dataclasses import dataclass
from typing import Any, Dict, List, Optional from typing import TYPE_CHECKING, Any, Dict, List, Optional
import numpy as np import numpy as np
if TYPE_CHECKING:
from wled_controller.core.filters.image_pool import ImagePool
@dataclass @dataclass
class FilterOptionDef: class FilterOptionDef:

View File

@@ -1,6 +1,6 @@
"""Downscaler postprocessing filter.""" """Downscaler postprocessing filter."""
from typing import Any, Dict, List, Optional from typing import List, Optional
import cv2 import cv2
import numpy as np import numpy as np

View File

@@ -1,6 +1,6 @@
"""Flip postprocessing filter.""" """Flip postprocessing filter."""
from typing import Any, Dict, List, Optional from typing import List, Optional
import numpy as np import numpy as np

View File

@@ -1,6 +1,6 @@
"""Pixelate postprocessing filter.""" """Pixelate postprocessing filter."""
from typing import Any, Dict, List, Optional from typing import List, Optional
import cv2 import cv2
import numpy as np import numpy as np

View File

@@ -1,6 +1,6 @@
"""Filter registry for discovering and instantiating postprocessing filters.""" """Filter registry for discovering and instantiating postprocessing filters."""
from typing import Dict, List, Type from typing import Dict, Type
from wled_controller.core.filters.base import PostprocessingFilter from wled_controller.core.filters.base import PostprocessingFilter
from wled_controller.utils import get_logger from wled_controller.utils import get_logger

View File

@@ -9,7 +9,7 @@ Extracted from processor_manager.py to keep files under 800 lines.
import asyncio import asyncio
import time import time
from dataclasses import dataclass from dataclasses import dataclass
from typing import Dict, Optional from typing import Optional
from wled_controller.utils import get_logger from wled_controller.utils import get_logger

View File

@@ -19,9 +19,8 @@ from typing import Optional
import numpy as np import numpy as np
from wled_controller.core.capture.calibration import CalibrationConfig, PixelMapper, AdvancedPixelMapper, create_pixel_mapper from wled_controller.core.capture.calibration import CalibrationConfig, AdvancedPixelMapper, create_pixel_mapper
from wled_controller.core.capture.screen_capture import extract_border_pixels from wled_controller.core.capture.screen_capture import extract_border_pixels
from wled_controller.core.processing.live_stream import LiveStream
from wled_controller.utils import get_logger from wled_controller.utils import get_logger
from wled_controller.utils.timer import high_resolution_timer from wled_controller.utils.timer import high_resolution_timer
@@ -107,7 +106,6 @@ class PictureColorStripStream(ColorStripStream):
Lifecycle managed by ColorStripStreamManager. Lifecycle managed by ColorStripStreamManager.
source: PictureColorStripSource config source: PictureColorStripSource config
""" """
from wled_controller.storage.color_strip_source import PictureColorStripSource
# Support both single LiveStream and dict of streams (advanced mode) # Support both single LiveStream and dict of streams (advanced mode)
if isinstance(live_stream, dict): if isinstance(live_stream, dict):
@@ -1093,7 +1091,9 @@ class GradientColorStripStream(ColorStripStream):
(4, tt, p, v_arr), (5, v_arr, p, q), (4, tt, p, v_arr), (5, v_arr, p, q),
): ):
m = hi == sxt m = hi == sxt
ro[m] = rv[m]; go[m] = gv[m]; bo[m] = bv[m] ro[m] = rv[m]
go[m] = gv[m]
bo[m] = bv[m]
buf[:, 0] = np.clip(ro * 255.0, 0, 255).astype(np.uint8) buf[:, 0] = np.clip(ro * 255.0, 0, 255).astype(np.uint8)
buf[:, 1] = np.clip(go * 255.0, 0, 255).astype(np.uint8) buf[:, 1] = np.clip(go * 255.0, 0, 255).astype(np.uint8)
buf[:, 2] = np.clip(bo * 255.0, 0, 255).astype(np.uint8) buf[:, 2] = np.clip(bo * 255.0, 0, 255).astype(np.uint8)

View File

@@ -127,7 +127,7 @@ class CompositeColorStripStream(ColorStripStream):
def get_layer_brightness(self) -> List[Optional[float]]: def get_layer_brightness(self) -> List[Optional[float]]:
"""Return per-layer brightness values (0.0-1.0) from value sources, or None if no source.""" """Return per-layer brightness values (0.0-1.0) from value sources, or None if no source."""
enabled = [l for l in self._layers if l.get("enabled", True)] enabled = [layer for layer in self._layers if layer.get("enabled", True)]
result: List[Optional[float]] = [] result: List[Optional[float]] = []
with self._sub_lock: with self._sub_lock:
for i in range(len(enabled)): for i in range(len(enabled)):
@@ -155,10 +155,10 @@ class CompositeColorStripStream(ColorStripStream):
def update_source(self, source) -> None: def update_source(self, source) -> None:
"""Hot-update: rebuild sub-streams if layer config changed.""" """Hot-update: rebuild sub-streams if layer config changed."""
new_layers = list(source.layers) new_layers = list(source.layers)
old_layer_ids = [(l.get("source_id"), l.get("blend_mode"), l.get("opacity"), l.get("enabled"), l.get("brightness_source_id")) old_layer_ids = [(layer.get("source_id"), layer.get("blend_mode"), layer.get("opacity"), layer.get("enabled"), layer.get("brightness_source_id"))
for l in self._layers] for layer in self._layers]
new_layer_ids = [(l.get("source_id"), l.get("blend_mode"), l.get("opacity"), l.get("enabled"), l.get("brightness_source_id")) new_layer_ids = [(layer.get("source_id"), layer.get("blend_mode"), layer.get("opacity"), layer.get("enabled"), layer.get("brightness_source_id"))
for l in new_layers] for layer in new_layers]
self._layers = new_layers self._layers = new_layers

View File

@@ -5,7 +5,6 @@ that transitions through dawn, daylight, sunset, and night over a continuous
24-hour cycle. Can use real wall-clock time or a configurable simulation speed. 24-hour cycle. Can use real wall-clock time or a configurable simulation speed.
""" """
import math
import threading import threading
import time import time
from typing import Optional from typing import Optional

View File

@@ -3,7 +3,7 @@
Extracted from processor_manager.py to keep files under 800 lines. Extracted from processor_manager.py to keep files under 800 lines.
""" """
from typing import Dict, List, Optional, Tuple from typing import Dict, List, Optional
from wled_controller.core.capture.calibration import CalibrationConfig from wled_controller.core.capture.calibration import CalibrationConfig
from wled_controller.core.devices.led_client import create_led_client from wled_controller.core.devices.led_client import create_led_client

View File

@@ -15,7 +15,7 @@ import httpx
import numpy as np import numpy as np
from wled_controller.core.capture_engines import EngineRegistry from wled_controller.core.capture_engines import EngineRegistry
from wled_controller.core.filters import FilterRegistry, PostprocessingFilter from wled_controller.core.filters import FilterRegistry
from wled_controller.core.processing.live_stream import ( from wled_controller.core.processing.live_stream import (
LiveStream, LiveStream,
ProcessedLiveStream, ProcessedLiveStream,

View File

@@ -12,9 +12,9 @@ from __future__ import annotations
import asyncio import asyncio
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from dataclasses import dataclass, field from dataclasses import dataclass
from datetime import datetime from datetime import datetime
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Tuple from typing import TYPE_CHECKING, Callable, Dict, Optional, Tuple
if TYPE_CHECKING: if TYPE_CHECKING:
from wled_controller.core.processing.color_strip_stream_manager import ColorStripStreamManager from wled_controller.core.processing.color_strip_stream_manager import ColorStripStreamManager

View File

@@ -613,7 +613,7 @@ class WledTargetProcessor(TargetProcessor):
last_send_time = 0.0 last_send_time = 0.0
_last_preview_broadcast = 0.0 _last_preview_broadcast = 0.0
prev_frame_time_stamp = time.perf_counter() prev_frame_time_stamp = time.perf_counter()
loop = asyncio.get_running_loop() asyncio.get_running_loop()
_init_device_info = self._ctx.get_device_info(self._device_id) _init_device_info = self._ctx.get_device_info(self._device_id)
_total_leds = getattr(self, '_effective_led_count', None) or (_init_device_info.led_count if _init_device_info else 0) _total_leds = getattr(self, '_effective_led_count', None) or (_init_device_info.led_count if _init_device_info else 0)

View File

@@ -8,7 +8,6 @@ Equivalent to setting WLED_DEMO=true before starting the regular server.
""" """
import os import os
import sys
def main(): def main():

View File

@@ -2,26 +2,15 @@
import uuid import uuid
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import List, Optional from typing import List
from wled_controller.storage.base_store import BaseJsonStore from wled_controller.storage.base_store import BaseJsonStore
from wled_controller.storage.utils import resolve_ref from wled_controller.storage.utils import resolve_ref
from wled_controller.storage.color_strip_source import ( from wled_controller.storage.color_strip_source import (
AdvancedPictureColorStripSource,
ApiInputColorStripSource,
AudioColorStripSource,
CandlelightColorStripSource,
ColorCycleColorStripSource,
ColorStripSource, ColorStripSource,
CompositeColorStripSource, CompositeColorStripSource,
DaylightColorStripSource,
EffectColorStripSource,
GradientColorStripSource,
MappedColorStripSource, MappedColorStripSource,
NotificationColorStripSource,
PictureColorStripSource,
ProcessedColorStripSource, ProcessedColorStripSource,
StaticColorStripSource,
) )
from wled_controller.utils import get_logger from wled_controller.utils import get_logger

View File

@@ -4,7 +4,7 @@ import json
import uuid import uuid
from datetime import datetime, timezone from datetime import datetime, timezone
from pathlib import Path from pathlib import Path
from typing import Dict, List, Optional from typing import List, Optional
from wled_controller.storage.base_store import BaseJsonStore from wled_controller.storage.base_store import BaseJsonStore
from wled_controller.utils import get_logger from wled_controller.utils import get_logger

View File

@@ -2,7 +2,6 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import List, Optional
from wled_controller.storage.output_target import OutputTarget from wled_controller.storage.output_target import OutputTarget
from wled_controller.storage.utils import resolve_ref from wled_controller.storage.utils import resolve_ref

View File

@@ -1,6 +1,5 @@
"""Output target storage using JSON files.""" """Output target storage using JSON files."""
import json
import uuid import uuid
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import List, Optional from typing import List, Optional

View File

@@ -1,7 +1,7 @@
"""Utility functions for retrieving friendly monitor/display names.""" """Utility functions for retrieving friendly monitor/display names."""
import sys import sys
from typing import Dict, Optional from typing import Dict
from wled_controller.utils import get_logger from wled_controller.utils import get_logger
@@ -129,7 +129,7 @@ def get_monitor_refresh_rates() -> Dict[int, int]:
# Enumerate all display devices # Enumerate all display devices
idx = 0 idx = 0
while True: while True:
device_name = ctypes.create_unicode_buffer(32) ctypes.create_unicode_buffer(32)
if not user32.EnumDisplayDevicesW(None, idx, None, 0): if not user32.EnumDisplayDevicesW(None, idx, None, 0):
# Try getting display settings by index # Try getting display settings by index
devmode = DEVMODE() devmode = DEVMODE()

View File

@@ -4,8 +4,7 @@ These tests exercise the FastAPI route handlers using dependency override
to inject test stores, avoiding real hardware dependencies. to inject test stores, avoiding real hardware dependencies.
""" """
from datetime import datetime, timezone from unittest.mock import AsyncMock, MagicMock
from unittest.mock import AsyncMock, MagicMock, patch
import pytest import pytest
from fastapi import FastAPI from fastapi import FastAPI

View File

@@ -1,7 +1,6 @@
"""Tests for webhook routes — trigger, validation, rate limiting.""" """Tests for webhook routes — trigger, validation, rate limiting."""
import time import time
from unittest.mock import AsyncMock, MagicMock, patch
import pytest import pytest

View File

@@ -1,10 +1,6 @@
"""Pytest configuration and shared fixtures.""" """Pytest configuration and shared fixtures."""
import json
import os
from datetime import datetime, timezone from datetime import datetime, timezone
from pathlib import Path
from unittest.mock import AsyncMock, MagicMock
import pytest import pytest
@@ -15,11 +11,8 @@ from wled_controller.storage.sync_clock_store import SyncClockStore
from wled_controller.storage.output_target_store import OutputTargetStore from wled_controller.storage.output_target_store import OutputTargetStore
from wled_controller.storage.automation import ( from wled_controller.storage.automation import (
Automation, Automation,
AlwaysCondition,
WebhookCondition,
) )
from wled_controller.storage.automation_store import AutomationStore from wled_controller.storage.automation_store import AutomationStore
from wled_controller.storage.value_source import StaticValueSource, ValueSource
from wled_controller.storage.value_source_store import ValueSourceStore from wled_controller.storage.value_source_store import ValueSourceStore

View File

@@ -1,8 +1,7 @@
"""Tests for AutomationEngine — condition evaluation in isolation.""" """Tests for AutomationEngine — condition evaluation in isolation."""
import asyncio
from datetime import datetime, timezone from datetime import datetime, timezone
from unittest.mock import AsyncMock, MagicMock, patch from unittest.mock import MagicMock, patch
import pytest import pytest
@@ -12,7 +11,6 @@ from wled_controller.storage.automation import (
ApplicationCondition, ApplicationCondition,
Automation, Automation,
DisplayStateCondition, DisplayStateCondition,
MQTTCondition,
StartupCondition, StartupCondition,
SystemIdleCondition, SystemIdleCondition,
TimeOfDayCondition, TimeOfDayCondition,

View File

@@ -3,7 +3,6 @@
import threading import threading
import time import time
import pytest
from wled_controller.core.processing.sync_clock_runtime import SyncClockRuntime from wled_controller.core.processing.sync_clock_runtime import SyncClockRuntime

View File

@@ -7,9 +7,7 @@ Uses the `client` fixture (which has the correct auth header set), and
helpers to make unauthenticated requests by temporarily removing the header. helpers to make unauthenticated requests by temporarily removing the header.
""" """
import pytest
from tests.e2e.conftest import API_KEY
def _unauth_get(client, url): def _unauth_get(client, url):

View File

@@ -6,7 +6,6 @@ Tests creating entities, backing up, deleting, then restoring from backup.
import io import io
import json import json
import pytest
class TestBackupRestoreFlow: class TestBackupRestoreFlow:

View File

@@ -3,7 +3,6 @@
Tests creating, listing, updating, cloning, and deleting color strip sources. Tests creating, listing, updating, cloning, and deleting color strip sources.
""" """
import pytest
class TestColorStripSourceLifecycle: class TestColorStripSourceLifecycle:

View File

@@ -4,7 +4,6 @@ Tests the complete device lifecycle through the API:
create -> get -> update -> brightness -> power -> delete -> verify gone. create -> get -> update -> brightness -> power -> delete -> verify gone.
""" """
import pytest
class TestDeviceLifecycle: class TestDeviceLifecycle:

View File

@@ -4,7 +4,6 @@ Tests target CRUD with a dependency on a device:
create device -> create target -> list -> update -> delete target -> cleanup device. create device -> create target -> list -> update -> delete target -> cleanup device.
""" """
import pytest
class TestOutputTargetLifecycle: class TestOutputTargetLifecycle:

View File

@@ -1,7 +1,6 @@
"""Tests for BaseJsonStore — the shared data-layer base class.""" """Tests for BaseJsonStore — the shared data-layer base class."""
import json import json
import threading
from concurrent.futures import ThreadPoolExecutor, as_completed from concurrent.futures import ThreadPoolExecutor, as_completed
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path

View File

@@ -1,6 +1,5 @@
"""Tests for DeviceStore — device CRUD, persistence, name uniqueness, thread safety.""" """Tests for DeviceStore — device CRUD, persistence, name uniqueness, thread safety."""
import threading
from concurrent.futures import ThreadPoolExecutor, as_completed from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path from pathlib import Path

View File

@@ -7,7 +7,6 @@ from wled_controller.storage.output_target_store import OutputTargetStore
from wled_controller.storage.wled_output_target import WledOutputTarget from wled_controller.storage.wled_output_target import WledOutputTarget
from wled_controller.storage.key_colors_output_target import ( from wled_controller.storage.key_colors_output_target import (
KeyColorsOutputTarget, KeyColorsOutputTarget,
KeyColorsSettings,
) )

View File

@@ -1,6 +1,5 @@
"""Tests for API endpoints (public + authenticated).""" """Tests for API endpoints (public + authenticated)."""
import pytest
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from wled_controller.main import app from wled_controller.main import app

View File

@@ -1,7 +1,5 @@
"""Tests for configuration management.""" """Tests for configuration management."""
import os
from pathlib import Path
import pytest import pytest
import yaml import yaml
@@ -9,13 +7,8 @@ import yaml
from wled_controller.config import ( from wled_controller.config import (
Config, Config,
ServerConfig, ServerConfig,
StorageConfig,
AuthConfig,
MQTTConfig,
LoggingConfig,
get_config, get_config,
reload_config, reload_config,
is_demo_mode,
) )

View File

@@ -1,7 +1,6 @@
"""Tests for device storage.""" """Tests for device storage."""
import pytest import pytest
from pathlib import Path
from wled_controller.storage.device_store import Device, DeviceStore from wled_controller.storage.device_store import Device, DeviceStore

View File

@@ -1,9 +1,6 @@
"""Tests for processor manager.""" """Tests for processor manager."""
import asyncio
import pytest import pytest
import respx
from httpx import Response
from wled_controller.core.processing.processor_manager import ProcessorManager from wled_controller.core.processing.processor_manager import ProcessorManager
from wled_controller.core.processing.processing_settings import ProcessingSettings from wled_controller.core.processing.processing_settings import ProcessingSettings