### Build Documentation with Sphinx Source: https://github.com/python-caldav/caldav/blob/master/docs/source/about.md Generate project documentation using the setup script. ```bash $ python setup.py build_sphinx ``` -------------------------------- ### Start Davis Server Source: https://github.com/python-caldav/caldav/blob/master/tests/docker-test-servers/davis/README.md Initializes the Davis container environment using the provided start script. ```bash cd tests/docker-test-servers/davis ./start.sh ``` -------------------------------- ### Start DAViCal Docker Containers Source: https://github.com/python-caldav/caldav/blob/master/tests/docker-test-servers/davical/README.md Initializes the PostgreSQL and DAViCal containers for testing. ```bash cd tests/docker-test-servers/davical ./start.sh ``` -------------------------------- ### Start Local Test Container Source: https://github.com/python-caldav/caldav/blob/master/tests/docker-test-servers/README.md Standard command to initialize a test server container from its directory. ```bash docker-compose up -d ``` -------------------------------- ### Start CalendarServer Source: https://github.com/python-caldav/caldav/blob/master/tests/docker-test-servers/ccs/README.md Execute this script to start the Apple CalendarServer instance. ```bash ./start.sh ``` -------------------------------- ### Run Pytest with Automatic Baikal Setup Source: https://github.com/python-caldav/caldav/blob/master/tests/docker-test-servers/baikal/README.md Execute tests using pytest. The framework automatically detects and starts the Baikal Docker container if Docker is available. ```bash pytest tests/ ``` ```bash tox -e py ``` -------------------------------- ### Quick Start with Async API Source: https://github.com/python-caldav/caldav/blob/master/docs/source/async.md Demonstrates basic usage of the AsyncDAVClient to retrieve calendars and event counts. ```python import asyncio from caldav import aio async def main(): async with await aio.get_async_davclient() as client: principal = await client.get_principal() calendars = await principal.get_calendars() for cal in calendars: print(f"Calendar: {await cal.get_display_name()}") events = await cal.get_events() print(f" {len(events)} events") asyncio.run(main()) ``` -------------------------------- ### Manually Start Baikal Docker Container Source: https://github.com/python-caldav/caldav/blob/master/tests/docker-test-servers/baikal/README.md Start the Baikal CalDAV server manually by navigating to the test directory and executing the start script. This prepares the server for testing. ```bash cd tests/docker-test-servers/baikal ./start.sh ``` -------------------------------- ### Install Server Compatibility Tester Source: https://github.com/python-caldav/caldav/blob/master/docs/source/configfile.md Install the companion tool used to probe CalDAV server capabilities. ```default pip install caldav-server-tester ``` -------------------------------- ### Configure client via INI file Source: https://github.com/python-caldav/caldav/blob/master/docs/design/GET_DAVCLIENT_ANALYSIS.md Example of an INI-style configuration file and its usage with the factory function. ```ini # ~/.caldav.conf [default] caldav_url = https://caldav.example.com caldav_user = alice caldav_pass = hunter2 ``` -------------------------------- ### Demonstrate Connection Probe Behavior Source: https://github.com/python-caldav/caldav/blob/master/docs/design/GET_DAVCLIENT_ANALYSIS.md Example showing that client instantiation does not immediately validate server connectivity. ```python # This succeeds even if server is unreachable: client = get_davclient(url="https://invalid-server.com", username="x", password="y") # Error only happens on first actual call: principal = client.principal() # <-- ConnectionError here ``` -------------------------------- ### Demonstrate configuration priority ambiguity Source: https://github.com/python-caldav/caldav/blob/master/docs/design/GET_DAVCLIENT_ANALYSIS.md Example showing potential confusion regarding parameter versus environment variable priority. ```python get_davclient(url="A") # Uses "A" # But if CALDAV_URL=B is set, which wins? (Answer: parameter, but not obvious) ``` -------------------------------- ### Manually Start SOGo Docker Containers Source: https://github.com/python-caldav/caldav/blob/master/tests/docker-test-servers/sogo/README.md Start SOGo and PostgreSQL containers manually. This script waits for SOGo to initialize and verifies CalDAV access. ```bash cd tests/docker-test-servers/sogo ./start.sh ``` -------------------------------- ### Use Async Client Factory Source: https://github.com/python-caldav/caldav/blob/master/docs/design/GET_DAVCLIENT_ANALYSIS.md Examples of using the async factory with explicit parameters or environment variables. ```python from caldav import aio # Simple: async with await aio.get_client(url="...", username="...", password="...") as client: calendars = await client.get_calendars() # From environment: async with await aio.get_client() as client: # Reads CALDAV_* env vars calendars = await client.get_calendars() ``` -------------------------------- ### Configure client via environment variables Source: https://github.com/python-caldav/caldav/blob/master/docs/design/GET_DAVCLIENT_ANALYSIS.md Example of setting environment variables for 12-factor app compliance and using them in code. ```bash export CALDAV_URL=https://caldav.example.com export CALDAV_USERNAME=alice export CALDAV_PASSWORD=hunter2 python my_script.py # No hardcoded credentials! ``` ```python # In code: with get_davclient() as client: # Automatically reads env vars! ... ``` -------------------------------- ### Async API Migration Guide Source: https://github.com/python-caldav/caldav/blob/master/docs/source/async.md Guidelines for transitioning from synchronous to asynchronous caldav usage. ```APIDOC ## Async Migration ### Description To use the asynchronous API, import classes from `caldav.aio`. All I/O operations must be awaited. ### Usage - **Imports**: Use `from caldav import aio`. - **Context Manager**: Use `async with await aio.get_async_davclient() as client:`. - **I/O Operations**: All network-bound methods (e.g., `get_principal`, `get_calendars`, `get_events`) must be prefixed with `await`. - **Cached Properties**: Properties like `url`, `name`, and `data` do not require I/O and remain synchronous. ``` -------------------------------- ### Async API Usage Example Source: https://github.com/python-caldav/caldav/blob/master/docs/design/SANS_IO_IMPLEMENTATION_PLAN2.md Demonstrates how asynchronous users interact directly with the client methods, bypassing domain object methods for operations like getting events or searching. ```python # Async users call client methods directly - no Calendar.get_events() async with AsyncDAVClient(url=...) as client: principal = await client.get_principal() calendars = await client.get_calendars(principal.calendar_home_set) events = await client.get_events(calendars[0]) # Or with search: events = await client.search_calendar(calendars[0], start=..., end=...) ``` -------------------------------- ### Install Embedded Test Servers Source: https://github.com/python-caldav/caldav/blob/master/tests/README.md Install the necessary packages to run embedded CalDAV test servers. ```bash pip install radicale xandikos ``` -------------------------------- ### Get CalDAV Client with Environment Variables or Config File Source: https://context7.com/python-caldav/caldav/llms.txt Obtain a CalDAV client by relying on environment variables (CALDAV_URL, CALDAV_USERNAME, CALDAV_PASSWORD) or a configuration file. This simplifies connection setup when credentials are pre-configured. ```python # Using environment variables (CALDAV_URL, CALDAV_USERNAME, CALDAV_PASSWORD) # or config file (~/.config/caldav/calendar.conf) with get_davclient() as client: calendars = client.get_calendars() for cal in calendars: print(f"Calendar: {cal.get_display_name()}") ``` -------------------------------- ### Manually Start Nextcloud Server Source: https://github.com/python-caldav/caldav/blob/master/tests/docker-test-servers/nextcloud/README.md Start the Nextcloud Docker container manually. This script initializes the container, creates test users, and enables necessary apps. Nextcloud will be accessible at http://localhost:8801. ```bash cd tests/docker-test-servers/nextcloud ./start.sh ``` -------------------------------- ### Start Baikal Test Server Source: https://github.com/python-caldav/caldav/blob/master/tests/docker-test-servers/README.md Commands to navigate to the Baikal directory and launch the container in detached mode. ```bash cd baikal docker-compose up -d ``` -------------------------------- ### Troubleshoot container startup Source: https://github.com/python-caldav/caldav/blob/master/tests/docker-test-servers/cyrus/README.md Commands to inspect logs or restart the Cyrus container when it fails to start. ```bash # Check container logs docker-compose logs cyrus # Restart container docker-compose restart cyrus ``` -------------------------------- ### Start Cyrus manually Source: https://github.com/python-caldav/caldav/blob/master/tests/docker-test-servers/cyrus/README.md Use these commands to initialize the Cyrus container manually instead of relying on the automatic test framework. ```bash cd tests/docker-test-servers/cyrus ./start.sh ``` -------------------------------- ### Manage Docker Test Servers Source: https://github.com/python-caldav/caldav/blob/master/tests/README.md Commands to inspect logs, reset, and start the Baikal Docker test server. ```bash cd tests/docker-test-servers/baikal docker-compose logs docker-compose down -v # Reset everything docker-compose up -d ``` -------------------------------- ### Define test server configuration Source: https://github.com/python-caldav/caldav/blob/master/tests/README.md Example YAML structure for defining embedded, Docker, or external CalDAV servers. ```yaml test-servers: radicale: type: embedded enabled: true baikal: type: docker enabled: true username: testuser password: testpass # Your own server my-server: type: external enabled: true url: https://caldav.example.com username: testuser password: secret ``` -------------------------------- ### Get Events (Sync) Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/collection.md Retrieves a list of Event objects from the calendar in a synchronous manner. No special setup is required for sync clients. ```python events = calendar.get_events() ``` -------------------------------- ### Get Free/Busy Information Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/collection.md Searches the calendar and returns only the free/busy information for a specified time range. Defaults to the current date if start and end times are not provided. ```python free_busy_info = calendar.freebusy_request(start=start_datetime, end=end_datetime) ``` -------------------------------- ### Initialize Client via Factory Source: https://github.com/python-caldav/caldav/blob/master/docs/design/GET_DAVCLIENT_ANALYSIS.md Use the factory function to instantiate a client with configuration parameters. ```python from caldav import get_davclient with get_davclient(url="...", username="...", password="...") as client: ... ``` -------------------------------- ### Configure Nextcloud Test Server Source: https://github.com/python-caldav/caldav/blob/master/tests/docker-test-servers/nextcloud/README.md Example configuration for disabling the Nextcloud test server by setting 'enabled' to false in the YAML file. This prevents the test framework from starting the Nextcloud container. ```yaml nextcloud: type: docker enabled: false ``` -------------------------------- ### Check Container Logs Source: https://github.com/python-caldav/caldav/blob/master/tests/docker-test-servers/nextcloud/README.md View the logs of the Nextcloud Docker container to troubleshoot startup issues. This command helps in diagnosing problems when the container fails to start. ```bash docker-compose logs nextcloud ``` -------------------------------- ### Initialize Client with Credentials Source: https://github.com/python-caldav/caldav/blob/master/docs/source/tutorial.md Connect to a CalDAV server by explicitly providing authentication credentials. ```python from caldav import get_davclient ## Invalid domain, invalid password ... ## ... this probably ought to raise an error? with get_davclient( username='alice', password='hunter2', url='https://calendar.example.com/dav/') as client: ... ``` -------------------------------- ### Configure test servers Source: https://github.com/python-caldav/caldav/blob/master/tests/README.md Commands to prepare the test server configuration file. ```bash cp tests/caldav_test_servers.yaml.example tests/caldav_test_servers.yaml ``` ```sh chmod og-r tests/caldav_test_servers.yaml ``` ```bash pytest ``` -------------------------------- ### Get All Journals Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/collection.md Lists all journal entries within the calendar. ```APIDOC ## GET /api/calendar/get_journals ### Description Lists all journal entries from the calendar. ### Method GET (or equivalent internal method call) ### Endpoint Not directly exposed as an HTTP endpoint, but represents an internal library function. ### Response #### Success Response (200) - **list[Journal]** - A list of Journal objects. ### Response Example ```json [ { "journal_data": "..." } ] ``` ``` -------------------------------- ### Compare Sync and Async Client Patterns Source: https://github.com/python-caldav/caldav/blob/master/docs/design/GET_DAVCLIENT_ANALYSIS.md Demonstrate the consistency between factory-based and direct instantiation for async clients. ```python # If we prefer factories: from caldav import aio async with aio.get_client(url="...", username="...", password="...") as client: ... # Or direct (current aio.py approach): from caldav import aio async with aio.CalDAVClient(url="...", username="...", password="...") as client: ... ``` -------------------------------- ### Example Usage of Generated DAVClient Methods Source: https://github.com/python-caldav/caldav/blob/master/docs/design/METHOD_GENERATION_ANALYSIS.md Demonstrates the identical usage of dynamically generated methods like `propfind` and `proppatch` on a `client` object. These methods are now directly available on the class instance. ```python client.propfind(url, body, depth) # Works the same client.proppatch(url, body) # Works the same ``` -------------------------------- ### GET /caldav/collection/multiget Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/collection.md Retrieves data for multiple events using their URLs. ```APIDOC ## GET /caldav/collection/multiget ### Description Retrieves data for multiple events concurrently using a list of their URLs. This method is useful for fetching details of several events efficiently. ### Method GET ### Endpoint /caldav/collection/multiget ### Parameters #### Query Parameters - **event_urls** (Iterable[URL]) - Required - An iterable of URLs for the events whose data needs to be retrieved. - **raise_notfound** (boolean) - Optional - If True, raises an exception if any of the specified URLs are not found. Defaults to False. ### Response #### Success Response (200) - **Iterable[_CC]** - An iterable containing the data for the requested events. ``` -------------------------------- ### AsyncDAVClient with High-Level Methods Source: https://github.com/python-caldav/caldav/blob/master/docs/design/URL_AND_METHOD_RESEARCH.md This example illustrates an alternative approach for the `AsyncDAVClient` class, proposing the addition of high-level convenience methods like `query_properties` that wrap lower-level HTTP operations such as `propfind`. ```python class AsyncDAVClient: # Low-level HTTP wrappers (keep for backward compat & _query()) async def propfind(url, body, depth) -> DAVResponse: ... async def report(url, body, depth) -> DAVResponse: ... # High-level convenience methods async def query_properties( self, url: Optional[str] = None, properties: Optional[List[BaseElement]] = None, depth: int = 0, ) -> Dict: """ High-level property query that returns parsed properties. Wraps propfind() with XML parsing. """ ... ``` -------------------------------- ### Depth Parameter Usage Source: https://github.com/python-caldav/caldav/blob/master/docs/design/API_ANALYSIS.md Examples of methods that utilize the depth parameter. ```python propfind(url, props, depth: int = 0) report(url, query, depth: int = 0) ``` -------------------------------- ### Ruff Configuration for Initial Async Files (Phase 1) Source: https://github.com/python-caldav/caldav/blob/master/docs/design/RUFF_CONFIGURATION_PROPOSAL.md Ruff configuration for Phase 1, explicitly listing initial async files to be checked. Includes linting rules and formatter settings. ```toml [tool.ruff] line-length = 100 target-version = "py39" # Explicitly list new async files include = [ "caldav/async_davclient.py", "caldav/async_davobject.py", "caldav/async_collection.py", "tests/test_async_davclient.py", "tests/test_async_collection.py", ] [tool.ruff.lint] # Based on icalendar-searcher config select = [ "E", # pycodestyle errors "F", # pyflakes "W", # pycodestyle warnings "I", # isort "UP", # pyupgrade (modernize code) "B", # flake8-bugbear (find bugs) "ANN", # type annotations ] ignore = [ "E501", # Line too long (formatter handles this) "ANN401", # Any type (sometimes necessary) ] [tool.ruff.format] # Use Ruff's formatter (Black-compatible) quote-style = "double" indent-style = "space" [tool.ruff.lint.isort] known-first-party = ["caldav"] ``` -------------------------------- ### Using Context Managers: Sync vs. Async Source: https://github.com/python-caldav/caldav/blob/master/docs/source/async.md Demonstrates the usage of context managers for DAV clients in both synchronous and asynchronous code. ```python # Sync with get_davclient() as client: ... # Async async with await aio.get_davclient() as client: ... ``` -------------------------------- ### GET /api/users/{id} Source: https://github.com/python-caldav/caldav/blob/master/docs/design/API_ANALYSIS.md Retrieves details for a specific user based on their unique ID. ```APIDOC ## GET /api/users/{id} ### Description Retrieves the details of a specific user using their unique identifier. ### Method GET ### Endpoint /api/users/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the user to retrieve. ### Response #### Success Response (200) - **id** (string) - The unique identifier for the user. - **username** (string) - The username of the user. - **email** (string) - The email address of the user. - **created_at** (string) - The timestamp when the user was created. #### Response Example ```json { "id": "user-12345", "username": "johndoe", "email": "john.doe@example.com", "created_at": "2023-10-27T10:00:00Z" } ``` ``` -------------------------------- ### Configure async client without probing Source: https://github.com/python-caldav/caldav/blob/master/docs/source/async_tutorial.md Shows how to initialize a client with specific credentials while disabling the default OPTIONS probe. ```python import asyncio from caldav import aio async def main(): ## Invalid domain, invalid password ... ## ... this probably ought to raise an error? client = await aio.get_async_davclient( username='alice', password='hunter2', url='https://calendar.example.com/dav/', probe=False) async with client: ... asyncio.run(main()) ``` -------------------------------- ### Getting iCalendar Instance for Modification Source: https://github.com/python-caldav/caldav/blob/master/docs/design/DATA_PROPERTIES_USAGE.md Retrieve the iCalendar instance to modify its properties, such as subcomponents. ```python object_by_id.icalendar_instance ``` ```python assert object_by_id.icalendar_instance ``` -------------------------------- ### Use get_davclient in application code Source: https://github.com/python-caldav/caldav/blob/master/docs/design/GET_DAVCLIENT_ANALYSIS.md Recommended pattern for initializing a client using the factory function. ```python from caldav import get_davclient with get_davclient() as client: principal = client.principal() calendars = principal.get_calendars() ``` -------------------------------- ### Public Internal Authentication Methods Source: https://github.com/python-caldav/caldav/blob/master/docs/design/API_ANALYSIS.md Examples of methods that are currently public but should be treated as internal. ```python extract_auth_types(header: str) # Should be _extract_auth_types build_auth_object(...) # Should be _build_auth_object ``` -------------------------------- ### Initialize CalDAV Client (Sync) Source: https://github.com/python-caldav/caldav/blob/master/docs/design/CODE_FLOW.md Instantiate a synchronous DAVClient with server URL, username, and password to interact with CalDAV services. ```python from caldav import DAVClient client = DAVClient(url="https://server/dav/", username="user", password="pass") principal = client.principal() calendars = principal.get_calendars() ``` -------------------------------- ### Managing icalendar_instance Source: https://github.com/python-caldav/caldav/blob/master/docs/design/DATA_PROPERTIES_USAGE.md Examples of interacting with the icalendar_instance property to manipulate calendar components and properties. ```python self.icalendar_instance.subcomponents ``` ```python obj.icalendar_instance.subcomponents = [] ``` ```python self.icalendar_instance, components=[...] ``` ```python calendar = self.icalendar_instance ``` ```python if not self.icalendar_instance: ``` ```python self.icalendar_instance.get("method", None) ``` ```python self.icalendar_instance.pop("METHOD") ``` ```python obj.icalendar_instance ``` ```python self.icalendar_instance = icalendar.Calendar.from_ical(...) ``` ```python obj.icalendar_instance.walk("vevent")[0]["uid"] ``` ```python o.icalendar_instance ``` ```python new_obj.icalendar_instance ``` -------------------------------- ### Current Wrapper Implementation for PROPFIND Source: https://github.com/python-caldav/caldav/blob/master/docs/design/ELIMINATE_METHOD_WRAPPERS_ANALYSIS.md This is an example of a thin adapter wrapper for the PROPFIND method, which adds method-specific headers before calling the main request method. It's part of a pattern that could be eliminated. ```python def propfind(self, url=None, props="", depth=0): return self.request( url or str(self.url), "PROPFIND", props, {"Depth": str(depth)} ) ``` -------------------------------- ### Create and complete a task Source: https://github.com/python-caldav/caldav/blob/master/docs/source/tutorial.md Demonstrates creating a tasklist with VTODO support, adding a task, and marking it as complete. ```python from caldav import get_davclient from datetime import date with get_davclient() as client: my_principal = client.get_principal() ## This can be read as "create me a tasklist" cal = my_principal.make_calendar( name="Test tasklist", supported_calendar_component_set=['VTODO']) ## ... but for most servers it's an ordinary calendar! cal.add_todo( summary="prepare for the Norwegian national day", due=date(2025,5,16)) my_tasks = cal.search( todo=True) assert len(my_tasks) == 1 my_tasks[0].complete() my_tasks = cal.search( todo=True) assert len(my_tasks) == 0 my_tasks = cal.search( todo=True, include_completed=True) assert my_tasks ``` -------------------------------- ### Create a Calendar Source: https://github.com/python-caldav/caldav/blob/master/docs/source/tutorial.md Initialize a client, retrieve the principal, and create a new calendar. ```python from caldav import get_davclient ## Get a client ... with get_davclient() as client: ## ... from the client get the principal ... my_principal = client.get_principal() ## ... from the principal we can create calendar ... my_new_calendar = my_principal.make_calendar(name="Test calendar") ## Enable the debug breakpoint to investigate the calendar object #breakpoint() my_new_calendar.delete() ``` -------------------------------- ### Initialize JMAP client from configuration Source: https://github.com/python-caldav/caldav/blob/master/docs/source/jmap.md Clients can be initialized using the configuration file. Specific sections can be targeted using the config_section parameter. ```python client = get_jmap_client() ``` ```python from caldav.jmap import get_jmap_client client = get_jmap_client(config_section="jmap") ``` -------------------------------- ### Get All Calendars (Sync) Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/collection.md Use this method to list all calendar collections in a CalendarSet for synchronous clients. ```python calendars = calendar_set.get_calendars() ``` -------------------------------- ### Get All Events Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/collection.md Lists all events from the calendar. For asynchronous clients, this returns a coroutine that needs to be awaited. ```APIDOC ## GET /api/calendar/get_events ### Description Lists all events from the calendar. For sync clients, returns a list of Event objects. For async clients, returns a coroutine. ### Method GET (or equivalent internal method call) ### Endpoint Not directly exposed as an HTTP endpoint, but represents an internal library function. ### Response #### Success Response (200) - **list[Event]** - A list of Event objects or a coroutine. ### Response Example (Sync) ```json [ { "event_data": "..." } ] ``` ### Response Example (Async) ```python events = await calendar.get_events() ``` ``` -------------------------------- ### Manual Implementation: _query_properties() Wrapper Source: https://github.com/python-caldav/caldav/blob/master/docs/design/METHOD_GENERATION_ANALYSIS.md Manual implementation of a _query_properties wrapper that directly calls the client's propfind method. This approach retains mocking capabilities but introduces boilerplate code. ```python # In DAVObject - eliminate _query() entirely def _query_properties(self, props=None, depth=0): """Query properties""" root = None if props is not None and len(props) > 0: prop = dav.Prop() + props root = dav.Propfind() + prop body = "" if root: body = etree.tostring(root.xmlelement(), encoding="utf-8", xml_declaration=True) # Direct call to method wrapper ret = self.client.propfind(self.url, body, depth) if ret.status == 404: raise error.NotFoundError(errmsg(ret)) if ret.status >= 400: raise error.exception_by_method["propfind"](errmsg(ret)) return ret ``` -------------------------------- ### Get Event by UID Source: https://context7.com/python-caldav/caldav/llms.txt Retrieves a specific event from the calendar using its unique identifier (UID). ```python from caldav import get_calendar from datetime import date, datetime with get_calendar() as calendar: # Get event by UID event = calendar.get_event_by_uid("meeting-2024-06-15@example.com") if event: print(f"Found: {event.get_icalendar_component()['SUMMARY']}") ``` -------------------------------- ### Iterating Over Subcomponents Source: https://github.com/python-caldav/caldav/blob/master/docs/design/DATA_PROPERTIES_USAGE.md Example of iterating through the subcomponents of an iCalendar instance, often used for searching or processing. ```python for sub in target.icalendar_instance.subcomponents: ``` ```python for sub in search.icalendar_instance.subcomponents: ``` -------------------------------- ### Configure client for testing Source: https://github.com/python-caldav/caldav/blob/master/docs/design/GET_DAVCLIENT_ANALYSIS.md Using environment variables to toggle test server usage. ```bash export PYTHON_CALDAV_USE_TEST_SERVER=1 python my_script.py # Uses test server from conf.py ``` -------------------------------- ### Accessing and Manipulating obj.data Source: https://github.com/python-caldav/caldav/blob/master/docs/design/DATA_PROPERTIES_USAGE.md Examples of how the data property is set, validated, and accessed across the library. ```python self.data = data ``` ```python calendar.add_event(self.data) ``` ```python data=self.data ``` ```python self.data = r.raw ``` ```python url, self.data = next(mydata) ``` ```python error.assert_(self.data) ``` ```python self.url, self.data, {...} ``` ```python str(self.data) ``` ```python self.data.count("BEGIN:VEVENT") ``` ```python if not self.data: ``` ```python to_unicode(self.data) ``` ```python caldavobj.data ``` ```python old_by_url[url].data ``` ```python obj.data if hasattr(obj, "data") ``` -------------------------------- ### Create Principal (Async) Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/collection.md Recommended way to create a Principal with async clients, as it handles asynchronous URL discovery. For sync clients, use the regular constructor. ```python principal = await Principal.create(async_client) ``` -------------------------------- ### Monitor Container Logs Source: https://github.com/python-caldav/caldav/blob/master/tests/docker-test-servers/davical/README.md Follows the logs of the docker-compose setup to monitor database and schema initialization. ```bash docker-compose logs -f ``` -------------------------------- ### Publishing to PyPI Source: https://github.com/python-caldav/caldav/blob/master/docs/design/RELEASE-HOWTO.md Commands to create a clean environment, build the package, and upload it to PyPI using twine. ```bash cd ~/caldav-release python3 -m venv venv . venv/bin/activate pip install -U pip build twine python -m build python -m twine upload dist/* ``` -------------------------------- ### Asynchronous JMAP Client - Initialization Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/jmap_client.md Demonstrates how to initialize and use the asynchronous JMAP client. ```APIDOC ## AsyncJMAPClient Initialization ### Description Initialize an asynchronous JMAP client for calendar operations. ### Usage ```python from caldav.jmap import get_async_jmap_client async with get_async_jmap_client(url="https://jmap.example.com/.well-known/jmap", username="alice", password="secret") as client: calendars = await client.get_calendars() ``` ### Parameters - **url** (str) - Required - URL of the JMAP session endpoint (`/.well-known/jmap`). - **username** (str | None) - Optional - Username for Basic auth. - **password** (str | None) - Optional - Password for Basic auth, or bearer token if no username. - **auth** (object | None) - Optional - A pre-built niquests-compatible auth object. Takes precedence over username/password if provided. - **auth_type** (str | None) - Optional - Force a specific auth type: `"basic"` or `"bearer"`. - **timeout** (int) - Optional - HTTP request timeout in seconds. Default is 30. ``` -------------------------------- ### Run Unit Tests with Pytest Source: https://github.com/python-caldav/caldav/blob/master/docs/source/about.md Install test dependencies and execute the test suite using pytest. ```bash $ pip install -e ".[test]" $ pytest ``` -------------------------------- ### GET /caldav/collection/todo/{uid} Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/collection.md Retrieves a specific task (todo) from the calendar using its unique identifier (UID). ```APIDOC ## GET /caldav/collection/todo/{uid} ### Description Retrieves a specific task or todo item from the calendar using its unique identifier (UID). This method is similar to `get_object_by_uid()`. ### Method GET ### Endpoint /caldav/collection/todo/{uid} ### Parameters #### Path Parameters - **uid** (string) - Required - The unique identifier of the todo item to retrieve. ### Response #### Success Response (200) - **CalendarObjectResource** - The `CalendarObjectResource` object representing the requested todo item. ``` -------------------------------- ### Export get_davclient in __init__.py Source: https://github.com/python-caldav/caldav/blob/master/docs/design/GET_DAVCLIENT_ANALYSIS.md Expose the factory function and the client class from the package root. ```python from .davclient import get_davclient __all__ = ["get_davclient", "DAVClient"] # Export both ``` -------------------------------- ### GET /caldav/collection/todos Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/collection.md Fetches a list of todo items from the calendar, with options for sorting and including completed tasks. ```APIDOC ## GET /caldav/collection/todos ### Description Fetches a list of todo items (tasks) from the calendar. This method is a wrapper around a search operation. For synchronous clients, it returns a list of `Todo` objects directly. For asynchronous clients, it returns a coroutine that needs to be awaited. ### Method GET ### Endpoint /caldav/collection/todos ### Parameters #### Query Parameters - **sort_keys** (Sequence[str]) - Optional - A sequence of strings specifying fields for sorting (e.g., ('due', 'priority')). - **include_completed** (boolean) - Optional - If True, includes completed tasks in the results. Defaults to False. - **sort_key** (string) - DEPRECATED - For backwards compatibility with version 0.4. ### Request Example ```python # Sync client example todos = calendar.get_todos() # Async client example todos = await calendar.get_todos() ``` ### Response #### Success Response (200) - **list[Todo]** - A list of `Todo` objects representing the tasks. ``` -------------------------------- ### GET /caldav/collection/supported-components Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/collection.md Retrieves a list of supported calendar component types (e.g., VEVENT, VTODO) by the calendar. ```APIDOC ## GET /caldav/collection/supported-components ### Description Retrieves a list of component types supported by the calendar, such as VJOURNAL, VTODO, or VEVENT. If the server does not explicitly define supported components (RFC 4791 section 5.2.3), a default list is returned. ### Method GET ### Endpoint /caldav/collection/supported-components ### Parameters #### Query Parameters - **with_fallback** (boolean) - Optional - If True (default), returns a default list if the server does not specify supported components. ### Response #### Success Response (200) - **list[string]** - A list of strings representing the supported component types. ``` -------------------------------- ### Create and delete a calendar asynchronously Source: https://github.com/python-caldav/caldav/blob/master/docs/source/async_tutorial.md Demonstrates initializing an async client, creating a new calendar, and cleaning it up. ```python import asyncio from caldav import aio async def main(): client = await aio.get_async_davclient() async with client: my_principal = await client.get_principal() my_new_calendar = await my_principal.make_calendar(name="Teest calendar") ## Enable the debug breakpoint to investigate the calendar object #breakpoint() await my_new_calendar.delete() asyncio.run(main()) ``` -------------------------------- ### Get Journal by UID Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/collection.md Retrieves a specific journal entry from the calendar using its unique identifier (UID). ```APIDOC ## GET /api/calendar/get_journal_by_uid ### Description Gets a journal entry from the calendar by its unique identifier (UID). ### Method GET (or equivalent internal method call) ### Endpoint Not directly exposed as an HTTP endpoint, but represents an internal library function. ### Parameters #### Path Parameters - **uid** (str) - Required - The unique identifier of the journal entry. ### Response #### Success Response (200) - **CalendarObjectResource** - An object representing the journal entry. ### Response Example ```json { "journal_data": "..." } ``` ``` -------------------------------- ### Usage of Synchronous DAVClient with Probe Source: https://github.com/python-caldav/caldav/blob/master/docs/design/GET_DAVCLIENT_ANALYSIS.md Demonstrates how to use the `get_davclient` function, either with the default connection verification or by explicitly skipping the probe using `probe=False`. ```python # Verify connection immediately: with get_davclient(url="...", username="...", password="...") as client: # If we get here, server is reachable principal = client.principal() # Skip probe (for testing or when server might be down): with get_davclient(url="...", probe=False) as client: # No connection attempt yet ... ``` -------------------------------- ### Get Journal Entries Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/collection.md Lists all journal entries from the calendar. This method returns a list of Journal objects. ```python journals = calendar.get_journals() ``` -------------------------------- ### Current Body Parameter Inconsistencies Source: https://github.com/python-caldav/caldav/blob/master/docs/design/API_ANALYSIS.md Examples of inconsistent default values for body parameters across methods. ```python request(url: str, method: str = "GET", body: str = "", ...) # Default "" propfind(url: Optional[str] = None, props: str = "", ...) # Default "" mkcalendar(url: str, body: str = "", ...) # Default "" proppatch(url: str, body: str, ...) # Required mkcol(url: str, body: str, ...) # Required ``` -------------------------------- ### Configure Server Compatibility Hints Source: https://github.com/python-caldav/caldav/blob/master/docs/source/v3-migration.md Apply server-specific workarounds using named profiles or individual flag overrides. ```python client = get_davclient(url="https://...", features="nextcloud", username="alice", password="secret") ``` ```python client = get_davclient(url="https://...", features={"search.text": {"support": "unsupported"}}) ``` -------------------------------- ### Importing get_davclient Source: https://github.com/python-caldav/caldav/blob/master/docs/design/GET_DAVCLIENT_ANALYSIS.md Demonstration of the required import statement. ```python # Doesn't work: from caldav import get_davclient # ImportError! # Must use: from caldav import get_davclient ``` -------------------------------- ### Working with Calendars Source: https://github.com/python-caldav/caldav/blob/master/docs/source/async.md Shows how to create a calendar, add an event, search for events, and delete a calendar using the async API. ```python import asyncio from caldav import aio from datetime import datetime, date async def calendar_demo(): async with await aio.get_async_davclient() as client: principal = await client.get_principal() # Create a new calendar my_calendar = await principal.make_calendar( name="My Async Calendar" ) # Add an event event = await my_calendar.add_event( dtstart=datetime(2025, 6, 15, 10, 0), dtend=datetime(2025, 6, 15, 11, 0), summary="Team meeting" ) # Search for events events = await my_calendar.search( event=True, start=date(2025, 6, 1), end=date(2025, 7, 1) ) print(f"Found {len(events)} events") # Clean up await my_calendar.delete() asyncio.run(calendar_demo()) ``` -------------------------------- ### Initialize CalDAV Client (Async) Source: https://github.com/python-caldav/caldav/blob/master/docs/design/CODE_FLOW.md Instantiate an asynchronous AsyncDAVClient using an async context manager for non-blocking CalDAV operations. ```python from caldav.aio import AsyncDAVClient async with AsyncDAVClient(url="https://server/dav/", username="user", password="pass") as client: principal = await client.principal() calendars = await principal.get_calendars() ``` -------------------------------- ### Get Calendar User Address Set Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/collection.md Retrieves the calendar user address set for a Principal, as defined in RFC6638. ```python addresses = principal.calendar_user_address_set() ``` -------------------------------- ### GET /caldav/collection/objects Source: https://github.com/python-caldav/caldav/blob/master/docs/source/caldav/collection.md Retrieves calendar objects from a collection. Supports synchronization using sync tokens for efficient updates. ```APIDOC ## GET /caldav/collection/objects ### Description Retrieves calendar objects from a collection. This method supports synchronization using sync tokens (RFC 6578) to efficiently fetch only added, deleted, or modified objects since the last sync. If no sync token is provided or if the token is unknown, all objects in the calendar are returned. The `load_objects` parameter controls whether full object data is loaded or just resource information. ### Method GET ### Endpoint /caldav/collection/objects ### Parameters #### Query Parameters - **sync_token** (string) - Optional - The synchronization token to use for fetching changes. - **load_objects** (boolean) - Optional - If True, loads the full object data. Defaults to False. - **disable_fallback** (boolean) - Optional - If True, raises an exception if the server does not support sync tokens, instead of falling back to a full retrieval. ### Response #### Success Response (200) - **SynchronizableCalendarObjectCollection** - An iterable collection of calendar objects or resources. ``` -------------------------------- ### Ruff Configuration for Rewritten Sync Wrappers (Phase 2) Source: https://github.com/python-caldav/caldav/blob/master/docs/design/RUFF_CONFIGURATION_PROPOSAL.md Ruff configuration for Phase 2, expanding the `include` list to incorporate rewritten sync wrapper files alongside existing async files. ```toml include = [ # Async files "caldav/async_davclient.py", "caldav/async_davobject.py", "caldav/async_collection.py", # Rewritten sync wrappers "caldav/davclient.py", # Added after rewrite # Tests "tests/test_async_*.py", "tests/test_davclient.py", # Added after rewrite ] ``` -------------------------------- ### Get vobject Component Copy Source: https://github.com/python-caldav/caldav/blob/master/docs/source/v3-migration.md Retrieve a copy of the vobject component for read-only access. Modifications to this copy will not be persisted. ```python # Get a copy of the vobject component — changes are NOT saved vobj_copy = event.get_vobject_instance() summary = vobj_copy.vevent.summary.value ```