Skip to content

feat(exceptions): classify DimplexApiError as transient (5xx/429) or hard (4xx) - #125

Merged
KRoperUK merged 1 commit into
mainfrom
fix/122-apierror-transient
Oct 9, 2026
Merged

KRoperUK merged 1 commit into
mainfrom
fix/122-apierror-transient

Conversation

@KRoperUK

@KRoperUK KRoperUK commented Oct 9, 2026

Copy link
Copy Markdown
Owner

Summary

DimplexApiError carried only status and message, so once client.py exhausted its internal retries a caller couldn't tell an exhausted 5xx/429 (transient — back off and keep going) from a hard 4xx (surface it). DimplexAuthError already has this classification; API errors didn't. Closes #122.

Adds keyword-only transient (default False) and code to DimplexApiError, keeping the positional (status, message) signature so every existing call site is unchanged. The two raise sites in client.py set transient from _RETRYABLE_STATUS membership (429/5xx) — the same set that drives the retry loop, so the classification has a single source of truth in client.py rather than duplicating the status list in the exception.

Type of change

  • Bug fix
  • New feature (non-breaking change which adds functionality)
  • Breaking change
  • Documentation / chore

Checklist

  • ruff check + ruff format pass
  • mypy strict passes (9 source files, no # type: ignore)
  • pytest passes and new behaviour is covered (200 passed; 2 new tests assert 5xx→transient=True, 4xx→transient=False, verified to fail against pristine main with AttributeError)
  • README + docs/api-reference.md updated with the new attribute

Behaviour changes worth calling out

Additive only. DimplexApiError(status, message) still works unchanged; transient defaults to False. A consumer (e.g. the Home Assistant coordinator) can now check err.transient to back off on a retried-and-failed 5xx/429 instead of surfacing it like a hard 4xx.

DimplexApiError carried only status and message, so once client.py exhausted
its internal retries a caller could not tell an exhausted 5xx/429 (transient --
back off and keep going) from a hard 4xx (surface it). DimplexAuthError already
has this structure; API errors did not.

Add keyword-only transient (default False) and code to DimplexApiError, keeping
the positional (status, message) signature so existing call sites are
unchanged. The two raise sites in client.py set transient from
_RETRYABLE_STATUS membership (429/5xx), the same set that drives the retry loop,
so the classification has a single source of truth.

Documents the attribute in the README and api-reference. Closes #122
@KRoperUK
KRoperUK merged commit 7bbbb8a into main Oct 9, 2026
10 checks passed
@KRoperUK
KRoperUK deleted the fix/122-apierror-transient branch October 9, 2026 15:58
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.

DimplexApiError has no transient/reauth classification, so callers can't distinguish exhausted-5xx from a hard 4xx

1 participant