async_client: Async JMAP calendar client#
Asynchronous JMAP client.
Mirrors JMAPClient with all public methods as coroutines.
Uses niquests’ AsyncSession for HTTP: the one part of calendaring-jmap with
no fallback to another HTTP library. See calendaring_jmap._http.
All response-parsing logic lives in _JMAPClientBase (client.py); each method here is a ~3-line async wrapper: get session, send request, delegate to parser.
- class calendaring_jmap.async_client.AsyncJMAPClient(url: str, username: str | None = None, password: str | None = None, auth=None, auth_type: str | None = None, timeout: int = 30)[source]#
Bases:
_JMAPClientBaseAsynchronous JMAP client for calendar operations.
The JMAP support is experimental, the API may change in minor-releases
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()
- Parameters:
url – URL of the JMAP session endpoint (
/.well-known/jmap).username – Username for Basic auth.
password – Password for Basic auth, or bearer token if no username.
auth – A pre-built niquests-compatible auth object. Takes precedence over username/password if provided.
auth_type – Force a specific auth type:
"basic"or"bearer".timeout – HTTP request timeout in seconds.
Unless a method’s own docstring says otherwise, its
account_idparameter is the JMAP account to operate on, defaulting to the authenticated user’s own primary account; pass a different account (typically one shared with you viashare_calendar) to operate on that account’s data instead.- async accept_invitation(event_id: str, own_email: str, account_id: str | None = None) None[source]#
Accept a meeting invitation, notifying the organizer.
See
accept_invitation()for the full semantics.
- async aclose() None[source]#
Release the persistent HTTP session and its connection pool.
Only needed when the client was not used as an async context manager: the documented Quick Start builds one directly. Idempotent; the session is recreated on the next request.
- async attach_to_event(event_id: str, blob_id: str, name: str, content_type: str, account_id: str | None = None) None[source]#
Attach an uploaded blob to a calendar event.
See
attach_to_event()for the full semantics.
- async confirm_push_verification(subscription_id: str, verification_code: str) None[source]#
Submit the verification code the server POSTed to
callback_url.See
confirm_push_verification()for the full semantics.
- async create_calendar(name: str, color: str | None = None, timezone: str | None = None) str[source]#
Create a calendar.
- Returns:
The server-assigned JMAP calendar ID.
- Raises:
JMAPMethodError – If the server rejects the create request.
- async create_event(calendar_id: str, ical_str: str, account_id: str | None = None, if_in_state: str | None = None) str[source]#
Create a calendar event from an iCalendar string.
- Parameters:
calendar_id – The JMAP calendar ID to create the event in.
ical_str – A VCALENDAR string representing the event.
account_id – The account owning
calendar_id; pass the owner’s account here to add an event to a calendar shared with you (seeget_calendars(account_id=...)).if_in_state – A state string from a prior call that read this account’s calendar state. If the account has changed since, the server rejects the create with
JMAPMethodError(error_type == "stateMismatch") instead of applying it (RFC 8620 Section 5.3). The state covers every event in the account, not just this one.Noneapplies unconditionally.
- Returns:
The server-assigned JMAP event ID.
- Raises:
JMAPMethodError – If the server rejects the create request.
ValueError – If
ical_stris malformed in a wayical_to_jscalrejects (missingUID/DTSTART, a negative duration, mismatchedDTSTART/DTENDvalue types).
- async create_task(task_list_id: str, title: str, **kwargs) str[source]#
Create a task in a task list.
- Parameters:
task_list_id – The JMAP task list ID to create the task in.
title – Task title (maps to VTODO
SUMMARY).**kwargs – Optional JMAP Task fields using wire names:
description,due,start,timeZone,estimatedDuration,percentComplete,progress,priority.
- Returns:
The server-assigned JMAP task ID.
- Raises:
JMAPMethodError – If the server rejects the create request.
- async decline_invitation(event_id: str, own_email: str, account_id: str | None = None) None[source]#
Decline a meeting invitation, notifying the organizer.
Same as
accept_invitation(), settingparticipationStatusto declined instead.
- async delete_calendar(calendar_id: str, on_destroy_remove_events: bool = False, account_id: str | None = None) None[source]#
Delete a calendar.
- Parameters:
calendar_id – The JMAP calendar ID to delete.
on_destroy_remove_events – If
False(the default), deleting a calendar that still has events fails with acalendarHasEventerror instead of deleting anything. PassTrueto remove those events along with the calendar.account_id – The account owning
calendar_id; pass the owner’s account here to delete a calendar shared with you.
- Raises:
JMAPMethodError – If the server rejects the delete.
error_typeis"calendarHasEvent"when the calendar still has events andon_destroy_remove_eventswas leftFalse.
- async delete_event(event_id: str, account_id: str | None = None, send_scheduling_messages: bool = False, if_in_state: str | None = None) None[source]#
Delete a calendar event.
- Parameters:
event_id – The JMAP event ID to delete.
account_id – The account owning
event_id; pass the owner’s account here to delete an event on a calendar shared with you.send_scheduling_messages – If true, and this account is the event’s origin, the server sends an iTIP CANCEL to the event’s participants (draft-ietf-jmap-calendars section 5.9.2.2).
if_in_state – A state string from a prior call that read this account’s calendar state. If the account has changed since, the server rejects the delete with
JMAPMethodError(error_type == "stateMismatch") instead of applying it (RFC 8620 Section 5.3). The state covers every event in the account, not just this one.Noneapplies unconditionally.
- Raises:
JMAPMethodError – If the server rejects the delete.
- async delete_task(task_id: str) None[source]#
Delete a task.
- Parameters:
task_id – The JMAP task ID to delete.
- Raises:
JMAPMethodError – If the server rejects the delete.
- async download_attachment(blob_id: str, content_type: str | None = None, filename: str | None = None, account_id: str | None = None) bytes[source]#
Download a JMAP blob by id.
See
download_attachment()for the full semantics.
- async get_address_books(account_id: str | None = None) list[JMAPAddressBook][source]#
Fetch all address books for an account.
See
get_address_books()for the full semantics, including the capability-fallback behavior.
- async get_availability(account_ids: list[str], start: str, end: str, show_details: bool = False) dict[str, list[BusyInterval]][source]#
Return busy intervals for each of your own accounts over a time period.
See
get_availability()for the full semantics.
- async get_calendar_subscriptions() list[JMAPCalendar[Literal[True]]][source]#
Fetch the calendars the authenticated account is subscribed to.
JMAP Calendars has no separate subscription object; this is
get_calendars()filtered tois_subscribed.- Returns:
List of
JMAPCalendarobjects withis_subscribedset.
- async get_calendars(account_id: str | None = None) list[JMAPCalendar[Literal[True]]][source]#
Fetch all calendars for an account.
- Parameters:
account_id – Pass a different account here to browse calendars another user has shared with you, once
share_calendarhas granted access; the session only lists accounts you can actually reach (seeSession.raw["accounts"]).- Returns:
List of
JMAPCalendarobjects.
- async get_event(event_id: str, account_id: str | None = None) JMAPCalendarObject[source]#
Fetch a calendar event as an iCalendar string.
- Parameters:
event_id – The JMAP event ID to retrieve.
account_id – The account owning
event_id; pass the owner’s account here to fetch an event on a calendar shared with you.
- Returns:
A
JMAPCalendarObjectwrapping the raw JSCalendar dict.parentisNonesince noJMAPCalendaris available at the client level.- Raises:
JMAPMethodError – If the event is not found.
- async get_event_attachments(event_id: str, account_id: str | None = None) list[JMAPAttachment][source]#
Return the attachments on a calendar event.
See
get_event_attachments()for the full semantics.
- async get_objects_by_sync_token(sync_token: str, account_id: str | None = None, max_changes: int | None = None) tuple[list[JMAPCalendarObject], list[JMAPCalendarObject], list[str], str, str, bool][source]#
Fetch one page of events changed since a previous sync token.
Calls
CalendarEvent/changesto discover which events were created, modified, or destroyed sincesync_tokenwas issued. Created and modified events are returned asJMAPCalendarObjectinstances; destroyed events are returned as IDs (the objects no longer exist on the server).- Parameters:
sync_token – A state string previously returned by
get_sync_token()or by a prior call to this method.account_id – The account to fetch changes for; pass a different account here to sync a calendar shared with you. Must match the account
sync_tokenwas issued for.max_changes – Optional upper bound on the number of changes the server returns in this page. See
get_objects_by_sync_token()for the paging behavior this enables.
- Returns:
added: objects for newly created events (parentisNone).modified: objects for updated events (parentisNone).deleted: Event IDs that were destroyed.old_state: Thesync_tokenargument echoed back by the server. Compare this againstsync_tokento detect a server that silently accepted an invalid or stale state instead of reporting an error (RFC 8620 Section 5.2 does not require a server to validatesinceStateagainst a real prior state; confirmed live that Cyrus echoes back whatever value it was given, including one that was never actually issued, rather than rejecting it).new_state: Pass to the next call to this method assync_token, whether or nothas_more_changesis set. Named to matcholdState/newStateas a pair (RFC 8620 Section 5.2), notsync_token: both names refer to the same kind of value, a state string previously returned by this method orget_sync_token().has_more_changes: If true, the server capped this page and more changes remain; call this method again withnew_stateto fetch the next page (RFC 8620 Section 5.2).
- Return type:
A 6-tuple
(added, modified, deleted, old_state, new_state, has_more_changes)
- async get_sync_token(account_id: str | None = None) str[source]#
Return the current CalendarEvent state string for use as a sync token.
Calls
CalendarEvent/getwith an empty ID list, so no event data is transferred, only thestatefield from the response.- Parameters:
account_id – The account to read the state of; pass a different account here to sync a calendar shared with you, since a JMAP state string is scoped to one account, not the whole session.
- Returns:
Opaque state string. Pass to
get_objects_by_sync_token()to retrieve only what changed since this point.
- async get_task(task_id: str) dict[source]#
Fetch a task by ID.
- Parameters:
task_id – The JMAP task ID to retrieve.
- Returns:
Raw JMAP Task dict as returned by the server.
- Raises:
JMAPMethodError – If the task is not found.
- async get_task_lists() list[dict][source]#
Fetch all task lists for the authenticated account.
- Returns:
List of raw JMAP TaskList dicts as returned by the server.
- async get_task_sync_token(account_id: str | None = None) str[source]#
Return the current Task state string for use as a sync token.
Calls
Task/getwith an empty ID list, so no task data is transferred, only thestatefield from the response. Reads theTasktype’s own state counter, notTaskList’s: RFC 8620 Section 5.2’s/changesis scoped per type, andget_tasks_by_sync_token()callsTask/changes, which only accepts a state previously returned forTaskitself.- Parameters:
account_id – The account to read the state of; pass a different account here to sync a task list shared with you, since a JMAP state string is scoped to one account, not the whole session.
- Returns:
Opaque state string. Pass to
get_tasks_by_sync_token()to retrieve only what changed since this point.
- async get_tasks_by_sync_token(sync_token: str, account_id: str | None = None, max_changes: int | None = None) tuple[list[dict], list[dict], list[str], str, str, bool][source]#
Fetch one page of tasks changed since a previous sync token.
Calls
Task/changesto discover which tasks were created, modified, or destroyed sincesync_tokenwas issued. Created and modified tasks are returned as raw JMAP Task dicts, matching every other task method’s own return convention; destroyed tasks are returned as IDs.- Parameters:
sync_token – A state string previously returned by
get_task_sync_token()or by a prior call to this method.account_id – The account to fetch changes for; pass a different account here to sync a task list shared with you. Must match the account
sync_tokenwas issued for.max_changes – Optional upper bound on the number of changes the server returns in this page. See
get_objects_by_sync_token()for the paging behavior this enables.
- Returns:
added: raw dicts for newly created tasks.modified: raw dicts for updated tasks.deleted: Task IDs that were destroyed.old_state: Thesync_tokenargument echoed back by the server. Seeget_objects_by_sync_token()for why this is worth comparing againstsync_tokenyourself.new_state: Pass to the next call to this method assync_token, whether or nothas_more_changesis set. Seeget_objects_by_sync_token()for why this is namednew_staterather thansync_token.has_more_changes: If true, the server capped this page and more changes remain; call this method again withnew_stateto fetch the next page (RFC 8620 Section 5.2).
- Return type:
A 6-tuple
(added, modified, deleted, old_state, new_state, has_more_changes)
- async renew_push(subscription_id: str, expires: str | None = None) None[source]#
Extend (or shorten) a push subscription’s expiry.
See
renew_push()for the full semantics.
- async search_contacts(text: str | None = None, email: str | None = None, account_id: str | None = None) list[JMAPContact][source]#
Search for contact cards.
See
search_contacts()for the full semantics.
- async search_events(calendar_id: str | None = None, start: str | None = None, end: str | None = None, text: str | None = None, has_attachment: bool | None = None, participant_email: str | None = None, participation_status: str | None = None, participant_role: str | None = None, account_id: str | None = None, position: int = 0, limit: int | None = None, calculate_total: bool = False) EventSearchResult[source]#
Search for calendar events.
See
search_events()for the full semantics, including whyhas_attachment/participant_email/participation_status/participant_rolefilter client-side and their confirmed server-specific false-negatives, and howtotalbehaves oncalculate_total.
- async search_tasks(text: str | None = None, due_before: str | None = None, due_after: str | None = None, progress: str | None = None) list[dict][source]#
Search for tasks.
See
search_tasks()for the full semantics, including whydue_before/due_after/progressfilter client-side and what theTask/query-unsupported fallback can and cannot help with.
- async send_invite(calendar_id: str, ical_str: str, account_id: str | None = None, if_in_state: str | None = None) str[source]#
Create a calendar event and notify its participants.
Identical to
create_event(), except the server actually dispatches iTIP invitations to the event’s participants (an iCalendar string with ATTENDEE/ORGANIZER properties).create_eventitself never sends scheduling messages; use this instead when the event has participants who need to be notified.- Parameters:
calendar_id – The JMAP calendar ID to create the event in.
ical_str – A VCALENDAR string representing the event.
account_id – The account owning
calendar_id, same ascreate_event().if_in_state – See
create_event().
- Returns:
The server-assigned JMAP event ID.
- Raises:
JMAPMethodError – If the server rejects the create request, or with
error_type == "noSupportedScheduleMethods"if a participant has no usable delivery method.ValueError – Same conditions as
create_event().
- async set_default_alerts(calendar_id: str, alerts_with_time: dict | None = None, alerts_without_time: dict | None = None, account_id: str | None = None) None[source]#
Set a calendar’s default alerts for new events.
alerts_with_timeapplies to timed events,alerts_without_timeto all-day events (draft-ietf-jmap-calendars section 4). Each is a map of alert ID to Alert dict (RFC 8984 Section 4.5.2). PassNoneto leave a property unchanged; pass{}to clear it.- Parameters:
account_id – The account owning
calendar_id; pass the owner’s account here to set default alerts on a calendar shared with you.- Raises:
JMAPMethodError – If the server rejects the update.
Share a calendar with another account.
account_idmust already be a resolved JMAP Principal ID, not an email address. This client has noPrincipal/query/Principal/getsupport yet (RFC 9670), so resolving an email address to a Principal ID is left to the caller.Replaces
account_id’s entry in the calendar’sshareWithmap wholesale; other accounts already sharing the calendar are left untouched.rightsitself is not merged with any rights that account already had, so granting an additional right to an account that is already shared with needs the full rights dict, not just the new key. Requires the caller to already hold themayShareright, and cannot grant a right the caller does not themselves hold.- Parameters:
account_id – The account to grant rights to.
rights – Dict of right names to bool, e.g.
{"mayReadItems": True}. Replaces any rights this account already had on this calendar.owning_account_id – The account owning
calendar_id; pass the owner’s account here to re-share a calendar that was itself shared with you (if you holdmayShareon it).
- Raises:
JMAPMethodError – If the server rejects the update, for example with
forbiddenwhen the caller lacksmayShare.
- async subscribe_push(callback_url: str, device_client_id: str, types: list[str] | None = None) str[source]#
Register a push subscription.
See
subscribe_push()for the full semantics, including why this client cannot complete the verification handshake by itself.
- async tentatively_accept(event_id: str, own_email: str, account_id: str | None = None) None[source]#
Tentatively accept a meeting invitation, notifying the organizer.
Same as
accept_invitation(), settingparticipationStatusto tentative instead.
- async unsubscribe_push(subscription_id: str) None[source]#
Destroy a push subscription.
See
unsubscribe_push()for the full semantics.
- async update_calendar(calendar_id: str, name: str | None = None, color: str | None = None, timezone: str | None = None, account_id: str | None = None) None[source]#
Update a calendar’s name, color, or time zone.
name,color, andtimeZoneare per-user properties (draft-ietf-jmap-calendars section 4.3). Called by the calendar’s owner, this changes the value for everyone until a sharee sets their own override. Called by a sharee, it only ever changes that sharee’s own view; it can never rename or recolor the calendar for the owner or anyone else it is shared with.- Parameters:
account_id – The account owning
calendar_id; pass the owner’s account here to update a calendar shared with you.- Raises:
JMAPMethodError – If the server rejects the update.
- async update_event(event_id: str, ical_str: str, account_id: str | None = None, if_in_state: str | None = None) None[source]#
Update a calendar event from an iCalendar string.
- Parameters:
event_id – The JMAP event ID to update.
ical_str – A VCALENDAR string with the updated event data.
account_id – The account owning
event_id; pass the owner’s account here to update an event on a calendar shared with you.if_in_state – A state string from a prior call that read this account’s calendar state. If the account has changed since, the server rejects the update with
JMAPMethodError(error_type == "stateMismatch") instead of applying it (RFC 8620 Section 5.3). The state covers every event in the account, not just this one.Noneapplies unconditionally. Sent unchanged on every retry of the null-key-dropping loop below, since those retries narrow the same patch rather than re-reading the account’s state.
- Raises:
JMAPMethodError – If the server rejects the update.
ValueError – If
ical_stris malformed in a wayical_to_jscalrejects (missingUID/DTSTART, a negative duration, mismatchedDTSTART/DTENDvalue types).