Merge branch 'stable'

This commit is contained in:
Takeshi KOMIYA 2016-01-11 00:27:26 +09:00
commit e4b9eb51f6
70 changed files with 777 additions and 147 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
*.pyc
*.egg
*.so
*.swp
.dir-locals.el
.ropeproject/

29
CHANGES
View File

@ -69,14 +69,39 @@ Bugs fixed
* #2168: Fix raw directive does not work for text writer
* #2171: Fix cannot linkcheck url with unicode
* #2182: LaTeX: support image file names with more than 1 dots
* #2189: Fix previous sibling link for first file in subdirectory uses last file, not intended previous from root toctree
* #2189: Fix previous sibling link for first file in subdirectory uses last file, not
intended previous from root toctree
* #2003: Fix decode error under python2 (only) when ``make linkcheck`` is run
* #2186: Fix LaTeX output of \mathbb in math
* #1480, #2188: LaTeX: Support math in section titles
* #2071: Fix same footnote in more than two section titles => LaTeX/PDF Bug
* #2040: Fix UnicodeDecodeError in sphinx-apidoc when author contains non-ascii characters
* #2193: Fix shutil.SameFileError if source directory and destination directory are same
* #2178: Fix unparseable C++ cross-reference when referencing a function with :cpp:any:
* #2206: Fix Sphinx latex doc build failed due to a footnotes
* #2201: Fix wrong table caption for tables with over 30 rows
* #2213: Set <blockquote> in the classic theme to fit with <p>
* #1815: Fix linkcheck does not raise an exception if warniserror set to true and link is
broken
* #2197: Fix slightly cryptic error message for missing index.rst file
* #1894: Unlisted phony targets in quickstart Makefile
* #2125: Fix unifies behavior of collapsed fields (``GroupedField`` and ``TypedField``)
* #1408: Check latex_logo validity before copying
* #771: Fix latex output doesn't set tocdepth
* #1820: On Windows, console coloring is broken with colorama version 0.3.3.
Now sphinx use colorama>=0.3.5 to avoid this problem.
* #2072: Fix footnotes in chapter-titles do not appear in PDF output
* #1580: Fix paragraphs in longtable don't work in Latex output
* #1366: Fix centered image not centered in latex
* #1860: Fix man page using ``:samp:`` with braces - font doesn't reset
* #1610: Sphinx crashes in japanese indexing in some systems
* Fix Sphinx crashes if mecab initialization failed
* #2160: Fix broken TOC of PDFs if section includes an image
* #2172: Fix dysfunctional admonition \py@lightbox in sphinx.sty. Thanks to jfbu.
* #2198,#2205: ``make gettext`` generate broken msgid for definition lists.
* #2062: Escape characters in doctests are treated incorrectly with Python 2.
* #2225: Fix if the option does not begin with dash, linking is not performed
* #2226: Fix math is not HTML-encoded when :nowrap: is given (jsmath, mathjax)
Release 1.3.3 (released Dec 2, 2015)
====================================

View File

@ -62,11 +62,11 @@
</table>
<p>{%trans%}
You can also download PDF versions of the Sphinx documentation:
a <a href="http://sphinx-doc.org/sphinx.pdf">version</a> generated from
You can also download PDF/EPUB versions of the Sphinx documentation:
a <a href="http://readthedocs.org/projects/sphinx/downloads/pdf/stable/">PDF version</a> generated from
the LaTeX Sphinx produces, and
a <a href="http://sphinx-doc.org/sphinx-rst2pdf.pdf">version</a> generated
by rst2pdf.{%endtrans%}
a <a href="http://readthedocs.org/projects/sphinx/downloads/epub/stable/">EPUB version</a>.
{%endtrans%}
</p>
<h2>{%trans%}Examples{%endtrans%}</h2>

View File

@ -14,15 +14,7 @@
<p>{%trans%}Current version: <b>{{ version }}</b>{%endtrans%}</p>
<p>{%trans%}Get Sphinx from the <a href="https://pypi.python.org/pypi/Sphinx">Python Package
Index</a>, or install it with:{%endtrans%}</p>
{% if version.split('b')|length > 1 %}
<pre>pip install Sphinx=={{ version }}</pre>
<p>{%trans%}<a href="http://sphinx-doc.org/">Stable version docs</a>
are also available.{%endtrans%}</p>
{% else %}
<pre>pip install -U Sphinx</pre>
<p>{%trans%}Latest <a href="http://sphinx-doc.org/latest/">development version docs</a>
are also available.{%endtrans%}</p>
{% endif %}
{% endif %}
<h3>{%trans%}Questions? Suggestions?{%endtrans%}</h3>

View File

@ -17,7 +17,11 @@ Build environment API
.. attribute:: srcdir
Source directory (the directory containing ``conf.py``).
Source directory.
.. attribute:: confdir
Directory containing ``conf.py``.
.. attribute:: doctreedir

View File

@ -242,9 +242,8 @@ objects:
.. rst:role:: option
A command-line option to an executable program. The leading hyphen(s) must
be included. This generates a link to a :rst:dir:`option` directive, if it
exists.
A command-line option to an executable program. This generates a link to
a :rst:dir:`option` directive, if it exists.
The following role creates a cross-reference to a term in a

View File

@ -58,7 +58,7 @@ requires = [
extras_require = {
# Environment Marker works for wheel 0.24 or later
':sys_platform=="win32"': [
'colorama',
'colorama>=0.3.5',
],
'websupport': [
'sqlalchemy>=0.9',
@ -73,7 +73,7 @@ extras_require = {
# for sdist installation with pip-1.5.6
if sys.platform == 'win32':
requires.append('colorama')
requires.append('colorama>=0.3.5')
# Provide a "compile_catalog" command that also creates the translated
# JavaScript files if Babel is available.

View File

@ -20,6 +20,7 @@ from docutils.frontend import OptionParser
from sphinx import package_dir, addnodes
from sphinx.util import texescape
from sphinx.errors import SphinxError
from sphinx.locale import _
from sphinx.builders import Builder
from sphinx.environment import NoUri
@ -94,9 +95,18 @@ class LaTeXBuilder(Builder):
destination_path=path.join(self.outdir, targetname),
encoding='utf-8')
self.info("processing " + targetname + "... ", nonl=1)
toctrees = self.env.get_doctree(docname).traverse(addnodes.toctree)
if toctrees:
if toctrees[0].get('maxdepth'):
tocdepth = int(toctrees[0].get('maxdepth'))
else:
tocdepth = None
else:
tocdepth = None
doctree = self.assemble_doctree(
docname, toctree_only,
appendices=((docclass != 'howto') and self.config.latex_appendices or []))
doctree['tocdepth'] = tocdepth
self.post_process_images(doctree)
self.info("writing... ", nonl=1)
doctree.settings = docsettings
@ -191,6 +201,9 @@ class LaTeXBuilder(Builder):
# the logo is handled differently
if self.config.latex_logo:
logobase = path.basename(self.config.latex_logo)
copyfile(path.join(self.confdir, self.config.latex_logo),
path.join(self.outdir, logobase))
logotarget = path.join(self.outdir, logobase)
if not path.isfile(path.join(self.confdir, self.config.latex_logo)):
raise SphinxError('logo file %r does not exist' % self.config.latex_logo)
elif not path.isfile(logotarget):
copyfile(path.join(self.confdir, self.config.latex_logo), logotarget)
self.info('done')

View File

@ -243,11 +243,12 @@ class CheckExternalLinksBuilder(Builder):
elif status == 'working':
self.info(darkgreen('ok ') + uri + info)
elif status == 'broken':
self.info(red('broken ') + uri + red(' - ' + info))
self.write_entry('broken', docname, lineno, uri + ': ' + info)
if self.app.quiet:
if self.app.quiet or self.app.warningiserror:
self.warn('broken link: %s' % uri,
'%s:%s' % (self.env.doc2path(docname), lineno))
else:
self.info(red('broken ') + uri + red(' - ' + info))
elif status == 'redirected':
text, color = {
301: ('permanently', darkred),

View File

@ -3924,6 +3924,9 @@ class CPPXRefRole(XRefRole):
parent = env.ref_context.get('cpp:parentSymbol', None)
if parent:
refnode['cpp:parentKey'] = parent.get_lookup_key()
if refnode['reftype'] == 'any':
# Remove parentheses from the target (not from title)
title, target = self._fix_parens(env, True, title, target)
# TODO: should this really be here?
if not has_explicit_title:
target = target.lstrip('~') # only has a meaning for the title
@ -4048,6 +4051,14 @@ class CPPDomain(Domain):
name = text_type(fullNestedName).lstrip(':')
docname = s.docname
assert docname
if declaration.objectType == 'function':
title = name
if title.endswith('()'):
title = title[:-2] # remove parentheses
if env.config.add_function_parentheses:
title += '()'
contnode.pop(0)
contnode.insert(0, nodes.Text(title))
return make_refnode(builder, fromdocname, docname,
declaration.get_newest_id(), contnode, name
), declaration.objectType

View File

@ -210,10 +210,6 @@ class Program(Directive):
class OptionXRefRole(XRefRole):
def process_link(self, env, refnode, has_explicit_title, title, target):
# validate content
if not re.match(r'(.+ )?[-/+\w]', target):
env.warn_node('Malformed :option: %r, does not contain option '
'marker - or -- or / or +' % target, refnode)
refnode['std:program'] = env.ref_context.get('std:program')
return title, target
@ -666,22 +662,23 @@ class StandardDomain(Domain):
return make_refnode(builder, fromdocname, docname,
labelid, contnode)
elif typ == 'option':
target = target.strip()
# most obvious thing: we are a flag option without program
if target.startswith(('-', '/', '+')):
progname = node.get('std:program')
elif re.search(r'[-/+]', target):
try:
progname, target = re.split(r' (?=-|--|/|\+)', target, 1)
except ValueError:
return None
progname = ws_re.sub('-', progname.strip())
else:
progname = None
target = target.strip()
docname, labelid = self.data['progoptions'].get((progname, target), ('', ''))
if not docname:
commands = []
while ws_re.search(target):
subcommand, target = ws_re.split(target, 1)
commands.append(subcommand)
progname = "-".join(commands)
docname, labelid = self.data['progoptions'].get((progname, target),
('', ''))
if not docname:
if docname:
break
else:
return None
return make_refnode(builder, fromdocname, docname,
labelid, contnode)
else:

View File

@ -618,7 +618,7 @@ class BuildEnvironment:
self._read_serial(docnames, app)
if config.master_doc not in self.all_docs:
self.warn(None, 'master file %s not found' %
raise SphinxError('master file %s not found' %
self.doc2path(config.master_doc))
self.app = None

View File

@ -45,14 +45,6 @@ else:
return text
class _SpoofOutSphinx(doctest._SpoofOut):
# override: convert console encoding to unicode
if PY2:
def getvalue(self):
result = doctest._SpoofOut.getvalue(self)
return result.decode('string_escape')
# set up the necessary directives
class TestDirective(Directive):
@ -184,11 +176,6 @@ class TestCode(object):
class SphinxDocTestRunner(doctest.DocTestRunner):
def __init__(self, *args, **kw):
doctest.DocTestRunner.__init__(self, *args, **kw)
# Override a fake output target for capturing doctest output.
self._fakeout = _SpoofOutSphinx()
def summarize(self, out, verbose=None):
string_io = StringIO()
old_stdout = sys.stdout
@ -262,9 +249,10 @@ Results of doctest builder run on %s
self.outfile.write(text)
def _warn_out(self, text):
self.info(text, nonl=True)
if self.app.quiet:
if self.app.quiet or self.app.warningiserror:
self.warn(text)
else:
self.info(text, nonl=True)
if isinstance(text, binary_type):
text = force_decode(text, None)
self.outfile.write(text)

View File

@ -26,7 +26,7 @@ def html_visit_math(self, node):
def html_visit_displaymath(self, node):
if node['nowrap']:
self.body.append(self.starttag(node, 'div', CLASS='math'))
self.body.append(node['latex'])
self.body.append(self.encode(node['latex']))
self.body.append('</div>')
raise nodes.SkipNode
for i, part in enumerate(node['latex'].split('\n\n')):

View File

@ -30,7 +30,7 @@ def html_visit_displaymath(self, node):
self.body.append(self.starttag(node, 'div', CLASS='math'))
if node['nowrap']:
self.body.append(self.builder.config.mathjax_display[0] +
node['latex'] +
self.encode(node['latex']) +
self.builder.config.mathjax_display[1])
self.body.append('</div>')
raise nodes.SkipNode

View File

@ -371,10 +371,10 @@ epub_copyright = copyright
# The basename for the epub file. It defaults to the project name.
#epub_basename = project
# The HTML theme for the epub output. Since the default themes are not optimized
# for small screen space, using the same theme for HTML and epub output is
# usually not wise. This defaults to 'epub', a theme designed to save visual
# space.
# The HTML theme for the epub output. Since the default themes are not
# optimized for small screen space, using the same theme for HTML and epub
# output is usually not wise. This defaults to 'epub', a theme designed to save
# visual space.
#epub_theme = 'epub'
# The language of the text. It defaults to the language option
@ -489,9 +489,7 @@ $(SPHINXOPTS) %(rsrcdir)s
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) %(rsrcdir)s
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp \
epub latex latexpdf text man changes linkcheck doctest coverage gettext
.PHONY: help
help:
\t@echo "Please use \\`make <target>' where <target> is one of"
\t@echo " html to make standalone HTML files"
@ -520,40 +518,48 @@ help:
(if enabled)"
\t@echo " coverage to run coverage check of the documentation (if enabled)"
.PHONY: clean
clean:
\trm -rf $(BUILDDIR)/*
.PHONY: html
html:
\t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
\t@echo
\t@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
.PHONY: dirhtml
dirhtml:
\t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
\t@echo
\t@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
.PHONY: singlehtml
singlehtml:
\t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
\t@echo
\t@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
.PHONY: pickle
pickle:
\t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
\t@echo
\t@echo "Build finished; now you can process the pickle files."
.PHONY: json
json:
\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
\t@echo
\t@echo "Build finished; now you can process the JSON files."
.PHONY: htmlhelp
htmlhelp:
\t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
\t@echo
\t@echo "Build finished; now you can run HTML Help Workshop with the" \\
\t ".hhp project file in $(BUILDDIR)/htmlhelp."
.PHONY: qthelp
qthelp:
\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
\t@echo
@ -563,6 +569,7 @@ qthelp:
\t@echo "To view the help file:"
\t@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/%(project_fn)s.qhc"
.PHONY: applehelp
applehelp:
\t$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
\t@echo
@ -571,6 +578,7 @@ applehelp:
\t "~/Library/Documentation/Help or install it in your application" \\
\t "bundle."
.PHONY: devhelp
devhelp:
\t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
\t@echo
@ -581,11 +589,13 @@ devhelp:
$$HOME/.local/share/devhelp/%(project_fn)s"
\t@echo "# devhelp"
.PHONY: epub
epub:
\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
\t@echo
\t@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
.PHONY: latex
latex:
\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
\t@echo
@ -593,28 +603,33 @@ latex:
\t@echo "Run \\`make' in that directory to run these through (pdf)latex" \\
\t "(use \\`make latexpdf' here to do that automatically)."
.PHONY: latexpdf
latexpdf:
\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
\t@echo "Running LaTeX files through pdflatex..."
\t$(MAKE) -C $(BUILDDIR)/latex all-pdf
\t@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
.PHONY: latexpdfja
latexpdfja:
\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
\t@echo "Running LaTeX files through platex and dvipdfmx..."
\t$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
\t@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
.PHONY: text
text:
\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
\t@echo
\t@echo "Build finished. The text files are in $(BUILDDIR)/text."
.PHONY: man
man:
\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
\t@echo
\t@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
.PHONY: texinfo
texinfo:
\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
\t@echo
@ -622,43 +637,51 @@ texinfo:
\t@echo "Run \\`make' in that directory to run these through makeinfo" \\
\t "(use \\`make info' here to do that automatically)."
.PHONY: info
info:
\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
\t@echo "Running Texinfo files through makeinfo..."
\tmake -C $(BUILDDIR)/texinfo info
\t@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
.PHONY: gettext
gettext:
\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
\t@echo
\t@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
.PHONY: changes
changes:
\t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
\t@echo
\t@echo "The overview file is in $(BUILDDIR)/changes."
.PHONY: linkcheck
linkcheck:
\t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
\t@echo
\t@echo "Link check complete; look for any errors in the above output " \\
\t "or in $(BUILDDIR)/linkcheck/output.txt."
.PHONY: doctest
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."
.PHONY: coverage
coverage:
\t$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
\t@echo "Testing of coverage in the sources finished, look at the " \\
\t "results in $(BUILDDIR)/coverage/python.txt."
.PHONY: xml
xml:
\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
\t@echo
\t@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
.PHONY: pseudoxml
pseudoxml:
\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
\t@echo

View File

@ -29,6 +29,7 @@ try:
except ImportError:
native_module = False
from sphinx.errors import SphinxError
from sphinx.search import SearchLanguage
@ -86,9 +87,16 @@ class MecabBinder(object):
if dict:
param += ' -d %s' % dict
fs_enc = sys.getfilesystemencoding() or sys.getdefaultencoding()
self.ctypes_libmecab = ctypes.CDLL(libpath)
self.ctypes_libmecab.mecab_new2.argtypes = (ctypes.c_char_p,)
self.ctypes_libmecab.mecab_new2.restype = ctypes.c_void_p
self.ctypes_libmecab.mecab_sparse_tostr.argtypes = (ctypes.c_void_p, ctypes.c_char_p)
self.ctypes_libmecab.mecab_sparse_tostr.restype = ctypes.c_char_p
self.ctypes_mecab = self.ctypes_libmecab.mecab_new2(param)
self.ctypes_mecab = self.ctypes_libmecab.mecab_new2(param.encode(fs_enc))
if self.ctypes_mecab is None:
raise SphinxError('mecab initialization failed')
def __del__(self):
if self.ctypes_libmecab:

View File

@ -270,16 +270,15 @@
\fbox{\TheSbox}
}
\newcommand{\py@lightbox}{{%
\setlength\parskip{0pt}\par
\noindent\rule[0ex]{\linewidth}{0.5pt}%
\par\noindent\vspace{-0.5ex}%
}}
\newcommand{\py@endlightbox}{{%
\setlength{\parskip}{0pt}%
\par\noindent\rule[0.5ex]{\linewidth}{0.5pt}%
\par\vspace{-0.5ex}%
}}
\newcommand{\py@lightbox}{%
\par\allowbreak
\noindent\rule{\linewidth}{0.5pt}\par\nobreak
{\parskip\z@skip\noindent}%
}
\newcommand{\py@endlightbox}{%
\par\nobreak
{\parskip\z@skip\noindent\rule[.4\baselineskip]{\linewidth}{0.5pt}}\par
}
% Some are quite plain:
\newcommand{\py@noticestart@note}{\py@lightbox}

View File

@ -223,7 +223,7 @@ a.headerlink:hover {
color: white;
}
div.body p, div.body dd, div.body li {
div.body p, div.body dd, div.body li, div.body blockquote {
text-align: justify;
line-height: 130%;
}

View File

@ -106,8 +106,6 @@ class GroupedField(Field):
def make_field(self, types, domain, items):
fieldname = nodes.field_name('', self.label)
listnode = self.list_type()
if len(items) == 1 and self.can_collapse:
return Field.make_field(self, types, domain, items[0])
for fieldarg, content in items:
par = nodes.paragraph()
par += self.make_xref(self.rolename, domain, fieldarg,
@ -115,6 +113,9 @@ class GroupedField(Field):
par += nodes.Text(' -- ')
par += content
listnode += nodes.list_item('', par)
if len(items) == 1 and self.can_collapse:
fieldbody = nodes.field_body('', listnode[0][0])
return nodes.field('', fieldname, fieldbody)
fieldbody = nodes.field_body('', listnode)
return nodes.field('', fieldname, fieldbody)

View File

@ -47,8 +47,10 @@ def apply_source_workaround(node):
node.line = definition_list_item.line - 1
node.rawsource = node.astext() # set 'classifier1' (or 'classifier2')
if isinstance(node, nodes.term):
# overwrite: ``term : classifier1 : classifier2`` -> ``term text``
node.rawsource = node.astext()
# strip classifier from rawsource of term
for classifier in reversed(node.parent.traverse(nodes.classifier)):
node.rawsource = re.sub(
'\s*:\s*%s' % classifier.astext(), '', node.rawsource)
# workaround: recommonmark-0.2.0 doesn't set rawsource attribute
if not node.rawsource:

View File

@ -25,6 +25,7 @@ from sphinx import highlighting
from sphinx.errors import SphinxError
from sphinx.locale import admonitionlabels, _
from sphinx.util import split_into
from sphinx.util.nodes import clean_astext
from sphinx.util.osutil import ustrftime
from sphinx.util.texescape import tex_escape_map, tex_replace_map
from sphinx.util.smartypants import educate_quotes_latex
@ -53,6 +54,7 @@ HEADER = r'''%% Generated by Sphinx.
\author{%(author)s}
\newcommand{\sphinxlogo}{%(logo)s}
\renewcommand{\releasename}{%(releasename)s}
%(tocdepth)s
%(makeindex)s
'''
@ -234,7 +236,6 @@ class Table(object):
self.has_verbatim = False
self.caption = None
self.longtable = False
self.footnotes = []
class LaTeXTranslator(nodes.NodeVisitor):
@ -276,6 +277,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
'printindex': '\\printindex',
'transition': '\n\n\\bigskip\\hrule{}\\bigskip\n\n',
'figure_align': 'htbp',
'tocdepth': '',
}
# sphinx specific document classes
@ -360,6 +362,13 @@ class LaTeXTranslator(nodes.NodeVisitor):
if self.elements['extraclassoptions']:
self.elements['classoptions'] += ',' + \
self.elements['extraclassoptions']
if document.get('tocdepth'):
if document.settings.docclass == 'howto':
self.elements['tocdepth'] = ('\\setcounter{tocdepth}{%d}' %
document['tocdepth'])
else:
self.elements['tocdepth'] = ('\\setcounter{tocdepth}{%d}' %
(document['tocdepth'] - 1))
self.highlighter = highlighting.PygmentsBridge(
'latex',
@ -377,7 +386,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
sys.maxsize]]
self.bodystack = []
self.footnotestack = []
self.termfootnotestack = []
self.footnote_restricted = False
self.pending_footnotes = []
self.curfilestack = []
self.handled_abbrs = set()
if document.settings.docclass == 'howto':
@ -416,6 +426,19 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body = self.bodystack.pop()
return body
def restrict_footnote(self, node):
if self.footnote_restricted is False:
self.footnote_restricted = node
self.pending_footnotes = []
def unrestrict_footnote(self, node):
if self.footnote_restricted == node:
self.footnote_restricted = False
for footnode in self.pending_footnotes:
footnode['footnotetext'] = True
footnode.walkabout(self)
self.pending_footnotes = []
def format_docclass(self, docclass):
""" prepends prefix to sphinx document classes
"""
@ -697,13 +720,18 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.this_is_the_title = 0
raise nodes.SkipNode
elif isinstance(parent, nodes.section):
short = ''
if node.traverse(nodes.image):
short = '[%s]' % ' '.join(clean_astext(node).split()).translate(tex_escape_map)
try:
self.body.append(r'\%s{' % self.sectionnames[self.sectionlevel])
self.body.append(r'\%s%s{' % (self.sectionnames[self.sectionlevel], short))
except IndexError:
# just use "subparagraph", it's not numbered anyway
self.body.append(r'\%s{' % self.sectionnames[-1])
self.body.append(r'\%s%s{' % (self.sectionnames[-1], short))
self.context.append('}\n')
self.restrict_footnote(node)
if self.next_section_ids:
for id in self.next_section_ids:
self.context[-1] += self.hypertarget(id, anchor=False)
@ -733,6 +761,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.table.caption = self.popbody()
else:
self.body.append(self.context.pop())
self.unrestrict_footnote(node)
def visit_subtitle(self, node):
if isinstance(node.parent, nodes.sidebar):
@ -893,6 +922,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.tableheaders = []
# Redirect body output until table is finished.
self.pushbody(self.tablebody)
self.restrict_footnote(node)
def depart_table(self, node):
if self.table.rowcount > 30:
@ -936,7 +966,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
else:
self.body.append('{|' + ('L|' * self.table.colcount) + '}\n')
if self.table.longtable and self.table.caption is not None:
self.body.append(u'\\caption{%s}' % self.table.caption)
self.body.append(u'\\caption{')
for caption in self.table.caption:
self.body.append(caption)
self.body.append('}')
for id in self.next_table_ids:
self.body.append(self.hypertarget(id, anchor=False))
self.next_table_ids.clear()
@ -963,10 +996,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append(endmacro)
if not self.table.longtable and self.table.caption is not None:
self.body.append('\\end{threeparttable}\n\n')
if self.table.footnotes:
for footnode in self.table.footnotes:
footnode['footnotetext'] = True
footnode.walkabout(self)
self.unrestrict_footnote(node)
self.table = None
self.tablebody = None
@ -1078,6 +1108,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
context += str(extracols + 1)
context += '}{l|}{}'
self.table.col += extracols
if len(node.traverse(nodes.paragraph)) >= 2:
self.table.has_problematic = True
self.context.append(context)
def depart_entry(self, node):
@ -1140,16 +1172,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
if node.get('ids'):
ctx += self.hypertarget(node['ids'][0])
self.body.append('\\item[{')
self.termfootnotestack.append([])
self.restrict_footnote(node)
self.context.append(ctx)
def depart_term(self, node):
self.body.append(self.context.pop())
footnotes = self.termfootnotestack.pop()
for footnode in footnotes:
footnode['footnotetext'] = True
footnode.walkabout(self)
self.unrestrict_footnote(node)
self.in_term -= 1
def visit_termsep(self, node):
@ -1264,12 +1292,12 @@ class LaTeXTranslator(nodes.NodeVisitor):
(1, 'top'): ('', ''),
(1, 'middle'): ('\\raisebox{-0.5\\height}{', '}'),
(1, 'bottom'): ('\\raisebox{-\\height}{', '}'),
(0, 'center'): ('{\\hfill', '\\hfill}'),
(0, 'center'): ('{\\hspace*{\\fill}', '\\hspace*{\\fill}}'),
# These 2 don't exactly do the right thing. The image should
# be floated alongside the paragraph. See
# http://www.w3.org/TR/html4/struct/objects.html#adef-align-IMG
(0, 'left'): ('{', '\\hfill}'),
(0, 'right'): ('{\\hfill', '}'),
(0, 'left'): ('{', '\\hspace*{\\fill}}'),
(0, 'right'): ('{\\hspace*{\\fill}', '}'),
}
try:
pre.append(align_prepost[is_inline, attrs['align']][0])
@ -1306,6 +1334,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
for id in self.next_figure_ids:
ids += self.hypertarget(id, anchor=False)
self.next_figure_ids.clear()
self.restrict_footnote(node)
if (len(node.children) and
isinstance(node.children[0], nodes.image) and
node.children[0]['ids']):
@ -1333,6 +1362,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_figure(self, node):
self.body.append(self.context.pop())
self.unrestrict_footnote(node)
def visit_caption(self, node):
self.in_caption += 1
@ -1668,18 +1698,11 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.body.append('\\protect\\footnotemark[%s]' % num)
else:
self.body.append('\\footnotemark[%s]' % num)
elif self.table:
elif self.footnote_restricted:
self.footnotestack[-1][num][1] = True
self.body.append('\\protect\\footnotemark[%s]' % num)
self.table.footnotes.append(footnode)
elif self.in_term:
self.body.append('\\footnotemark[%s]' % num)
self.termfootnotestack[-1].append(footnode)
self.pending_footnotes.append(footnode)
else:
if self.in_caption:
raise UnsupportedError('%s:%s: footnotes in float captions '
'are not supported by LaTeX' %
(self.curfilestack[-1], node.line))
self.footnotestack[-1][num][1] = True
footnode.walkabout(self)
raise nodes.SkipChildren

View File

@ -30,12 +30,42 @@ class ManualPageWriter(Writer):
self.builder.translator_class or ManualPageTranslator)
def translate(self):
transform = NestedInlineTransform(self.document)
transform.apply()
visitor = self.translator_class(self.builder, self.document)
self.visitor = visitor
self.document.walkabout(visitor)
self.output = visitor.astext()
class NestedInlineTransform(object):
"""
Flatten nested inline nodes:
Before:
<strong>foo=<emphasis>1</emphasis>&bar=<emphasis>2</emphasis></strong>
After:
<strong>foo=</strong><emphasis>var</emphasis><strong>&bar=</strong><emphasis>2</emphasis>
"""
def __init__(self, document):
self.document = document
def apply(self):
def is_inline(node):
return isinstance(node, (nodes.literal, nodes.emphasis, nodes.strong))
for node in self.document.traverse(is_inline):
if any(is_inline(subnode) for subnode in node):
pos = node.parent.index(node)
for subnode in reversed(node[1:]):
node.remove(subnode)
if is_inline(subnode):
node.parent.insert(pos + 1, subnode)
else:
newnode = node.__class__('', subnode, **node.attributes)
node.parent.insert(pos + 1, newnode)
class ManualPageTranslator(BaseTranslator):
"""
Custom translator.

View File

@ -7,7 +7,7 @@ This is inline math: :math:`a^2 + b^2 = c^2`.
.. math::
a^2 + b^2 = c^2
a + 1 < b
.. math::
:label: foo
@ -23,4 +23,9 @@ This is inline math: :math:`a^2 + b^2 = c^2`.
n \in \mathbb N
.. math::
:nowrap:
a + 1 < b
Referencing equation :eq:`foo`.

View File

@ -174,7 +174,17 @@ Others
.. option:: arg
Link to :option:`perl +p` and :option:`arg`.
Link to :option:`perl +p` and :option:`arg`
.. program:: hg
.. option:: commit
.. program:: git commit
.. option:: -p
Link to :option:`hg commit` and :option:`git commit -p`.
User markup

View File

@ -7,3 +7,5 @@ extensions = ['sphinx.ext.autosummary']
# The suffix of source filenames.
source_suffix = '.rst'
autosummary_generate = True
exclude_patterns = ['_build']

View File

@ -1,2 +1,3 @@
master_doc = 'contents'
source_suffix = '.txt'
exclude_patterns = ['_build']

View File

@ -0,0 +1 @@
exclude_patterns = ['_build']

View File

@ -2,3 +2,4 @@
master_doc = 'index'
html_theme = 'classic'
exclude_patterns = ['_build']

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
master_doc = 'index'
exclude_patterns = ['_build']

View File

@ -1,2 +1,3 @@
project = 'test-directive-only'
exclude_patterns = ['_build']

View File

@ -1,5 +1,6 @@
extensions = ['sphinx.ext.doctest']
project = 'test project for doctest'
master_doc = 'doctest.txt'
master_doc = 'doctest'
source_suffix = '.txt'
exclude_patterns = ['_build']

View File

@ -136,3 +136,14 @@ umlauts: äöü.
>>> print('Japanese: 日本語')
Japanese: 日本語
keep control char in raw string
-------------------------------
.. doctest::
>>> print('one\ntwo')
one
two
>>> print(r'one\ntwo')
one\ntwo

View File

@ -3,3 +3,4 @@
project = 'Sphinx docutils conf <Tests>'
source_suffix = '.txt'
keep_warnings = True
exclude_patterns = ['_build']

View File

@ -0,0 +1,10 @@
any role
--------
* :cpp:any:`Sphinx`
* ref function without parens :cpp:any:`hello`.
* ref function with parens :cpp:any:`hello()`.
* :cpp:any:`Sphinx::version`
* :cpp:any:`version`
* :cpp:any:`List`
* :cpp:any:`MyEnum`

View File

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
master_doc = 'index'
html_theme = 'classic'
exclude_patterns = ['_build']

View File

@ -0,0 +1,37 @@
test-domain-cpp
===============
directives
----------
.. cpp:class:: public Sphinx
The description of Sphinx class.
.. cpp:function:: int hello(char *name)
The description of hello function.
.. cpp:member:: float Sphinx::version
The description of Sphinx::version.
.. cpp:var:: int version
The description of version.
.. cpp:type:: std::vector<int> List
The description of List type.
.. cpp:enum:: MyEnum
An unscoped enum.
.. cpp:enum-class:: MyScopedEnum
A scoped enum.
.. cpp:enum-struct:: protected MyScopedVisibilityEnum : std::underlying_type<MySpecificEnum>::type
A scoped enum with non-default visibility, and with a specified underlying type.

View File

@ -0,0 +1,10 @@
roles
-----
* :cpp:class:`Sphinx`
* ref function without parens :cpp:func:`hello`.
* ref function with parens :cpp:func:`hello()`.
* :cpp:member:`Sphinx::version`
* :cpp:var:`version`
* :cpp:type:`List`
* :cpp:enum:`MyEnum`

View File

@ -5,3 +5,4 @@ import sys, os
templates_path = ['_templates']
master_doc = 'index'
html_theme = 'base_theme2'
exclude_patterns = ['_build']

View File

@ -2,3 +2,4 @@
extensions = ['sphinx.ext.graphviz']
master_doc = 'index'
exclude_patterns = ['_build']

View File

@ -2,6 +2,7 @@
extensions = ['sphinx.ext.ifconfig']
master_doc = 'index'
exclude_patterns = ['_build']
confval1 = True

View File

@ -6,6 +6,7 @@ import os
sys.path.insert(0, os.path.abspath('.'))
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
master_doc = 'index'
exclude_patterns = ['_build']
if 'test_linkcode' in tags:

View File

@ -2,3 +2,4 @@
master_doc = 'index'
html_theme = 'classic'
exclude_patterns = ['_build']

View File

@ -33,9 +33,11 @@ The section with a reference to [AuthorYear]_
.. [1] Second
.. [#] Third
The section with a reference to [1]_
The section with a reference to [#]_
=====================================
.. [#] Footnote in section
`URL in term <http://sphinx-doc.org/>`_
Description Description Description ...
@ -46,3 +48,95 @@ Footnote in term [#]_
Description2
.. [#] Footnote in term
.. figure:: rimg.png
This is the figure caption with a footnote to [#]_.
.. [#] Footnote in caption
.. list-table:: footnote [#]_ in caption of normal table
:widths: 1 1
:header-rows: 1
* - name
- desc
* - a
- b
* - a
- b
.. [#] Foot note in table
.. list-table:: footnote [#]_ in caption of longtable
:widths: 1 1
:header-rows: 1
* - name
- desc
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
* - a
- b
.. [#] Foot note in longtable

View File

@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
master_doc = 'index'
exclude_patterns = ['_build']
rst_epilog = '''
.. |picture| image:: pic.png
:width: 15pt
:height: 15pt
:alt: alternative_text
'''

View File

@ -0,0 +1,18 @@
test-image-in-section
=====================
this is dummy content
|picture| Test section
----------------------
blah blah blah
Another section
---------------
another blah
Other [blah] |picture| section
------------------------------
other blah

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

View File

@ -7,3 +7,4 @@ templates_path = ['_templates']
html_additional_pages = {'index': 'index.html'}
release = version = '2013.120'
gettext_additional_targets = ['index']
exclude_patterns = ['_build']

View File

@ -25,14 +25,14 @@ msgstr "SOME TERM"
msgid "The corresponding definition"
msgstr "THE CORRESPONDING DEFINITION"
msgid "Some other term"
msgstr "SOME OTHER TERM"
msgid "Some *term* `with link <http://sphinx-doc.org/>`__"
msgstr "SOME *TERM* `WITH LINK <http://sphinx-doc.org/>`__"
msgid "The corresponding definition #2"
msgstr "THE CORRESPONDING DEFINITION #2"
msgid "Some term with"
msgstr "SOME TERM WITH"
msgid "Some **term** with"
msgstr "SOME **TERM** WITH"
msgid "classifier1"
msgstr "CLASSIFIER1"

View File

@ -6,9 +6,9 @@ i18n with definition terms
Some term
The corresponding definition
Some other term
Some *term* `with link <http://sphinx-doc.org/>`__
The corresponding definition #2
Some term with : classifier1 : classifier2
Some **term** with : classifier1 : classifier2
The corresponding definition

View File

@ -0,0 +1 @@
exclude_patterns = ['_build']

View File

@ -2,3 +2,4 @@
master_doc = 'index'
html_theme = 'classic'
exclude_patterns = ['_build']

View File

@ -3,3 +3,4 @@
project = 'Sphinx smallest project'
source_suffix = '.txt'
keep_warnings = True
exclude_patterns = ['_build']

View File

@ -5,6 +5,7 @@ source_suffix = '.txt'
keep_warnings = True
templates_path = ['_templates']
release = version = '2013.120'
exclude_patterns = ['_build']
extensions = ['sphinx.ext.autosummary']
autosummary_generate = ['autosummary_templating']

View File

@ -2,4 +2,5 @@
html_theme = 'test-theme'
master_doc = 'index'
exclude_patterns = ['_build']

View File

@ -2,3 +2,4 @@
master_doc = 'index'
html_theme = 'classic'
exclude_patterns = ['_build']

View File

@ -2,3 +2,4 @@
master_doc = 'index'
html_theme = 'classic'
exclude_patterns = ['_build']

View File

@ -0,0 +1,27 @@
:tocdepth: 2
===
Bar
===
should be 2
Bar A
=====
should be 2.1
.. toctree::
baz
Bar B
=====
should be 2.2
Bar B1
------
should be 2.2.1

View File

@ -0,0 +1,5 @@
Baz A
-----
should be 2.1.1

View File

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
master_doc = 'index'
html_theme = 'classic'
exclude_patterns = ['_build']

View File

@ -0,0 +1,26 @@
===
Foo
===
should be 1
Foo A
=====
should be 1.1
Foo A1
------
should be 1.1.1
Foo B
=====
should be 1.2
Foo B1
------
should be 1.2.1

View File

@ -0,0 +1,9 @@
test-toctree-max-depth
======================
.. toctree::
:numbered:
:maxdepth: 2
foo
bar

View File

@ -1,3 +1,4 @@
project = 'versioning test root'
master_doc = 'index'
source_suffix = '.txt'
exclude_patterns = ['_build']

View File

@ -12,6 +12,7 @@
from six import BytesIO
from textwrap import dedent
from sphinx.errors import SphinxError
from util import with_app, rootdir, tempdir, SkipTest, TestApp
@ -73,6 +74,18 @@ def test_build_all():
yield verify_build, buildername, srcdir
@with_app(buildername='text')
def test_master_doc_not_found(app, status, warning):
(app.srcdir / 'contents.txt').move(app.srcdir / 'contents.txt.bak')
try:
app.builder.build_all()
assert False # SphinxError not raised
except Exception as exc:
assert isinstance(exc, SphinxError)
finally:
(app.srcdir / 'contents.txt.bak').move(app.srcdir / 'contents.txt')
@with_app(buildername='text', testroot='circular')
def test_circular_toctree(app, status, warning):
app.builder.build_all()

View File

@ -16,7 +16,7 @@ from six import PY3, iteritems
from six.moves import html_entities
from sphinx import __display_version__
from util import remove_unicode_literals, gen_with_app
from util import remove_unicode_literals, gen_with_app, with_app
from etree13 import ElementTree as ET
@ -31,9 +31,7 @@ http://www.python.org/logo.png
reading included file u'.*?wrongenc.inc' seems to be wrong, try giving an \
:encoding: option\\n?
%(root)s/includes.txt:4: WARNING: download file not readable: .*?nonexisting.png
(%(root)s/markup.txt:\\d+: WARNING: Malformed :option: u'&option', does \
not contain option marker - or -- or / or \\+
%(root)s/undecodable.txt:3: WARNING: undecodable source characters, replacing \
(%(root)s/undecodable.txt:3: WARNING: undecodable source characters, replacing \
with "\\?": b?'here: >>>(\\\\|/)xbb<<<'
)?"""
@ -234,6 +232,23 @@ HTML_XPATH = {
(".//td[@class='field-body']/ul/li/strong", '^hour$'),
(".//td[@class='field-body']/ul/li/em", '^DuplicateType$'),
(".//td[@class='field-body']/ul/li/em", tail_check(r'.* Some parameter')),
# others
(".//a[@class='reference internal'][@href='#cmdoption-perl-arg-+p']/code/span",
'perl'),
(".//a[@class='reference internal'][@href='#cmdoption-perl-arg-+p']/code/span",
'\+p'),
(".//a[@class='reference internal'][@href='#cmdoption-perl-arg-arg']/code/span",
'arg'),
(".//a[@class='reference internal'][@href='#cmdoption-hg-arg-commit']/code/span",
'hg'),
(".//a[@class='reference internal'][@href='#cmdoption-hg-arg-commit']/code/span",
'commit'),
(".//a[@class='reference internal'][@href='#cmdoption-git-commit-p']/code/span",
'git'),
(".//a[@class='reference internal'][@href='#cmdoption-git-commit-p']/code/span",
'commit'),
(".//a[@class='reference internal'][@href='#cmdoption-git-commit-p']/code/span",
'-p'),
],
'contents.html': [
(".//meta[@name='hc'][@content='hcval']", ''),
@ -914,3 +929,18 @@ def test_numfig_with_secnum_depth(app, status, warning):
for xpath, check, be_found in paths:
yield check_xpath, etree, fname, xpath, check, be_found
@with_app(buildername='html')
def test_jsmath(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'math.html').text()
assert '<div class="math">\na^2 + b^2 = c^2</div>' in content
assert '<div class="math">\n\\begin{split}a + 1 &lt; b\\end{split}</div>' in content
assert ('<span class="eqno">(1)</span><div class="math" id="equation-foo">\n'
'e^{i\\pi} = 1</div>' in content)
assert ('<span class="eqno">(2)</span><div class="math">\n'
'e^{ix} = \\cos x + i\\sin x</div>' in content)
assert '<div class="math">\nn \\in \\mathbb N</div>' in content
assert '<div class="math">\na + 1 &lt; b</div>' in content

View File

@ -16,6 +16,7 @@ from subprocess import Popen, PIPE
from six import PY3
from sphinx.errors import SphinxError
from sphinx.writers.latex import LaTeXTranslator
from util import SkipTest, remove_unicode_literals, with_app
@ -334,7 +335,17 @@ def test_reference_in_caption(app, status, warning):
assert '\\chapter{The section with a reference to {[}AuthorYear{]}}' in result
assert '\\caption{The table title with a reference to {[}AuthorYear{]}}' in result
assert '\\paragraph{The rubric title with a reference to {[}AuthorYear{]}}' in result
assert '\\chapter{The section with a reference to \\protect\\footnotemark[1]}' in result
assert ('\\chapter{The section with a reference to \\protect\\footnotemark[4]}\n'
'\\label{index:the-section-with-a-reference-to}'
'\\footnotetext[4]{\nFootnote in section\n}' in result)
assert ('\\caption{This is the figure caption with a footnote to '
'\\protect\\footnotemark[6].}\end{figure}\n'
'\\footnotetext[6]{\nFootnote in caption\n}')in result
assert ('\\caption{footnote \\protect\\footnotemark[7] '
'in caption of normal table}') in result
assert '\\end{threeparttable}\n\n\\footnotetext[7]{\nFoot note in table\n}' in result
assert '\\caption{footnote \\protect\\footnotemark[8] in caption of longtable}' in result
assert '\end{longtable}\n\n\\footnotetext[8]{\nFoot note in longtable\n}' in result
@with_app(buildername='latex', testroot='footnotes',
@ -353,8 +364,8 @@ def test_latex_show_urls_is_inline(app, status, warning):
'(http://sphinx-doc.org/\\textasciitilde{}test/)' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term} (http://sphinx-doc.org/)}] '
'\\leavevmode\nDescription' in result)
assert ('\\item[{Footnote in term \\footnotemark[4]}] '
'\\leavevmode\\footnotetext[4]{\nFootnote in term\n}\nDescription' in result)
assert ('\\item[{Footnote in term \\protect\\footnotemark[5]}] '
'\\leavevmode\\footnotetext[5]{\nFootnote in term\n}\nDescription' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist} '
'(http://sphinx-doc.org/)}] \\leavevmode\nDescription' in result)
assert ('\\href{https://github.com/sphinx-doc/sphinx}'
@ -378,12 +389,12 @@ def test_latex_show_urls_is_footnote(app, status, warning):
assert 'Third footnote: \\footnote[5]{\nThird\n}' in result
assert ('\\href{http://sphinx-doc.org/~test/}{URL including tilde}'
'\\footnote[4]{\nhttp://sphinx-doc.org/\\textasciitilde{}test/\n}' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}\\footnotemark[6]}] '
'\\leavevmode\\footnotetext[6]{\nhttp://sphinx-doc.org/\n}\nDescription' in result)
assert ('\\item[{Footnote in term \\footnotemark[8]}] '
'\\leavevmode\\footnotetext[8]{\nFootnote in term\n}\nDescription' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}\\footnotemark[7]}] '
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}\\protect\\footnotemark[7]}] '
'\\leavevmode\\footnotetext[7]{\nhttp://sphinx-doc.org/\n}\nDescription' in result)
assert ('\\item[{Footnote in term \\protect\\footnotemark[9]}] '
'\\leavevmode\\footnotetext[9]{\nFootnote in term\n}\nDescription' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}\\protect\\footnotemark[8]}] '
'\\leavevmode\\footnotetext[8]{\nhttp://sphinx-doc.org/\n}\nDescription' in result)
assert ('\\href{https://github.com/sphinx-doc/sphinx}'
'{https://github.com/sphinx-doc/sphinx}\n' in result)
assert ('\\href{mailto:sphinx-dev@googlegroups.com}'
@ -405,11 +416,61 @@ def test_latex_show_urls_is_no(app, status, warning):
assert '\\href{http://sphinx-doc.org/~test/}{URL including tilde}' in result
assert ('\\item[{\\href{http://sphinx-doc.org/}{URL in term}}] '
'\\leavevmode\nDescription' in result)
assert ('\\item[{Footnote in term \\footnotemark[4]}] '
'\\leavevmode\\footnotetext[4]{\nFootnote in term\n}\nDescription' in result)
assert ('\\item[{Footnote in term \\protect\\footnotemark[5]}] '
'\\leavevmode\\footnotetext[5]{\nFootnote in term\n}\nDescription' in result)
assert ('\\item[{\\href{http://sphinx-doc.org/}{Term in deflist}}] '
'\\leavevmode\nDescription' in result)
assert ('\\href{https://github.com/sphinx-doc/sphinx}'
'{https://github.com/sphinx-doc/sphinx}\n' in result)
assert ('\\href{mailto:sphinx-dev@googlegroups.com}'
'{sphinx-dev@googlegroups.com}\n' in result)
@with_app(buildername='latex', testroot='image-in-section')
def test_image_in_section(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'Python.tex').text(encoding='utf8')
print(result)
print(status.getvalue())
print(warning.getvalue())
assert ('\chapter[Test section]{\includegraphics[width=15pt,height=15pt]{{pic}.png} Test section}'
in result)
assert ('\chapter[Other {[}blah{]} section]{Other {[}blah{]} \includegraphics[width=15pt,height=15pt]{{pic}.png} section}' in result)
assert ('\chapter{Another section}' in result)
@with_app(buildername='latex', confoverrides={'latex_logo': 'notfound.jpg'})
def test_latex_logo_if_not_found(app, status, warning):
try:
app.builder.build_all()
assert False # SphinxError not raised
except Exception as exc:
assert isinstance(exc, SphinxError)
@with_app(buildername='latex', testroot='toctree-maxdepth',
confoverrides={'latex_documents': [
('index', 'SphinxTests.tex', 'Sphinx Tests Documentation',
'Georg Brandl', 'manual'),
]})
def test_toctree_maxdepth_manual(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')
print(result)
print(status.getvalue())
print(warning.getvalue())
assert '\\setcounter{tocdepth}{1}' in result
@with_app(buildername='latex', testroot='toctree-maxdepth',
confoverrides={'latex_documents': [
('index', 'SphinxTests.tex', 'Sphinx Tests Documentation',
'Georg Brandl', 'howto'),
]})
def test_toctree_maxdepth_howto(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8')
print(result)
print(status.getvalue())
print(warning.getvalue())
assert '\\setcounter{tocdepth}{2}' in result

View File

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
"""
test_build_manpage
~~~~~~~~~~~~~~~~~~
Test the build process with manpage builder with the test root.
:copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from __future__ import print_function
from util import with_app
@with_app(buildername='man')
def test_all(app, status, warning):
app.builder.build_all()
assert (app.outdir / 'SphinxTests.1').exists()
content = (app.outdir / 'SphinxTests.1').text()
assert r'\fBprint \fP\fIi\fP\fB\en\fP' in content

View File

@ -9,9 +9,11 @@
:license: BSD, see LICENSE for details.
"""
import re
from six import text_type
from util import raises
from util import raises, with_app
from sphinx import addnodes
from sphinx.domains.cpp import DefinitionParser, DefinitionError, NoOldIdError
@ -393,3 +395,49 @@ def test_templates():
# for a in ids:
# print(a)
# raise DefinitionError("")
@with_app(testroot='domain-cpp')
def test_build_domain_cpp(app, status, warning):
app.builder.build_all()
roles = (app.outdir / 'roles.html').text()
assert re.search('<li><a .*?><code .*?><span .*?>Sphinx</span></code></a></li>', roles)
assert re.search(('<li>ref function without parens <a .*?><code .*?><span .*?>'
'hello\(\)</span></code></a>\.</li>'), roles)
assert re.search(('<li>ref function with parens <a .*?><code .*?><span .*?>'
'hello\(\)</span></code></a>\.</li>'), roles)
assert re.search('<li><a .*?><code .*?><span .*?>Sphinx::version</span></code></a></li>',
roles)
assert re.search('<li><a .*?><code .*?><span .*?>version</span></code></a></li>', roles)
assert re.search('<li><a .*?><code .*?><span .*?>List</span></code></a></li>', roles)
assert re.search('<li><a .*?><code .*?><span .*?>MyEnum</span></code></a></li>', roles)
any_role = (app.outdir / 'any-role.html').text()
assert re.search('<li><a .*?><code .*?><span .*?>Sphinx</span></code></a></li>', any_role)
assert re.search(('<li>ref function without parens <a .*?><code .*?><span .*?>'
'hello\(\)</span></code></a>\.</li>'), any_role)
assert re.search(('<li>ref function with parens <a .*?><code .*?><span .*?>'
'hello\(\)</span></code></a>\.</li>'), any_role)
assert re.search('<li><a .*?><code .*?><span .*?>Sphinx::version</span></code></a></li>',
any_role)
assert re.search('<li><a .*?><code .*?><span .*?>version</span></code></a></li>', any_role)
assert re.search('<li><a .*?><code .*?><span .*?>List</span></code></a></li>', any_role)
assert re.search('<li><a .*?><code .*?><span .*?>MyEnum</span></code></a></li>', any_role)
@with_app(testroot='domain-cpp', confoverrides={'add_function_parentheses': False})
def test_build_domain_cpp_with_add_function_parentheses_is_False(app, status, warning):
app.builder.build_all()
roles = (app.outdir / 'roles.html').text()
assert re.search(('<li>ref function without parens <a .*?><code .*?><span .*?>'
'hello</span></code></a>\.</li>'), roles)
assert re.search(('<li>ref function with parens <a .*?><code .*?><span .*?>'
'hello</span></code></a>\.</li>'), roles)
any_role = (app.outdir / 'any-role.html').text()
assert re.search(('<li>ref function without parens <a .*?><code .*?><span .*?>'
'hello</span></code></a>\.</li>'), any_role)
assert re.search(('<li>ref function with parens <a .*?><code .*?><span .*?>'
'hello</span></code></a>\.</li>'), any_role)

View File

@ -16,6 +16,7 @@ import re
from subprocess import Popen, PIPE
from xml.etree import ElementTree
from babel.messages import pofile
from nose.tools import assert_equal
from six import string_types
@ -40,6 +41,11 @@ def gen_with_intl_app(builder, confoverrides={}, *args, **kw):
return gen_with_app(builder, *args, **default_kw)
def read_po(pathname):
with pathname.open() as f:
return pofile.read_po(f)
def setup_module():
if not root.exists():
(rootdir / 'roots' / 'test-intl').copytree(root)
@ -175,16 +181,16 @@ def test_text_builder(app, status, warning):
u'WARNING: Literal block expected; none found.'
yield assert_re_search, expected_warning_expr, warnings
# --- definition terms: regression test for #975
# --- definition terms: regression test for #975, #2198, #2205
result = (app.outdir / 'definition_terms.txt').text(encoding='utf-8')
expect = (u"\nI18N WITH DEFINITION TERMS"
u"\n**************************\n"
u"\nSOME TERM"
u"\n THE CORRESPONDING DEFINITION\n"
u"\nSOME OTHER TERM"
u"\nSOME *TERM* WITH LINK"
u"\n THE CORRESPONDING DEFINITION #2\n"
u"\nSOME TERM WITH : CLASSIFIER1 : CLASSIFIER2"
u"\nSOME **TERM** WITH : CLASSIFIER1 : CLASSIFIER2"
u"\n THE CORRESPONDING DEFINITION\n"
)
yield assert_equal, result, expect
@ -280,8 +286,8 @@ def test_text_builder(app, status, warning):
u"\n * **foo** -- DESCRIPTION OF PARAMETER foo\n"
u"\n * **bar** -- DESCRIPTION OF PARAMETER bar\n"
u"\nclass Cls3(values)\n"
u"\n Raises ValueError:"
u"\n IF THE VALUES ARE OUT OF RANGE\n"
u"\n Raises:"
u"\n **ValueError** -- IF THE VALUES ARE OUT OF RANGE\n"
u"\nclass Cls4(values)\n"
u"\n Raises:"
u"\n * **TypeError** -- IF THE VALUES ARE NOT VALID\n"
@ -304,6 +310,31 @@ def test_text_builder(app, status, warning):
yield assert_in, d.upper() + " BODY", result
@gen_with_intl_app('gettext', freshenv=True)
def test_gettext_builder(app, status, warning):
app.builder.build_all()
# --- definition terms: regression test for #2198, #2205
expect = read_po(app.srcdir / 'definition_terms.po')
actual = read_po(app.outdir / 'definition_terms.pot')
for expect_msg in [m for m in expect if m.id]:
yield assert_in, expect_msg.id, [m.id for m in actual if m.id]
# --- glossary terms: regression test for #1090
expect = read_po(app.srcdir / 'glossary_terms.po')
actual = read_po(app.outdir / 'glossary_terms.pot')
for expect_msg in [m for m in expect if m.id]:
yield assert_in, expect_msg.id, [m.id for m in actual if m.id]
warnings = warning.getvalue().replace(os.sep, '/')
yield assert_not_in, 'term not in glossary', warnings
# --- glossary term inconsistencies: regression test for #1090
expect = read_po(app.srcdir / 'glossary_terms_inconsistency.po')
actual = read_po(app.outdir / 'glossary_terms_inconsistency.pot')
for expect_msg in [m for m in expect if m.id]:
yield assert_in, expect_msg.id, [m.id for m in actual if m.id]
@gen_with_intl_app('html', freshenv=True)
def test_html_builder(app, status, warning):
app.builder.build_all()

View File

@ -55,7 +55,8 @@ def test_catalog_write_mo(dir):
cat = i18n.CatalogInfo(dir, 'test', 'utf-8')
cat.write_mo('en')
assert path.exists(cat.mo_path)
assert read_mo(open(cat.mo_path, 'rb')) is not None
with open(cat.mo_path, 'rb') as f:
assert read_mo(f) is not None
@with_tempdir