Repository navigation
Fix the review issues 14 to 23 - #24
Merged
Merged
Conversation
An emulated move() wrote the copy before the etag check, so a stale item left a copy at the target on every retry. It now checks the etag first, and removes the copy if the delete still loses a race. An emulated sync token named only the collection id, so another account's "default" accepted it; it is now bound to the backend too. Fixes #23 Fixes #20 Prompt: work on the new issues [the ten issues filed on 2026-10-20, #14 to /23] Assisted-By: Claude Opus 5.5 (1M context) Reviewed-by: Tobias Brox <tobias@redpill-linpro.com>
On a borrowed collection, tidy_up deleted everything added during the test, including other clients' items, and test_set_name left the collection renamed. The suite now notes what it creates there and deletes only that, and puts the name back. Where collections can be made but not deleted, it reuses those an earlier run left instead of leaving one full collection per test. Fixes #18 Fixes #19 Prompt: work on the new issues [the ten issues filed on 2026-10-20, #14 to /23] Assisted-By: Claude Opus 5.5 (1M context) Reviewed-by: Tobias Brox <tobias@redpill-linpro.com>
No conformance test listed more than seven objects, so a backend that read only the first page of a paged API passed, and then reported the rest as deleted. A new test stores page_size_hint objects (120) and checks search(), iter_search(), get() of the last one and changes(). The memory store caches each object's UID, as every add compared it with every stored object's. Fixes #16 Prompt: work on the new issues [the ten issues filed on 2026-10-20, #14 to /23] Assisted-By: Claude Opus 5.5 (1M context) Reviewed-by: Tobias Brox <tobias@redpill-linpro.com>
test_collection_never_widens_backend never reached its assertion: no profile declared a collection feature at backend level. The feed profile now declares write unsupported for the whole backend, and a test shows that a wider collection fails it. test_changes_full_listing picked its item kind from a frozenset, so the kind depended on PYTHONHASHSEED; it now follows KINDS. Refs #21 Refs #17 Prompt: work on the new issues [the ten issues filed on 2026-10-20, #14 to /23] Assisted-By: Claude Opus 5.5 (1M context) Reviewed-by: Tobias Brox <tobias@redpill-linpro.com>
A stored object that did not parse, or that icalendar-searcher could not match (an RDATE series with an override, before its next release), made search(), get() and changes() raise for the whole collection. Listing primitives now return a BrokenObject for it, and the read raises PartialResultError carrying the results from the rest and the objects left out, with their bytes for repair. Workspace.search() keeps the partial results. Fixes #14 Fixes #22 Prompt: work on the new issues [the ten issues filed on 2026-10-20, #14 to /23] Followup-Prompt: (asked whether a read should warn and skip, raise with partial results, or only guard the searcher error) Raise, partial results Assisted-By: Claude Opus 5.5 (1M context) Reviewed-by: Tobias Brox <tobias@redpill-linpro.com>
Backends that broke a clause of API_DESIGN passed the whole suite. New tests cover changes() across a move, a listing after a save made elsewhere, iter_search() field by field, get() of an exact UID in this collection only, UIDs kept on every add path, text filters, and the read paths of a read-only backend (with a new unseed() hook). Each comes with a broken memory backend that the suite must catch. Fixes #17 Prompt: work on the new issues [the ten issues filed on 2026-10-20, #14 to /23] Followup-Prompt: (asked whether to do the larger conformance issues now) Do them now Assisted-By: Claude Opus 5.5 (1M context) Reviewed-by: Tobias Brox <tobias@redpill-linpro.com>
Backends that lost alarms, time zones, dates, text or recurrence exceptions passed the conformance suite. It now stores a corpus of real-world objects with verify=True, searches tasks and events by range, and checks what safe completion of a recurring task writes. The new features alarms, timezones and dates give a backend that cannot keep them an honest declaration, with the losses planned for it. recurrence now covers EXDATE, and drops a series' overrides along with its RRULE. Fixes #15 Refs #21 Prompt: work on the new issues [the ten issues filed on 2026-10-20, #14 to /23] Followup-Prompt: (asked whether to do the larger conformance issues now) Do them now Assisted-By: Claude Opus 5.5 (1M context) Reviewed-by: Tobias Brox <tobias@redpill-linpro.com>
Branch coverage showed conformance branches no memory profile ran. Three test profiles (events only, tasks without a status, a feed of tasks) reach them, and found three suite bugs: a task-only native-id test, complete() without a status, and an unprobed create-collection. CI now fails below 95% branch coverage of the suite. Fixes #21 Prompt: work on the new issues [the ten issues filed on 2026-10-20, #14 to /23] Followup-Prompt: (asked whether to do the larger conformance issues now) Do them now Assisted-By: Claude Opus 5.5 (1M context) Reviewed-by: Tobias Brox <tobias@redpill-linpro.com>
tobixen
added a commit
that referenced
this pull request
Oct 22, 2026
Rebased onto #24, which changed what the listing primitives return and added three features. An object that does not parse now comes back from _query, _fetch_many and the sync report as a BrokenObject carrying the server's bytes. caldav still parses every object when it filters the results itself, and fails on the first that does not parse (python-caldav/caldav#815). It filters every search with a time range, every search on a server without case-sensitive text search (Radicale, CCS, Zimbra, SOGo, GMX, OX), and every UID lookup, so there one bad object still fails the call. The tests for that are marked as expected failures until caldav is fixed. timezones follows caldav's save-load.event.timezone hint; alarms and dates are FULL on a server caldav has hints for and UNKNOWN on another, like everything else the server has to store. Prompt: [merge the PRs] Followup-Prompt: "calendaring has worked around this for now by passing `post_filter=False` and filtering on its own side" - don't do that. just accept that there is a bug until it has been fixed upstream. [quoting the draft of python-caldav/caldav#815] Assisted-By: Claude Opus 5.5 (1M context) Reviewed-by: Tobias Brox <tobias@redpill-linpro.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Disclaimer: Code and the text below the line are AI-generated, by Claude Opus 5.5, from the prompts:
Fixes the ten issues from the review of PR 8 and PR 9.
move()checks the etag before copying, and removes the copy if the delete then fails on a stale etag (Emulated move() checks the etag only after copying; each retry leaves another stale copy #23). An emulated sync token is now tied to the backend as well as the collection id (Emulated change feed accepts a sync token from another backend's collection with the same id #20).BrokenObjectinstead of raising. A read that left something out raisesPartialResultError, carrying what it could read and the raw bytes of the rest;Workspace.search()keeps the partial results. A broken object is never reported as deleted.verify=True, which needed three new §5.1 features,alarms,timezonesanddates(Conformance suite passes backends that lose alarms, time zones, all-day dates, non-ASCII text and recurrence exceptions #15);Every new suite test has a broken memory backend that it must catch.
To know before merging:
alarms,timezonesanddates, and should returnBrokenObjectfrom_query. Expect the new suite tests to fail against it at first.recurrence.edit-occurrence,recurrence.edit-this-and-futureandtask.complete-recurringare still not run (Q3).🤖 Generated with Claude Code