Skip to content

fix: normalize range validation for light, cover, and valve domains#84

Merged
Faerkeren merged 1 commit into
mainfrom
fix/75-normalize-range-validation
May 27, 2026
Merged

fix: normalize range validation for light, cover, and valve domains#84
Faerkeren merged 1 commit into
mainfrom
fix/75-normalize-range-validation

Conversation

@Faerkeren

Copy link
Copy Markdown
Contributor

Closes #75

Issue validity

Valid and actionable. Four public action methods had inconsistent or missing numeric range validation, making the client's behaviour unpredictable and pushing input checking onto callers.

Method Documented range Old behaviour New behaviour
light.set_brightness 0–255 int() coerce only, no range check Raises ValueError outside 0–255
light.set_rgb each component 0–255 no coerce, no range check Raises ValueError for any component outside 0–255
cover.set_position 0–100 int() coerce only (docstring said "clamped") Raises ValueError outside 0–100
valve.set_position 0–100 no range check at all Raises ValueError outside 0–100; validation runs before feature-support guard

fan.set_percentage, humidifier.set_humidity, and media_player.set_volume already validated correctly and are unchanged.

Fix

  • Added src/haclient/domains/_utils.py with a single shared helper:

    def validate_range(value: int, lo: int, hi: int, name: str) -> int

    Coerces to int, checks the closed interval, and raises ValueError with a consistent message ("{name} must be between {lo} and {hi}, got {value}").

  • Applied to light.set_brightness, light.set_rgb (all three components), cover.set_position, and valve.set_position.

  • Docstrings updated with explicit Raises sections where missing.

Tests

Four new test functions added to tests/test_domains.py:

  • test_light_set_brightness_validation — below-range, above-range, boundary (0, 255)
  • test_light_set_rgb_validation — below/above range for each of r, g, b; boundaries (0,0,0) and (255,255,255)
  • test_cover_set_position_validation — below-range, above-range, boundary (0, 100)
  • test_valve_set_position_validation — range validation fires even when feature is absent; boundaries dispatched when feature is present

Checks run

  • pytest: 311 passed, coverage 97.17% (threshold 95%)
  • ruff check + ruff format --check: all passed
  • mypy src: no issues

)

Introduce a shared validate_range() helper in domains/_utils.py and
apply it consistently to the four action methods that previously had
inconsistent or missing input validation:

- light.set_brightness: now validates 0-255 (was int() coerce only)
- light.set_rgb: now validates each component 0-255 (was no validation)
- cover.set_position: now validates 0-100 (docstring said clamped but
  only coerced with int())
- valve.set_position: now validates 0-100 (was no range check at all);
  validation fires before the feature-support guard so callers receive
  an immediate ValueError for clearly invalid input even on binary valves

fan.set_percentage, humidifier.set_humidity, and
media_player.set_volume already validated correctly and are unchanged.

Tests added: below-range, above-range, and boundary values for all
four fixed methods (4 new test functions, 311 tests total pass).
@Faerkeren Faerkeren merged commit 631cfc5 into main May 27, 2026
12 checks passed
@Faerkeren Faerkeren deleted the fix/75-normalize-range-validation branch May 27, 2026 03:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Normalize validation for ranged domain actions

1 participant