Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
28f97e2
feat(jmap): add JMAP calendar client foundation
SashankBhamidi Feb 19, 2026
7d14f94
style: apply ruff formatting fixes
SashankBhamidi Feb 19, 2026
edb0009
feat(jmap): add context manager support to JMAPClient
SashankBhamidi Feb 19, 2026
d32d8da
fix(jmap): correct RFC attributions in constants.py; add get_jmap_cli…
SashankBhamidi Feb 19, 2026
06c6221
fix(jmap): exclude server-set fields from JMAPCalendar.to_jmap()
SashankBhamidi Feb 20, 2026
9add0b7
feat(jmap): add JMAPEvent dataclass and CalendarEvent method builders
SashankBhamidi Feb 20, 2026
d8a2c30
fix(jmap): resolve relative apiUrl in fetch_session against base URL
SashankBhamidi Feb 20, 2026
4295d24
style(jmap): remove redundant section-label comment from JMAPClient
SashankBhamidi Feb 20, 2026
cbad191
fix(jmap): handle null collection fields in JMAPEvent.from_jmap; expa…
SashankBhamidi Feb 20, 2026
b7605dd
feat(jmap): add iCalendar ↔ JSCalendar conversion layer
SashankBhamidi Feb 20, 2026
ea68767
fix(deps): ignore pytz in deptry DEP003 check
SashankBhamidi Feb 20, 2026
cd04ae9
fix(jmap): correct parse_event_set return type; handle int byMonth va…
SashankBhamidi Feb 20, 2026
0a451c8
style: apply ruff-format to jscal_to_ical byMonth fix
SashankBhamidi Feb 20, 2026
d6c5525
refactor(jmap): deduplicate participant imip extraction
SashankBhamidi Feb 20, 2026
be8cd5d
feat(jmap): add event CRUD methods to JMAPClient
SashankBhamidi Feb 20, 2026
326c063
fix(jmap): add timeout to fetch_session; drop unused variable in test
SashankBhamidi Feb 20, 2026
5f0dc59
feat(jmap): add JMAPClient.search_events with batched query+get
SashankBhamidi Feb 20, 2026
ff55e65
fix(jmap): narrow broad exception catch in pytz timezone handling
SashankBhamidi Feb 20, 2026
23d578b
feat(jmap): add get_sync_token and get_objects_by_sync_token
SashankBhamidi Feb 20, 2026
b1f4b55
feat(jmap): add Task and TaskList support via RFC 9553
SashankBhamidi Feb 20, 2026
02a88f1
style: remove section-label comments from JMAP test files
SashankBhamidi Feb 20, 2026
703ad6b
feat(jmap): add AsyncJMAPClient mirroring public methods as coroutines
SashankBhamidi Feb 20, 2026
206360c
fix(jmap): replace deprecated pytz with stdlib zoneinfo in jscal_to_ical
SashankBhamidi Feb 20, 2026
791aa42
fix(jmap): replace deprecated pytz with stdlib zoneinfo in jscal_to_ical
SashankBhamidi Feb 20, 2026
98fa9cc
fix(jmap): remove duplicate pytz block left by partial suggestion apply
SashankBhamidi Feb 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions caldav/jmap/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
"""
JMAP calendar support for python-caldav.

Provides synchronous and asynchronous JMAP clients with the same public API as
the CalDAV client, so user code works regardless of server protocol.

Basic usage::

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

from caldav.jmap.async_client import AsyncJMAPClient
from caldav.jmap.client import JMAPClient
from caldav.jmap.error import (
JMAPAuthError,
JMAPCapabilityError,
JMAPError,
JMAPMethodError,
)

_JMAP_KEYS = {"url", "username", "password", "auth", "auth_type", "timeout"}


def get_jmap_client(**kwargs) -> JMAPClient | None:
"""Create a :class:`JMAPClient` from configuration.

Configuration is read from the same sources as :func:`caldav.get_davclient`:

1. Explicit keyword arguments (``url``, ``username``, ``password``, …)
2. Environment variables (``CALDAV_URL``, ``CALDAV_USERNAME``, …)
3. Config file (``~/.config/caldav/calendar.conf`` or equivalent)

Returns ``None`` if no configuration is found, matching the behaviour
of :func:`caldav.get_davclient`.

Example::

client = get_jmap_client(url="https://jmap.example.com/.well-known/jmap",
username="alice", password="secret")
"""
from caldav.config import get_connection_params

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 _JMAP_KEYS})


def get_async_jmap_client(**kwargs) -> AsyncJMAPClient | None:
"""Create an :class:`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()
"""
from caldav.config import get_connection_params

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 _JMAP_KEYS})


__all__ = [
"JMAPClient",
"AsyncJMAPClient",
"get_jmap_client",
"get_async_jmap_client",
"JMAPError",
"JMAPCapabilityError",
"JMAPAuthError",
"JMAPMethodError",
]
Loading