Skip to content

Release: dev -> master#119

Open
github-actions[bot] wants to merge 68 commits into
masterfrom
dev
Open

Release: dev -> master#119
github-actions[bot] wants to merge 68 commits into
masterfrom
dev

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Automated release PR. Contains merged feature PRs and a single version bump.

KJonline and others added 7 commits April 25, 2026 16:01
Provides architecture overview, command reference, and development guidance for AI-assisted code editing. Documents async/sync package generation, device discovery pattern, token refresh strategy, and file-based testing workflow.
- Scan interval fixed at 2 minutes (_SCAN_INTERVAL constant); removed
  updateInterval() method and scan_interval config option from startSession()
- Added forceUpdate() to Hive class for power users needing an immediate
  poll; skips with debug log if another poll is already in flight
- Extracted _pollDevices() as the single internal poll call site; used by
  both updateData() and forceUpdate()
- Removed all Hive camera code (discontinued product): camera.py,
  data/camera.json, getCamera(), getCameraImage/Recording API methods,
  camera URLs, camera param from request(), deviceList["camera"],
  Camera_Temp sensor command, and hivecamera PRODUCTS block
- Added pytest-asyncio tests for forceUpdate() idle and locked scenarios

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ranch protection

- Added dev-release-pr.yml workflow that triggers on dev branch pushes to automatically bump patch version in setup.py and create a release PR to master (skips if PR already exists or commit message contains 'chore: bump version')
- Added guard-master.yml workflow that enforces PRs to master branch must originate from dev branch only
- Both workflows use GitHub CLI (gh) for PR operations and configure github-actions[bot] as commit
…mic-refresh

Refactor: fix scan interval at 2 min, add forceUpdate, remove camera
Comment thread src/api/hive_api.py Fixed
KJonline and others added 22 commits April 25, 2026 18:53
…mplicit (fall through) returns'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…lease pipeline, document branching model

- Removed python-package.yml (duplicated by ci.yml lint-flake8 job)
- Removed release_draft.yml (superseded by automatic release notes in release-on-master.yml)
- Removed dev branch trigger from ci.yml (now runs on PRs and master pushes only)
- Added release-on-master.yml workflow that reads version from setup.py, creates tag vX.Y.Z and GitHub Release with auto-generated notes on master pushes (skips if tag exists)
- Added docs/workflows/README.md documenting the feature
…nges

- Added paths filter to master push trigger (src, tests, requirements, setup files, config files, CI workflow itself)
- Added identical paths filter to pull_request trigger
- Prevents unnecessary CI runs when only docs, README, or other non-code files change
Consolidate GitHub workflows and document release automation
Deletes alarm.py, alarm.json, and removes all alarm-related code from
hive.py, session.py, const.py, hive_async_api.py, and hive_api.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Renames all camelCase instance attributes to follow Python snake_case
convention: tokenData→token_data, tokenCreated→token_created,
tokenExpiry→token_expiry, homeID→home_id, lastUpdate→last_update,
scanInterval→scan_interval, userID→user_id, errorList→error_list,
updateLock→update_lock, _refreshLock→_refresh_lock,
_refreshThreshold→_refresh_threshold, _updateTask→_update_task,
_lastPollSlow→_last_poll_slow, _slowPollThreshold→_slow_poll_threshold.

Updated across session.py, hive.py, hive_api.py, hive_async_api.py,
and hive_helper.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
entityCache→entity_cache, deviceList→device_list,
_entityCacheKey→_entity_cache_key, getCachedDevice→get_cached_device,
setCachedDevice→set_cached_device, shouldUseCachedData→should_use_cached_data.

Updated across session.py, hive_helper.py, heating.py, hotwater.py,
light.py, plug.py, action.py, and sensor.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…aclasses

- hivedataclasses.py: update Device to snake_case fields, add EntityConfig
- const.py: replace string-based PRODUCTS/DEVICES with EntityConfig instances,
  remove ACTIONS constant, update sensor_commands to use attribute access
- session.py: replace eval() in createDevices with EntityConfig iteration,
  update addList to return Device objects with snake_case fields,
  update _entity_cache_key to use attribute access
- All device modules: replace device["hiveID"] dict access with device.hive_id
  attribute access throughout (hive_id, hive_type, ha_type, hive_name, ha_name,
  device_data, parent_device, is_group, device_id, device_name)
- Replace device.setdefault("status", ...) with direct attribute assignment

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes the blanket `# pylint: skip-file` from all source files and
replaces it with explicit `# pylint: disable=<codes>` directives that
document exactly which rules are suppressed and why:
- C0103: public API method names use camelCase (HA integration constraint)
- E1101: false positives from the mixin pattern (self.session injected by subclass)
- R0914/R0915: complex methods that would need major refactoring to split

Also fixes all pylint issues that were genuinely easy to resolve: removes
unnecessary else-after-return, converts f-strings in logging calls to lazy
% formatting, fixes inconsistent return statements, uses `in` for tuple
membership tests, and removes an unnecessary pass statement.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The updateLock attribute was renamed to update_lock in the snake_case
refactor. Update the test to match.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Converts remaining camelCase method names to Python snake_case convention:
- action.py: getAction→get_action, getState→get_state, setStatusOn→set_status_on, setStatusOff→set_status_off, actionType→action_type
- hive_api.py: refreshTokens→refresh_tokens, getLoginInfo→get_login_info, getAll→get_all, getDevices→get_devices, getProducts→get_products, getActions→get_actions, motionSensor→motion_sensor, getWeather→get_weather, setState
Adds camelCase wrapper methods that delegate to the new snake_case methods
to maintain compatibility with existing Home Assistant integration code:
- session.py: deviceList property, startSession, updateData
- heating.py: setMode, setTargetTemperature, setBoostOn, setBoostOff, getClimate
- hotwater.py: setMode, setBoostOn, setBoostOff, getWaterHeater
- light.py: turnOn, turnOff, getLight
- plug.py: turnOn, turnOff, getSwitch
- sensor.
…ead of dict construction

Replaces manual dict construction in get_* methods across heating.py, hotwater.py,
light.py, plug.py, and sensor.py with direct Device attribute assignment. Updates
set_cached_device to store and return the Device object itself rather than a
separate dict.

Adds dict-style access methods (__getitem__, __setitem__, __contains__, get) to
Device dataclass with camelCase→snake_case key translation via
Adds special-case handling for action-type entities in addList to construct Device
objects directly from the action data dict instead of calling get_device_data (which
expects product/device structure). Actions now populate minimal fields (hive_id,
hive_name, device_id, device_name, ha_name all set to action name/id, empty
device_data, parent_device set to hub_id).

Updates action.py get_action to assign status and device_data
…leaner state management

- .claude/settings.json, .codex/hooks.json: add PreToolUse hooks to prompt reading GRAPH_REPORT.md before file searches
- AGENTS.md, CLAUDE.md: document graphify usage rules (read GRAPH_REPORT.md first, prefer `graphify query/path/explain` over grep, run `graphify update` after code changes)
- pyproject.toml: add dev dependencies including graphifyy
- action.py: extract _set_action_state helper to deduplicate set
Adds graphify-out/ to exclusion patterns in .github/workflows/ci.yml (via find -not -path) and .pre-commit-config.yaml (via exclude directive) to prevent linting/formatting of generated knowledge graph artifacts. Includes initial graphify output: .graphify_python interpreter marker, GRAPH_REPORT.md with 689 nodes/1578 edges across 44 communities, and JSON cache files for extracted code entities.
…pers

- hivedataclasses.py: add SessionTokens and SessionConfig dataclasses to replace Map-based tokens/config dicts
- session.py: replace self.tokens/self.config Map instances with SessionTokens/SessionConfig dataclasses, update all attribute access to use dataclass fields
- hive_helper.py: move epoch_time from session.py to helper module as standalone function
- session.py: add _retry_with_backoff helper to deduplicate retry logic in
KJonline and others added 14 commits May 3, 2026 00:29
…it guard

Overwrites data.json with fully anonymised API dump (UUIDs, personal
details, device names, room names, security zones, action names all
genericised). Merges hotwater and sense product types from the previous
fixture to maintain coverage for those code paths. Wraps content in the
required {"original": "Using File", "parsed": {...}} structure.

Adds scripts/check_data_pii.py as a local pre-commit hook scoped to
src/data/*.json. Blocks commits containing real UUIDs, emails, phone
numbers, UK postcodes, or IP addresses, and enforces the original/parsed
wrapper so raw API dumps cannot be accidentally committed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace pyhive_integration with pyhive in packages list and package-dir mapping to use shorter, cleaner package name.
Generate comprehensive AST graph representation covering all Python modules (setup.py, heating.py, light.py, hotwater.py, sensor.py, switch.py, action.py, api/*.py, helper/*.py) and scripts. Includes 13,352 lines mapping classes, methods, functions, rationales, and their relationships for code visualization tooling.
ci: update ruff hook name from 'ruff' to 'ruff-check' in GitHub Actio…
- Normalize whitespace in claude.yml workflow comment
- Update pre-commit hook to use python3 instead of python for PII check script
chore: standardize formatting and Python interpreter in config files
@KJonline

KJonline commented May 6, 2026

Copy link
Copy Markdown
Contributor

@claude review this PR

KJonline and others added 11 commits May 9, 2026 13:16
* chore: update secrets baseline with new filter and regenerated line numbers

* ci: simplify GitHub Actions workflow and consolidate lint jobs into single pre-commit run

- Consolidate multiple individual lint jobs (bandit, codespell, ruff, yaml, json, executables) into single lint job running all pre-commit hooks
- Remove prepare-base job and complex virtual environment caching strategy
- Simplify caching to only cache pre-commit environments
- Add test matrix for Python 3.10-3.13
- Remove .secretlintrc.json from workflow triggers
- Remove CACHE_VERSION environment variable
- Add

* ci: remove pylint job, add coverage reporting, and clean up workflow comments

- Remove standalone pylint job from CI workflow
- Add pytest-cov to dev dependencies and enable coverage reporting in tests
- Update pylint config to auto-detect CPU count (jobs=0)
- Add context manager support to HiveSession with close() method
- Update Claude Code Review workflow permissions from read to write
- Remove commented-out configuration examples from workflow files
- Remove unused tests/common.py mock file

* ci: remove custom prompt and documentation comments from Claude Code Review workflow

* ci: simplify workflow path triggers and add pip caching to test matrix

- Consolidate workflow path triggers from specific files to `.github/workflows/**`
- Add pip caching to test job setup-python step
- Remove unused step ID from Claude workflow
- Enable claude_args with gh pr tools in Claude workflow
- Update README badge from CodeQL to CI workflow
- Update SECURITY.md with current version support and reporting instructions
- Add bandit to dev dependencies
- Move file_session fixture from test

* ci: add Dependabot configuration and improve debugging/coverage setup

- Add Dependabot config for weekly pip and GitHub Actions updates with dependency labels
- Add coverage report configuration to show missing lines
- Export Hive exception classes from package root for easier imports
- Clean up debugger logging and remove unused variables
- Remove unused home directory expansion in hive.py
- Fix traceback.print_exc() call to use no arguments
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 8.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v4...v8)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](actions/cache@v4...v5)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](actions/setup-python@v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v4...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore: refactor authentication code and update secrets baseline

- Move SRP crypto constants and functions from hive_auth_async.py to new srp_crypto.py module
- Extract device registration logic into DeviceRegistrationMixin class
- Add deprecation shim for src/action.py redirecting to apyhiveapi.devices.action
- Add unasync rules for devices/ and session/ directories in setup.py
- Update secrets baseline to reflect relocated hex entropy strings and regenerated line numbers

* chore: add token_created tracking to device authentication

- Add token_created field to HiveAuthAsync to track when access tokens were issued
- Update get_device_data() to return 4-tuple including token_created timestamp
- Set token_created to current datetime when receiving AuthenticationResult
- Load token_created from device_data config in DiscoveryMixin when available
- Add comprehensive docstring explaining token_created usage for accurate expiry calculation

* Potential fix for pull request finding 'Empty except'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

* ci: skip Claude review on draft PRs and add detailed review prompt

- Skip Claude Code Review workflow when PR is in draft state
- Replace plugin marketplace config with custom review prompt for pyhive-integration
- Update Claude PR Assistant permissions from read to write for pull-requests and issues
- Add debug logging to hub sensor status methods (smoke, dog bark, glass break)
- Remove unused logging import from session/__init__.py

* chore: replace magic number with named constant for device data length

- Add EXPECTED_DEVICE_DATA_LENGTH constant set to 3 in helper/const.py
- Replace hardcoded 3 with EXPECTED_DEVICE_DATA_LENGTH in discovery.py token_created check

---------

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
The previous lower-bound-only constraints let pip resolve boto3/botocore
to the newest PyPI release whenever this package is installed. Anything
in the same env that uses aiobotocore then breaks, because aiobotocore
pins botocore to a narrow range. In Home Assistant the symptom is
Cloudflare R2, IDrive e2, and Nice G.O. failing to set up after a user
opens the Hive config flow.

>=1.34,<1.38 keeps pip inside what aiobotocore 2.21.x accepts. Bump it
when downstream consumers move to aiobotocore 3.x.

Refs: #135
* test: add fake_session and make_device shared fixtures

* fix: make_device allows ha_type override via kwargs

* test: unit tests for Map dot-notation wrapper

* test: unit tests for Device, SessionTokens, SessionConfig dataclasses

* test: unit tests for SRP/HKDF pure crypto functions

* test: strengthen SRP crypto test coverage

* test: unit tests for BaseDeviceHandler plumbing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: strengthen base_handler test assertions and edge cases

* test: unit tests for HiveHelper and epoch_time

48 tests covering epoch_time, convert_minutes_to_time, sanitize_payload,
device_recovered, get_device_name, error_check, get_device_from_id, and
get_device_data — including boundary cases and branching paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: unit tests for HiveAttributes

22 tests covering online_offline, get_battery, get_mode, and state_attributes,
including HIVETOHA mapping behaviour, battery % formatting, and mode/battery
list gating.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: unit tests for DiscoveryMixin

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: unit tests for PollingMixin cache and rate-limit helpers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: smoke tests for camelCase compat alias delegation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: tests for BoostMixin get_boost_status and get_boost_time

* test: add HiveHub sensor status and Hive lifecycle tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: tests for HiveAction get/set state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: tests for Sensor / HiveSensor

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: tests for Switch / HiveSmartPlug

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: tests for Climate / HiveHeating

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: tests for WaterHeater / HiveHotwater

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: tests for Light / HiveLight and LightColorHandler

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: tests for SessionAuthMixin update_tokens, login, sms2fa, hive_refresh_tokens

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: E2E integration tests using file_session fixture

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: clean up hub/session-auth and add session polling/discovery tests

- Remove empty test_hub_smoke placeholder
- Remove redundant @pytest.mark.asyncio decorators (asyncio_mode=auto handles it)
- Add test_session_polling.py: 5 tests for update_data rate-limiting
- Add test_session_discovery.py: 8 tests for start_session branches and
  create_devices error/group-product filtering

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: add cache directories to .gitignore

* chore: add coverage configuration and ignore coverage output

* chore: refine coverage configuration and update lcov output filename

- Add source directive to track apyhiveapi package
- Enable skip_covered reporting option
- Rename lcov output from coverage.lcov to lcov.info
- Update .gitignore to reflect new lcov filename

* chore: add coverage target to Makefile

- Add coverage target to run pytest with coverage and generate lcov report

* chore: migrate coverage config to pyproject.toml and expand test coverage

- Remove standalone .coveragerc file
- Move coverage configuration into pyproject.toml [tool.coverage.*] sections
- Add pyhive package data directive for data/*.json files
- Normalize keywords casing in project metadata
- Add 4 tests for Switch.get_switch edge cases: cache miss fallthrough, non-dict device_data replacement, non-activeplug type handling
- Add test for Attributes.state_attributes when battery device returns

* chore: expand coverage configuration and update datetime.utcnow() to datetime.now(UTC)

- Move coverage output to coverage/ directory (html, lcov.info, .coverage)
- Add pytest coverage flags to pyproject.toml addopts
- Enable branch coverage and show_contexts in HTML reports
- Omit deprecation shim files from coverage (action.py, boost.py, etc.)
- Add exclude_also patterns for TYPE_CHECKING, abstractmethod, NotImplementedError
- Update .gitignore to reflect new coverage/ directory structure
- Replace

* chore: rename CI workflow to Lint and remove tests job

- Rename workflow from "CI" to "Lint"
- Narrow workflow path trigger from `.github/workflows/**` to `.github/workflows/ci.yml`
- Remove tests job (Python 3.10-3.13 matrix)
- Add blank lines between pre-commit job steps for readability
- Split apt-get install command across multiple lines

* chore: add unasync and tokenize-rt to dev dependencies

* chore: use datetime.timezone.utc instead of datetime.UTC for Python 3.10 compatibility

* chore: use datetime.timezone.utc in device_registration and remove unused test constants

- Replace datetime.UTC with datetime.timezone.utc in DeviceRegistrationMixin.register_device
- Remove unused constants from test_heating_extended.py (_TARGET_TEMP, _MANUAL_MODE, _BOOST_MODE, _BOOST_MINS)

* chore: lower codecov coverage targets from 100% to 10%

- Reduce project coverage target from 100% to 10%
- Reduce patch coverage target from 100% to 10%
- Keep threshold at 0% for both targets

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: lower coverage failure threshold from 100% to 10%

- Reduce --cov-fail-under from 100 to 10 in coverage workflow
- Update fail_under from 0 to 10 in pyproject.toml coverage config

* chore: restore coverage threshold to 100% and configure Codecov upload

- Increase --cov-fail-under from 10 to 100 in coverage workflow
- Update fail_under from 10 to 100 in pyproject.toml coverage config
- Add flags, slug, and disable_search parameters to Codecov action

* test: mock sys.settrace in set_debugging tests to avoid side effects

- Replace sys.gettrace() assertions with mock_settrace.assert_called_once_with() checks
- Import trace_debug function for direct comparison in test_set_debugging_with_function_sets_trace
- Remove manual sys.settrace(None) cleanup call

* test: remove manual sys.settrace(None) cleanup calls from debugger tests

- Remove sys.settrace(None) cleanup from test_context_enter_sets_trace
- Wrap multiply() call in mock_settrace context in test_decorator_enabled_true_executes_function
- Remove sys.settrace(None) cleanup from test_init_with_debug_true_sets_trace

* fix: preserve existing sys.settrace when entering/exiting DebugContext

- Store previous trace function in _previous_trace before setting new trace
- Restore previous trace on exit instead of unconditionally clearing to None
- Skip sys.settrace calls entirely when context is disabled
- Add tests for disabled context behavior and previous trace restoration

* test: add autouse fixture to prevent debug list state leakage between tests

- Add _reset_debug_list fixture that saves original debug list before each test
- Restore debug list to original state after test completion
- Import debug from apyhiveapi.hive module

* fix: remove custom debug infrastructure and fix CI coverage gap

The custom debug system (trace_debug, set_debugging, exception_handler,
DebugContext) called sys.settrace() without patching in tests, displacing
coverage.py's CTracer on Python <3.14 and causing CI to report ~50%
coverage even with all tests passing.

- Delete src/helper/debugger.py and tests/unit/test_debugger.py
- Remove debug, trace_debug, set_debugging, exception_handler from hive.py
- Strip debug-related tests from test_hive_module.py and test_hub.py
- Remove _restore_debug_global fixture from conftest.py (no longer needed)
- Add TestPollDevices to test_polling.py to cover _poll_devices directly
- Remove redundant --cov/--cov-report flags from coverage.yml (already in addopts)

All 939 tests pass at 100% coverage on Python 3.12, 3.13, and 3.14.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: use sentinel in branch test so it fires on Python 3.10

asyncio.current_task() returns None inside run_until_complete() on
Python 3.10, so setting _update_task = None made None is None → True,
meaning the False branch of the finally guard (113->116) was never
reached in CI.

Using a unique sentinel object ensures the branch fires on every Python
version regardless of how pytest-asyncio schedules the coroutine.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: lower coverage threshold from 100% to 99%

- Remove --cov-fail-under=100 flag from coverage workflow (use pyproject.toml value)
- Reduce fail_under from 100 to 99 in pyproject.toml coverage config

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@codecov

codecov Bot commented May 20, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

KJonline and others added 3 commits May 20, 2026 23:09
- Use .get("props", {}).get("zone") instead of direct key access in get_device_data
- Remove KeyError exception handler and warning log for missing zone data
- Only compare zones when both product_zone and device_zone exist
- Add test verifying TRV devices without zone props are silently skipped
…DivisionError, and more (#145)

* refactor: improve exception handling and code organization

- Replace __class__.__name__ string checks with direct error.response parsing for boto3 ClientError
- Remove redundant if checks when re-raising EndpointConnectionError as HiveApiError
- Defer asyncio.get_event_loop() call to async_init() using get_running_loop()
- Remove deprecated pool_region parameter from HiveAuthAsync.__init__
- Add HiveError base class and reorganize exception hierarchy (HiveConfigurationError, HiveAuthCredentialError)

* fix: use device_id (not hive_id) to look up data.devices in sensor HIVE_TYPES branch

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: guard against None from .get() before .split() in async_init and get_password_authentication_key

Import HiveUnknownConfiguration and raise it instead of letting AttributeError
propagate when REGION or UPID are absent from the SSO login info response, and
when _pool_id is None or missing an underscore in get_password_authentication_key.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: catch ZeroDivisionError in colour-temperature conversion methods

Extend the except clause in get_min_color_temp, get_max_color_temp, and
get_color_temp from KeyError-only to (KeyError, ZeroDivisionError) so that
a zero colourTemperature value returned by the Hive API returns None instead
of raising an unhandled ZeroDivisionError. Tests added for all three cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: epoch_time to_epoch now honours the pattern argument instead of hardcoding it

Removes the line that overwrote the caller-supplied `pattern` with a
hardcoded Hive format string, so custom format strings are respected.
Adds TestEpochTimePattern tests to confirm the fix and prevent regression.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: remove SSL verify=False and urllib3 warning suppression; use json.dumps in set_state

- Replace manual string-concatenation JSON building in set_state with json.dumps(kwargs)
  to prevent JSON injection when kwarg values contain double-quotes or backslashes
- Remove requests.get(verify=False) SSL bypass from get_login_info
- Remove urllib3 import and disable_warnings call that suppressed the SSL warning
- Update TestGetLoginInfo assertion to match new call signature (no verify=False)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore: remove unused POOL, deprecated refresh_tokens and its tests, and dead url/status guard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: add device context to bare _LOGGER.error(e) calls in get_mode and boost helpers

* fix: updateInterval now sets config.scan_interval instead of silently returning True

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: wrap updateInterval new_interval in timedelta(seconds=) to match SessionConfig type

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: guard api_resp_d None before dict access; defend homes list against null

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: raise HiveApiError for unhandled Cognito ClientError codes

Unhandled ClientError codes in initiate_auth and respond_to_auth_challenge
were silently swallowed, leaving response=None and crashing later with
TypeError. async_init would AttributeError on None when get_login_info
returned no data. All three now raise HiveApiError/HiveUnknownConfiguration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: token_created not updated in elif-token branch; bare refreshToken access

update_tokens() elif branch never set token_created (leaving it at
datetime.min) and crashed on KeyError when refreshToken was absent.
hive_refresh_tokens() used bare dict access for refreshToken. Both now
use safe access patterns and update token_created consistently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: close() must not close a caller-provided websession

close() previously closed the websession unconditionally. Added
_owns_websession flag (True when websession=None at construction time)
so callers who inject their own session retain ownership and lifecycle
control.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: use safe _get_product_state in get_mode BOOST path (heating + hotwater)

Bare dict access data["props"]["previous"]["mode"] raised KeyError when
previous was absent, silently swallowed by the outer except and logged
as an error. Replaced with _get_product_state which returns None safely
without triggering the error log path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: set_boost_off returns False instead of sending mode=None to API

When props.previous.mode is absent, set_boost_off was calling
_execute_state_change(mode=None) causing a silent API failure.
Now returns False early with a warning when previous mode cannot
be determined.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: return int brightness; return HS 2-tuple from get_color for HA hs_color

Brightness calculation returned a float (127.5 for 50%), but HA light
entities require int. get_color returned an RGB 3-tuple (r,g,b) but
HA hs_color expects (hue_degrees, saturation_percent) — Hive API stores
these natively so no conversion is needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: raise HiveUnknownConfiguration (not HiveReauthRequired) for empty device data

Empty device/product data after polling means configuration is unknown,
not that tokens expired — using HiveReauthRequired wrongly triggered
a full re-login. Also fixed bare d["id"]/p["id"] access in create_devices
to use .get() with a fallback key to avoid KeyError when the id field
is absent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: device registration wrong exceptions and unnecessary async methods

- confirm_device: non-CodeMismatch ClientErrors now raise HiveApiError
  instead of being silently swallowed
- forget_device: NotAuthorizedException now raises HiveApiError instead
  of the misleading HiveInvalid2FACode; all ClientErrors propagate
- generate_hash_device and get_device_authentication_key are pure
  computation with no I/O — converted from async def to def; callers
  updated to remove await

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: copy schedule slots in get_schedule_nnl to prevent mutation; guard hotwater schedule NNL

- get_schedule_nnl: slot dicts are now shallow-copied before Start_DateTime
  is added, preventing in-place mutation of the original schedule data that
  caused stale results on repeated calls
- hotwater.get_state: guard snan["now"] access so an empty NNL (fewer than
  3 schedule slots) does not raise KeyError; state falls back to the base
  status value instead

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: list→set for battery/mode, remove dead device_attributes code, fix Map.__delattr__

- SessionConfig.battery and .mode changed from list to set; discovery.py
  callers updated from .append() to .add() for O(1) membership checks
- HiveAttributes.get_mode: removed no-op HIVETOHA["Attribute"] lookup —
  mode strings never matched boolean keys so the lookup always passed
  through; now returns raw mode value directly
- HiveAttributes.get_battery: removed dead error_check call — battery state
  is always an integer, never False or "Failed", so error_check never
  triggered a meaningful action
- Map.__delattr__: was raising KeyError for missing keys via dict.__delitem__;
  now wraps in AttributeError to match Python's attribute protocol

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: cover remaining branch gaps in session/auth and session/polling

- update_tokens elif-'token' branch with update_expiry_time=False: token_created
  must not be updated (106->109 branch was uncovered)
- get_devices with homes_data as a non-dict (list): must not crash and home_id
  stays unset (196->181 branch was uncovered)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: remove deprecated refresh_tokens from HiveApi

The method was never called by any production or test code and was
explicitly marked as superseded by AWS token management. Removing it
brings coverage to 100%.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: remove redundant tests from catch-all and relocate unique ones

Deleted ~20 tests from test_remaining_branches.py that were exact
duplicates of tests in their dedicated _extended files. Moved the two
genuinely unique tests (get_state exception handler and dict-under-
sensitive-key sanitize path) to test_heating_extended.py and
test_helpers.py respectively. Coverage remains at 100%.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: migrate all unique tests from catch-all into dedicated files

Moves all remaining unique test classes from test_remaining_branches.py
into their respective device/session/helper extended files. Deletes the
empty catch-all. Coverage remains at 100%.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test: remove 3 duplicate tests from module files

test_schedule_mode_returns_nnl, test_motionsensor_returns_motion_status,
and test_empty_devices_after_get_devices_raises_unknown_configuration were
identical (same mocked setup, same assertions) to their counterparts in
the corresponding unit/_extended files. Removed from module files; unit
versions retained. Coverage remains at 100%.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: eliminate _extended test files by renaming and merging

Renamed 9 standalone extended files (git mv) and merged 4 extended files
into their base counterparts, deduplicating helpers and consolidating all
test classes under clean names with no _extended suffix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: consolidate API error handling and remove deprecated code

- Extracted _call_endpoint helper in both sync/async API classes to eliminate
  repetitive try/except blocks across get_all, get_devices, get_products,
  get_actions, motion_sensor, get_weather, set_state, and set_action
- Removed get_login_info from HiveApiAsync (unused; sync version retained)
- Replaced manual JSON string building in set_state with json.dumps
- Replaced fragile string manipulation for SSO parsing with regex in

* refactor: remove unused _BOOST_MINS constant from test_hotwater.py

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5 to 7.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](codecov/codecov-action@v5...v7)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Khole <29937485+KJonline@users.noreply.github.com>
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.

2 participants