objects – Object definitions

A “DAV object” is anything we get from the caldav server or push into the caldav server, notably principal, calendars and calendar events.

(This file has become huge and will be split up prior to the next release. I think it makes sense moving the CalendarObjectResource class hierarchy into a separate file)

class caldav.objects.Calendar(client=None, url=None, parent=None, name=None, id=None, props=None, **extra)

The Calendar object is used to represent a calendar collection. Refer to the RFC for details: https://tools.ietf.org/html/rfc4791#section-5.3.1

add_event(ical=None, no_overwrite=False, no_create=False, **ical_data)

Add a new event to the calendar, with the given ical.

Parameters:
  • ical - ical object (text)
  • no_overwrite - existing calendar objects should not be overwritten
  • no_create - don’t create a new object, existing calendar objects should be updated
  • ical_data - passed to lib.vcal.create_ical
add_journal(ical=None, no_overwrite=False, no_create=False, **ical_data)

Add a new journal entry to the calendar, with the given ical.

Parameters:
  • ical - ical object (text)
add_todo(ical=None, no_overwrite=False, no_create=False, **ical_data)

Add a new task to the calendar, with the given ical.

Parameters:
  • ical - ical object (text)
build_date_search_query(start, end=None, compfilter='VEVENT', expand='maybe')

WARNING: DEPRECATED

build_search_xml_query(comp_class=None, todo=None, ignore_completed1=None, ignore_completed2=None, ignore_completed3=None, event=None, filters=None, expand=None, start=None, end=None, props=None, **kwargs)

This method will produce a caldav search query as an etree object.

It is primarily to be used from the search method. See the documentation for the search method for more information.

calendar_multiget(event_urls)

get multiple events’ data @author mtorange@gmail.com @type events list of Event

Deprecated. Use self.search() instead.

Search events by date in the calendar. Recurring events are expanded if they are occuring during the specified time frame and if an end timestamp is given.

Parameters:
  • start = datetime.today().
  • end = same as above.
  • compfilter = defaults to events only. Set to None to fetch all calendar components.
  • expand - should recurrent events be expanded? (to preserve backward-compatibility the default “maybe” will be changed into True unless the date_search is open-ended)
  • verify_expand - not in use anymore, but kept for backward compatibility
Returns:
  • [CalendarObjectResource(), …]
event_by_url(href, data=None)

Returns the event with the given URL

events()

List all events from the calendar.

Returns:
  • [Event(), …]
freebusy_request(start, end)

Search the calendar, but return only the free/busy information.

Parameters:
  • start = datetime.today().
  • end = same as above.
Returns:
  • [FreeBusy(), …]
get_supported_components()

returns a list of component types supported by the calendar, in string format (typically [‘VJOURNAL’, ‘VTODO’, ‘VEVENT’])

journals()

List all journals from the calendar.

Returns:
  • [Journal(), …]
object_by_uid(uid, comp_filter=None, comp_class=None)

Get one event from the calendar.

Parameters:
  • uid: the event uid
  • comp_class: filter by component type (Event, Todo, Journal)
  • comp_filter: for backward compatibility
Returns:
  • Event() or None
objects(sync_token=None, load_objects=False)

objects_by_sync_token aka objects

Do a sync-collection report, ref RFC 6578 and https://github.com/python-caldav/caldav/issues/87

This method will return all objects in the calendar if no sync_token is passed (the method should then be referred to as “objects”), or if the sync_token is unknown to the server. If a sync-token known by the server is passed, it will return objects that are added, deleted or modified since last time the sync-token was set.

If load_objects is set to True, the objects will be loaded - otherwise empty CalendarObjectResource objects will be returned.

This method will return a SynchronizableCalendarObjectCollection object, which is an iterable.

objects_by_sync_token(sync_token=None, load_objects=False)

objects_by_sync_token aka objects

Do a sync-collection report, ref RFC 6578 and https://github.com/python-caldav/caldav/issues/87

This method will return all objects in the calendar if no sync_token is passed (the method should then be referred to as “objects”), or if the sync_token is unknown to the server. If a sync-token known by the server is passed, it will return objects that are added, deleted or modified since last time the sync-token was set.

If load_objects is set to True, the objects will be loaded - otherwise empty CalendarObjectResource objects will be returned.

This method will return a SynchronizableCalendarObjectCollection object, which is an iterable.

save()

The save method for a calendar is only used to create it, for now. We know we have to create it when we don’t have a url.

Returns:
  • self
save_event(ical=None, no_overwrite=False, no_create=False, **ical_data)

Add a new event to the calendar, with the given ical.

Parameters:
  • ical - ical object (text)
  • no_overwrite - existing calendar objects should not be overwritten
  • no_create - don’t create a new object, existing calendar objects should be updated
  • ical_data - passed to lib.vcal.create_ical
save_journal(ical=None, no_overwrite=False, no_create=False, **ical_data)

Add a new journal entry to the calendar, with the given ical.

Parameters:
  • ical - ical object (text)
save_todo(ical=None, no_overwrite=False, no_create=False, **ical_data)

Add a new task to the calendar, with the given ical.

Parameters:
  • ical - ical object (text)
save_with_invites(ical, attendees, **attendeeoptions)

sends a schedule request to the server. Equivalent with save_event, save_todo, etc, but the attendees will be added to the ical object before sending it to the server.

search(xml=None, comp_class=None, todo=None, include_completed=False, sort_keys=(), split_expanded=True, props=None, **kwargs)

Creates an XML query, does a REPORT request towards the server and returns objects found, eventually sorting them before delivery.

This method contains some special logics to ensure that it can consistently return a list of pending tasks on any server implementation. In the future it may also include workarounds and client side filtering to make sure other search results are consistent on different server implementations.

Parameters supported:

  • xml - use this search query, and ignore other filter parameters
  • comp_class - set to event, todo or journal to restrict search to this resource type. Some server implementations require this to be set.
  • todo - sets comp_class to Todo, and restricts search to pending tasks, unless the next parameter is set …
  • include_completed - include completed tasks
  • event - sets comp_class to event
  • text attribute search parameters: category, uid, summary, omment, description, location, status
  • no-category, no-summary, etc … search for objects that does not have those attributes. TODO: WRITE TEST CODE!
  • expand - do server side expanding of recurring events/tasks
  • start, end: do a time range search
  • filters - other kind of filters (in lxml tree format)
  • sort_keys - list of attributes to use when sorting

not supported yet: * negated text match * attribute not set

todos(sort_keys=('due', 'priority'), include_completed=False, sort_key=None)

fetches a list of todo events (refactored to a wrapper around search)

Parameters:
  • sort_keys: use this field in the VTODO for sorting (iterable of lower case string, i.e. (‘priority’,’due’)).
  • include_completed: boolean - by default, only pending tasks are listed
  • sort_key: DEPRECATED, for backwards compatibility with version 0.4.
class caldav.objects.CalendarObjectResource(client=None, url=None, data=None, parent=None, id=None, props=None)

Ref RFC 4791, section 4.1, a “Calendar Object Resource” can be an event, a todo-item, a journal entry, or a free/busy entry

add_attendee(attendee, no_default_parameters=False, **parameters)

For the current (event/todo/journal), add an attendee.

The attendee can be any of the following: * A principal * An email address prepended with “mailto:” * An email address without the “mailto:”-prefix * A two-item tuple containing a common name and an email address * (not supported, but planned: an ical text line starting with the word “ATTENDEE”)

Any number of attendee parameters can be given, those will be used as defaults unless no_default_parameters is set to True:

partstat=NEEDS-ACTION cutype=UNKNOWN (unless a principal object is given) rsvp=TRUE role=REQ-PARTICIPANT schedule-agent is not set

add_organizer()

goes via self.client, finds the principal, figures out the right attendee-format and adds an organizer line to the event

copy(keep_uid=False, new_parent=None)

Events, todos etc can be copied within the same calendar, to another calendar or even to another caldav server

data

vCal representation of the object as normal string

expand_rrule(start, end)

This method will transform the calendar content of the event and expand the calendar data from a “master copy” with RRULE set and into a “recurrence set” with RECURRENCE-ID set and no RRULE set. The main usage is for client-side expansion in case the calendar server does not support server-side expansion. It should be safe to save back to the server, the server should recognize it as recurrences and should not edit the “master copy”. If doing a self.load, the calendar content will be replaced with the “master copy”. However, as of 2022-10 there is no test code verifying this.

Parameters:
  • event – Event
  • start – datetime.datetime
  • end – datetime.datetime
get_dtend()

A VTODO may have due or duration set. Return or calculate due.

WARNING: this method is likely to be deprecated and moved to the icalendar library. If you decide to use it, please put caldav<2.0 in the requirements.

get_due()

A VTODO may have due or duration set. Return or calculate due.

WARNING: this method is likely to be deprecated and moved to the icalendar library. If you decide to use it, please put caldav<2.0 in the requirements.

get_duration()

According to the RFC, either DURATION or DUE should be set for a task, but never both - implicitly meaning that DURATION is the difference between DTSTART and DUE (personally I believe that’s stupid. If a task takes five minutes to complete - say, fill in some simple form that should be delivered before midnight at new years eve, then it feels natural for me to define “duration” as five minutes, DTSTART to “some days before new years eve” and DUE to 20xx-01-01 00:00:00 - but I digress.

This method will return DURATION if set, otherwise the difference between DUE and DTSTART (if both of them are set).

TODO: should be fixed for Event class as well (only difference is that DTEND is used rather than DUE) and possibly also for Journal (defaults to one day, probably?)

WARNING: this method is likely to be deprecated and moved to the icalendar library. If you decide to use it, please put caldav<2.0 in the requirements.

get_relatives(reltypes=None, relfilter=None, fetch_objects=True, ignore_missing=True)

By default, loads all objects pointed to by the RELATED-TO property and loads the related objects.

It’s possible to filter, either by passing a set or a list of acceptable relation types in reltypes, or by passing a lambda function in relfilter.

TODO: Make it possible to also check up reverse relationships

TODO: this is partially overlapped by plann.lib._relships_by_type in the plann tool. Should consolidate the code.

icalendar_component

icalendar component - should not be used with recurrence sets

icalendar_instance

icalendar instance of the object

instance

vobject instance of the object

load(only_if_unloaded=False)

(Re)load the object from the caldav server.

save(no_overwrite=False, no_create=False, obj_type=None, increase_seqno=True, if_schedule_tag_match=False)

Save the object, can be used for creation and update.

no_overwrite and no_create will check if the object exists. Those two are mutually exclusive. Some servers don’t support searching for an object uid without explicitly specifying what kind of object it should be, hence obj_type can be passed. obj_type is only used in conjunction with no_overwrite and no_create.

Returns:
  • self
set_relation(other, reltype=None, set_reverse=True)

Sets a relation between this object and another object (given by uid or object).

vobject_instance

vobject instance of the object

wire_data

vCal representation of the object in wire format (UTF-8, CRLN)

class caldav.objects.CalendarSet(client=None, url=None, parent=None, name=None, id=None, props=None, **extra)

A CalendarSet is a set of calendars.

calendar(name=None, cal_id=None)

The calendar method will return a calendar object. If it gets a cal_id but no name, it will not initiate any communication with the server

Parameters:
  • name: return the calendar with this display name
  • cal_id: return the calendar with this calendar id or URL
Returns:
  • Calendar(…)-object
calendars()

List all calendar collections in this set.

Returns:
  • [Calendar(), …]
make_calendar(name=None, cal_id=None, supported_calendar_component_set=None)

Utility method for creating a new calendar.

Parameters:
  • name: the display name of the new calendar
  • cal_id: the uuid of the new calendar
  • supported_calendar_component_set: what kind of objects (EVENT, VTODO, VFREEBUSY, VJOURNAL) the calendar should handle. Should be set to [‘VTODO’] when creating a task list in Zimbra - in most other cases the default will be OK.
Returns:
  • Calendar(…)-object
class caldav.objects.DAVObject(client=None, url=None, parent=None, name=None, id=None, props=None, **extra)

Base class for all DAV objects. Can be instantiated by a client and an absolute or relative URL, or from the parent object.

children(type=None)

List children, using a propfind (resourcetype) on the parent object, at depth = 1.

TODO: This is old code, it’s querying for DisplayName and ResourceTypes prop and returning a tuple of those. Those two are relatively arbitrary. I think it’s mostly only calendars having DisplayName, but it may make sense to ask for the children of a calendar also as an alternative way to get all events? It should be redone into a more generic method, and it should probably return a dict rather than a tuple. We should also look over to see if there is any code duplication.

delete()

Delete the object.

get_display_name()

Get calendar display name

get_properties(props=None, depth=0, parse_response_xml=True, parse_props=True)

Get properties (PROPFIND) for this object.

With parse_response_xml and parse_props set to True a best-attempt will be done on decoding the XML we get from the server - but this works only for properties that don’t have complex types. With parse_response_xml set to False, a DAVResponse object will be returned, and it’s up to the caller to decode. With parse_props set to false but parse_response_xml set to true, xml elements will be returned rather than values.

Parameters:
  • props = [dav.ResourceType(), dav.DisplayName(), …]
Returns:
  • {proptag: value, …}
save()

Save the object. This is an abstract method, that all classes derived from DAVObject implement.

Returns:
  • self
set_properties(props=None)

Set properties (PROPPATCH) for this object.

  • props = [dav.DisplayName(‘name’), …]
Returns:
  • self
class caldav.objects.Event(client=None, url=None, data=None, parent=None, id=None, props=None)

The Event object is used to represent an event (VEVENT).

As of 2020-12 it adds nothing to the inheritated class. (I have frequently asked myself if we need those subclasses … perhaps not)

class caldav.objects.FreeBusy(parent, data, url=None, id=None)

The FreeBusy object is used to represent a freebusy response from the server. __init__ is overridden, as a FreeBusy response has no URL or ID. The inheritated methods .save and .load is moot and will probably throw errors (perhaps the class hierarchy should be rethought, to prevent the FreeBusy from inheritating moot methods)

Update: With RFC6638 a freebusy object can have an URL and an ID.

class caldav.objects.Journal(client=None, url=None, data=None, parent=None, id=None, props=None)

The Journal object is used to represent a journal entry (VJOURNAL).

As of 2020-12 it adds nothing to the inheritated class. (I have frequently asked myself if we need those subclasses … perhaps not)

class caldav.objects.Principal(client=None, url=None)

This class represents a DAV Principal. It doesn’t do much, except keep track of the URLs for the calendar-home-set, etc.

A principal MUST have a non-empty DAV:displayname property (defined in Section 13.2 of [RFC2518]), and a DAV:resourcetype property (defined in Section 13.9 of [RFC2518]). Additionally, a principal MUST report the DAV:principal XML element in the value of the DAV:resourcetype property.

(TODO: the resourcetype is actually never checked, and the DisplayName is not stored anywhere)

calendar(name=None, cal_id=None, cal_url=None)

The calendar method will return a calendar object. It will not initiate any communication with the server.

calendar_user_address_set()

defined in RFC6638

calendars()

Return the principials calendars

get_vcal_address()

Returns the principal, as an icalendar.vCalAddress object

make_calendar(name=None, cal_id=None, supported_calendar_component_set=None)

Convenience method, bypasses the self.calendar_home_set object. See CalendarSet.make_calendar for details.

class caldav.objects.ScheduleInbox(client=None, principal=None, url=None)
class caldav.objects.ScheduleMailbox(client=None, principal=None, url=None)

RFC6638 defines an inbox and an outbox for handling event scheduling.

TODO: As ScheduleMailboxes works a bit like calendars, I’ve chosen to inheritate the Calendar class, but this is a bit incorrect, a ScheduleMailbox is a collection, but not really a calendar. We should create a common base class for ScheduleMailbox and Calendar eventually.

get_items()

TODO: work in progress TODO: perhaps this belongs to the super class?

class caldav.objects.ScheduleOutbox(client=None, principal=None, url=None)
class caldav.objects.SynchronizableCalendarObjectCollection(calendar, objects, sync_token)

This class may hold a cached snapshot of a calendar, and changes in the calendar can easily be copied over through the sync method.

To create a SynchronizableCalendarObjectCollection object, use calendar.objects(load_objects=True)

objects_by_url()

returns a dict of the contents of the SynchronizableCalendarObjectCollection, URLs -> objects.

sync()

This method will contact the caldav server, request all changes from it, and sync up the collection

class caldav.objects.Todo(client=None, url=None, data=None, parent=None, id=None, props=None)

The Todo object is used to represent a todo item (VTODO). A Todo-object can be completed. Extra logic for different ways to complete one recurrence of a recurrent todo. Extra logic to handle due vs duration.

complete(completion_timestamp=None, handle_rrule=False, rrule_mode='safe')

Marks the task as completed.

Parameters:
  • completion_timestamp - datetime object. Defaults to datetime.now().
  • handle_rrule - if set to True, the library will try to be smart if the task is recurring. The default is False, for backward compatibility. I may consider making this one mandatory.
  • rrule_mode - The RFC leaves a lot of room for intepretation on how to handle recurring tasks, and what works on one server may break at another. The following modes are accepted: * this_and_future - see doc for _complete_recurring_thisandfuture for details * safe - see doc for _complete_recurring_safe for details
set_due(due, move_dtstart=False, check_dependent=False)

The RFC specifies that a VTODO cannot have both due and duration, so when setting due, the duration field must be evicted

check_dependent=True will raise some error if there exists a parent calendar component (through RELATED-TO), and the parents due or dtend is before the new dtend).

WARNING: this method is likely to be deprecated and parts of it moved to the icalendar library. If you decide to use it, please put caldav<2.0 in the requirements.

WARNING: the check_dependent-logic may be rewritten to support RFC9253 in 1.x already

set_duration(duration, movable_attr='DTSTART')

If DTSTART and DUE/DTEND is already set, one of them should be moved. Which one? I believe that for EVENTS, the DTSTART should remain constant and DTEND should be moved, but for a task, I think the due date may be a hard deadline, hence by default we’ll move DTSTART.

TODO: can this be written in a better/shorter way?

WARNING: this method is likely to be deprecated and moved to the icalendar library. If you decide to use it, please put caldav<2.0 in the requirements.

uncomplete()

Undo completion - marks a completed task as not completed

caldav.objects.errmsg(r)

Utility for formatting a response xml tree to an error string