Python et caldav

Quand on souhaite sauvegarder des éléments de type calendrier, tâche ou contact il existe une norme international: Caldav.

Cette norme a été implémenté dans de nombreux serveurs et clients.

Il existe en python un serveur caldav nommé radicale et une librairie pour faire un client nommé caldav

Serveur Caldav: radicale

On peut trouver de nombreuses informations sur le site officiel https://radicale.org/

Un moyen simple pour lancer un serveur radicale est de lancer une image docker

docker run -d --name radicale  -p 5232:5232 tomsquest/docker-radicale

Il est maintenant possible de créer sa première collection via l’interface web http://localhost:5232/

Note

il faudra d’abord créer un compte ce qui est une bonne chose en soi …

Par défaut quand on lance radicale tout le monde peut créer un compte … il n’y a pas de gestion des autorisations et des droits mais il est assez simple de rajouter ces éléments en modifiant le fichier de configuration /config/config de cette façon

[auth]

    # Authentication method
    # Value: none | htpasswd | remote_user | http_x_remote_user
    type = htpasswd

    # Htpasswd filename
    htpasswd_filename = /config/users

    # Htpasswd encryption method
    # Value: plain | sha1 | ssha | crypt | bcrypt | md5
    # Only bcrypt can be considered secure.
    # bcrypt and md5 require the passlib library to be installed.
    htpasswd_encryption = plain

il suffit par la suite de créer un fichier /config/users contenant par exemple:

mylogin:mypassword

Warning

j’utilise içi un configuration avec un fichier en clair … c’est evidement pas la bonne solution mais elle a l’avantage d’être rapide

Note

vous pouvez retrouver plus d’informations sur https://radicale.org/configuration/

Librairie python caldav

La aussi l’installation est relativement simple via pip

pip install caldav

On peut retrouver les infos sur les sites

Un test complet sur https://bitbucket.org/cyrilrbt/caldav/src/default/tests/test_caldav.py?at=default&fileviewer=file-view-default

Exemple de code pour créer un event et un todo

from datetime import datetime
import caldav
from caldav.elements import dav, cdav

# Caldav url
url = "http://localhost:5232/fraoustin/cb420b5e-48d9-3224-8c70-eda6ab1ea05e/"

vcal = """BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VEVENT
UID:1234567891
DTSTAMP:20110510T182145Z
DTSTART:20110512T170000Z
DTEND:20100512T180000Z
SUMMARY:This is an event
END:VEVENT
END:VCALENDAR
"""
todo = """BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp.//CalDAV Client//EN
BEGIN:VTODO
UID:20070313T123432Z-456554@example.com
DTSTAMP:20070313T123432Z
DUE;VALUE=DATE:20070501
SUMMARY:Submit Quebec Income Tax Return for 2006
CLASS:CONFIDENTIAL
CATEGORIES:FAMILY,FINANCE
STATUS:NEEDS-ACTION
WHO:fraoustin@gmail.com
END:VTODO
END:VCALENDAR"""


client = caldav.DAVClient(url, username="fraoustin", password="XXXXX")
principal = client.principal()
calendars = principal.calendars()
if len(calendars) > 0:
    calendar = calendars[0]
    print("Using calendar", calendar)

    print("Renaming")
    calendar.set_properties([dav.DisplayName("Test calendar"),])
    print(calendar.get_properties([dav.DisplayName(),]))

    event = calendar.add_event(vcal)
    print("Event", event, "created")
    todo = calendar.add_todo(todo)
    print("Todo", todo, "created")

    print("Looking for events in 2010-05")
    results = calendar.date_search(
        datetime(2001, 5, 1), datetime(2018, 6, 1))

    for event in results:
        print("Found", event)

    todos = calendar.date_search(start=datetime(1997, 4, 14), end=datetime(2015,5,14), compfilter='VTODO')
    for todo in todos:
        print("Todo", todo)

    for todo in calendar.todos():
        try:
            print("Todo", todo.instance.vtodo.who.value)
        except:
            pass