You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- AI-POLICY.md: expand policy with guidance on AI-assisted code review,
vibe-coding caveats, and disclosure requirements
- CHANGELOG.md: update unreleased section with all v3.0-dev changes
- MANIFEST.in: include caldav_test_servers.yaml.example in sdist
- RELEASE-HOWTO.md: minor update
- docs/design/V3_CODE_REVIEW.md: add niquests and urllib3-future code reviews
- docs/design/niquests-code-review.md: new — review of niquests HTTP library
- docs/design/urllib3-future-code-review.md: new — review of urllib3-future
- docs/design/TODO.md: update outstanding tasks
- docs/source/tutorial.rst: revise for v3.0 async API and new patterns
- docs/source/about.rst, conf.py: minor fixes
- examples/scheduling_examples.py: remove accidentally committed breakpoints
Co-Authored-By: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+80-20Lines changed: 80 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,19 +18,24 @@ This project should adhere to [Semantic Versioning](https://semver.org/spec/v2.0
18
18
19
19
### Highlights
20
20
21
-
Version 3.0 should be fully backward-compatible with version 2.x - but there are massive code changes in version 3.0:
21
+
There shouldn't be many breaking changes in version 3.0, but there are massive code changes in version 3.0:
22
22
23
-
* "Black style" has been replaced with ruff. This causes quite some changes in the code.
24
-
* Version 3.0 introduces **full async support** using a Sans-I/O architecture. The same domain objects (Calendar, Event, Todo, etc.) now work with both synchronous and asynchronous clients. The async client uses niquests by default; httpx is also supported for projects that already have it as a dependency.
25
-
* Quite some refactoring work has been done
26
-
* Some work has been put down ensuring better consistency in the method names. Version 3.0 should be backward-compatible with version 2.0, so the old methods still work, but are deprecated.
23
+
***Full async support** using a Sans-I/O architecture. The same domain objects (Calendar, Event, Todo, etc.) now work with both synchronous and asynchronous clients. The async client uses niquests by default; httpx is also supported for projects that already have it as a dependency.
24
+
***Sans-I/O architecture** -- internal refactoring separates protocol logic (XML building/parsing) from I/O into a layered architecture: protocol layer (`caldav/protocol/`), operations layer (`caldav/operations/`), and response handling (`caldav/response.py`). This enables code reuse between sync and async implementations and improves testability.
25
+
***Lazy imports** -- `import caldav` is now significantly faster due to PEP 562 lazy loading. Heavy dependencies (lxml, niquests, icalendar) are deferred until first use. (https://github.com/python-caldav/caldav/issue/621)
26
+
***API naming consistency** -- methods have been renamed for consistency. Server-fetching methods use `get_` prefix, capability checks use `supports_*()`. Old method names still work but are deprecated.
27
+
***Ruff replaces Black** -- code formatting now uses ruff instead of Black, causing cosmetic changes throughout the codebase.
28
+
***Expanded compatibility hints** -- server-specific workarounds added for Zimbra, Bedework, CCS (Apple CalendarServer), Davis, DAViCal, GMX, ecloud, Synology, Posteo, PurelyMail, and more.
29
+
* Quite some other refactoring work has been done.
27
30
28
31
### Breaking Changes
29
32
30
33
(Be aware that some of the 2.x minor-versions also tagged some "Potentially Breaking Changes")
31
34
32
35
***Minimum Python version**: Python 3.10+ is now required (was 3.8+).
33
36
***Test Server Configuration**: `tests/conf.py` has been removed and `conf_private.py` will be ignored. See the Test Framework section below.
37
+
***`object.py` has been removed** as well as the `from caldav.object import *` in `caldav/__init__.py`. Some classes etc may appear to be missing, but the most important ones should still exist directly in the `caldav.*` namespace.
38
+
***Config file parse errors now raise exceptions**: `caldav.config.read_config()` now raises `ValueError` on YAML/JSON parse errors instead of logging and returning an empty dict. This ensures config errors are detected early.
34
39
35
40
### Deprecated
36
41
@@ -69,7 +74,7 @@ Additionally, direct `DAVClient()` instantiation should migrate to `get_davclien
69
74
70
75
### Added
71
76
72
-
***Full async API** - New `AsyncDAVClient` and async-compatible domain objects:
77
+
***Full async API** -- New `AsyncDAVClient` and async-compatible domain objects:
73
78
```python
74
79
from caldav.async_davclient import get_davclient
75
80
@@ -79,20 +84,25 @@ Additionally, direct `DAVClient()` instantiation should migrate to `get_davclien
79
84
for cal in calendars:
80
85
events =await cal.get_events()
81
86
```
82
-
***Sans-I/O architecture** - Internal refactoring separates protocol logic from I/O:
83
-
- Protocol layer (`caldav/protocol/`): Pure functions for XML building/parsing
- This enables code reuse between sync and async implementations
87
+
***Sans-I/O architecture** -- Internal refactoring separates protocol logic from I/O:
88
+
- Protocol layer (`caldav/protocol/`): Pure functions for XML building/parsing with typed dataclasses (DAVRequest, DAVResponse, PropfindResult, CalendarQueryResult)
89
+
- Operations layer (`caldav/operations/`): Sans-I/O business logic for CalDAV operations (properties, search, calendar management, principal discovery)
90
+
- Response layer (`caldav/response.py`): Shared `BaseDAVResponse` for sync/async
91
+
- Data state (`caldav/datastate.py`): Strategy pattern for managing data representations (raw string, icalendar, vobject) -- avoids unnecessary parse/serialize cycles
92
+
***Lazy imports (PEP 562)** -- `import caldav` is now fast. Heavy dependencies (lxml, niquests, icalendar) are deferred until first use. https://github.com/python-caldav/caldav/pull/621
93
+
***`DAVObject.name` deprecated** -- use `get_display_name()` instead. The old `.name` property now emits `DeprecationWarning`.
86
94
* Added python-dateutil and PyYAML as explicit dependencies (were transitive)
87
95
* Quite some methods have been renamed for consistency and to follow best current practices. See the deprecation section.
88
96
*`Calendar` class now accepts a `name` parameter in its constructor, addressing a long-standing API inconsistency (https://github.com/python-caldav/caldav/issues/128)
89
-
***Data representation API** - New efficient data access via `CalendarObjectResource` properties (https://github.com/python-caldav/caldav/issues/613):
***Data representation API** -- New efficient data access via `CalendarObjectResource` properties (https://github.com/python-caldav/caldav/issues/613):
* Fixed feature name parsing when names include `compatibility_hints.` prefix
136
+
* Fixed recursive `_search_with_comptypes` when `search.comp-type` is broken
137
+
* Fixed pending todo search on servers with broken comp-type filtering
138
+
* Fixed URL path quoting when extracting calendars from PROPFIND results
139
+
* Removed spurious warning on URL path mismatch, deduplicated `get_properties`
140
+
* Fixed `create-calendar` feature incorrectly derived as unsupported
141
+
* Fixed various async test issues (awaiting sync calls, missing feature checks, authorization error handling)
142
+
* Fixed `search.category` features to use correct `search.text.category` names
123
143
124
144
### Changed
125
145
126
146
* Sync client (`DAVClient`) now shares common code with async client via `BaseDAVClient`
127
147
* Response handling unified in `BaseDAVResponse` class
148
+
* Search refactored to use generator-based Sans-I/O pattern -- `_search_impl` yields `(SearchAction, data)` tuples consumed by sync or async wrappers
128
149
* Test configuration migrated from legacy `tests/conf.py` to new `tests/test_servers/` framework
150
+
* Configuration system expanded: `get_connection_params()` provides unified config discovery with clear priority (explicit params > test server config > env vars > config file)
151
+
* `${VAR}` and `${VAR:-default}` environment variable expansion in config values
152
+
* Ruff replaces Black for code formatting
153
+
* `caldav/objects.py` backward-compatibility shim removed (imports go directly to submodules)
129
154
130
155
### Test Framework
131
156
132
-
* Fixed Nextcloud Docker test server tmpfs permissions race condition
133
-
* Added deptry for dependency verification in CI
134
-
* The test server framework has been refactored with a new `tests/test_servers/` module. It provides **YAML-based server configuration**: see `tests/test_servers/__init__.py` for usage
157
+
* **New `tests/test_servers/` module** -- Complete rewrite of test infrastructure:
158
+
- `TestServer`base class hierarchy (EmbeddedTestServer, DockerTestServer, ExternalTestServer)
159
+
- YAML-based server configuration (`tests/caldav_test_servers.yaml.example`)
160
+
- `ServerRegistry`for server discovery and lifecycle management
@@ -148,7 +190,25 @@ Additionally, direct `DAVClient()` instantiation should migrate to `get_davclien
148
190
149
191
### Security
150
192
151
-
Nothing to report.
193
+
* UUID1 usage in UID generation (`calendarobject_ops.py`) may embed the host MAC address in calendar UIDs. Since calendar events are shared with third parties, this is a privacy concern. Planned fix: switch to UUID4.
194
+
195
+
### Compatibility Hints Expanded
196
+
197
+
Server-specific workarounds have been significantly expanded. Profiles added or updated for:
Copy file name to clipboardExpand all lines: RELEASE-HOWTO.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -45,5 +45,5 @@ This is most likely not complete, but should explain some of the "silly" steps a
45
45
* Forgetting to add new files to the git repo
46
46
* Having checked out a branch or tag or something, and tagging that as the new release rather than the latest HEAD.
47
47
* Forgetting to push to pypi, or pushing something else than the tagged revision to pypi
48
-
* Pushing out junk files in the pypi-release (i.e. .pyc-files, log files, temp files, `tests/conf_private.py`, etc
48
+
* Pushing out junk files in the pypi-release (i.e. .pyc-files, log files, temp files, `tests/conf_private.py`, `tests/caldav_test_servers.yaml`, etc
49
49
* Not adding the release to the "github releases" (I don't care much about this feature, but apparently some people check there to find the latest release version)
0 commit comments