Add Docutils-native XML and pseudo-XML builders

This commit is contained in:
Jonathan Waltman 2012-12-04 21:10:15 -06:00
parent 1e66d33c7b
commit 8ac4aa6282
10 changed files with 235 additions and 2 deletions

View File

@ -57,6 +57,9 @@ Release 1.2 (in development)
* PR#88: Added the "Sphinx Developer's Guide" (:file:`doc/devguide.rst`)
which outlines the basic development process of the Sphinx project.
* Added the Docutils-native XML and pseudo-XML builders. See
:class:`XMLBuilder` and :class:`PseudoXMLBuilder`.
Release 1.1.3 (Mar 10, 2012)
============================

View File

@ -13,7 +13,8 @@ ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) \
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) .
.PHONY: help clean html dirhtml singlehtml text man pickle json htmlhelp \
qthelp devhelp epub latex latexpdf changes linkcheck doctest
qthelp devhelp epub latex latexpdf changes linkcheck doctest xml \
pseudoxml
help:
@echo "Please use \`make <target>' where <target> is one of"
@ -147,3 +148,13 @@ info:
@echo "Running Texinfo files through makeinfo..."
make -C _build/texinfo info
@echo "makeinfo finished; the Info files are in _build/texinfo."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) _build/xml
@echo
@echo "Build finished. The XML files are in _build/XML."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) _build/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in _build/pseudoxml."

View File

@ -272,6 +272,29 @@ Note that a direct PDF builder using ReportLab is available in `rst2pdf
Its name is ``linkcheck``.
.. module:: sphinx.builders.xml
.. class:: XMLBuilder
This builder produces Docutils-native XML files. The output can be
transformed with standard XML tools such as XSLT processors into arbitrary
final forms.
Its name is ``xml``.
.. versionadded:: 1.2
.. class:: PseudoXMLBuilder
This builder is used for debugging the Sphinx/Docutils "Reader to Transform
to Writer" pipeline. It produces compact pretty-printed "pseudo-XML", files
where nesting is indicated by indentation (no end-tags). External
attributes for all elements are output, and internal attributes for any
leftover "pending" elements are also given.
Its name is ``pseudoxml``.
.. versionadded:: 1.2
Built-in Sphinx extensions that offer more builders are:

View File

@ -1342,6 +1342,16 @@ Options for the linkcheck builder
.. versionadded:: 1.2
Options for the XML builder
---------------------------
.. confval:: xml_pretty
If True, pretty-print the XML. Default is ``True``.
.. versionadded:: 1.2
.. rubric:: Footnotes
.. [1] A note on available globbing syntax: you can use the standard shell

View File

@ -334,4 +334,6 @@ BUILTIN_BUILDERS = {
'linkcheck': ('linkcheck', 'CheckExternalLinksBuilder'),
'websupport': ('websupport', 'WebSupportBuilder'),
'gettext': ('gettext', 'MessageCatalogBuilder'),
'xml': ('xml', 'XMLBuilder'),
'pseudoxml': ('xml', 'PseudoXMLBuilder'),
}

85
sphinx/builders/xml.py Normal file
View File

@ -0,0 +1,85 @@
# -*- coding: utf-8 -*-
"""
sphinx.builders.xml
~~~~~~~~~~~~~~~~~~~
Docutils-native XML and pseudo-XML builders.
:copyright: Copyright 2007-2012 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import codecs
from os import path
from docutils.io import StringOutput
from sphinx.builders import Builder
from sphinx.util.osutil import ensuredir, os_path
from sphinx.writers.xml import XMLWriter, PseudoXMLWriter
class XMLBuilder(Builder):
"""
Builds Docutils-native XML.
"""
name = 'xml'
format = 'xml'
out_suffix = '.xml'
_writer_class = XMLWriter
def init(self):
pass
def get_outdated_docs(self):
for docname in self.env.found_docs:
if docname not in self.env.all_docs:
yield docname
continue
targetname = self.env.doc2path(docname, self.outdir,
self.out_suffix)
try:
targetmtime = path.getmtime(targetname)
except Exception:
targetmtime = 0
try:
srcmtime = path.getmtime(self.env.doc2path(docname))
if srcmtime > targetmtime:
yield docname
except EnvironmentError:
# source doesn't exist anymore
pass
def get_target_uri(self, docname, typ=None):
return ''
def prepare_writing(self, docnames):
self.writer = self._writer_class(self)
def write_doc(self, docname, doctree):
destination = StringOutput(encoding='utf-8')
self.writer.write(doctree, destination)
outfilename = path.join(self.outdir, os_path(docname) + self.out_suffix)
ensuredir(path.dirname(outfilename))
try:
f = codecs.open(outfilename, 'w', 'utf-8')
try:
f.write(self.writer.output)
finally:
f.close()
except (IOError, OSError), err:
self.warn("error writing file %s: %s" % (outfilename, err))
def finish(self):
pass
class PseudoXMLBuilder(XMLBuilder):
"""
Builds pseudo-XML for display purposes.
"""
name = 'pseudoxml'
format = 'pseudoxml'
out_suffix = '.pseudoxml'
_writer_class = PseudoXMLWriter

View File

@ -184,6 +184,9 @@ class Config(object):
# gettext options
gettext_compact = (True, 'gettext'),
# XML options
xml_pretty = (True, 'env'),
)
def __init__(self, dirname, filename, overrides, tags):

View File

@ -387,7 +387,7 @@ to the full path of the 'sphinx-build' executable. Alternatively you
may add the Sphinx directory to PATH.
If you don't have Sphinx installed, grab it from
http://sphinx-doc.org/
http://sphinx-doc.org/
endef
$(error $(MSG))
endif
@ -423,6 +423,8 @@ help:
\t@echo " info to make Texinfo files and run them through makeinfo"
\t@echo " gettext to make PO message catalogs"
\t@echo " changes to make an overview of all changed/added/deprecated items"
\t@echo " xml to make Docutils-native XML files"
\t@echo " pseudoxml to make pseudoxml-XML files for display purposes"
\t@echo " linkcheck to check all external links for integrity"
\t@echo " doctest to run all doctests embedded in the documentation \
(if enabled)"
@ -547,6 +549,16 @@ doctest:
\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
\t@echo "Testing of doctests in the sources finished, look at the " \\
\t "results in $(BUILDDIR)/doctest/output.txt."
xml:
\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
\t@echo
\t@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
\t@echo
\t@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
'''
BATCHFILE = '''\
@ -585,6 +597,8 @@ if "%%1" == "help" (
\techo. texinfo to make Texinfo files
\techo. gettext to make PO message catalogs
\techo. changes to make an overview over all changed/added/deprecated items
\techo. xml to make Docutils-native XML files
\techo. pseudoxml to make pseudoxml-XML files for display purposes
\techo. linkcheck to check all external links for integrity
\techo. doctest to run all doctests embedded in the documentation if enabled
\tgoto end
@ -773,6 +787,22 @@ results in %%BUILDDIR%%/doctest/output.txt.
\tgoto end
)
if "%%1" == "xml" (
\t%%SPHINXBUILD%% -b xml %%ALLSPHINXOPTS%% %%BUILDDIR%%/xml
\tif errorlevel 1 exit /b 1
\techo.
\techo.Build finished. The XML files are in %%BUILDDIR%%/xml.
\tgoto end
)
if "%%1" == "pseudoxml" (
\t%%SPHINXBUILD%% -b pseudoxml %%ALLSPHINXOPTS%% %%BUILDDIR%%/pseudoxml
\tif errorlevel 1 exit /b 1
\techo.
\techo.Build finished. The pseudo-XML files are in %%BUILDDIR%%/pseudoxml.
\tgoto end
)
:end
'''

58
sphinx/writers/xml.py Normal file
View File

@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
"""
sphinx.writers.xml
~~~~~~~~~~~~~~~~~~
Docutils-native XML and pseudo-XML writers.
:copyright: Copyright 2007-2012 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from docutils import writers
from docutils.writers.docutils_xml import Writer as BaseXMLWriter
from docutils.writers.docutils_xml import XMLTranslator as BaseXMLTranslator
class XMLWriter(BaseXMLWriter):
def __init__(self, builder):
BaseXMLWriter.__init__(self)
self.builder = builder
def translate(self, *args, **kwargs):
self.document.settings.newlines = \
self.document.settings.indents = \
self.builder.env.config.xml_pretty
self.document.settings.xml_declaration = True
self.document.settings.doctype_declaration = True
return BaseXMLWriter.translate(self)
class XMLTranslator(BaseXMLTranslator):
def __init__(self, builder, doc):
BaseXMLTranslator.__init__(self, doc)
self.builder = builder
class PseudoXMLWriter(writers.Writer):
supported = ('pprint', 'pformat', 'pseudoxml')
"""Formats this writer supports."""
config_section = 'pseudoxml writer'
config_section_dependencies = ('writers',)
output = None
"""Final translated form of `document`."""
def __init__(self, builder):
writers.Writer.__init__(self)
self.builder = builder
def translate(self):
self.output = self.document.pformat()
def supports(self, format):
"""This writer supports all format-specific elements."""
return True

View File

@ -61,3 +61,11 @@ else:
@with_app(buildername='singlehtml', cleanenv=True)
def test_singlehtml(app):
app.builder.build_all()
@with_app(buildername='xml')
def test_xml(app):
app.builder.build_all()
@with_app(buildername='pseudoxml')
def test_pseudoxml(app):
app.builder.build_all()