Problem
Domain listener docstrings and annotations do not match the actual callback contract.
src/haclient/entity/base.py:33 defines ValueChangeHandler as (old_value, new_value). _schedule_value() calls handlers with two arguments at src/haclient/entity/base.py:175-189. State transition listeners are also dispatched with (old_state, new_state) at src/haclient/entity/base.py:146-148.
Many public domain APIs document a different contract:
src/haclient/domains/light.py:26-40, where on_turn_on() says the callback is zero-argument.
src/haclient/domains/light.py:58-71, where on_brightness_change() says the callback receives the new brightness value, not (old, new).
src/haclient/domains/sensor.py:23-38, where on_value_change() says the callback receives the new state string, not (old, new).
- Similar zero-argument or single-value wording appears across switch, binary_sensor, cover, lock, media_player, timer, vacuum, valve, climate, and humidifier listeners.
The public signatures also use Any -> Any, so type checking does not protect users from registering callbacks with the documented but wrong arity.
Suggested Fix
Choose one callback contract and make it consistent.
Recommended: keep the existing runtime behavior of (old, new) because tests already assert that shape, then:
- Update every public listener docstring to say callbacks receive
(old, new).
- Replace
func: Any) -> Any with typed callables such as ValueChangeHandler or a domain-specific alias.
- Add targeted tests that registering a zero-argument callback either fails early with a clear error or is no longer documented as valid.
- If zero-argument transition callbacks are preferred, add adapter helpers so transition listeners actually receive zero arguments and update existing tests accordingly.
Rationale
This is a user-facing API correctness bug. A user following the docs will register callbacks that raise TypeError when events fire. The library catches and logs those exceptions, so the callback silently does nothing from the caller’s perspective.
Problem
Domain listener docstrings and annotations do not match the actual callback contract.
src/haclient/entity/base.py:33definesValueChangeHandleras(old_value, new_value)._schedule_value()calls handlers with two arguments atsrc/haclient/entity/base.py:175-189. State transition listeners are also dispatched with(old_state, new_state)atsrc/haclient/entity/base.py:146-148.Many public domain APIs document a different contract:
src/haclient/domains/light.py:26-40, whereon_turn_on()says the callback is zero-argument.src/haclient/domains/light.py:58-71, whereon_brightness_change()says the callback receives the new brightness value, not(old, new).src/haclient/domains/sensor.py:23-38, whereon_value_change()says the callback receives the new state string, not(old, new).The public signatures also use
Any -> Any, so type checking does not protect users from registering callbacks with the documented but wrong arity.Suggested Fix
Choose one callback contract and make it consistent.
Recommended: keep the existing runtime behavior of
(old, new)because tests already assert that shape, then:(old, new).func: Any) -> Anywith typed callables such asValueChangeHandleror a domain-specific alias.Rationale
This is a user-facing API correctness bug. A user following the docs will register callbacks that raise
TypeErrorwhen events fire. The library catches and logs those exceptions, so the callback silently does nothing from the caller’s perspective.