Merge branch '2.0'

This commit is contained in:
Takeshi KOMIYA 2019-03-02 18:38:24 +09:00
commit 01f46111c5
23 changed files with 170 additions and 59 deletions

10
CHANGES
View File

@ -48,6 +48,13 @@ Features added
Bugs fixed
----------
* #6096: html: Anchor links are not added to figures
* #3620: html: Defer searchindex.js rather than loading it via ajax
* #6113: html: Table cells and list items have large margins
* #5508: ``linenothreshold`` option for ``highlight`` directive was ignored
* texinfo: ``make install-info`` causes syntax error
* texinfo: ``make install-info`` fails on macOS
Testing
--------
@ -312,9 +319,12 @@ Bugs fixed
* LaTeX: Remove extraneous space after author names on PDF title page (refs: #6004)
* #6026: LaTeX: A cross reference to definition list does not work
* #6046: LaTeX: ``TypeError`` is raised when invalid latex_elements given
* #6067: LaTeX: images having a target are concatenated to next line
* #6067: LaTeX: images having a target are not aligned even if specified
* #6019: imgconverter: Including multipage PDF fails
* #6047: autodoc: ``autofunction`` emits a warning for method objects
* #6028: graphviz: Ensure the graphviz filenames are reproducible
* #6068: doctest: ``skipif`` option may remove the code block from documentation
Testing
--------

View File

@ -315,7 +315,7 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
Configuration
-------------
There are also new config values that you can set:
There are also config values that you can set:
.. confval:: autoclass_content

View File

@ -131,7 +131,7 @@ Generating stub pages automatically
-----------------------------------
If you do not want to create stub pages with :program:`sphinx-autogen`, you can
also use this new config value:
also use these config values:
.. confval:: autosummary_generate

View File

@ -13,7 +13,7 @@ This extension features one additional builder, the :class:`CoverageBuilder`.
.. todo:: Write this section.
Several new configuration values can be used to specify what the builder
Several configuration values can be used to specify what the builder
should check:
.. confval:: coverage_ignore_modules

View File

@ -18,7 +18,7 @@ tracker, at :samp:`https://github.com/sphinx-doc/sphinx/issues/{num}`. Typing
this URL again and again is tedious, so you can use :mod:`~sphinx.ext.extlinks`
to avoid repeating yourself.
The extension adds one new config value:
The extension adds a config value:
.. confval:: extlinks

View File

@ -90,7 +90,7 @@ It adds these directives:
.. versionadded:: 1.6
All three directives support a ``name`` option to set the label to graph.
There are also these new config values:
There are also these config values:
.. confval:: graphviz_dot

View File

@ -43,7 +43,7 @@ Configuration
-------------
To use Intersphinx linking, add ``'sphinx.ext.intersphinx'`` to your
:confval:`extensions` config value, and use these new config values to activate
:confval:`extensions` config value, and use these config values to activate
linking:
.. confval:: intersphinx_mapping

View File

@ -154,8 +154,8 @@ class CodeBlock(SphinxDirective):
code = '\n'.join(lines)
literal = nodes.literal_block(code, code) # type: nodes.Element
literal['linenos'] = 'linenos' in self.options or \
'lineno-start' in self.options
if 'linenos' in self.options or 'lineno-start' in self.options:
literal['linenos'] = True
literal['classes'] += self.options.get('class', [])
if self.arguments:
# highlight language specified
@ -451,9 +451,9 @@ class LiteralInclude(SphinxDirective):
retnode['language'] = 'udiff'
elif 'language' in self.options:
retnode['language'] = self.options['language']
retnode['linenos'] = ('linenos' in self.options or
'lineno-start' in self.options or
'lineno-match' in self.options)
if ('linenos' in self.options or 'lineno-start' in self.options or
'lineno-match' in self.options):
retnode['linenos'] = True
retnode['classes'] += self.options.get('class', [])
extra_args = retnode['highlight_args'] = {}
if 'emphasize-lines' in self.options:

View File

@ -83,16 +83,6 @@ class TestDirective(SphinxDirective):
def run(self):
# type: () -> List[nodes.Node]
if 'skipif' in self.options:
condition = self.options['skipif']
context = {} # type: Dict[str, Any]
if self.config.doctest_global_setup:
exec(self.config.doctest_global_setup, context)
should_skip = eval(condition, context)
if self.config.doctest_global_cleanup:
exec(self.config.doctest_global_cleanup, context)
if should_skip:
return []
# use ordinary docutils nodes for test code: they get special attributes
# so that our builder recognizes them, and the other builders are happy.
code = '\n'.join(self.content)
@ -160,6 +150,8 @@ class TestDirective(SphinxDirective):
self.state.document.reporter.warning(
__("'%s' is not a valid pyversion option") % spec,
line=self.lineno)
if 'skipif' in self.options:
node['skipif'] = self.options['skipif']
return [node]
@ -404,6 +396,20 @@ Doctest summary
return node.line - 1
return None
def skipped(self, node):
# type: (nodes.Element) -> bool
if 'skipif' not in node:
return False
else:
condition = node['skipif']
context = {} # type: Dict[str, Any]
if self.config.doctest_global_setup:
exec(self.config.doctest_global_setup, context)
should_skip = eval(condition, context)
if self.config.doctest_global_cleanup:
exec(self.config.doctest_global_cleanup, context)
return should_skip
def test_doc(self, docname, doctree):
# type: (str, nodes.Node) -> None
groups = {} # type: Dict[str, TestGroup]
@ -429,8 +435,10 @@ Doctest summary
# type: (nodes.Node) -> bool
return isinstance(node, (nodes.literal_block, nodes.comment)) \
and 'testnodetype' in node
for node in doctree.traverse(condition): # type: nodes.Element
if self.skipped(node):
continue
source = node['test'] if 'test' in node else node.astext()
filename = self.get_filename_for_node(node, docname)
line_number = self.get_line_number(node)

View File

@ -17,15 +17,16 @@ html: $(addsuffix .html,$(ALLDOCS))
pdf: $(addsuffix .pdf,$(ALLDOCS))
install-info: info
for f in *.info; do \\
cp -t $(infodir) "$$f" && \\
$(INSTALL_INFO) --info-dir=$(infodir) "$$f" ; \\
for f in *.info; do \
mkdir -p $(infodir) && \
cp "$$f" $(infodir) && \
$(INSTALL_INFO) --info-dir=$(infodir) "$$f" ; \
done
uninstall-info: info
for f in *.info; do \\
rm -f "$(infodir)/$$f" ; \\
$(INSTALL_INFO) --delete --info-dir=$(infodir) "$$f" ; \\
for f in *.info; do \
rm -f "$(infodir)/$$f" ; \
$(INSTALL_INFO) --delete --info-dir=$(infodir) "$$f" ; \
done
%.info: %.texi

View File

@ -14,12 +14,7 @@
<script type="text/javascript" src="{{ pathto('_static/searchtools.js', 1) }}"></script>
{%- endblock %}
{% block extrahead %}
<script type="text/javascript">
jQuery(function() { Search.loadIndex("{{ pathto('searchindex.js', 1) }}"); });
</script>
{# this is used when loading the search index using $.ajax fails,
such as on Chrome for documents on localhost #}
<script type="text/javascript" id="searchindexloader"></script>
<script type="text/javascript" src="{{ pathto('searchindex.js', 1) }}" defer></script>
{{ super() }}
{% endblock %}
{% block body %}

View File

@ -401,11 +401,13 @@ table.citation td {
border-bottom: none;
}
th > p:first-child,
td > p:first-child {
margin-top: 0px;
}
td > p:only-child {
th > p:last-child,
td > p:last-child {
margin-bottom: 0px;
}
@ -482,7 +484,7 @@ li > p:first-child {
margin-top: 0px;
}
li > p:only-child {
li > p:last-child {
margin-bottom: 0px;
}

View File

@ -75,16 +75,6 @@ var Search = {
}
},
loadIndex : function(url) {
$.ajax({type: "GET", url: url, data: null,
dataType: "script", cache: true,
complete: function(jqxhr, textstatus) {
if (textstatus != "success") {
document.getElementById("searchindexloader").src = url;
}
}});
},
setIndex : function(index) {
var q;
this._index = index;

View File

@ -509,9 +509,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator):
if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'):
self.add_permalink_ref(node.parent, _('Permalink to this code'))
elif isinstance(node.parent, nodes.figure):
image_nodes = node.parent.traverse(nodes.image)
target_node = image_nodes and image_nodes[0] or node.parent
self.add_permalink_ref(target_node, _('Permalink to this image'))
self.add_permalink_ref(node.parent, _('Permalink to this image'))
elif node.parent.get('toctree'):
self.add_permalink_ref(node.parent.parent, _('Permalink to this toctree'))

View File

@ -455,9 +455,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'):
self.add_permalink_ref(node.parent, _('Permalink to this code'))
elif isinstance(node.parent, nodes.figure):
image_nodes = node.parent.traverse(nodes.image)
target_node = image_nodes and image_nodes[0] or node.parent
self.add_permalink_ref(target_node, _('Permalink to this image'))
self.add_permalink_ref(node.parent, _('Permalink to this image'))
elif node.parent.get('toctree'):
self.add_permalink_ref(node.parent.parent, _('Permalink to this toctree'))

View File

@ -1533,7 +1533,11 @@ class LaTeXTranslator(SphinxTranslator):
# in reverse order
post = [] # type: List[str]
include_graphics_options = []
is_inline = self.is_inline(node)
has_hyperlink = isinstance(node.parent, nodes.reference)
if has_hyperlink:
is_inline = self.is_inline(node.parent)
else:
is_inline = self.is_inline(node)
if 'width' in attrs:
if 'scale' in attrs:
w = self.latex_image_length(attrs['width'], attrs['scale'])
@ -1575,7 +1579,7 @@ class LaTeXTranslator(SphinxTranslator):
if self.in_parsed_literal:
pre.append('{\\sphinxunactivateextrasandspace ')
post.append('}')
if not is_inline:
if not is_inline and not has_hyperlink:
pre.append('\n\\noindent')
post.append('\n')
pre.reverse()
@ -1863,6 +1867,8 @@ class LaTeXTranslator(SphinxTranslator):
for id in node.get('ids'):
anchor = not self.in_caption
self.body += self.hypertarget(id, anchor=anchor)
if not self.is_inline(node):
self.body.append('\n')
uri = node.get('refuri', '')
if not uri and node.get('refid'):
uri = '%' + self.curfilestack[-1] + '#' + node['refid']
@ -1916,6 +1922,8 @@ class LaTeXTranslator(SphinxTranslator):
def depart_reference(self, node):
# type: (nodes.Element) -> None
self.body.append(self.context.pop())
if not self.is_inline(node):
self.body.append('\n')
def visit_number_reference(self, node):
# type: (nodes.Element) -> None

View File

@ -0,0 +1,23 @@
Code Blocks and Literal Includes with Line Numbers via linenothreshold
======================================================================
.. highlight:: python
:linenothreshold: 5
.. code-block::
class Foo:
pass
class Bar:
def baz():
pass
.. code-block::
# comment
value = True
.. literalinclude:: literal.inc
.. literalinclude:: literal-short.inc

View File

@ -0,0 +1,3 @@
# Very small literal include (linenothreshold check)
value = True

View File

@ -15,6 +15,13 @@ test-image
.. image:: testimäge.png
.. image:: rimg.png
:target: https://www.sphinx-doc.org/
.. image:: rimg.png
:align: center
:target: https://www.python.org/
.. a remote image
.. image:: https://www.python.org/static/img/python-logo.png

View File

@ -1254,6 +1254,15 @@ def test_html_inventory(app):
'The basic Sphinx documentation for testing')
@pytest.mark.sphinx('html', testroot='images', confoverrides={'html_sourcelink_suffix': ''})
def test_html_anchor_for_figure(app):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
assert ('<p class="caption"><span class="caption-text">The caption of pic</span>'
'<a class="headerlink" href="#id1" title="Permalink to this image">¶</a></p>'
in content)
@pytest.mark.sphinx('html', testroot='directives-raw')
def test_html_raw_directive(app, status, warning):
app.builder.build_all()

View File

@ -1220,16 +1220,28 @@ def test_latex_raw_directive(app, status, warning):
@pytest.mark.sphinx('latex', testroot='images')
def test_latex_remote_images(app, status, warning):
def test_latex_images(app, status, warning):
app.builder.build_all()
result = (app.outdir / 'python.tex').text(encoding='utf8')
# images are copied
assert '\\sphinxincludegraphics{{python-logo}.png}' in result
assert (app.outdir / 'python-logo.png').exists()
# not found images
assert '\\sphinxincludegraphics{{NOT_EXIST}.PNG}' not in result
assert ('WARNING: Could not fetch remote image: '
'http://example.com/NOT_EXIST.PNG [404]' in warning.getvalue())
# an image having target
assert ('\\sphinxhref{https://www.sphinx-doc.org/}'
'{\\sphinxincludegraphics{{rimg}.png}}\n\n' in result)
# a centerized image having target
assert ('\\sphinxhref{https://www.python.org/}{{\\hspace*{\\fill}'
'\\sphinxincludegraphics{{rimg}.png}\\hspace*{\\fill}}}\n\n' in result)
@pytest.mark.sphinx('latex', testroot='latex-index')
def test_latex_index(app, status, warning):

View File

@ -565,3 +565,52 @@ def test_code_block_highlighted(app, status, warning):
assert codeblocks[1]['language'] == 'python2'
assert codeblocks[2]['language'] == 'python3'
assert codeblocks[3]['language'] == 'python2'
@pytest.mark.sphinx('html', testroot='directive-code')
def test_linenothreshold(app, status, warning):
app.builder.build(['linenothreshold'])
html = (app.outdir / 'linenothreshold.html').text()
lineos_head = '<td class="linenos"><div class="linenodiv"><pre>'
lineos_tail = '</pre></div></td>'
# code-block using linenothreshold
_, matched, html = html.partition(lineos_head +
'1\n'
'2\n'
'3\n'
'4\n'
'5\n'
'6' + lineos_tail)
assert matched
# code-block not using linenothreshold
html, matched, _ = html.partition(lineos_head +
'1\n'
'2' + lineos_tail)
assert not matched
# literal include using linenothreshold
_, matched, html = html.partition(lineos_head +
' 1\n'
' 2\n'
' 3\n'
' 4\n'
' 5\n'
' 6\n'
' 7\n'
' 8\n'
' 9\n'
'10\n'
'11\n'
'12\n'
'13' + lineos_tail)
assert matched
# literal include not using linenothreshold
html, matched, _ = html.partition(lineos_head +
'1\n'
'2\n'
'3' + lineos_tail)
assert not matched

View File

@ -9,7 +9,6 @@
"""
import re
import sys
import pytest
@ -152,9 +151,8 @@ def test_expressions():
exprCheck(p + "'\\x0A'", t + "10")
exprCheck(p + "'\\u0a42'", t + "2626")
exprCheck(p + "'\\u0A42'", t + "2626")
if sys.maxunicode > 65535:
exprCheck(p + "'\\U0001f34c'", t + "127820")
exprCheck(p + "'\\U0001F34C'", t + "127820")
exprCheck(p + "'\\U0001f34c'", t + "127820")
exprCheck(p + "'\\U0001F34C'", t + "127820")
# TODO: user-defined lit
exprCheck('(... + Ns)', '(... + Ns)', id4='flpl2Ns')