Adds [tool.ruff] and [tool.ty] config to pyproject.toml with a curated ruff rule set (E, F, W, I, UP, B, C4, SIM, RUF, ASYNC, LOG, G, PIE, RET, PERF, N), pins ruff/ty in requirements-dev.txt, reformats the whole tree with `ruff format`, and fixes the pre-existing lint and type-check debt those tools surfaced so both run clean. Production-code type fixes include: HA's ConfigFlowResult vs. the generic FlowResult in config_flow.py, narrowing BoundEntity.desc to its platform-specific subclass (SelectDesc/NumberDesc/SensorDesc/etc.) via cast() instead of an unchecked annotation, converting HA device_class strings to their proper enum types, a resolve_registry callback typed as `object` instead of `DeviceRegistry | None`, and a couple of other narrow correctness fixes (CA key type validation, an index-out-of-bounds false positive from an empty-tuple fallback, a bool/dict argument swap). Test-file fixes are mechanical: narrowing SamsungEntityDescription to the correct subclass via isinstance()/cast() before accessing subclass-only fields, and asserting Optional write_fn/unit_fn fields are set before calling them.
41 lines
1.5 KiB
Python
41 lines
1.5 KiB
Python
"""Tests for the /mode/vs/0 match_fn discriminator in capabilities/
|
|
air_purifier.py (issue #130).
|
|
|
|
`_has_top_level_modes` decides whether a given air-purifier dump's shared
|
|
/mode/vs/0 href binds to the older ARTIK051_TVTL family's MODE capability
|
|
(packed options[] scheme) or the newer TP1X_DA-AC-AIR family's FAN
|
|
capability (modes/supportedModes reported directly). Pure function, no
|
|
coordinator/entity dependency needed to test it directly -- same rationale
|
|
as test_climate_wind_oscillation_fallback.py's `_oscillation_swing`.
|
|
"""
|
|
|
|
from custom_components.localthings.registry.capabilities.air_purifier import (
|
|
_has_top_level_modes,
|
|
)
|
|
|
|
|
|
def test_new_family_with_supported_modes_list_matches():
|
|
rep = {
|
|
"x.com.samsung.da.modes": ["Smart"],
|
|
"x.com.samsung.da.supportedModes": ["Smart", "Max", "Mid", "WindFree", "Sleep"],
|
|
}
|
|
assert _has_top_level_modes(rep, {}) is True
|
|
|
|
|
|
def test_old_family_with_no_supported_modes_field_does_not_match():
|
|
"""The ARTIK051_TVTL family's /mode/vs/0 packs everything into
|
|
options[] (Light_On, Comode_Off, ...) and has no top-level
|
|
supportedModes at all."""
|
|
rep = {
|
|
"x.com.samsung.da.options": ["Light_On", "Comode_Off", "OptionCode_60282"],
|
|
}
|
|
assert _has_top_level_modes(rep, {}) is False
|
|
|
|
|
|
def test_non_list_supported_modes_does_not_match():
|
|
assert _has_top_level_modes({"x.com.samsung.da.supportedModes": "Smart"}, {}) is False
|
|
|
|
|
|
def test_empty_rep_does_not_match():
|
|
assert _has_top_level_modes({}, {}) is False
|