v2.0.1
·
47 commits
to main
since this release
Immutable
release. Only release title and notes can be modified.
Summary
This major release delivers a production-ready async client with robust TLS handling, resilient request logic (timeouts, retries, rate limits), and a fully wired CI pipeline (lint, type-check, tests, coverage). It replaces the legacy synchronous v1 client and prepares the project for Home Assistant and broader integration.
Highlights
- Async client
- New
FmdClientwith an async factory (await FmdClient.create(...)) and async context manager (async with ...). - Clean session lifecycle management and connection pooling controls.
- New
- TLS/SSL
- HTTPS-only
base_urlenforcement (rejects plain HTTP). - Configurable validation:
ssl=False(dev only) or pass a customssl.SSLContext. - Certificate pinning example included in docs.
- HTTPS-only
- Reliability
- Timeouts applied across all HTTP requests.
- Retries with exponential backoff and optional jitter for 5xx and connection errors.
- 429 rate-limit handling with Retry-After support.
- Safe behavior for command POSTs (no unsafe retries).
- Features
- Client-side export to ZIP (locations + pictures).
- Device helper with convenience actions (e.g., request location, play sound, take picture).
- Safety and ergonomics
- Sanitized logging (no sensitive payloads); token masking helper.
- Typed package (
py.typed) and mypy-clean.
- CI/CD
- GitHub Actions: lint (flake8), type-check (mypy), unit tests matrix (Ubuntu/Windows; Py 3.8–3.12).
- Coverage with branch analysis and Codecov upload + badges.
- Publish workflows for TestPyPI (non-main) and PyPI (main or Release).
Breaking changes
- API surface moved to async:
- Before (v1, sync):
client = FmdApi(...); client.authenticate(...); client.get_all_locations() - Now (v2, async):
client = await FmdClient.create(base_url, fmd_id, password, ...)await client.get_locations(...),await client.get_pictures(...),await client.send_command(...)- Prefer:
async with FmdClient.create(...) as client: ...
- Before (v1, sync):
- Transport requirements:
base_urlmust be HTTPS; plain HTTP raisesValueError.
- Python versions:
- Targets Python 3.8+ (3.7 removed from classifiers).
Migration guide
- Replace
FmdApiusage with the asyncFmdClient:- Use
await FmdClient.create(...)andasync withfor safe resource management. - Update all calls to await the async methods.
- Use
- TLS and self-signed setups:
- For dev-only scenarios: pass
ssl=False. - For proper self-signed use: pass a custom
ssl.SSLContext. - For high-security setups: consider the certificate pinning example in README.
- For dev-only scenarios: pass
- Connection tuning:
- Optional:
conn_limit,conn_limit_per_host,keepalive_timeouton the TCPConnector via client init.
- Optional:
Error handling and semantics
- 401 triggers one automatic re-authenticate then retries the request.
- 429 honors Retry-After, otherwise uses exponential backoff with jitter.
- Transient 5xx/connection errors are retried (except unsafe command POST replays).
- Exceptions are normalized to
FmdApiExceptionwhere appropriate; messages mask sensitive data.
Documentation and examples
- README: TLS/self-signed guidance, warnings, and certificate pinning example.
- Debugging:
pin_cert_example.pydemonstrates secure pinning and avoids CLI secrets.
CI/CD and release automation
- Tests: unit suite expanded; functional tests run when credentials are available.
- Coverage: ~83% overall; XML + branch coverage uploaded to Codecov (badges included).
- Workflows:
test.yml: runs on push/PR for all branches (lint, mypy, unit tests matrix, coverage, optional functional tests).publish.yml: builds on push/releases; publishes to TestPyPI for non-main pushes, PyPI on main or release.
Checklist
- All unit tests pass
- Flake8 clean
- Mypy clean
- Coverage collected and uploaded
- README/docs updated (TLS, pinning, badges)
- Packaging: sdist and wheel built; publish workflows configured
Notes
- Use
ssl=Falsesparingly and never in production. - Consider adding Dependabot and security scanning in a follow-up.
- A
CHANGELOG.mdentry for 2.0.0 is recommended if not already included.
BREAKING CHANGE: v2 switches to an async client, enforces HTTPS, and drops Python 3.7; synchronous v1 usage must be migrated as noted above.