Source code for calendaring_jmap

# SPDX-FileCopyrightText: 2026 calendaring-jmap contributors
# SPDX-License-Identifier: AGPL-3.0-or-later

"""
Calendar operations over JMAP (RFC 8620 + JMAP Calendars).

Provides synchronous and asynchronous JMAP clients for calendar listing,
event CRUD, incremental sync, and task CRUD.

Basic usage::

    from calendaring_jmap import get_jmap_client

    client = get_jmap_client(
        url="https://jmap.example.com/.well-known/jmap",
        username="alice",
        password="secret",
    )
    calendars = client.get_calendars()

Async usage::

    from calendaring_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()
"""

from calendaring_jmap._config import _CONN_KEYS, get_connection_params
from calendaring_jmap._version import __version__
from calendaring_jmap.async_client import AsyncJMAPClient
from calendaring_jmap.client import JMAPClient
from calendaring_jmap.error import (
    JMAPAuthError,
    JMAPCapabilityError,
    JMAPError,
    JMAPMethodError,
)
from calendaring_jmap.objects.attachment import JMAPAttachment
from calendaring_jmap.objects.busy_interval import BusyInterval
from calendaring_jmap.objects.calendar import JMAPCalendar
from calendaring_jmap.objects.calendar_object import JMAPCalendarObject
from calendaring_jmap.objects.contact import JMAPAddressBook, JMAPContact


[docs] def get_jmap_client(**kwargs) -> JMAPClient | None: """Create a :class:`~calendaring_jmap.client.JMAPClient` from configuration. Configuration is read in priority order: 1. Explicit keyword arguments (``url``, ``username``, ``password``, …) 2. Environment variables (``JMAP_URL``, ``JMAP_USERNAME``, …) 3. A YAML config file (``~/.config/calendaring-jmap/calendar.yaml`` or equivalent) Returns ``None`` if no configuration is found, rather than raising. Example:: client = get_jmap_client(url="https://jmap.example.com/.well-known/jmap", username="alice", password="secret") """ conn_params = get_connection_params(**kwargs) if conn_params is None: return None return JMAPClient(**{k: v for k, v in conn_params.items() if k in _CONN_KEYS})
[docs] def get_async_jmap_client(**kwargs) -> AsyncJMAPClient | None: """Create an :class:`~calendaring_jmap.async_client.AsyncJMAPClient` from configuration. Accepts the same arguments and reads configuration from the same sources as :func:`get_jmap_client`. Returns ``None`` if no configuration is found. Example:: 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() """ conn_params = get_connection_params(**kwargs) if conn_params is None: return None return AsyncJMAPClient(**{k: v for k, v in conn_params.items() if k in _CONN_KEYS})
__all__ = [ "AsyncJMAPClient", "BusyInterval", "JMAPAddressBook", "JMAPAttachment", "JMAPAuthError", "JMAPCalendar", "JMAPCalendarObject", "JMAPCapabilityError", "JMAPClient", "JMAPContact", "JMAPError", "JMAPMethodError", "__version__", "get_async_jmap_client", "get_jmap_client", ]