(backport) Make docs build independent of app

This commit is contained in:
Markus Unterwaditzer 2018-03-16 18:03:45 +01:00
parent 0094acddd0
commit 68f2cf3195
11 changed files with 306 additions and 277 deletions

View file

@ -9,15 +9,18 @@ Package maintainers and users who have to manually update their installation
may want to subscribe to `GitHub's tag feed
<https://github.com/pimutils/vdirsyncer/tags.atom>`_.
Version 0.16.6
==============
- **Packagers:** Documentation building no longer needs a working installation
of vdirsyncer.
Version 0.16.5
==============
*released on 13 June 2018*
- **Packagers:** click-log 0.3 is required.
- All output will now happen on stderr (because of the upgrade of ``click-log``).
Version 0.16.4
==============

View file

@ -1,2 +1,3 @@
sphinx != 1.4.7
sphinx_rtd_theme
setuptools_scm

View file

@ -6,7 +6,7 @@ import os
from sphinx.ext import autodoc
import vdirsyncer
import setuptools_scm
extensions = ['sphinx.ext.autodoc']
@ -19,7 +19,7 @@ project = u'vdirsyncer'
copyright = (u'2014-{}, Markus Unterwaditzer & contributors'
.format(datetime.date.today().strftime('%Y')))
release = vdirsyncer.__version__
release = setuptools_scm.get_version(root='..', relative_to=__file__)
version = '.'.join(release.split('.')[:2]) # The short X.Y version.
rst_epilog = '.. |vdirsyncer_version| replace:: %s' % release
@ -75,9 +75,10 @@ def github_issue_role(name, rawtext, text, lineno, inliner,
prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg]
import vdirsyncer
from docutils import nodes
link = '{}/{}/{}'.format(vdirsyncer.PROJECT_HOME,
PROJECT_HOME = 'https://github.com/pimutils/vdirsyncer'
link = '{}/{}/{}'.format(PROJECT_HOME,
'issues' if name == 'gh' else 'pull',
issue_num)
linktext = ('issue #{}' if name == 'gh'
@ -87,64 +88,9 @@ def github_issue_role(name, rawtext, text, lineno, inliner,
return [node], []
def format_storage_config(cls, header=True):
if header is True:
yield '[storage example_for_{}]'.format(cls.storage_name)
yield 'type = "{}"'.format(cls.storage_name)
from vdirsyncer.storage.base import Storage
from vdirsyncer.utils import get_storage_init_specs
handled = set()
for spec in get_storage_init_specs(cls, stop_at=Storage):
defaults = spec.defaults or ()
defaults = dict(zip(spec.args[-len(defaults):], defaults))
for key in spec.args[1:]:
if key in handled:
continue
handled.add(key)
comment = '' if key not in defaults else '#'
value = defaults.get(key, '...')
yield '{}{} = {}'.format(comment, key, json.dumps(value))
class StorageDocumenter(autodoc.ClassDocumenter):
'''Custom formatter for auto-documenting storage classes. It assumes that
the first line of the class' docstring is its own paragraph.
After that first paragraph, an example configuration will be inserted and
Sphinx' __init__ signature removed.'''
objtype = 'storage'
domain = None
directivetype = 'storage'
option_spec = {}
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
from vdirsyncer.storage.base import Storage
return isinstance(member, Storage)
def format_signature(self):
return ''
def add_directive_header(self, sig):
directive = getattr(self, 'directivetype', self.objtype)
name = self.object.storage_name
self.add_line(u'.. %s:: %s%s' % (directive, name, sig),
'<autodoc>')
def get_doc(self, encoding=None, ignore=1):
rv = autodoc.ClassDocumenter.get_doc(self, encoding, ignore)
config = [u' ' + x for x in format_storage_config(self.object)]
rv[0] = rv[0][:1] + [u'::', u''] + config + [u''] + rv[0][1:]
return rv
def setup(app):
from sphinx.domains.python import PyObject
app.add_object_type('storage', 'storage', 'pair: %s; storage',
doc_field_types=PyObject.doc_field_types)
app.add_role('gh', github_issue_role)
app.add_role('ghpr', github_issue_role)
app.add_autodocumenter(StorageDocumenter)

View file

@ -150,9 +150,107 @@ Supported Storages
CalDAV and CardDAV
++++++++++++++++++
.. autostorage:: vdirsyncer.storage.dav.CalDAVStorage
.. note::
.. autostorage:: vdirsyncer.storage.dav.CardDAVStorage
Please also see :ref:`supported-servers`, as some servers may not work
well.
.. storage:: caldav
CalDAV.
::
[storage example_for_caldav]
type = "caldav"
#start_date = null
#end_date = null
#item_types = []
url = "..."
#username = ""
#password = ""
#verify = true
#auth = null
#useragent = "vdirsyncer/0.16.4"
#verify_fingerprint = null
#auth_cert = null
You can set a timerange to synchronize with the parameters ``start_date``
and ``end_date``. Inside those parameters, you can use any Python
expression to return a valid :py:class:`datetime.datetime` object. For
example, the following would synchronize the timerange from one year in the
past to one year in the future::
start_date = "datetime.now() - timedelta(days=365)"
end_date = "datetime.now() + timedelta(days=365)"
Either both or none have to be specified. The default is to synchronize
everything.
You can set ``item_types`` to restrict the *kind of items* you want to
synchronize. For example, if you want to only synchronize events (but don't
download any tasks from the server), set ``item_types = ["VEVENT"]``. If
you want to synchronize events and tasks, but have some ``VJOURNAL`` items
on the server you don't want to synchronize, use ``item_types = ["VEVENT",
"VTODO"]``.
:param start_date: Start date of timerange to show, default -inf.
:param end_date: End date of timerange to show, default +inf.
:param item_types: Kind of items to show. The default, the empty list, is
to show all. This depends on particular features on the server, the
results are not validated.
:param url: Base URL or an URL to a calendar.
:param username: Username for authentication.
:param password: Password for authentication.
:param verify: Verify SSL certificate, default True. This can also be a
local path to a self-signed SSL certificate. See :ref:`ssl-tutorial`
for more information.
:param verify_fingerprint: Optional. SHA1 or MD5 fingerprint of the
expected server certificate. See :ref:`ssl-tutorial` for more
information.
:param auth: Optional. Either ``basic``, ``digest`` or ``guess``. The
default is preemptive Basic auth, sending credentials even if server
didn't request them. This saves from an additional roundtrip per
request. Consider setting ``guess`` if this causes issues with your
server.
:param auth_cert: Optional. Either a path to a certificate with a client
certificate and the key or a list of paths to the files with them.
:param useragent: Default ``vdirsyncer``.
.. storage:: carddav
CardDAV.
::
[storage example_for_carddav]
type = "carddav"
url = "..."
#username = ""
#password = ""
#verify = true
#auth = null
#useragent = "vdirsyncer/0.16.4"
#verify_fingerprint = null
#auth_cert = null
:param url: Base URL or an URL to an addressbook.
:param username: Username for authentication.
:param password: Password for authentication.
:param verify: Verify SSL certificate, default True. This can also be a
local path to a self-signed SSL certificate. See :ref:`ssl-tutorial`
for more information.
:param verify_fingerprint: Optional. SHA1 or MD5 fingerprint of the
expected server certificate. See :ref:`ssl-tutorial` for more
information.
:param auth: Optional. Either ``basic``, ``digest`` or ``guess``. The
default is preemptive Basic auth, sending credentials even if server
didn't request them. This saves from an additional roundtrip per
request. Consider setting ``guess`` if this causes issues with your
server.
:param auth_cert: Optional. Either a path to a certificate with a client
certificate and the key or a list of paths to the files with them.
:param useragent: Default ``vdirsyncer``.
Google
++++++
@ -206,9 +304,42 @@ or write anything to it.
a rather hidden `settings page
<https://calendar.google.com/calendar/syncselect>`_.
.. autostorage:: vdirsyncer.storage.google.GoogleCalendarStorage
.. storage:: google_calendar
.. autostorage:: vdirsyncer.storage.google.GoogleContactsStorage
Google calendar.
::
[storage example_for_google_calendar]
type = "google_calendar"
token_file = "..."
client_id = "..."
client_secret = "..."
#start_date = null
#end_date = null
#item_types = []
Please refer to :storage:`caldav` regarding the ``item_types`` and timerange parameters.
:param token_file: A filepath where access tokens are stored.
:param client_id/client_secret: OAuth credentials, obtained from the Google
API Manager.
.. storage:: google_contacts
Google contacts.
::
[storage example_for_google_contacts]
type = "google_contacts"
token_file = "..."
client_id = "..."
client_secret = "..."
:param token_file: A filepath where access tokens are stored.
:param client_id/client_secret: OAuth credentials, obtained from the Google
API Manager.
EteSync
+++++++
@ -224,17 +355,123 @@ To use it, you need to install some optional dependencies::
On first usage you will be prompted for the service password and the encryption
password. Neither are stored.
.. autostorage:: vdirsyncer.storage.etesync.EtesyncContacts
.. storage:: etesync_contacts
.. autostorage:: vdirsyncer.storage.etesync.EtesyncCalendars
Contacts for etesync.
::
[storage example_for_etesync_contacts]
email = ...
secrets_dir = ...
#server_path = ...
#db_path = ...
:param email: The email address of your account.
:param secrets_dir: A directory where vdirsyncer can store the encryption
key and authentication token.
:param server_url: Optional. URL to the root of your custom server.
:param db_path: Optional. Use a different path for the database.
.. storage:: etesync_calendars
Calendars for etesync.
::
[storage example_for_etesync_calendars]
email = ...
secrets_dir = ...
#server_path = ...
#db_path = ...
:param email: The email address of your account.
:param secrets_dir: A directory where vdirsyncer can store the encryption
key and authentication token.
:param server_url: Optional. URL to the root of your custom server.
:param db_path: Optional. Use a different path for the database.
Local
+++++
.. autostorage:: vdirsyncer.storage.filesystem.FilesystemStorage
.. storage:: filesystem
.. autostorage:: vdirsyncer.storage.singlefile.SingleFileStorage
Saves each item in its own file, given a directory.
::
[storage example_for_filesystem]
type = "filesystem"
path = "..."
fileext = "..."
#encoding = "utf-8"
#post_hook = null
Can be used with `khal <http://lostpackets.de/khal/>`_. See :doc:`vdir` for
a more formal description of the format.
Directories with a leading dot are ignored to make usage of e.g. version
control easier.
:param path: Absolute path to a vdir/collection. If this is used in
combination with the ``collections`` parameter in a pair-section, this
should point to a directory of vdirs instead.
:param fileext: The file extension to use (e.g. ``.txt``). Contained in the
href, so if you change the file extension after a sync, this will
trigger a re-download of everything (but *should* not cause data-loss
of any kind).
:param encoding: File encoding for items, both content and filename.
:param post_hook: A command to call for each item creation and
modification. The command will be called with the path of the
new/updated file.
.. storage:: singlefile
Save data in single local ``.vcf`` or ``.ics`` file.
The storage basically guesses how items should be joined in the file.
.. versionadded:: 0.1.6
.. note::
This storage is very slow, and that is unlikely to change. You should
consider using :storage:`filesystem` if it fits your usecase.
:param path: The filepath to the file to be written to. If collections are
used, this should contain ``%s`` as a placeholder for the collection
name.
:param encoding: Which encoding the file should use. Defaults to UTF-8.
Example for syncing with :storage:`caldav`::
[pair my_calendar]
a = my_calendar_local
b = my_calendar_remote
collections = ["from a", "from b"]
[storage my_calendar_local]
type = "singlefile"
path = ~/.calendars/%s.ics
[storage my_calendar_remote]
type = "caldav"
url = https://caldav.example.org/
#username =
#password =
Example for syncing with :storage:`caldav` using a ``null`` collection::
[pair my_calendar]
a = my_calendar_local
b = my_calendar_remote
[storage my_calendar_local]
type = "singlefile"
path = ~/my_calendar.ics
[storage my_calendar_remote]
type = "caldav"
url = https://caldav.example.org/username/my_calendar/
#username =
#password =
Read-only storages
++++++++++++++++++
@ -243,4 +480,50 @@ These storages don't support writing of their items, consequently ``read_only``
is set to ``true`` by default. Changing ``read_only`` to ``false`` on them
leads to an error.
.. autostorage:: vdirsyncer.storage.http.HttpStorage
.. storage:: http
Use a simple ``.ics`` file (or similar) from the web.
``webcal://``-calendars are supposed to be used with this, but you have to
replace ``webcal://`` with ``http://``, or better, ``https://``.
::
[pair holidays]
a = holidays_local
b = holidays_remote
collections = null
[storage holidays_local]
type = "filesystem"
path = ~/.config/vdir/calendars/holidays/
fileext = .ics
[storage holidays_remote]
type = "http"
url = https://example.com/holidays_from_hicksville.ics
Too many WebCAL providers generate UIDs of all ``VEVENT``-components
on-the-fly, i.e. all UIDs change every time the calendar is downloaded.
This leads many synchronization programs to believe that all events have
been deleted and new ones created, and accordingly causes a lot of
unnecessary uploads and deletions on the other side. Vdirsyncer completely
ignores UIDs coming from :storage:`http` and will replace them with a hash
of the normalized item content.
:param url: URL to the ``.ics`` file.
:param username: Username for authentication.
:param password: Password for authentication.
:param verify: Verify SSL certificate, default True. This can also be a
local path to a self-signed SSL certificate. See :ref:`ssl-tutorial`
for more information.
:param verify_fingerprint: Optional. SHA1 or MD5 fingerprint of the
expected server certificate. See :ref:`ssl-tutorial` for more
information.
:param auth: Optional. Either ``basic``, ``digest`` or ``guess``. The
default is preemptive Basic auth, sending credentials even if server
didn't request them. This saves from an additional roundtrip per
request. Consider setting ``guess`` if this causes issues with your
server.
:param auth_cert: Optional. Either a path to a certificate with a client
certificate and the key or a list of paths to the files with them.
:param useragent: Default ``vdirsyncer``.

View file

@ -93,26 +93,6 @@ def prepare_client_cert(cert):
return cert
HTTP_STORAGE_PARAMETERS = '''
:param username: Username for authentication.
:param password: Password for authentication.
:param verify: Verify SSL certificate, default True. This can also be a
local path to a self-signed SSL certificate. See :ref:`ssl-tutorial`
for more information.
:param verify_fingerprint: Optional. SHA1 or MD5 fingerprint of the
expected server certificate. See :ref:`ssl-tutorial` for more
information.
:param auth: Optional. Either ``basic``, ``digest`` or ``guess``. The
default is preemptive Basic auth, sending credentials even if server
didn't request them. This saves from an additional roundtrip per
request. Consider setting ``guess`` if this causes issues with your
server.
:param auth_cert: Optional. Either a path to a certificate with a client
certificate and the key or a list of paths to the files with them.
:param useragent: Default ``vdirsyncer``.
'''
def _install_fingerprint_adapter(session, fingerprint):
prefix = 'https://'
try:

View file

@ -12,7 +12,7 @@ from requests.exceptions import HTTPError
from .base import Storage, normalize_meta_value
from .. import exceptions, http, utils
from ..http import HTTP_STORAGE_PARAMETERS, USERAGENT, prepare_auth, \
from ..http import USERAGENT, prepare_auth, \
prepare_client_cert, prepare_verify
from ..vobject import Item
@ -397,17 +397,6 @@ class DAVSession(object):
class DAVStorage(Storage):
__doc__ = '''
:param url: Base URL or an URL to a collection.
''' + HTTP_STORAGE_PARAMETERS + '''
.. note::
Please also see :ref:`supported-servers`, as some servers may not work
well.
'''
# the file extension of items. Useful for testing against radicale.
fileext = None
# mimetype of items
@ -714,36 +703,6 @@ class DAVStorage(Storage):
class CalDAVStorage(DAVStorage):
__doc__ = '''
CalDAV.
You can set a timerange to synchronize with the parameters ``start_date``
and ``end_date``. Inside those parameters, you can use any Python
expression to return a valid :py:class:`datetime.datetime` object. For
example, the following would synchronize the timerange from one year in the
past to one year in the future::
start_date = datetime.now() - timedelta(days=365)
end_date = datetime.now() + timedelta(days=365)
Either both or none have to be specified. The default is to synchronize
everything.
You can set ``item_types`` to restrict the *kind of items* you want to
synchronize. For example, if you want to only synchronize events (but don't
download any tasks from the server), set ``item_types = ["VEVENT"]``. If
you want to synchronize events and tasks, but have some ``VJOURNAL`` items
on the server you don't want to synchronize, use ``item_types = ["VEVENT",
"VTODO"]``.
:param start_date: Start date of timerange to show, default -inf.
:param end_date: End date of timerange to show, default +inf.
:param item_types: Kind of items to show. The default, the empty list, is
to show all. This depends on particular features on the server, the
results are not validated.
''' + DAVStorage.__doc__
storage_name = 'caldav'
fileext = '.ics'
item_mimetype = 'text/calendar'
@ -868,11 +827,6 @@ class CalDAVStorage(DAVStorage):
class CardDAVStorage(DAVStorage):
__doc__ = '''
CardDAV.
''' + DAVStorage.__doc__
storage_name = 'carddav'
fileext = '.vcf'
item_mimetype = 'text/vcard'

View file

@ -100,14 +100,6 @@ class _Session:
class EtesyncStorage(Storage):
'''
:param email: The email address of your account.
:param secrets_dir: A directory where vdirsyncer can store the encryption
key and authentication token.
:param server_url: Optional. URL to the root of your custom server.
:param db_path: Optional. Use a different path for the database.
'''
_collection_type = None
_item_type = None
_at_once = False
@ -225,20 +217,12 @@ class EtesyncStorage(Storage):
class EtesyncContacts(EtesyncStorage):
__doc__ = '''
Contacts for EteSync.
''' + EtesyncStorage.__doc__
_collection_type = AddressBook
_item_type = Contact
storage_name = 'etesync_contacts'
class EtesyncCalendars(EtesyncStorage):
__doc__ = '''
Calendars for EteSync.
''' + EtesyncStorage.__doc__
_collection_type = Calendar
_item_type = Event
storage_name = 'etesync_calendars'

View file

@ -17,28 +17,6 @@ logger = logging.getLogger(__name__)
class FilesystemStorage(Storage):
'''
Saves each item in its own file, given a directory.
Can be used with `khal <http://lostpackets.de/khal/>`_. See :doc:`vdir` for
a more formal description of the format.
Directories with a leading dot are ignored to make usage of e.g. version
control easier.
:param path: Absolute path to a vdir/collection. If this is used in
combination with the ``collections`` parameter in a pair-section, this
should point to a directory of vdirs instead.
:param fileext: The file extension to use (e.g. ``.txt``). Contained in the
href, so if you change the file extension after a sync, this will
trigger a re-download of everything (but *should* not cause data-loss
of any kind).
:param encoding: File encoding for items, both content and filename.
:param post_hook: A command to call for each item creation and
modification. The command will be called with the path of the
new/updated file.
'''
storage_name = 'filesystem'
_repr_attributes = ('path',)

View file

@ -101,20 +101,7 @@ class GoogleSession(dav.DAVSession):
_save_token(token)
GOOGLE_PARAMS_DOCS = '''
:param token_file: A filepath where access tokens are stored.
:param client_id/client_secret: OAuth credentials, obtained from the Google
API Manager.
'''
class GoogleCalendarStorage(dav.CalDAVStorage):
__doc__ = '''Google calendar.
Please refer to :storage:`caldav` regarding
the ``item_types`` and timerange parameters.
''' + GOOGLE_PARAMS_DOCS
class session_class(GoogleSession):
url = 'https://apidata.googleusercontent.com/caldav/v2/'
scope = ['https://www.googleapis.com/auth/calendar']
@ -150,10 +137,6 @@ class GoogleCalendarStorage(dav.CalDAVStorage):
class GoogleContactsStorage(dav.CardDAVStorage):
__doc__ = '''Google contacts.
''' + GOOGLE_PARAMS_DOCS
class session_class(GoogleSession):
# Google CardDAV is completely bonkers. Collection discovery doesn't
# work properly, well-known URI takes us directly to single collection

View file

@ -4,45 +4,12 @@ import urllib.parse as urlparse
from .base import Storage
from .. import exceptions
from ..http import HTTP_STORAGE_PARAMETERS, USERAGENT, prepare_auth, \
from ..http import USERAGENT, prepare_auth, \
prepare_client_cert, prepare_verify, request
from ..vobject import Item, split_collection
class HttpStorage(Storage):
__doc__ = '''
Use a simple ``.ics`` file (or similar) from the web.
``webcal://``-calendars are supposed to be used with this, but you have to
replace ``webcal://`` with ``http://``, or better, ``https://``.
Too many WebCAL providers generate UIDs of all ``VEVENT``-components
on-the-fly, i.e. all UIDs change every time the calendar is downloaded.
This leads many synchronization programs to believe that all events have
been deleted and new ones created, and accordingly causes a lot of
unnecessary uploads and deletions on the other side. Vdirsyncer completely
ignores UIDs coming from :storage:`http` and will replace them with a hash
of the normalized item content.
:param url: URL to the ``.ics`` file.
''' + HTTP_STORAGE_PARAMETERS + '''
A simple example::
[pair holidays]
a = holidays_local
b = holidays_remote
collections = null
[storage holidays_local]
type = "filesystem"
path = ~/.config/vdir/calendars/holidays/
fileext = .ics
[storage holidays_remote]
type = "http"
url = https://example.com/holidays_from_hicksville.ics
'''
storage_name = 'http'
read_only = True
_repr_attributes = ('username', 'url')

View file

@ -30,56 +30,6 @@ def _writing_op(f):
class SingleFileStorage(Storage):
'''Save data in single local ``.vcf`` or ``.ics`` file.
The storage basically guesses how items should be joined in the file.
.. versionadded:: 0.1.6
.. note::
This storage is very slow, and that is unlikely to change. You should
consider using :storage:`filesystem` if it fits your usecase.
:param path: The filepath to the file to be written to. If collections are
used, this should contain ``%s`` as a placeholder for the collection
name.
:param encoding: Which encoding the file should use. Defaults to UTF-8.
Example for syncing with :storage:`caldav`::
[pair my_calendar]
a = my_calendar_local
b = my_calendar_remote
collections = ["from a", "from b"]
[storage my_calendar_local]
type = "singlefile"
path = ~/.calendars/%s.ics
[storage my_calendar_remote]
type = "caldav"
url = https://caldav.example.org/
#username =
#password =
Example for syncing with :storage:`caldav` using a ``null`` collection::
[pair my_calendar]
a = my_calendar_local
b = my_calendar_remote
[storage my_calendar_local]
type = "singlefile"
path = ~/my_calendar.ics
[storage my_calendar_remote]
type = "caldav"
url = https://caldav.example.org/username/my_calendar/
#username =
#password =
'''
storage_name = 'singlefile'
_repr_attributes = ('path',)