chore(deps): Update dependency caldav to v3#4
Open
renovate[bot] wants to merge 1 commit into
Open
Conversation
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.
This PR contains the following updates:
>=1.3,<2→>=3.2,<4Release Notes
python-caldav/caldav (caldav)
v3.2.1Compare Source
The changeset in 3.2.1 is predominently added async integration tests. Those tests should now be replicating all the logic in the good old sync integration tests under
test_caldav.py. Some few more bugs were found while adding those tests.There are two "feature commits" adding new parameters to existing functions. Those are minor additions and was required while fixing things (test breakage plus observed crash due to weird real-world-data), hence I define this to be a patch-release rather than a minor-release.
Added
Calendar.delete()has had a "wipe-mode" since v2.2.0, deleting items from the calendar if it's not possible to delete the calendar itself. Now a tristatewipeparameter has been added,wipe=Trueto wipe rather than delete the calendar,wipe=Falseto not wipe, and default behaviour (wipe=None) is still "wipe if needed". (Useful for NextCloud tests, where events stuck on calendars in the "trashbin" pollutes the namespace preventing the same event to be added to a new calendar).save()only_this_recurrenceparameter is now a tristate:True(default) - unchanged, if the object is a recurrence it will be merged with the master event, making sure the saved recurrence is stored as an exception to the RRULE. If the master object does not exist, then it will raiseNotFoundError.None(new) - same as True, except that if the master object does not exist, the recurrence will just be sent directly to the server as-is.False- unchanged, the recurrence will be sent directly to the server as-is.Noneis used in theadd_object(). This change was needed to avoid a crash when trying to add a recurrence-object without a master to the server. (So much ado for a very weird edge case).Fixed
HTTPDigestAuth.handle_401()callsr.connection.send()which returns a coroutine in async context, causingAttributeError: 'coroutine' object has no attribute 'history'. Fixed by usingAsyncHTTPDigestAuthfor the async client. See jawah/niquests#387Calendar.freebusy_request()was not async-aware._async_complete()raisedNotImplementedErrorforhandle_rrule=True._async_put()did notawaitthe retry coroutine returned by_post_put()._async_get_object_by_uid()was missinginclude_completed=True, unlike the sync version._async_search_with_comptypes()did not skip component types unsupported by the server, unlike the sync version.DisplayNameis now omitted from theMKCALENDARrequest body whencreate-calendar.set-displaynameis unsupported.Changed
niquests(preferred) →httpxyz→httpx. See #611Test framework
These changes are not part of the shipped library, but make up the bulk of the 3.2.1 changeset.
Async tests
tests/test_async_integration.pygrew by ~1700 lines) to mirror the sync suite intest_caldav.py. Part ofgit bug bug show e44ee06aka #667testCheckCompatibilityno longer takes ~8 minutes on servers with a search-cache delay (e.g. Bedework) — two bugs causing repeated cache-delay waits were fixed, and some redundant Bedework compatibility-matrix entries were cleaned up.test_caldav.py,test_caldav_unit.py).tests/test_servers/: registered Baikal'sURL_ENV_VARso the async-httpx CI job can reach it, and added aget_available_servers()helper used by the async integration tests.Docker test servers
Emulate Docker CLI using podmanbanner string.uid=…,gid=…tmpfs mount options that Podman does not support (CCS / CalendarServer runs as root inside the container, so the ownership hint wasn't needed).testuser@example.org), weak passwords are rejected, and a workaround was added for Stalwart advertisinghttps://even when reached overhttp://in local dev.mailto:email addresses for the scheduling test users (so iTIP delivery works), and disabled the CalDAV trashbin (calendarRetentionObligation=0) so HTTPDELETEhard-deletes objects and re-using a UID doesn't hit aUNIQUEconstraint violation.imapd.confwithvirtdomains: off(the defaultvirtdomains: useridcaused 403s on iTIP delivery due to userid/ACL mismatch), unpinned from the March 2026 digest now that:latestis stable again, and pointed the health-check at the CalDAV port.GitHub CI
async (niquests fallback)job toasync (niquests)to reflect that niquests is the default install, not a fallback.async (niquests),async (httpxyz fallback)andasync (httpx fallback).scheme://hostname:portinstead of silently rewriting them, which the 30-day cache had been masking — placeholder URLs were replaced with concrete examples (http://proxy.example.com:8080) indavclient.pyandasync_davclient.py, and.lycheeignorewas updated accordingly.v3.2.0Compare Source
The two most significant news in v3.2 are relatively well-tested support for scheduling (RFC6638) and better-tested support for async. Care should still be taken, those features are backed by many tests, but lacks testing for how well they support real-world use-case scenarios. While async support was added in version 3.0, it was not well-enough tested. Still only a fraction of all the integration tests for sync usage has been duplicated in the async integration test, I expect to release 3.2.1 with symmetric async integration tests before 2025-07.
Added
add_organizer()now accepts an optional explicit organizer argument (aPrincipal,vCalAddress, or email string)If-Schedule-Tag-MatchorIf-Matchheaders will be sent. AScheduleTagMismatchErrororEtagMismatchErrorwill be raised on 412.Changed
save()then insertsSEQUENCE:1unless theincrease_seqnoparameter is set to False.Fixed
search()-results - #650_resolve_properties()would crash for some disbehaving servers. pycalendar/calendar-cli#114Calendar.get_supported_components()would crash for some servers. #653accept_invite(),decline_invite()andtentatively_accept_invite()when the server does not expose thecalendar-user-address-setproperty. #399get_object_by_uid(), aligning it with the rest of the search API. Closes #586AI transparency
I've been experimenting with Claude Code over the last few months, concerns have been raised that it may have negatively affected code quality - and indeed, this is probably a major reason why the async support in v3.0 was simply not good enough. I've been working a bit more on the AI-POLICY.md, some of the directions for the future looks like this:
The 3.2-release may not be fully up to those standards, as they were made while working on 3.2.
The branch v3.2-development contains "raw" commits, most of the commits are either AI-written (including commit message) or human-written. I've done quite some work trying to squash the commits into fewer commits, in the main branch all the recent commit messages are handwritten, and most of the commits have some notes on how much is AI-generated and why AI-generation was chosen. The manual walk-through of all the commits has been tedious, but useful for QA-purposes. I'm considering this to be the way forward.
I have all relatively fresh communication with Claude in JSON-files, and I was considering to embed them into the repository for increased transparency. Everything considered, I think it would involve too much noise, so I've skipped it as for now. If you want it, I will publish it.
Housekeeping and documentation
copy,lxml.etree,CalendarSet,cdav/davre-exports,Optional,timezone,Event/Todotype stubs), replaced bareexcept:clauses with specific exception types (KeyError,AttributeError,Exceptionwhere broad catching is intentional), and removed unused local variables.funding.json(https://fundingjson.org/) at the repository root. Closes #608Test framework, compatibility hints, documentation, examples
_AsyncTestSchedulingBaseadded: async counterpart of_TestSchedulingBasewithtest_invite_and_respondandtest_freebusy;TestAsyncSchedulingFor<Server>classes generated for each server withscheduling_usersconfigured.Breaking changes
scheduling.freebusy, rfc4791-freebusy have been collapsed down intofreebusy(instead offreebusy.rfc4791).search.text.by-uidwas removed, there is (probably?) no servers supporting one but not the other. (Though the checks on this may be wrong, as workarounds are automatically employed for servers not supporting text search). #586v3.1.0Compare Source
Highlights:
get_calendars(): a singleget_calendars()call can now span multiple config-file sections (including glob/wildcard expansion), aggregating calendars from multiple servers into oneCalendarCollection. This was the idea (and has been implemented in myplannproject for quite some time), but fell short of getting into the v3.0-release.Added
get_icalendar_component()returns a deep-copy of the inner VEVENT/VTODO/VJOURNAL sub-component for read-only inspection, consistent with theget_icalendar_instance()naming convention.edit_icalendar_component()context manager yields the inner component for editing and delegates toedit_icalendar_instance()so all borrow/state/save machinery is reused.get_calendars()now accepts aconfig_sectionvalue that is expanded viaexpand_config_section(), so wildcards like"work_*"or"all"resolve to multiple leaf sections; each section gets its ownDAVClientand all calendars are aggregated into aCalendarCollection.CalendarCollectionnow closes all its clients on context-manager exit.get_all_file_connection_params(config_file, section).PYTHON_CALDAV_USE_TEST_SERVER=1(ortestconfig=True) falls back to automatically starting the first available enabled server from the test-server registry when notesting_allowedconfig section is present. Three new env vars (PYTHON_CALDAV_TEST_EMBEDDED,PYTHON_CALDAV_TEST_DOCKER,PYTHON_CALDAV_TEST_EXTERNAL) control which server categories are eligible. Per-serverpriority:keys in config files are honoured.caldav/testing.py(shipped with the package):EmbeddedServer,XandikosServer,RadicaleServer— so pip-installed users can usePYTHON_CALDAV_USE_TEST_SERVER=1without a source checkout.Fixed
get_object_by_uid()(andget_event_by_uid(),get_todo_by_uid(),get_journal_by_uid(), and their deprecated aliases) raisedTypeErrorwith async clients becausesearch()returned a coroutine that was iterated directly. Fixes #642complete()and the save()-recurrence path were not awaited for async clients.uncomplete(),set_relation(),get_relatives(), andinvite()lacked async dispatch._handle_reverse_relations()calledget_relatives()withoutawait, silently returning a coroutine.get_calendar()andget_calendars()were missing from thecaldav.aiore-export.get_calendars(config_section=…)silently ignoredcalendar_nameandcalendar_urlkeys in config sections — they were stripped before reaching the filter logic.expand_config_section()was not called when reading the config file, socontains:-style meta-sections had no effect.dateobjects passed tocalendar.search()orcalendar.searcher()as time-range boundaries now get coerced to UTCdatetimebefore being forwarded toicalendar_searcher, silencing the "Date-range searches not well supported yet" warning.XandikosServer.is_accessible()now sends a minimalPROPFINDrequesting only{DAV:}resourcetypeinstead of an implicitallprop, avoiding spuriousNotImplementedErrorlog lines from Xandikos during test-server startup.Tests and documentation
docs/source/async_tutorial.rst. Covers the same ground as the sync tutorial plus a "Parallel Operations" section demonstratingasyncio.gather(). The sync tutorial now links to it.docs/source/configfile.rsthas been rewritten and extended; tests forinheritsand env-var expansion added.docs/source/tutorial.rstrewritten and fixed.docs/source/.v3.0.2Compare Source
Highlight: Reintroducing debug communication dump functionality.
Fixed
PYTHON_CALDAV_COMMDUMPis given, caldav communication is dumped to /tmp - details in #248 . This is regarded as "fix" rather than "feature" as it was introduced in v1.4.0 and accidentally dropped during the v3.0 refactoring. Restored, with the dump logic extracted into a shared helper so both the sync and async code paths benefit. Test code added to make sure it won't disappear again. Fixes #638search()raisedNotImplementedErrorwhen a full calendar-query XML was passed and the server does not supportsearch.comp-type.optional. This is a really rare and deprecated code path, but stillNotImplementedErrorisn't good. Now it falls back to a single REPORT with the XML as-is. Fixes #637Tests and documentation
v3.0.1Compare Source
Highlights:
Test runs before release
Added
tests/docker-test-servers/ox/. However, OX is undertested as both the caldav-server-checker and the test suite does not play well with OX (events with historic DTSTART etc are used, OX doesn't support that).search.unlimited-time-rangefeature flag with a workaround insearch.pythat injects a broad time range (1970–2126) for servers that return an empty result set when no time range is specified (but this still doesn't help to OX).Fixed
AsyncDAVClientfailed to initialize when using httpx < 0.23.0 becauseproxy=Nonewas unconditionally passed tohttpx.AsyncClientwhich did not accept aproxykeyword argument in older releases. Fixes #632"Deviation from expectations found"log error in production, or an assertion failure in debug mode.Security
Potentially Breaking Changes
search.comp-type-optionalhas been renamed tosearch.comp-type.optionalfor consistency with the dotted-key naming convention used elsewhere. If you have this key set in a local server configuration, update it accordingly.Documentation
Some minor improvements, including a fix for #635 - use canonical RFC-links.
v3.0.0Compare Source
Version 3.0 should be fully backward-compatible with version 2.x - but there are massive code changes in version 3.0, so if you're using the Python CalDAV client library in some sharp production environment, I would recommend to wait for two months before upgrading.
Highlights
AsyncDAVClientand async domain objects using a Sans-I/O architecture. The sameCalendar,Event,Todo, etc. objects work with both sync and async clients.caldav.jmappackage withJMAPClientandAsyncJMAPClientfor servers implementing RFC 8620 (JMAP Core) and RFC 8984 (JMAP Calendars). Note that this is experimental, and the public API may be changed in upcoming minor-releases.Test runs before release
The tests broke with lots of AuthorizationErrors with GMX. The tests were running successfully towards GMX before releasing the last alpha-release. It's probably a transient issue. I don't want to delay the release by doing more research into it.
Breaking Changes
Be aware that some of the 2.x minor-versions also tagged some "Potentially Breaking Changes" - so if you're upgrading i.e. from 2.1, you may want to browse through the "Potentially Breaking Changes" for the intermediate minor releases too.
tests/conf.pyhas been removed andconf_private.pywill be ignored. See the Test Framework section below.caldav/objects.pyremoved -- the backward-compatibility re-export shim has been deleted. Any code doingfrom caldav.objects import <something>must be updated; all public symbols remain available directly viacaldavor from their respective submodules.caldav.config.read_config()now raisesValueErroron YAML/JSON parse errors instead of logging and returning an empty dict. This ensures config errors are detected early.Deprecated
The following have been deprecated and emit
DeprecationWarning:calendar.date_search()- usecalendar.search()insteadclient.principals()- useclient.search_principals()insteadobj.split_expanded- may be removed in a future versionobj.expand_rrule- may be removed in a future version.instanceproperty on calendar objects - use.vobject_instanceor.icalendar_instanceresponse.find_objects_and_props()- useresponse.resultsinsteadThe
save_*-methods are deprecated but do not yet emit warnings (see #71):calendar.save_event()- usecalendar.add_event()insteadcalendar.save_todo()- usecalendar.add_todo()insteadcalendar.save_journal()- usecalendar.add_journal()insteadcalendar.save_object()- usecalendar.add_object()insteadMethods that fetch data from the server should use the
get_prefix (see #92). The following are deprecated but do not yet emit warnings:calendar.event_by_uid()- usecalendar.get_event_by_uid()insteadcalendar.todo_by_uid()- usecalendar.get_todo_by_uid()insteadcalendar.journal_by_uid()- usecalendar.get_journal_by_uid()insteadcalendar.object_by_uid()- usecalendar.get_object_by_uid()insteadprincipal.calendars()- useprincipal.get_calendars()insteadcalendar.events()- usecalendar.get_events()insteadcalendar.todos()- usecalendar.get_todos()insteadcalendar.journals()- usecalendar.get_journals()insteadcalendar.objects_by_sync_token()- usecalendar.get_objects_by_sync_token()insteadThe following
check_*_support()methods are deprecated but do not yet emit warnings:client.check_dav_support()- useclient.supports_dav()insteadclient.check_cdav_support()- useclient.supports_caldav()insteadclient.check_scheduling_support()- useclient.supports_scheduling()instead(Those methods actively probe the server;
is_supported()is a configuration lookup.)Additionally, direct
DAVClient()instantiation should migrate toget_davclient()factory method (seedocs/design/API_NAMING_CONVENTIONS.md)Added
Experimental JMAP calendar client — new
caldav.jmappackage providing a JMAP clientfor servers implementing RFC 8620 (JMAP Core) and RFC 8984 (JMAP Calendars).
Features:
JMAPClientand asynchronousAsyncJMAPClientwith mirrored APIscreate_event,get_event,update_event,delete_event,search_events)get_sync_token/get_objects_by_sync_tokencreate_task,get_task,update_task,delete_taskget_jmap_client()factory reads from the same config sources asget_davclient()(env vars, config file)Full async API - New
AsyncDAVClientand async-compatible domain objects:Retry-After / rate-limit handling (RFC 6585 / RFC 9110) --
DAVClientandAsyncDAVClientnow exposerate_limit_handle,rate_limit_default_sleep, andrate_limit_max_sleepparameters (this may be specified in the configuration file as well). Whenrate_limit_handle=Truethe client automatically sleeps and retries on 429 Too Many Requests and 503 Service Unavailable responses that include aRetry-Afterheader. Whenrate_limit_handle=False(default) aRateLimitErroris raised immediately so callers can implement their own back-off strategy. Newcaldav.lib.error.RateLimitErrorhasretry_after(raw header string) andretry_after_seconds(parsed float) attributes. #627search.is-not-defined.categoryandsearch.is-not-defined.dtend-- new client-side workaround sub-features for servers that do not support theCALDAV:is-not-definedfilter natively for these properties.Base+override feature profiles -- YAML config now supports inheriting from a base profile:
Compatibility fixes
save-load.event.recurrences.exceptionwhich is supported if the server stores master+exception VEVENTs as a single calendar object as per the RFC. Stalwart splits them into separate objects. Stalwart recombines the data when doing an expanded search, soexpand=Truesearches now automatically fall back to server-sideCALDAV:expand. (Arguably,unsupportedhere could also mean the exception data was simply discarded. If needed, I'll refine this in a future version)save-load.journal.mixed-calendar- some calendar servers offers a separate journal list.save-load.reuse-deleted-uid- server allows immediate reuse of an uid if the old object has been deletedsearch.time-range.*.old-dates- test data mostly have historic dates. Calendars are primarily made for future happenings. Some calendar servers does not support searching for things that happened 20 years ago, even for a very small calendar.search.is-not-defined.categoryandsearch.is-not-defined.dtend- actually, those are artifacts. The bug was on the client side, not server side. I may delete them in a future release.calendar-home-setproperty is not available (e.g. GMX).CalendarObjectResource.load()now falls back to UID-based lookup when servers change object URLs after a save.Added python-dateutil and PyYAML as explicit dependencies (were transitive)
Quite some methods have been renamed for consistency and to follow best current practices. See the Deprecated section.
Calendarclass now accepts anameparameter in its constructor, addressing a long-standing API inconsistency (#128)CalendarObjectResource.id property - Returns the UID of calendar objects (#515)
calendar.searcher() API - Factory method for advanced search queries (#590):
Improved API for accessing the
CalendarObjectResourceproperties (#613 ):get_data(),get_icalendar_instance,get_vobject_instance,get_icalendar_component:edit_*(but noedit_data- the data is an immutable string, should use simplyobject.data = foofor editing it)with obj.get_foo, the client may edit foo, and thenobj.save()to send it to the server.Fixed
is-not-definedfilter for CATEGORIES did not work, and for DTEND it did not work for full day events. (this was fixes in theicalendar-searcher, version 1.0.5).Changed
CalendarObjectResourceproperties (#613 )import caldavis now significantly faster. Heavy dependencies (lxml, niquests, icalendar) are deferred until first use. #621_search_implyields(SearchAction, data)tuples consumed by sync or async wrappersget_connection_params()provides unified config discovery with clear priority (explicit params > test server config > env vars > config file)${VAR}and${VAR:-default}environment variable expansion in config valuestests/conf.pyto newtests/test_servers/frameworkSecurity
Test Framework
tests/test_servers/module. It provides YAML-based server configuration: seetests/test_servers/__init__.pyfor usageconvert_conf_private.pymigration tool for legacy config formattest_lazy_import.py; expandedtest_async_davclient.py,test_async_integration.py,test_compatibility_hints.py,test_search.py,test_caldav_unit.pyCheckRecurrenceSearchnow also verifies implicit recurrence support for all-day (VALUE=DATE) recurring events, marking the feature asfragile(with behaviour description) when only datetime recurring events work.GitHub Pull Requests Merged
calendar.search-- Tobias Brox (@tobixen)get_display_name()-- Tobias Brox (@tobixen)GitHub Pull Requests Closed (not merged)
GitHub Issues Closed
add_objectvssave_object(reopened, reverted and closed)get_davclientto be importable from caldav -- Tobias Brox (@tobixen)Credits
The following people contributed to this release through issue reports, pull requests, and/or commits:
Time Spent
Since the 2.2.1-release and excluding the JMAP-work done by Sashank,
Tobias has spent around 132 hours on this project.
In the 3.0-release, AI-tools have been used for improving quality and
speed. My first impression was very good. It seemed like the AI
understood the project, and it could fix things faster and better than
what I could do myself - I really didn't expect it to create any good
code at all. Well, sometimes it does, other times not. Soon enough I
also learned that the AI is good at creating crap code, breaking
things and Claude is particularly good at duplicating code and code
paths. In the end, despite using Claude I've spent more time on this
release than what I had estimated. However, I believe I've done a
quite through work on preserving backward-compatibility while also
developing a better API.
From my roadmap, those are the estimates:
In addition, lots of time spent on things that aren't covered by the roadmap:
v2.2.6Compare Source
v2.2.6 - various minor fixes
This will hopefully be the last releases before v3.0. 2.2.4 is without niquests dependency, 2.2.6 depends on niquests
See CHANGELOG.md for details.
v2.2.5Compare Source
v2.2.4Compare Source
v2.2.3: - multiplexing/authentication workaroundCompare Source
Users of the ckulka/baikal:nginx docker image could not get HTTP/2 multiplexing to work together with authentication. Workarounds done to turn off multiplexing on affected systems.
v2.2.2Compare Source
v2.2.1: v2.2 - compatibility work and miscCompare Source
Highlights:
featuresconfiguration flag.v2.2.1 comes with the requests dependency, v2.2.2 comes with niquests dependency (and v2.2.0 with a non-existing riquests dependency ... duh)
v2.1.2: Version 2.1.2Compare Source
Version 2.1.0 comes without niquests in the dependency file. Version 2.1.2 come with niquests in the dependency file. Also fixed up some minor mistakes in the CHANGELOG. Version 2.1.1 was yet another mistake done during the release process and should be ignored.
See description of version 2.1.0 or CHANGELOG.md for more details.
v2.1.1Compare Source
v2.1.0Compare Source
I'm working on a caldav compatibility checker side project. While doing so, I'm working on redefining the "compatibility matrix". This should only affect the test code. If you maintain a file
tests/conf_private.py, chances are that the latest changesets will break Since "running tests towards private CalDAV servers" is not considered to be part of the public API, I deem this to be allowed without bumping the major version number. If you are affected and can't figure out of it, reach out by email, GitHub issue or GitHub discussions. (Frankly, I'm interessted if anyone except me uses this, so feel free to reach out also if you can figure out of it).As always, the new release comes with quite some bugfixes, compatibility fixes and workarounds improving the support for various calendar servers observed in the wild.
v2.0.1: reverts from niquests back to requestsCompare Source
See #530
v2.0.0: Version 2.0.0Compare Source
Here are the most important changes in 2.0:
davclient.principals()to search for other principals on the server - and from there it's possible to do calendar searches and probe what calendars one have access to. If the server will allow it.Configuration
📅 Schedule: (in timezone Europe/Paris)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.