dochelpers.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #!/usr/bin/python2 -O
  2. # -*- coding: utf-8 -*-
  3. '''Documentation helpers
  4. This module contains classes and functions which help to mainain documentation,
  5. particulary our custom Sphinx extension.
  6. '''
  7. import csv
  8. import posixpath
  9. import sys
  10. import urllib2
  11. import docutils
  12. import docutils.parsers.rst.roles
  13. def fetch_ticket_info(uri):
  14. '''Fetch info about particular trac ticket given
  15. :param str uri: URI at which ticket resides
  16. :rtype: mapping
  17. :raises: urllib2.HTTPError
  18. '''
  19. data = urllib2.urlopen(uri + '?format=csv').read()
  20. reader = csv.reader((line + '\n' for line in data.split('\r\n')),
  21. quoting=csv.QUOTE_MINIMAL, quotechar='"')
  22. return dict(zip(*((cell.decode('utf-8') for cell in row) for row in list(reader)[:2])))
  23. def ticket(name, rawtext, text, lineno, inliner, options={}, content=[]):
  24. '''Link to qubes ticket
  25. :param str name: The role name used in the document
  26. :param str rawtext: The entire markup snippet, with role
  27. :param str text: The text marked with the role
  28. :param int lineno: The line noumber where rawtext appearn in the input
  29. :param docutils.parsers.rst.states.Inliner inliner: The inliner instance that called this function
  30. :param options: Directive options for customisation
  31. :param content: The directive content for customisation
  32. '''
  33. ticket = text.lstrip('#')
  34. if not ticket.isdigit():
  35. msg = inliner.reporter.error('Invalid ticket identificator: {!r}'.format(text), line=lineno)
  36. prb = inliner.problematic(rawtext, rawtext, msg)
  37. return [prb], [msg]
  38. app = inliner.document.settings.env.app
  39. uri = posixpath.join(app.config.ticket_base_uri, ticket)
  40. try:
  41. info = fetch_ticket_info(uri)
  42. except urllib2.HTTPError, e:
  43. msg = inliner.reporter.error('Error while fetching ticket info: {!s}'.format(e), line=lineno)
  44. prb = inliner.problematic(rawtext, rawtext, msg)
  45. return [prb], [msg]
  46. docutils.parsers.rst.roles.set_classes(options)
  47. node = docutils.nodes.reference(
  48. rawtext,
  49. '#{} ({})'.format(ticket, info['summary']),
  50. refuri=uri,
  51. **options)
  52. return [node], []
  53. def setup(app):
  54. app.add_role('ticket', ticket)
  55. app.add_config_value('ticket_base_uri', 'https://wiki.qubes-os.org/ticket/', 'env')
  56. # vim: ts=4 sw=4 et