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`) * PR#88: Added the "Sphinx Developer's Guide" (:file:`doc/devguide.rst`)
which outlines the basic development process of the Sphinx project. 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) Release 1.1.3 (Mar 10, 2012)
============================ ============================

View File

@ -13,7 +13,8 @@ ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) \
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) . I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) .
.PHONY: help clean html dirhtml singlehtml text man pickle json htmlhelp \ .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: help:
@echo "Please use \`make <target>' where <target> is one of" @echo "Please use \`make <target>' where <target> is one of"
@ -147,3 +148,13 @@ info:
@echo "Running Texinfo files through makeinfo..." @echo "Running Texinfo files through makeinfo..."
make -C _build/texinfo info make -C _build/texinfo info
@echo "makeinfo finished; the Info files are in _build/texinfo." @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``. 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: Built-in Sphinx extensions that offer more builders are:

View File

@ -1342,6 +1342,16 @@ Options for the linkcheck builder
.. versionadded:: 1.2 .. 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 .. rubric:: Footnotes
.. [1] A note on available globbing syntax: you can use the standard shell .. [1] A note on available globbing syntax: you can use the standard shell

View File

@ -334,4 +334,6 @@ BUILTIN_BUILDERS = {
'linkcheck': ('linkcheck', 'CheckExternalLinksBuilder'), 'linkcheck': ('linkcheck', 'CheckExternalLinksBuilder'),
'websupport': ('websupport', 'WebSupportBuilder'), 'websupport': ('websupport', 'WebSupportBuilder'),
'gettext': ('gettext', 'MessageCatalogBuilder'), '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 options
gettext_compact = (True, 'gettext'), gettext_compact = (True, 'gettext'),
# XML options
xml_pretty = (True, 'env'),
) )
def __init__(self, dirname, filename, overrides, tags): 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. may add the Sphinx directory to PATH.
If you don't have Sphinx installed, grab it from If you don't have Sphinx installed, grab it from
http://sphinx-doc.org/ http://sphinx-doc.org/
endef endef
$(error $(MSG)) $(error $(MSG))
endif endif
@ -423,6 +423,8 @@ help:
\t@echo " info to make Texinfo files and run them through makeinfo" \t@echo " info to make Texinfo files and run them through makeinfo"
\t@echo " gettext to make PO message catalogs" \t@echo " gettext to make PO message catalogs"
\t@echo " changes to make an overview of all changed/added/deprecated items" \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 " linkcheck to check all external links for integrity"
\t@echo " doctest to run all doctests embedded in the documentation \ \t@echo " doctest to run all doctests embedded in the documentation \
(if enabled)" (if enabled)"
@ -547,6 +549,16 @@ doctest:
\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest \t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
\t@echo "Testing of doctests in the sources finished, look at the " \\ \t@echo "Testing of doctests in the sources finished, look at the " \\
\t "results in $(BUILDDIR)/doctest/output.txt." \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 = '''\ BATCHFILE = '''\
@ -585,6 +597,8 @@ if "%%1" == "help" (
\techo. texinfo to make Texinfo files \techo. texinfo to make Texinfo files
\techo. gettext to make PO message catalogs \techo. gettext to make PO message catalogs
\techo. changes to make an overview over all changed/added/deprecated items \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. linkcheck to check all external links for integrity
\techo. doctest to run all doctests embedded in the documentation if enabled \techo. doctest to run all doctests embedded in the documentation if enabled
\tgoto end \tgoto end
@ -773,6 +787,22 @@ results in %%BUILDDIR%%/doctest/output.txt.
\tgoto end \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 :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) @with_app(buildername='singlehtml', cleanenv=True)
def test_singlehtml(app): def test_singlehtml(app):
app.builder.build_all() 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()