diff --git a/vdirsyncer/storage/dav/base.py b/vdirsyncer/storage/dav/base.py index 9bc7090..a3469e2 100644 --- a/vdirsyncer/storage/dav/base.py +++ b/vdirsyncer/storage/dav/base.py @@ -26,6 +26,10 @@ class DavStorage(Storage): get_multi_template = None # The LXML query for extracting results in get_multi get_multi_data_query = None + # The leif class to use for autodiscovery + # This should be the class *name* (i.e. "module attribute name") instead of + # the class, because leif is an optional dependency + leif_class = None _session = None _repr_attributes = ('url', 'username') @@ -74,6 +78,25 @@ class DavStorage(Storage): if self.dav_header not in response.headers.get('DAV', ''): raise exceptions.StorageError('URL is not a collection') + @classmethod + def discover(cls, url, **kwargs): + if kwargs.pop('collection', None) is not None: + raise TypeError('collection argument must not be given.') + from leif import leif + d = getattr(leif, cls.leif_class)( + url, + user=kwargs.get('username', None), + password=kwargs.get('password', None), + ssl_verify=kwargs.get('verify', True) + ) + for c in d.discover(): + collection = c['href'] + if collection.startswith(url): + collection = collection[len(url):] + s = cls(url=url, collection=collection, **kwargs) + s.displayname = c['displayname'] + yield s + def _normalize_href(self, href): '''Normalize the href to be a path only relative to hostname and schema.''' diff --git a/vdirsyncer/storage/dav/caldav.py b/vdirsyncer/storage/dav/caldav.py index b7990b7..7df8c4e 100644 --- a/vdirsyncer/storage/dav/caldav.py +++ b/vdirsyncer/storage/dav/caldav.py @@ -21,6 +21,7 @@ class CaldavStorage(DavStorage): fileext = '.ics' item_mimetype = 'text/calendar' dav_header = 'calendar-access' + leif_class = 'CalDiscover' start_date = None end_date = None diff --git a/vdirsyncer/storage/dav/carddav.py b/vdirsyncer/storage/dav/carddav.py index 52a94ca..2194b6b 100644 --- a/vdirsyncer/storage/dav/carddav.py +++ b/vdirsyncer/storage/dav/carddav.py @@ -17,6 +17,7 @@ class CarddavStorage(DavStorage): fileext = '.vcf' item_mimetype = 'text/vcard' dav_header = 'addressbook' + leif_class = 'CardDiscover' get_multi_template = '''