diff --git a/doc/apidoc/conf.py b/doc/apidoc/conf.py index 8399d849..3a05d7ff 100644 --- a/doc/apidoc/conf.py +++ b/doc/apidoc/conf.py @@ -28,8 +28,7 @@ sys.path.insert(0, os.path.abspath('../../')) # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -#extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode'] -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode'] +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode', 'qubes.dochelpers'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/doc/apidoc/index.rst b/doc/apidoc/index.rst index 4b1aa224..ec19628b 100644 --- a/doc/apidoc/index.rst +++ b/doc/apidoc/index.rst @@ -17,6 +17,7 @@ Contents: qubes-plugins qubes-ext qubes-log + qubes-dochelpers Indices and tables ================== diff --git a/doc/apidoc/qubes-dochelpers.rst b/doc/apidoc/qubes-dochelpers.rst new file mode 100644 index 00000000..6f1c9ae1 --- /dev/null +++ b/doc/apidoc/qubes-dochelpers.rst @@ -0,0 +1,8 @@ +:py:mod:`qubes.dochelpers` Helpers for Sphinx documentation +=========================================================== + +.. automodule:: qubes.dochelpers + :members: + :show-inheritance: + +.. vim: ts=3 sw=3 et diff --git a/qubes/dochelpers.py b/qubes/dochelpers.py new file mode 100644 index 00000000..95a333e1 --- /dev/null +++ b/qubes/dochelpers.py @@ -0,0 +1,76 @@ +#!/usr/bin/python2 -O +# -*- coding: utf-8 -*- + +'''Documentation helpers + +This module contains classes and functions which help to mainain documentation, +particulary our custom Sphinx extension. + +''' + +import csv +import posixpath +import sys +import urllib2 + +import docutils +import docutils.parsers.rst.roles + +def fetch_ticket_info(uri): + '''Fetch info about particular trac ticket given + + :param str uri: URI at which ticket resides + :rtype: mapping + :raises: urllib2.HTTPError + ''' + + data = urllib2.urlopen(uri + '?format=csv').read() + reader = csv.reader((line + '\n' for line in data.split('\r\n')), + quoting=csv.QUOTE_MINIMAL, quotechar='"') + + return dict(zip(*((cell.decode('utf-8') for cell in row) for row in list(reader)[:2]))) + + +def ticket(name, rawtext, text, lineno, inliner, options={}, content=[]): + '''Link to qubes ticket + + :param str name: The role name used in the document + :param str rawtext: The entire markup snippet, with role + :param str text: The text marked with the role + :param int lineno: The line noumber where rawtext appearn in the input + :param docutils.parsers.rst.states.Inliner inliner: The inliner instance that called this function + :param options: Directive options for customisation + :param content: The directive content for customisation + ''' + + ticket = text.lstrip('#') + if not ticket.isdigit(): + msg = inliner.reporter.error('Invalid ticket identificator: {!r}'.format(text), line=lineno) + prb = inliner.problematic(rawtext, rawtext, msg) + return [prb], [msg] + + app = inliner.document.settings.env.app + uri = posixpath.join(app.config.ticket_base_uri, ticket) + try: + info = fetch_ticket_info(uri) + except urllib2.HTTPError, e: + msg = inliner.reporter.error('Error while fetching ticket info: {!s}'.format(e), line=lineno) + prb = inliner.problematic(rawtext, rawtext, msg) + return [prb], [msg] + + docutils.parsers.rst.roles.set_classes(options) + + node = docutils.nodes.reference( + rawtext, + '#{} ({})'.format(ticket, info['summary']), + refuri=uri, + **options) + + return [node], [] + + +def setup(app): + app.add_role('ticket', ticket) + app.add_config_value('ticket_base_uri', 'https://wiki.qubes-os.org/ticket/', 'env') + +# vim: ts=4 sw=4 et