Calendrier

Description

This project is a CalDAV (RFC4791) client library for Python.

Features:

Quickstart

All code examples below was snippets from the basic_usage_examples.py, but the documentation and the examples may have drifted apart (TODO: does there exist some good system for this? Just use docstrings and doctests?)

Setting up a caldav client object and a principal object

with caldav.DAVClient(url=url, username=username, password=password) as client:
    dav_principal = client.principal()
    ...

Creating a calendar

test_calendar = dav_principal.make_calendar(name="First test calendar from Python caldav")

Création de l’agenda “Absences SAGE”

Création de l’agenda “Absences SAGE” (NEXTCLOUD_JUPYTER_CALENDRIER_ABSENCES = “Absences SAGE”)

import os
import caldav
import icalendar
from django.conf import settings


caldav_url = settings.NEXTCLOUD_JUPYTER_CALDAV_URL
username =settings.NEXTCLOUD_JUPYTER_USERNAME
password = os.environ["MY_IMPRONONCIABLE"]
client = caldav.DAVClient(url=caldav_url, username=username, password=password)
dav_principal = client.principal()
dav_principal.make_calendar(name=settings.NEXTCLOUD_JUPYTER_CALENDRIER_ABSENCES)
In [3]:     caldav_url = settings.NEXTCLOUD_JUPYTER_CALDAV_URL
   ...:     username =settings.NEXTCLOUD_JUPYTER_USERNAME
   ...:

In [4]:     password = os.environ["MY_IMPRONONCIABLE"]
   ...:     client = caldav.DAVClient(url=caldav_url, username=username, password=password)
   ...:     dav_principal = client.principal()
   ...:

In [5]:     dav_principal.make_calendar(name=settings.NEXTCLOUD_JUPYTER_CALENDRIER_ABSENCES)
   ...:
Out[5]: Calendar(https://cloud.jupyter.eu/remote.php/dav/calendars/BDA3E7B3-F1C5-412B-9A68-2F561CAB268E/af9b36fc-3fee-11ed-a91f-0242ac130002/)

Fetching calendars

calendars = dav_principal.calendars()
In [35]: calendars
Out[35]:
[Calendar(https://nuage.magellan.eu/remote.php/dav/calendars/BDA3E7B3-F1C5-412B-9A68-2F561CAB268E/personal/),
 Calendar(https://nuage.magellan.eu/remote.php/dav/calendars/BDA3E7B3-F1C5-412B-9A68-2F561CAB268E/intranet/),
 Calendar(https://nuage.magellan.eu/remote.php/dav/calendars/BDA3E7B3-F1C5-412B-9A68-2F561CAB268E/contact_birthdays/),
 Calendar(https://nuage.magellan.eu/remote.php/dav/calendars/BDA3E7B3-F1C5-412B-9A68-2F561CAB268E/calendrier-absences/),
 Calendar(https://nuage.magellan.eu/remote.php/dav/calendars/BDA3E7B3-F1C5-412B-9A68-2F561CAB268E/test-agenda/),
 Calendar(https://nuage.magellan.eu/remote.php/dav/calendars/BDA3E7B3-F1C5-412B-9A68-2F561CAB268E/d1e576ce-3d95-11ed-91df-0242ac140002/),
 Calendar(https://nuage.magellan.eu/remote.php/dav/calendars/BDA3E7B3-F1C5-412B-9A68-2F561CAB268E/personal_shared_by_A85F874B-7468-4D99-9744-3DB0D2229F71/),
 Calendar(https://nuage.magellan.eu/remote.php/dav/calendars/BDA3E7B3-F1C5-412B-9A68-2F561CAB268E/personal_shared_by_45F7422B-982F-4B40-A1EB-2E61CA5515C4/)]

In [36]: c5 = calendars[5]

In [37]: c5
Out[37]: Calendar(https://nuage.magellan.eu/remote.php/dav/calendars/BDA3E7B3-F1C5-412B-9A68-2F561CAB268E/d1e576ce-3d95-11ed-91df-0242ac140002/)

In [38]: c5.name
Out[38]: 'First test calendar from Python caldav'

Find a calendar with its name

import os
import caldav
import icalendar
from django.conf import settings


caldav_url = settings.NEXTCLOUD_ID3_CALDAV_URL
username =settings.NEXTCLOUD_ID3_USERNAME
password = os.environ["MY_IMPRONONCIABLE"]
client = caldav.DAVClient(url=caldav_url, username=username, password=password)
dav_principal = client.principal()
try:
    calendar_name = "sage_absences"
    the_calendar = dav_principal.calendar(name=calendar_name)
    the_calendar.delete()
except Exception as error:
    logger.error(f"{calendar_name=} {error}")

Delete a calendar

Example 1

import os
import caldav
import icalendar
from django.conf import settings


caldav_url = settings.NEXTCLOUD_ID3_CALDAV_URL
username =settings.NEXTCLOUD_ID3_USERNAME
password = os.environ["MY_IMPRONONCIABLE"]
client = caldav.DAVClient(url=caldav_url, username=username, password=password)
dav_principal = client.principal()
try:
    calendar_name = "sage_absences"
    the_calendar = dav_principal.calendar(name=calendar_name)
    the_calendar.delete()
except Exception as error:
    logger.error(f"{calendar_name=} {error}")

Create an event to the calendar

Example 1

my_event = my_calendar.save_event(
    dtstart=datetime.datetime(2020,5,17,8),
    dtend=datetime.datetime(2020,5,18,1),
    summary="Do the needful",
    rrule={'FREQ': 'YEARLY'))

Example 2

 1 for absence in absences_employe:
 2     summary = absence.str_agenda()
 3     description = f"SAGE {summary}"
 4     location = "Congés/Absences"
 5     if absence.is_journee_complete():
 6         dtstart = current_day.set(hour=0, minute=0, second=0)
 7         dtend = current_day.add(days=1).set(
 8             hour=0, minute=0, second=0
 9         )
10         # conversion vers date
11         dtstart = pendulum_to_date(dtstart)
12         dtend = pendulum_to_date(dtend)
13     else:
14         if absence.is_demi_journee_matin():
15             dtstart = current_day.set(hour=8)
16             dtend = current_day.set(hour=12)
17         if absence.is_demi_journee_apres_midi():
18             dtstart = current_day.set(hour=13)
19             dtend = current_day.set(hour=17)
20         # conversion vers datetime
21         dtstart = pendulum_to_datetime(dtstart)
22         dtend = pendulum_to_datetime(dtend)
23         logger.info(f"Absence demi-journée {dtstart=} => {dtend=}")
24
25     try:
26         # Ecriture de l'événement
27         new_event = the_calendar.save_event(
28             dtstart=dtstart,
29             dtend=dtend,
30             summary=summary,
31             description=description,
32             location=location,
33         )
34         logger.info(
35             f"Successfull insertion in calendar {summary} {dtstart=} {dtend=}"
36         )
37     except Exception as error:
38         logger.error(f"{error=}")

Delete en event

1 liste_events = the_calendar.date_search(
2     start=dtstart_search, end=dtend_search, expand=True
3 )
4 if len(liste_events) > 0:
5     for event in liste_events:
6         event.delete()

Get all events from a calendar

Get all events from a calendar

all_events = my_calendar.events()

Do a date search in a calendar

Do a date search in a calendar

Example 1

1 events_fetched = my_calendar.date_search(
2     start=datetime(2021, 1, 1), end=datetime(2024, 1, 1), expand=True)

Example 2

 1 client = caldav.DAVClient(
 2     url=settings.NEXTCLOUD_ID3_CALDAV_URL,
 3     username=settings.NEXTCLOUD_ID3_USERNAME,
 4     password=password,
 5 )
 6 dav_principal = client.principal()
 7 try:
 8     calendar_name = settings.NEXTCLOUD_ID3_CALENDRIER_ABSENCES
 9     logger.info(f"Searching {calendar_name=} ...")
10     the_calendar = dav_principal.calendar(name=calendar_name)
11 except Exception as error:
12     logger.error(f"{calendar_name=} {error}")
13
14 dtstart_search = pendulum.datetime(year, month, 1, tz=settings.TIME_ZONE).start_of(
15     "day"
16 )
17 dtend_search = dtstart_search.end_of("month").end_of("day")
18 # conversion vers datetime
19 dtstart_search = pendulum_to_datetime(dtstart_search)
20 dtend_search = pendulum_to_datetime(dtend_search)
21 liste_events = the_calendar.date_search(
22     start=dtstart_search, end=dtend_search, expand=True
23 )
24 if len(liste_events) > 0:
25     for event in liste_events:
26         event.delete()

Create an event described through some ical text

Adding an event described through some ical text

my_event = my_new_calendar.save_event("""BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VEVENT
UID:20200516T060000Z-123401@example.com
DTSTAMP:20200516T060000Z
DTSTART:20200517T060000Z
DTEND:20200517T230000Z
RRULE:FREQ=YEARLY
SUMMARY:Do the needful
END:VEVENT
END:VCALENDAR
""")

Find a calendar with a known URL without going through the Principal-object

Find a calendar with a known URL without going through the Principal-object:

the_same_calendar = client.calendar(url=my_new_calendar.url)