From 121b864f313e0a5b060de8848fcf1be0e5700a47 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 21 Feb 2010 11:50:08 +0100 Subject: [PATCH] Add manual page writer. --- CHANGES | 2 + doc/Makefile | 6 + doc/builders.rst | 16 ++ doc/conf.py | 5 + doc/config.rst | 29 +++ doc/ext/appapi.rst | 10 +- sphinx/application.py | 2 + sphinx/builders/__init__.py | 1 + sphinx/builders/manpage.py | 93 +++++++++ sphinx/config.py | 3 + sphinx/ext/autosummary/__init__.py | 6 +- sphinx/ext/todo.py | 3 +- sphinx/quickstart.py | 58 +++++- sphinx/writers/manpage.py | 308 +++++++++++++++++++++++++++++ tests/test_build.py | 9 + tests/test_quickstart.py | 5 + 16 files changed, 543 insertions(+), 13 deletions(-) create mode 100644 sphinx/builders/manpage.py create mode 100644 sphinx/writers/manpage.py diff --git a/CHANGES b/CHANGES index 3129ca296..72a8b4627 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,8 @@ Release 1.0 (in development) * Support for docutils 0.4 has been removed. +* Added a manual page builder. + * New more compact doc field syntax is now recognized: ``:param type name: description``. diff --git a/doc/Makefile b/doc/Makefile index bfd5ca833..153a93dba 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -21,6 +21,7 @@ help: @echo " htmlhelp to make HTML files and a HTML help project" @echo " epub to make an epub file" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " man to make manual pages" @echo " changes to make an overview over all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @@ -47,6 +48,11 @@ text: @echo @echo "Build finished." +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) _build/man + @echo + @echo "Build finished." + pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle diff --git a/doc/builders.rst b/doc/builders.rst index 9895fabc2..5c61fba05 100644 --- a/doc/builders.rst +++ b/doc/builders.rst @@ -127,6 +127,22 @@ Note that a direct PDF builder using ReportLab is available in `rst2pdf .. versionadded:: 0.4 +.. module:: sphinx.builders.manpage +.. class:: ManualPageBuilder + + This builder produces manual pages in the groff format. You have to specify + which documents are to be included in which manual pages via the + :confval:`man_pages` configuration value. + + Its name is ``man``. + + .. note:: + + This builder requires the docutils manual page writer, which is only + available as of docutils 0.6. + + .. versionadded:: 1.0 + .. currentmodule:: sphinx.builders.html .. class:: SerializingHTMLBuilder diff --git a/doc/conf.py b/doc/conf.py index 57556990f..b1a55b0e4 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -49,6 +49,11 @@ latex_elements = { todo_include_todos = True +man_pages = [ + ('contents', 'sphinx-all', 'Sphinx documentation generator system manual', + 'Georg Brandl', 1), +] + # -- Extension interface ------------------------------------------------------- diff --git a/doc/config.rst b/doc/config.rst index 0793759ad..6f9a76033 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -914,6 +914,35 @@ These options influence LaTeX output. Use the ``'pointsize'`` key in the :confval:`latex_elements` value. +.. _man-options: + +Options for manual page output +------------------------------ + +These options influence manual page output. + +.. confval:: man_pages + + This value determines how to group the document tree into manual pages. It + must be a list of tuples ``(startdocname, name, description, authors, + section)``, where the items are: + + * *startdocname*: document name that is the "root" of the manual page. All + documents referenced by it in TOC trees will be included in the manual file + too. (If you want one master manual page, use your :confval:`master_doc` + here.) + * *name*: name of the manual page. This should be a short string without + spaces or special characters. It is used to determine the file name as + well as the name of the manual page (in the NAME section). + * *description*: description of the manual page. This is used in the NAME + section. + * *authors*: A list of strings with authors, or a single string. + * *section*: The manual page section. Used for the output file name as well + as in the manual page header. + + .. versionadded:: 1.0 + + .. rubric:: Footnotes .. [1] A note on available globbing syntax: you can use the standard shell diff --git a/doc/ext/appapi.rst b/doc/ext/appapi.rst index a643a4787..8df028e1d 100644 --- a/doc/ext/appapi.rst +++ b/doc/ext/appapi.rst @@ -61,11 +61,11 @@ the following public API: Register a Docutils node class. This is necessary for Docutils internals. It may also be used in the future to validate nodes in the parsed documents. - Node visitor functions for the Sphinx HTML, LaTeX and text writers can be - given as keyword arguments: the keyword must be one or more of ``'html'``, - ``'latex'``, ``'text'``, the value a 2-tuple of ``(visit, depart)`` methods. - ``depart`` can be ``None`` if the ``visit`` function raises - :exc:`docutils.nodes.SkipNode`. Example: + Node visitor functions for the Sphinx HTML, LaTeX, text and manpage writers + can be given as keyword arguments: the keyword must be one or more of + ``'html'``, ``'latex'``, ``'text'``, ``'man'``, the value a 2-tuple of + ``(visit, depart)`` methods. ``depart`` can be ``None`` if the ``visit`` + function raises :exc:`docutils.nodes.SkipNode`. Example: .. code-block:: python diff --git a/sphinx/application.py b/sphinx/application.py index 2b26fa66b..95ca6279e 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -351,6 +351,8 @@ class Sphinx(object): from sphinx.writers.latex import LaTeXTranslator as translator elif key == 'text': from sphinx.writers.text import TextTranslator as translator + elif key == 'man': + from sphinx.writers.manpage import ManualPageTranslator as translator else: # ignore invalid keys for compatibility continue diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 6ab6af3e1..e345d570f 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -326,6 +326,7 @@ BUILTIN_BUILDERS = { 'epub': ('epub', 'EpubBuilder'), 'latex': ('latex', 'LaTeXBuilder'), 'text': ('text', 'TextBuilder'), + 'man': ('manpage', 'ManualPageBuilder'), 'changes': ('changes', 'ChangesBuilder'), 'linkcheck': ('linkcheck', 'CheckExternalLinksBuilder'), } diff --git a/sphinx/builders/manpage.py b/sphinx/builders/manpage.py new file mode 100644 index 000000000..7b3aef1d5 --- /dev/null +++ b/sphinx/builders/manpage.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +""" + sphinx.builders.manpage + ~~~~~~~~~~~~~~~~~~~~~~~ + + Manual pages builder. + + :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +from os import path + +from docutils.io import FileOutput +from docutils.frontend import OptionParser + +from sphinx import addnodes +from sphinx.errors import SphinxError +from sphinx.builders import Builder +from sphinx.environment import NoUri +from sphinx.util.nodes import inline_all_toctrees +from sphinx.util.console import bold, darkgreen +try: + from sphinx.writers.manpage import ManualPageWriter + has_manpage_writer = True +except ImportError: + has_manpage_writer = False + + +class ManualPageBuilder(Builder): + """ + Builds groff output in manual page format. + """ + name = 'man' + format = 'man' + supported_image_types = [] + + def init(self): + if not has_manpage_writer: + raise SphinxError('The docutils manual page writer can\'t be ' + 'found; it is only available as of docutils 0.6.') + if not self.config.man_pages: + self.warn('no "man_pages" config value found; no manual pages ' + 'will be written') + + def get_outdated_docs(self): + return 'all manpages' # for now + + def get_target_uri(self, docname, typ=None): + if typ == 'token': + return '' + raise NoUri + + def write(self, *ignored): + docwriter = ManualPageWriter(self) + docsettings = OptionParser( + defaults=self.env.settings, + components=(docwriter,)).get_default_values() + + self.info(bold('writing... '), nonl=True) + + for info in self.config.man_pages: + docname, name, description, authors, section = info + if isinstance(authors, basestring): + authors = [authors] + + targetname = '%s.%s' % (name, section) + self.info(darkgreen(targetname) + ' { ', nonl=True) + destination = FileOutput( + destination_path=path.join(self.outdir, targetname), + encoding='utf-8') + + tree = self.env.get_doctree(docname) + docnames = set() + largetree = inline_all_toctrees(self, docnames, docname, tree, + darkgreen) + self.info('} ', nonl=True) + self.env.resolve_references(largetree, docname, self) + # remove pending_xref nodes + for pendingnode in largetree.traverse(addnodes.pending_xref): + pendingnode.replace_self(pendingnode.children) + + largetree.settings = docsettings + largetree.settings.title = name + largetree.settings.subtitle = description + largetree.settings.authors = authors + largetree.settings.section = section + + docwriter.write(largetree, destination) + self.info() + + def finish(self): + pass diff --git a/sphinx/config.py b/sphinx/config.py index 1c262eb1b..0de30a5a3 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -141,6 +141,9 @@ class Config(object): # text options text_sectionchars = ('*=-~"+`', 'text'), text_windows_newlines = (False, 'text'), + + # manpage options + man_pages = ([], None), ) def __init__(self, dirname, filename, overrides, tags): diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index a4d46b1f0..cf67c7fb4 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -486,11 +486,13 @@ def setup(app): app.add_node(autosummary_toc, html=(autosummary_toc_visit_html, autosummary_noop), latex=(autosummary_noop, autosummary_noop), - text=(autosummary_noop, autosummary_noop)) + text=(autosummary_noop, autosummary_noop), + man=(autosummary_noop, autosummary_noop)) app.add_node(autosummary_table, html=(autosummary_table_visit_html, autosummary_noop), latex=(autosummary_noop, autosummary_noop), - text=(autosummary_noop, autosummary_noop)) + text=(autosummary_noop, autosummary_noop), + man=(autosummary_noop, autosummary_noop)) app.add_directive('autosummary', Autosummary) app.add_role('autolink', autolink_role) app.connect('doctree-read', process_autosummary_toc) diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py index 96f9fdfc4..ac3629194 100644 --- a/sphinx/ext/todo.py +++ b/sphinx/ext/todo.py @@ -159,7 +159,8 @@ def setup(app): app.add_node(todo_node, html=(visit_todo_node, depart_todo_node), latex=(visit_todo_node, depart_todo_node), - text=(visit_todo_node, depart_todo_node)) + text=(visit_todo_node, depart_todo_node), + man=(visit_todo_node, depart_todo_node)) app.add_directive('todo', Todo) app.add_directive('todolist', TodoList) diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index daa88c369..4ad6e18dd 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -226,13 +226,25 @@ latex_documents = [ #latex_domain_indices = True +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('%(master_str)s', '%(project_manpage)s', u'%(project_doc)s', + [u'%(author_str)s'], 1) +] +''' + +EPUB_CONFIG = ''' + # -- Options for Epub output --------------------------------------------------- # Bibliographic Dublin Core info. -#epub_title = '' -#epub_author = '' -#epub_publisher = '' -#epub_copyright = '' +epub_title = u'%(project_str)s' +epub_author = u'%(author_str)s' +epub_publisher = u'%(author_str)s' +epub_copyright = u'%(copyright_str)s' # The language of the text. It defaults to the language option # or en if the language is not set. @@ -324,6 +336,8 @@ help: \t@echo " epub to make an epub" \t@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" \t@echo " latexpdf to make LaTeX files and run them through pdflatex" +\t@echo " text to make text files" +\t@echo " man to make manual pages" \t@echo " changes to make an overview of all changed/added/deprecated items" \t@echo " linkcheck to check all external links for integrity" \t@echo " doctest to run all doctests embedded in the documentation \ @@ -400,6 +414,16 @@ latexpdf: latex \tmake -C %(rbuilddir)s/latex all-pdf \t@echo "pdflatex finished; the PDF files are in %(rbuilddir)s/latex." +text: +\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text +\t@echo +\t@echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: +\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man +\t@echo +\t@echo "Build finished. The manual pages are in $(BUILDDIR)/man." + changes: \t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes \t@echo @@ -444,6 +468,8 @@ if "%%1" == "help" ( \techo. devhelp to make HTML files and a Devhelp project \techo. epub to make an epub \techo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter +\techo. text to make text files +\techo. man to make manual pages \techo. changes to make an overview over all changed/added/deprecated items \techo. linkcheck to check all external links for integrity \techo. doctest to run all doctests embedded in the documentation if enabled @@ -531,6 +557,20 @@ if "%%1" == "latex" ( \tgoto end ) +if "%%1" == "text" ( +\t%%SPHINXBUILD%% -b text %%ALLSPHINXOPTS%% %%BUILDDIR%%/text +\techo. +\techo.Build finished. The text files are in %%BUILDDIR%%/text. +\tgoto end +) + +if "%%1" == "man" ( +\t%%SPHINXBUILD%% -b man %%ALLSPHINXOPTS%% %%BUILDDIR%%/man +\techo. +\techo.Build finished. The manual pages are in %%BUILDDIR%%/man. +\tgoto end +) + if "%%1" == "changes" ( \t%%SPHINXBUILD%% -b changes %%ALLSPHINXOPTS%% %%BUILDDIR%%/changes \techo. @@ -703,6 +743,11 @@ document is a custom template, you can also set this to another filename.''' do_prompt(d, 'master', 'Please enter a new file name, or rename the ' 'existing file and press Enter', d['master']) + print ''' +Sphinx can also add configuration for epub output:''' + do_prompt(d, 'epub', 'Do you want to use the epub builder (y/N)', + 'n', boolean) + print ''' Please indicate if you want to use one of the following Sphinx extensions:''' do_prompt(d, 'ext_autodoc', 'autodoc: automatically insert docstrings ' @@ -735,6 +780,7 @@ directly.''' 'y', boolean) d['project_fn'] = make_filename(d['project']) + d['project_manpage'] = d['project_fn'].lower() d['now'] = time.asctime() d['underline'] = len(d['project']) * '=' d['extensions'] = ', '.join( @@ -751,7 +797,7 @@ directly.''' # escape backslashes and single quotes in strings that are put into # a Python string literal - for key in ('project', 'copyright', 'author_texescaped', + for key in ('project', 'copyright', 'author', 'author_texescaped', 'project_doc_texescaped', 'version', 'release', 'master'): d[key + '_str'] = d[key].replace('\\', '\\\\').replace("'", "\\'") @@ -772,6 +818,8 @@ directly.''' mkdir_p(path.join(srcdir, d['dot'] + 'static')) conf_text = QUICKSTART_CONF % d + if d['epub']: + conf_text += EPUB_CONFIG % d if d['ext_intersphinx']: conf_text += INTERSPHINX_CONFIG diff --git a/sphinx/writers/manpage.py b/sphinx/writers/manpage.py new file mode 100644 index 000000000..6ba61a40c --- /dev/null +++ b/sphinx/writers/manpage.py @@ -0,0 +1,308 @@ +# -*- coding: utf-8 -*- +""" + sphinx.writers.manpage + ~~~~~~~~~~~~~~~~~~~~~~ + + Manual page writer, extended for Sphinx custom nodes. + + :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +from docutils import nodes +from docutils.writers.manpage import MACRO_DEF, Writer, \ + Translator as BaseTranslator + +from sphinx import addnodes +from sphinx.locale import admonitionlabels, versionlabels, _ +from sphinx.util.osutil import ustrftime + + +class ManualPageWriter(Writer): + def __init__(self, builder): + Writer.__init__(self) + self.builder = builder + + def translate(self): + visitor = ManualPageTranslator(self.builder, self.document) + self.visitor = visitor + self.document.walkabout(visitor) + self.output = visitor.astext() + + +class ManualPageTranslator(BaseTranslator): + """ + Custom translator. + """ + + def __init__(self, builder, *args, **kwds): + BaseTranslator.__init__(self, *args, **kwds) + self.builder = builder + + self.in_productionlist = 0 + + # first title is the manpage title + self.section_level = -1 + + # docinfo set by man_pages config value + self._docinfo['title'] = self.document.settings.title + self._docinfo['subtitle'] = self.document.settings.subtitle + self._docinfo['author'] = self.document.settings.authors + self._docinfo['manual_section'] = self.document.settings.section + + # docinfo set by other config values + self._docinfo['title_upper'] = self._docinfo['title'].upper() + if builder.config.today: + self._docinfo['date'] = builder.config.today + else: + self._docinfo['date'] = ustrftime(builder.config.today_fmt + or _('%B %d, %Y')) + self._docinfo['copyright'] = builder.config.copyright + self._docinfo['version'] = builder.config.version + self._docinfo['manual_group'] = builder.config.project + + # since self.append_header() is never called, need to do this here + self.body.append(MACRO_DEF) + + # overwritten -- added quotes around all .TH arguments + def header(self): + tmpl = (".TH \"%(title_upper)s\" \"%(manual_section)s\"" + " \"%(date)s\" \"%(version)s\" \"%(manual_group)s\"\n" + ".SH NAME\n" + "%(title)s \- %(subtitle)s\n") + return tmpl % self._docinfo + + def visit_start_of_file(self, node): + pass + def depart_start_of_file(self, node): + pass + + def visit_desc(self, node): + self.visit_definition_list(node) + def depart_desc(self, node): + self.depart_definition_list(node) + + def visit_desc_signature(self, node): + self.visit_definition_list_item(node) + self.visit_term(node) + def depart_desc_signature(self, node): + self.depart_term(node) + + def visit_desc_addname(self, node): + pass + def depart_desc_addname(self, node): + pass + + def visit_desc_type(self, node): + pass + def depart_desc_type(self, node): + pass + + def visit_desc_returns(self, node): + self.body.append(' -> ') + def depart_desc_returns(self, node): + pass + + def visit_desc_name(self, node): + pass + def depart_desc_name(self, node): + pass + + def visit_desc_parameterlist(self, node): + self.body.append('(') + self.first_param = 1 + def depart_desc_parameterlist(self, node): + self.body.append(')') + + def visit_desc_parameter(self, node): + if not self.first_param: + self.body.append(', ') + else: + self.first_param = 0 + def depart_desc_parameter(self, node): + pass + + def visit_desc_optional(self, node): + self.body.append('[') + def depart_desc_optional(self, node): + self.body.append(']') + + def visit_desc_annotation(self, node): + pass + def depart_desc_annotation(self, node): + pass + + def visit_desc_content(self, node): + self.visit_definition(node) + def depart_desc_content(self, node): + self.depart_definition(node) + + def visit_refcount(self, node): + self.body.append(self.defs['emphasis'][0]) + def depart_refcount(self, node): + self.body.append(self.defs['emphasis'][1]) + + def visit_versionmodified(self, node): + self.visit_paragraph(node) + text = versionlabels[node['type']] % node['version'] + if len(node): + text += ': ' + else: + text += '.' + self.body.append(text) + def depart_versionmodified(self, node): + self.depart_paragraph(node) + + # overwritten -- we don't want source comments to show up + def visit_comment(self, node): + raise nodes.SkipNode + + # overwritten -- added ensure_eol() + def visit_footnote(self, node): + self.ensure_eol() + BaseTranslator.visit_footnote(self, node) + + # overwritten -- handle footnotes rubric + def visit_rubric(self, node): + self.ensure_eol() + if len(node.children) == 1: + rubtitle = node.children[0].astext() + if rubtitle in ('Footnotes', _('Footnotes')): + self.body.append('.SH ' + self.deunicode(rubtitle).upper() + + '\n') + raise nodes.SkipNode + else: + self.body.append('.sp\n') + def depart_rubric(self, node): + pass + + def visit_seealso(self, node): + self.visit_admonition(node) + def depart_seealso(self, node): + self.depart_admonition(node) + + # overwritten -- use our own label translations + def visit_admonition(self, node, name=None): + if name: + self.body.append('.IP %s\n' % + admonitionlabels.get(name, name)) + + def visit_productionlist(self, node): + self.ensure_eol() + names = [] + self.in_productionlist += 1 + self.body.append('.sp\n.nf\n') + for production in node: + names.append(production['tokenname']) + maxlen = max(len(name) for name in names) + for production in node: + if production['tokenname']: + lastname = production['tokenname'].ljust(maxlen) + self.body.append(self.defs['strong'][0]) + self.body.append(self.deunicode(lastname)) + self.body.append(self.defs['strong'][1]) + self.body.append(' ::= ') + else: + self.body.append('%s ' % (' '*len(lastname))) + production.walkabout(self) + self.body.append('\n') + self.body.append('\n.fi\n') + self.in_productionlist -= 1 + raise nodes.SkipNode + + def visit_production(self, node): + pass + def depart_production(self, node): + pass + + # overwritten -- don't visit inner marked up nodes + def visit_reference(self, node): + self.body.append(self.defs['reference'][0]) + self.body.append(node.astext()) + self.body.append(self.defs['reference'][1]) + raise nodes.SkipNode + + def visit_centered(self, node): + self.ensure_eol() + self.body.append('.sp\n.ce\n') + def depart_centered(self, node): + self.body.append('\n.ce 0\n') + + def visit_compact_paragraph(self, node): + pass + def depart_compact_paragraph(self, node): + pass + + def visit_highlightlang(self, node): + pass + def depart_highlightlang(self, node): + pass + + def visit_download_reference(self, node): + pass + def depart_download_reference(self, node): + pass + + def visit_toctree(self, node): + raise nodes.SkipNode + + def visit_index(self, node): + raise nodes.SkipNode + + def visit_tabular_col_spec(self, node): + raise nodes.SkipNode + + def visit_glossary(self, node): + pass + def depart_glossary(self, node): + pass + + def visit_acks(self, node): + self.ensure_eol() + self.body.append(', '.join(n.astext() + for n in node.children[0].children) + '.') + self.body.append('\n') + raise nodes.SkipNode + + def visit_hlist(self, node): + self.visit_bullet_list(node) + def depart_hlist(self, node): + self.depart_bullet_list(node) + + def visit_hlistcol(self, node): + pass + def depart_hlistcol(self, node): + pass + + def visit_literal_emphasis(self, node): + return self.visit_emphasis(node) + def depart_literal_emphasis(self, node): + return self.depart_emphasis(node) + + def visit_abbreviation(self, node): + pass + def depart_abbreviation(self, node): + pass + + # overwritten: handle section titles better than in 0.6 release + def visit_title(self, node): + if isinstance(node.parent, addnodes.seealso): + self.body.append('.IP "') + return + elif isinstance(node.parent, nodes.section): + if self.section_level == 0: + # skip the document title + raise nodes.SkipNode + elif self.section_level == 1: + self.body.append('.SH %s\n' % + self.deunicode(node.astext().upper())) + raise nodes.SkipNode + return BaseTranslator.visit_title(self, node) + def depart_title(self, node): + if isinstance(node.parent, addnodes.seealso): + self.body.append('"\n') + return + return BaseTranslator.depart_title(self, node) + + def unknown_visit(self, node): + raise NotImplementedError('Unknown node: ' + node.__class__.__name__) diff --git a/tests/test_build.py b/tests/test_build.py index 82657fc09..f18ff1754 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -45,6 +45,15 @@ def test_epub(app): def test_changes(app): app.builder.build_all() +try: + from docutils.writers.manpage import Writer +except ImportError: + pass +else: + @with_app(buildername='man') + def test_man(app): + app.builder.build_all() + @with_app(buildername='singlehtml', cleanenv=True) def test_singlehtml(app): app.builder.build_all() diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py index 5138e2c60..cb40d27cf 100644 --- a/tests/test_quickstart.py +++ b/tests/test_quickstart.py @@ -129,6 +129,7 @@ def test_quickstart_all_answers(tempdir): 'viewcode': 'no', 'Create Makefile': 'no', 'Create Windows command file': 'no', + 'Do you want to use the epub builder': 'yes', } qs.raw_input = mock_raw_input(answers, needanswer=True) qs.TERM_ENCODING = 'utf-8' @@ -151,6 +152,10 @@ def test_quickstart_all_answers(tempdir): assert ns['latex_documents'] == [ ('contents', 'STASI.tex', u'STASI™ Documentation', u'Wolfgang Schäuble \\& G\'Beckstein', 'manual')] + assert ns['epub_author'] == u'Wolfgang Schäuble & G\'Beckstein' + assert ns['man_pages'] == [ + ('contents', 'stasi', u'STASI™ Documentation', + [u'Wolfgang Schäuble & G\'Beckstein'], 1)] assert (tempdir / 'build').isdir() assert (tempdir / 'source' / '.static').isdir()