Add PyKumoBase.has_profile() to expose profile-populated state#72
Merged
Conversation
Consumers such as hass-kumo need to know whether the unit profile has
been populated from a successful poll before relying on capability
methods (has_auto_mode(), has_heat_mode(), get_fan_speeds(), etc.).
Those methods return silent defaults (False / a fallback list) when
_profile is empty, so a truthiness check on their return value cannot
distinguish real hardware data from the defaults.
Add has_profile() -> bool to PyKumoBase, implemented as bool(self._profile).
The profile is initialised to {} at construction and populated after the
first successful update_status() call; this provides a clean, stable
predicate without exposing the internal dict.
Add three unit tests covering the empty, populated, and reset cases.
Enables hass-kumo PR #223 to replace its direct _profile access with
the new public method once this is released.
Co-Authored-By: Claude <noreply@anthropic.com>
d-walsh
added a commit
to d-walsh/hass-kumo-1
that referenced
this pull request
Jun 8, 2026
The profile-populated guard currently accesses pykumo's private _profile attribute directly. dlarrick/pykumo#72 adds a public has_profile() method for exactly this purpose. Add a TODO comment so the migration path is clear once pykumo cuts a release with that method and the requirement can be bumped. Co-Authored-By: Claude <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR exposes whether a unit’s capability profile has been populated by adding a small public API (PyKumoBase.has_profile()) so consumers can avoid caching capability defaults before the first successful poll.
Changes:
- Add
PyKumoBase.has_profile() -> boolreturning whether_profileis non-empty. - Add unit tests covering the populated/unpopulated profile state transitions.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
pykumo/py_kumo_base.py |
Adds has_profile() to let callers detect whether capability data is real vs fallback defaults. |
tests/test_py_kumo_base.py |
Adds tests validating has_profile() before/after profile population and after clearing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Neither import was referenced in any test body; removing them silences the ruff F401 warning and makes pre-commit pass cleanly. Co-Authored-By: Claude <noreply@anthropic.com>
Contributor
Author
|
Removed the unused MagicMock and patch imports; pre-commit/ruff clean now. |
d-walsh
added a commit
to d-walsh/hass-kumo-1
that referenced
this pull request
Jun 15, 2026
pykumo 0.5.2 ships PyKumoBase.has_profile() (merged from dlarrick/pykumo#72), replacing the private _profile attribute access that was guarded with a noqa. - manifest.json: pykumo>=0.5.0 → pykumo>=0.5.2 - climate.py _refresh_capabilities(): replace `if not self._pykumo._profile:` (with noqa: SLF001 and TODO comment) with `if not self._pykumo.has_profile()` Co-Authored-By: Claude <noreply@anthropic.com>
dlarrick
pushed a commit
to dlarrick/hass-kumo
that referenced
this pull request
Jun 16, 2026
* climate: refresh HVAC capabilities on every coordinator poll Fixes the silent capability-strip bug reported in #105: when a unit's WiFi adapter is offline at HA startup, pykumo returns empty profiles and `__init__` caches `_hvac_modes = [OFF, COOL]` permanently. Heat-cool commands are then silently rejected until the next HA restart, even after the adapter reconnects. Changes: - Extract the capability derivation block into `_refresh_capabilities()`. - Call it from `__init__` (same behavior as before for online units) and from `update()` after every successful coordinator poll. - Use an **upgrade-only** merge for `_hvac_modes`: modes are only ever added, never removed. A transient poll failure cannot strip a capability that was already confirmed. `fan_modes` and `swing_modes` are refreshed from the live profile unconditionally (pykumo preserves the last-good profile across failures, so this is always safe). - Add a DEBUG log line after each refresh so capability changes are visible in HA logs without enabling extra verbosity. Co-Authored-By: Claude <noreply@anthropic.com> * climate: gate _refresh_capabilities on non-empty pykumo profile pykumo initialises _profile to {} and only populates it after a successful network poll. The previous code guarded fan_modes with `if fan_speeds:`, but get_fan_speeds() falls back to a hard-coded 5-item list when numberOfFanSpeeds is absent (KeyError → speeds = 5), so the guard always passed and the stale default list was cached as real hardware data. Fix: skip all capability derivation when _profile is empty. The entity keeps its safe init defaults ([OFF, COOL], empty fan/swing lists) until the first successful poll populates the profile. Once populated, the existing upgrade-only logic for hvac_modes and the overwrite logic for fan/swing modes work correctly. Co-Authored-By: Claude <noreply@anthropic.com> * climate: note TODO to switch to has_profile() once pykumo#72 releases The profile-populated guard currently accesses pykumo's private _profile attribute directly. dlarrick/pykumo#72 adds a public has_profile() method for exactly this purpose. Add a TODO comment so the migration path is clear once pykumo cuts a release with that method and the requirement can be bumped. Co-Authored-By: Claude <noreply@anthropic.com> * climate: fix _refresh_capabilities docstring for fan/swing update logic The previous docstring said fan_modes/swing_modes are overwritten on every populated-profile call. The code actually uses a truthy guard (if fan_speeds: / if vane_dirs:) so a transient empty read never clobbers a previously confirmed list. Update the docstring to match. No logic changes. Co-Authored-By: Claude <noreply@anthropic.com> * Bump pykumo to >=0.5.2 and migrate _profile to has_profile() pykumo 0.5.2 ships PyKumoBase.has_profile() (merged from dlarrick/pykumo#72), replacing the private _profile attribute access that was guarded with a noqa. - manifest.json: pykumo>=0.5.0 → pykumo>=0.5.2 - climate.py _refresh_capabilities(): replace `if not self._pykumo._profile:` (with noqa: SLF001 and TODO comment) with `if not self._pykumo.has_profile()` Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: d-walsh <2351963+d-walsh@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add a one-line public method
has_profile() -> booltoPyKumoBasethat tells callers whether the unit profile has been populated from a successful poll.Motivation
_profilestarts as{}at construction and is populated after the first successfulupdate_status()call. Capability methods —has_auto_mode(),has_heat_mode(),get_fan_speeds(),get_vane_directions(), etc. — all read_profileand return silent defaults (False/ a hardcoded fallback list) when the profile is empty. A truthiness check on their return values cannot distinguish real hardware data from those defaults.Consumers that derive capability lists (e.g. which HVAC modes are supported) and cache the result need a reliable way to know whether the profile is populated before trusting capability output. Without this, capabilities derived before the first successful poll (e.g. when the WiFi adapter is offline at startup) are silently wrong and never corrected.
This is the exact scenario described in hass-kumo PR #223, which currently works around it via
self._pykumo._profile— a direct reach into a private attribute.Change
3 unit tests added in
tests/test_py_kumo_base.py.Relationship to hass-kumo
hass-kumo PR dlarrick/hass-kumo#223 adds a profile-populated guard before refreshing HVAC capabilities. Once this method is available and released, that PR can replace
self._pykumo._profilewithself._pykumo.has_profile()and bump thepykumorequirement accordingly.