Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [2.0.8] - 2025-02-01

### Added
- `decrypt_data_blob_async()` method for non-blocking decryption in async contexts
- Exported `Location`, `PhotoResult`, and `RateLimitError` from package root
- `CHANGELOG.md` following Keep a Changelog format
- Comprehensive exception documentation (Raises sections) for all public API methods

### Changed
- Improved lock message sanitization to re-collapse whitespace after removing special characters
- Simplified `get_history()` signature by removing unused `start`/`end` parameters
- Improved docstrings for helpers.py functions

### Removed
- Dead code: `_parse_location_blob()` function that was never called
- Placeholder comment from helpers.py

### Fixed
- Lock messages containing only special characters now correctly fall back to plain "lock" command

## [2.0.7] - 2025-01-15

### Changed
- Cleanup release to trigger new PyPI deployment
- No functional changes from 2.0.6

## [2.0.6] - 2025-01-10

### Added
- 100% test coverage achieved

### Changed
- Full type safety with strict mypy checks
- Improved method signatures with precise return types

## [2.0.5] - 2025-01-08

### Added
- Strict typing enforcement (Phase 1)
- Comprehensive edge case tests for `Location` parsing
- `docs/strict_typing_enforcement_plan.md` roadmap

### Changed
- Updated community instance URL to https://server.fmd-foss.org/

## [2.0.4] - 2024-11-09

### Added
- Password-free authentication via `export_auth_artifacts()` and `from_auth_artifacts()`
- `drop_password=True` option to discard raw password after onboarding
- `Device.get_picture_blobs()` and `Device.decode_picture()` methods
- `Device.lock(message=...)` with sanitization (quotes, backticks, semicolons removed)
- Wipe PIN validation (alphanumeric ASCII only, no spaces)
- PNG detection via magic bytes in `export_data_zip()`

### Changed
- 401 handling now supports hash-based token refresh
- Private key loading supports both PEM and DER formats
- Test coverage increased to ~98%

### Deprecated
- `Device.take_front_photo()` - use `take_front_picture()`
- `Device.take_rear_photo()` - use `take_rear_picture()`
- `Device.fetch_pictures()` - use `get_picture_blobs()`
- `Device.download_photo()` - use `decode_picture()`

## [2.0.0] - 2024-10-01

### Added
- Async client with `FmdClient.create()` factory method
- Async context manager support (`async with`)
- HTTPS enforcement (plain HTTP rejected)
- Configurable SSL validation (`ssl=False` for dev, custom `SSLContext` for production)
- Request timeouts on all HTTP calls
- Retry logic with exponential backoff and jitter for 5xx errors
- 429 rate-limit handling with Retry-After support
- Client-side ZIP export (locations + pictures)
- `Device` helper class for convenience actions
- `py.typed` marker for PEP 561 compliance
- GitHub Actions CI (lint, type-check, tests, coverage)
- Codecov integration with badges

### Changed
- Complete rewrite from sync to async API
- Python 3.8+ required (3.7 dropped)

### Removed
- Legacy synchronous `FmdApi` class

### Security
- Sanitized logging (no sensitive payloads exposed)
- Token masking in debug output

## [1.x] - Legacy

Previous synchronous implementation. See git history for details.

[Unreleased]: https://github.com/devinslick/fmd_api/compare/v2.0.8...HEAD
[2.0.8]: https://github.com/devinslick/fmd_api/compare/v2.0.7...v2.0.8
[2.0.7]: https://github.com/devinslick/fmd_api/compare/v2.0.6...v2.0.7
[2.0.6]: https://github.com/devinslick/fmd_api/compare/v2.0.5...v2.0.6
[2.0.5]: https://github.com/devinslick/fmd_api/compare/v2.0.4...v2.0.5
[2.0.4]: https://github.com/devinslick/fmd_api/compare/v2.0.0...v2.0.4
[2.0.0]: https://github.com/devinslick/fmd_api/releases/tag/v2.0.0
51 changes: 31 additions & 20 deletions docs/HOME_ASSISTANT_REVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,10 @@ async def decrypt_data_blob_async(self, data_b64: str) -> bytes:

**HA Rationale:** Event loop blocking causes UI freezes and integration performance issues.

**Status:** ❌ TODO
**Status:** ✅ FIXED
- Added `decrypt_data_blob_async()` method that uses `run_in_executor()`
- Added test coverage for the async method
- Documented the sync vs async usage in docstrings

---

Expand Down Expand Up @@ -350,7 +353,9 @@ async def decrypt_data_blob_async(self, data_b64: str) -> bytes:

**HA Rationale:** Good practice for library maintenance and user communication.

**Status:** ❌ TODO
**Status:** ✅ FIXED
- Added `CHANGELOG.md` following Keep a Changelog format
- Documents all releases from 2.0.0 to current

---

Expand All @@ -375,7 +380,9 @@ async def get_locations(...) -> List[str]:

**HA Rationale:** Users need to know how to handle errors properly.

**Status:** ❌ TODO
**Status:** ✅ FIXED
- Added Raises sections to all public API methods in client.py
- Documented ValueError, FmdApiException, aiohttp.ClientError, asyncio.TimeoutError

---

Expand All @@ -391,7 +398,10 @@ async def get_locations(...) -> List[str]:

**HA Rationale:** Demonstrates code quality and test thoroughness.

**Status:** ❌ TODO
**Status:** ✅ FIXED
- Coverage reporting implemented with pytest-cov
- 100% branch coverage achieved
- Codecov badge added to README

---

Expand All @@ -413,7 +423,8 @@ __all__ = [

**HA Rationale:** Makes API more discoverable and IDE-friendly.

**Status:** ❌ TODO
**Status:** ✅ FIXED
- Added `Location`, `PhotoResult`, and `RateLimitError` to `__all__` exports

---

Expand Down Expand Up @@ -502,14 +513,14 @@ def __init__(self, ..., ssl_context: Optional[ssl.SSLContext] = None):
- Improve type hints
- Add retry logic — DONE
- Configure connection pooling — DONE
- Make decryption async
- Make decryption async — DONE

**For Best Practices (Minor):**
- Add CI badges — PARTIAL (Added Tests + Codecov badges; PyPI/version badges pending)
- Create CHANGELOG.md
- Document exceptions
- Add test coverage reporting
- Export all public models
- Create CHANGELOG.md — DONE
- Document exceptions — DONE
- Add test coverage reporting — DONE (100% branch coverage)
- Export all public models — DONE
Comment on lines 507 to +523
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

This section marks "Add test coverage reporting" as DONE (100% branch coverage), but earlier in the same document (section 18: "No Test Coverage Reporting") the status is still listed as ❌ TODO. To avoid confusion when tracking Home Assistant review items, it would be good to update the earlier section's status or clarify the distinction (e.g., measurement vs. badges) so the checklist is internally consistent.

Copilot uses AI. Check for mistakes.

---

Expand Down Expand Up @@ -566,16 +577,16 @@ def __init__(self, ..., ssl_context: Optional[ssl.SSLContext] = None):

Before submitting to Home Assistant:

- [ ] All critical issues resolved
- [ ] Major security concerns addressed
- [ ] Type hints complete and accurate
- [ ] Documentation comprehensive
- [ ] Test coverage > 80%
- [ ] CHANGELOG.md up to date
- [ ] Stable version released to PyPI
- [ ] Code passes `flake8` and `mypy`
- [ ] CI runs tests on all supported Python versions
- [ ] CI enforces linting and type checking
- [x] All critical issues resolved
- [x] Major security concerns addressed
- [x] Type hints complete and accurate
- [x] Documentation comprehensive
- [x] Test coverage > 80% (Currently at 100%)
- [x] CHANGELOG.md up to date
- [x] Stable version released to PyPI
- [x] Code passes `flake8` and `mypy`
- [x] CI runs tests on all supported Python versions
- [x] CI enforces linting and type checking

---

Expand Down
6 changes: 5 additions & 1 deletion fmd_api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# fmd_api package exports
from .client import FmdClient
from .device import Device
from .exceptions import FmdApiException, AuthenticationError, DeviceNotFoundError, OperationError
from .models import Location, PhotoResult
from .exceptions import FmdApiException, AuthenticationError, DeviceNotFoundError, OperationError, RateLimitError
from ._version import __version__

__all__ = [
"FmdClient",
"Device",
"Location",
"PhotoResult",
"FmdApiException",
"AuthenticationError",
"DeviceNotFoundError",
"OperationError",
"RateLimitError",
"__version__",
]
2 changes: 1 addition & 1 deletion fmd_api/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "2.0.7"
__version__ = "2.0.8"
Loading
Loading