Skip to content

v2.0.1

Choose a tag to compare

@devinslick devinslick released this 04 Nov 23:05
· 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 FmdClient with an async factory (await FmdClient.create(...)) and async context manager (async with ...).
    • Clean session lifecycle management and connection pooling controls.
  • TLS/SSL
    • HTTPS-only base_url enforcement (rejects plain HTTP).
    • Configurable validation: ssl=False (dev only) or pass a custom ssl.SSLContext.
    • Certificate pinning example included in docs.
  • 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: ...
  • Transport requirements:
    • base_url must be HTTPS; plain HTTP raises ValueError.
  • Python versions:
    • Targets Python 3.8+ (3.7 removed from classifiers).

Migration guide

  • Replace FmdApi usage with the async FmdClient:
    • Use await FmdClient.create(...) and async with for safe resource management.
    • Update all calls to await the async methods.
  • 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.
  • Connection tuning:
    • Optional: conn_limit, conn_limit_per_host, keepalive_timeout on the TCPConnector via client init.

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 FmdApiException where appropriate; messages mask sensitive data.

Documentation and examples

  • README: TLS/self-signed guidance, warnings, and certificate pinning example.
  • Debugging: pin_cert_example.py demonstrates 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=False sparingly and never in production.
  • Consider adding Dependabot and security scanning in a follow-up.
  • A CHANGELOG.md entry 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.