Skip to content

Fix ruff lint errors in api.py - #390

Merged
sveinse merged 1 commit into
custom-components:masterfrom
rhammen:ruff-cleanup
Jul 9, 2026
Merged

Fix ruff lint errors in api.py#390
sveinse merged 1 commit into
custom-components:masterfrom
rhammen:ruff-cleanup

Conversation

@rhammen

@rhammen rhammen commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Resolves all 36 ruff check errors in the vendored Zaptec API client (custom_components/zaptec/zaptec/api.py), taking that file from 36 → 0. This chips away at the non-clean ruff check baseline tracked in #258 (CI currently runs ruff check with --exit-zero).

Almost entirely annotations, comment/logging tidy-ups, and two safe latent-type fixes. See the Behavior note below for the one edge case that is not purely cosmetic.

Lint fixes

  • Add missing return-type and argument annotations (ANN001/003/201/204/205)
  • Replace the mutable default arg for excludes with the None-default pattern (B006)
  • Move the "stream already running" precondition raise out of the try (TRY301)
  • Bind loop-captured log messages as an immutable default arg (B023)
  • Reword a stale FIXME comment to NOTE (TD001/002/003, FIX001)
  • Remove commented-out debug lines (ERA001)
  • Drop redundant exception args from logging.exception(...) calls (TRY401)
  • Remove an unnecessary AsyncGenerator None type arg (UP043)

Two safe latent-type fixes (surfaced while annotating)

  • Initialize operation_mode/final_stop_active so they aren't possibly-unbound in is_command_valid's debug log
  • Widen Zaptec.__contains__ key param to object for a compatible Mapping override

⚠️ Behavior note (TRY301)

The TRY301 fix moves the "stream already running" precondition raise RuntimeError(...) from inside stream_main's try to before it. Previously that error was caught by the method's own except Exception (logged as "Stream failed", and the finally reset _stream_running); now it propagates to the caller instead. This guard is only hit if stream_main is invoked while a stream is already running — which shouldn't happen in normal use (stream() calls cancel_stream() first, and the manager starts one background task per installation) — and no test exercises it. Arguably more correct (a programming-error guard shouldn't be swallowed by the stream's own handler, and it no longer clobbers a live stream's _stream_running flag), but calling it out since it's the one non-cosmetic change. Happy to use a # noqa: TRY301 instead if maintainers prefer to keep the old swallow-and-log behavior.

Verification

  • ruff check custom_components tests — passes (api.py now 0 errors)
  • ruff format --diff — clean
  • Test suite passes (offline subset; the two live-API fixture files are excluded per the known DNS/env gap)

Follow-up (separate PRs)

This is deliberately scoped to lint-only. I'd like to follow up with staged PRs to raise api.py to high-quality code:

  1. Offline unit tests for the core logic (retry/backoff, request status handling, state_to_attrs, is_command_valid, stream_update, hierarchy parsing) — currently the only api test requires live login.
  2. Type foundation — annotate instance attrs, parameterize bare generics, Mapping covariance, typed accessors to remove ZaptecBaseCharger/Installation downcasts.
  3. Typed API response models (TypedDict/pydantic) to eliminate the pervasive Any on API payloads.
  4. Correctness cleanups — the command() variable reuse + int(final_stop_active) guard, explicit kwargs for set_limit_current, instance-scoped debug flags.

Happy to split/reorder these however maintainers prefer.

🤖 Generated with Claude Code

Resolve all 36 ruff check errors (down from 36 to 0) in the vendored
Zaptec API client:

- Add missing return-type and argument annotations (ANN001/003/201/204/205)
- Replace mutable default arg for `excludes` with the None-default pattern (B006)
- Move the "stream already running" precondition raise out of the try (TRY301)
- Bind loop-captured log messages as an immutable default arg (B023)
- Reword a stale FIXME comment to NOTE (TD001/002/003, FIX001)
- Remove commented-out debug lines (ERA001)
- Drop redundant exception args from logging.exception calls (TRY401)
- Remove unnecessary AsyncGenerator None type arg (UP043)

Also fix two pre-existing latent type issues:
- Initialize operation_mode/final_stop_active so they are not possibly
  unbound in is_command_valid's debug log (reportPossiblyUnbound)
- Widen ZaptecBase.__contains__ key param to object for a compatible
  Mapping override (reportIncompatibleMethodOverride)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rhammen rhammen mentioned this pull request Jul 8, 2026
@sveinse sveinse added this to the v0.8.8 milestone Jul 8, 2026

@sveinse sveinse left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks great.

Comment thread custom_components/zaptec/zaptec/api.py
@sveinse
sveinse merged commit 7e90071 into custom-components:master Jul 9, 2026
7 checks passed
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