Repository navigation
Stores built from a storage, and resolutions that apply themselves - #41
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Documentation build overview
28 files changed ·
|
There was a problem hiding this comment.
🟡 Changes recommended
The changes can destroy saved state when the destination already ends in .new and allow post-construction mapping mutations to bypass validation, accepting invalid incremental entries and advancing the scope token.
2 open issues
What changed in this PR
Refactors storage and conflict handling to support new backends without subclass hooks and move resolution behavior out of Replica, addressing #39 and #40.
Changes:
- Introduces public storage interfaces and optional
MemoryKeeperpersistence. - Moves resolution and push-outcome behavior into their value classes and returns detailed conflict-resolution results.
- Updates validation, transaction error handling, tests, examples, and documentation.
| File | Description |
|---|---|
src/calendaring_sync/tests/test_sync_unit.py |
Updates interface tests and adds failure-path coverage. |
src/calendaring_sync/tests/conftest.py |
Adds a custom-storage test fixture. |
src/calendaring_sync/tests/_storage.py |
Adds a minimal storage implementation for tests. |
src/calendaring_sync/store/sqlite.py |
Separates SQLite storage and transaction operations. |
src/calendaring_sync/store/memory.py |
Adds memory storage transactions and keeper persistence. |
src/calendaring_sync/store/base.py |
Defines storage interfaces and centralizes store safeguards. |
src/calendaring_sync/store/__init__.py |
Updates the package description. |
src/calendaring_sync/session.py |
Delegates push-outcome validation. |
src/calendaring_sync/replica.py |
Delegates effects and reports conflict-resolution results. |
src/calendaring_sync/objects/resolution.py |
Implements resolution behavior and result fields. |
src/calendaring_sync/objects/record.py |
Clarifies copy terminology in documentation. |
src/calendaring_sync/objects/push.py |
Implements push-outcome checks and effects. |
src/calendaring_sync/objects/feed.py |
Clarifies a feed-entry comment. |
src/calendaring_sync/objects/edit.py |
Updates synced-copy terminology. |
src/calendaring_sync/objects/conflict.py |
Clarifies conflict documentation. |
src/calendaring_sync/objects/change_set.py |
Validates incremental entries during construction. |
src/calendaring_sync/objects/_data.py |
Updates shared-field comments. |
src/calendaring_sync/error.py |
Clarifies stale-conflict documentation. |
src/calendaring_sync/adapters/base.py |
Explains underscored adapter hooks. |
src/calendaring_sync/_classify.py |
Updates classifier documentation terminology. |
src/calendaring_sync/__init__.py |
Exports new storage and result types. |
news/9.feature.rst |
Documents detailed conflict-resolution results. |
news/40.feature.rst |
Announces storage composition. |
news/28.feature.rst |
Documents keeper-based persistence. |
docs/reference/store.rst |
Documents the new public storage interfaces. |
docs/reference/guarantees.rst |
Updates the concurrent-read capability reference. |
docs/reference/glossary.rst |
Defines storage and copy terminology. |
docs/how-to/store.rst |
Explains keepers and custom storage. |
docs/how-to/mirror.rst |
Clarifies mirrored-copy terminology. |
docs/how-to/conflicts.rst |
Explains conflict-resolution results. |
docs/explanation/design.rst |
Updates storage architecture and conflict terminology. |
docs/examples/keeper.py |
Adds a file-backed keeper example. |
docs/contribute.rst |
Updates the storage module description. |
docs/conf.py |
Hides private bases in generated documentation. |
Review effort: Balanced
| for object_id, change in change_set.changes.items(): | ||
| if not change_set.full_listing and isinstance(change, Unchanged): | ||
| raise ValueError(f"Unchanged object {object_id!r} outside a full listing") | ||
| self._apply(scope.id, object_id, change, now, claimed, freed) |
There was a problem hiding this comment.
Fixed in b41eae6 differently: ChangeSet now keeps its own read-only copy, so later changes to the mapping never reach it.
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

Closes #39.
Closes #40.
From @niccokunzmann's reviews of #29 and #30, done before the release so nothing needs a deprecation later.
A store is a
StateStoreover aStoragenow. A new storage implementsStorageandStorageTransaction, both with public names, and gets every check from the store. AMemoryKeeperreplaces subclassingMemoryStoreto keep its data in a file.Resolutions and push outcomes decide their own effect, so the replica has no
matchon them anymore. Nothing public changed, and no test either.Also the three fixes I promised in the threads, and
resolve_conflictsreturns the conflicts it resolved, left open or found changed, instead of a count.Fixed: a failed rollback replaced the block's own error, so Ctrl-C came out as
UnexpectedStoreError.The adapter hooks keep their underscores: the app calls
sync()on the adapter, and a publicread()orsend()next to it would skip the session.