{"id":7063,"library":"caldav","title":"CalDAV Client Library","description":"caldav is a Python client library for the CalDAV (RFC4791) protocol, enabling interaction with CalDAV servers to manage calendars, events, and tasks. Version 3.1.0 focuses on robustness, improved async support, and enhanced multi-server capabilities. The library maintains an active development cycle, frequently releasing bug fixes and server compatibility improvements, with major releases occurring every few years and minor releases more often.","status":"active","version":"3.1.0","language":"en","source_language":"en","source_url":"https://github.com/python-caldav/caldav","tags":["caldav","calendar","icalendar","http","async","dav"],"install":[{"cmd":"pip install caldav","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Command-line interface tools.","package":"click"},{"reason":"HTTP client for network requests.","package":"httpx"},{"reason":"iCalendar format parsing and generation.","package":"icalendar"},{"reason":"XML parsing for DAV operations.","package":"lxml"},{"reason":"Extensions to the standard datetime module.","package":"python-dateutil"},{"reason":"Data validation and settings management (optional for some features).","package":"pydantic","optional":true}],"imports":[{"symbol":"DAVClient","correct":"from caldav.davclient import DAVClient"},{"symbol":"AsyncDAVClient","correct":"from caldav.davclient import AsyncDAVClient"},{"symbol":"Calendar","correct":"from caldav.objects import Calendar"},{"symbol":"Event","correct":"from caldav.objects import Event"}],"quickstart":{"code":"import os\nfrom caldav.davclient import DAVClient\n\n# Replace with your CalDAV server details or use environment variables\nCALDAV_URL = os.environ.get('CALDAV_URL', 'http://localhost:8008/dav.php/')\nCALDAV_USER = os.environ.get('CALDAV_USER', 'user1')\nCALDAV_PASS = os.environ.get('CALDAV_PASS', 'user1')\n\ndef get_calendars_sync():\n    print(f\"Connecting to CalDAV server at {CALDAV_URL} as {CALDAV_USER}\")\n    try:\n        with DAVClient(url=CALDAV_URL, username=CALDAV_USER, password=CALDAV_PASS) as client:\n            # Get the principal (user's root DAV resource)\n            principal = client.principal()\n            print(f\"Connected to principal: {principal.url}\")\n\n            # Get all calendars for the principal\n            calendars = principal.calendars()\n            if not calendars:\n                print(\"No calendars found.\")\n                return\n\n            print(f\"Found {len(calendars)} calendar(s):\")\n            for calendar in calendars:\n                print(f\"- {calendar.name} (URL: {calendar.url})\")\n                # Example: Fetch first event from the first calendar (if any)\n                events = calendar.events()\n                if events:\n                    event = events[0]\n                    print(f\"  First event: {event.summary} (UID: {event.uid})\")\n                else:\n                    print(\"  No events found in this calendar.\")\n\n    except Exception as e:\n        print(f\"An error occurred: {e}\")\n\nif __name__ == \"__main__\":\n    get_calendars_sync()","lang":"python","description":"This quickstart demonstrates how to connect to a CalDAV server, authenticate, retrieve the user's principal, list available calendars, and fetch the first event from each calendar. Credentials can be provided directly or via environment variables for security."},"warnings":[{"fix":"Review the official changelog for specific changes. Test your application thoroughly against the new version, especially if relying on intricate internal behaviors or less common APIs. Consider migrating gradually if in production.","message":"Version 3.0.0 introduced 'massive code changes' and internal refactoring (e.g., transition from Black to Ruff, sans-io design concepts), despite claims of backward compatibility. Users upgrading from 2.x should thoroughly test their applications.","severity":"breaking","affected_versions":"2.x -> 3.0.0+"},{"fix":"Upgrade to `caldav` v3.1.0 or later for the most stable async experience. Ensure you are correctly `await`ing all asynchronous calls and consulting the latest async examples in the documentation.","message":"Async support was significantly refined and fixed in v3.1.0, indicating potential instability or non-intuitive usage patterns in earlier 3.x versions due to identified 'gaps' in the 'sans-io' design concept.","severity":"gotcha","affected_versions":"3.0.0 - 3.0.2"},{"fix":"For 2.x versions, explicitly install the `niquests` package (`pip install niquests`) if experiencing import errors, or upgrade to a 3.x version where `httpx` is the primary HTTP client.","message":"The `niquests` dependency fluctuated in 2.x versions (e.g., introduced, removed, re-introduced), which could lead to `ModuleNotFoundError` or unexpected behavior depending on the exact minor version installed.","severity":"gotcha","affected_versions":"2.1.0 - 2.2.6"},{"fix":"If you relied on specific behavior of `get_calendars()` in a multi-server context or if your code parses the results assuming a single source, review your implementation to ensure compatibility with the new aggregation capabilities.","message":"As of v3.1.0, the `get_calendars()` method can now span multiple configuration file sections and use glob/wildcard expansion to aggregate calendars from multiple servers into a single `CalendarCollection`. This is an enhancement, but existing code might make assumptions about single-server behavior.","severity":"gotcha","affected_versions":"3.1.0+"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Install the package using pip: `pip install caldav`.","cause":"The `caldav` package is not installed in your current Python environment.","error":"ModuleNotFoundError: No module named 'caldav'"},{"fix":"Always check if the result of a method call (e.g., `principal.calendars()`, `calendar.events()`) is not empty before attempting to access its elements. For example: `events = calendar.events(); if events: first_event = events[0]`.","cause":"This typically occurs when trying to access elements (e.g., `events()[0]`) of a list-like object (like `calendar.events()`) that has returned `None` or an empty list, meaning no items were found.","error":"TypeError: 'NoneType' object is not subscriptable"},{"fix":"Verify the `CALDAV_URL` is correct and accessible. Ensure the CalDAV server is running and not blocked by a firewall. Check if the port (e.g., 8008, 443) is correct and open.","cause":"The CalDAV server could not be reached or refused the connection. This can be due to incorrect URL, server being down, firewall issues, or incorrect port.","error":"httpx.ConnectError: [Errno 111] Connection refused"},{"fix":"Ensure all methods of `AsyncDAVClient` and its derived objects (like `principal.calendars()`, `calendar.events()`) are properly `await`ed. Your code must be run within an `async def` function and executed using an async event loop (e.g., `asyncio.run()`).","cause":"You are attempting to use an `AsyncDAVClient` method (or object) in an asynchronous context without correctly using `await`, or your async setup is incorrect.","error":"TypeError: object AsyncDAVClient can't be used in 'await' expression (or similar async errors)"}]}