diff --git a/CHANGES b/CHANGES index 45918fa10..9cafae631 100644 --- a/CHANGES +++ b/CHANGES @@ -170,6 +170,13 @@ Features added Bugs fixed ---------- +* #5037: LaTeX ``\sphinxupquote{}`` breaks in Russian +* sphinx.testing uses deprecated pytest API; ``Node.get_marker(name)`` +* #5016: crashed when recommonmark.AutoStrictify is enabled +* #5022: latex: crashed with docutils package provided by Debian/Ubuntu +* #5009: latex: a label for table is vanished if table does not have a caption +* #5048: crashed with numbered toctree + Testing -------- diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py index 20ad5a20c..a98ab5883 100644 --- a/sphinx/directives/code.py +++ b/sphinx/directives/code.py @@ -249,7 +249,7 @@ class LiteralIncludeReader(object): new_lines = self.read_file(self.filename) old_filename = self.options.get('diff') old_lines = self.read_file(old_filename) - diff = unified_diff(old_lines, new_lines, old_filename, self.filename) # type: ignore + diff = unified_diff(old_lines, new_lines, old_filename, self.filename) return list(diff) def pyobject_filter(self, lines, location=None): diff --git a/sphinx/environment/collectors/toctree.py b/sphinx/environment/collectors/toctree.py index 3d8c89f43..fe67bbcba 100644 --- a/sphinx/environment/collectors/toctree.py +++ b/sphinx/environment/collectors/toctree.py @@ -169,13 +169,14 @@ class TocTreeCollector(EnvironmentCollector): elif isinstance(subnode, addnodes.compact_paragraph): numstack[-1] += 1 if depth > 0: - number = tuple(numstack) + number = list(numstack) + secnums[subnode[0]['anchorname']] = tuple(numstack) else: number = None - secnums[subnode[0]['anchorname']] = number - subnode[0]['secnumber'] = list(number) + secnums[subnode[0]['anchorname']] = None + subnode[0]['secnumber'] = number if titlenode: - titlenode['secnumber'] = list(number) + titlenode['secnumber'] = number titlenode = None elif isinstance(subnode, addnodes.toctree): _walk_toctree(subnode, depth) diff --git a/sphinx/io.py b/sphinx/io.py index b9fa3f002..c90090e74 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -13,6 +13,7 @@ import re from docutils.core import Publisher from docutils.io import FileInput, NullOutput +from docutils.parsers.rst import Parser as RSTParser from docutils.readers import standalone from docutils.statemachine import StringList, string2lines from docutils.writers import UnfilteredWriter @@ -304,6 +305,13 @@ def read_doc(app, env, filename): source = input_class(app, env, source=None, source_path=filename, encoding=env.config.source_encoding) parser = app.registry.create_source_parser(app, filetype) + if parser.__class__.__name__ == 'CommonMarkParser' and parser.settings_spec == (): + # a workaround for recommonmark + # If recommonmark.AutoStrictify is enabled, the parser invokes reST parser + # internally. But recommonmark-0.4.0 does not provide settings_spec for reST + # parser. As a workaround, this copies settings_spec for RSTParser to the + # CommonMarkParser. + parser.settings_spec = RSTParser.settings_spec pub = Publisher(reader=reader, parser=parser, diff --git a/sphinx/templates/latex/longtable.tex_t b/sphinx/templates/latex/longtable.tex_t index 5a151808c..98981d7a9 100644 --- a/sphinx/templates/latex/longtable.tex_t +++ b/sphinx/templates/latex/longtable.tex_t @@ -9,8 +9,12 @@ <%= table.get_colspec() %> <%- if table.caption -%> \caption{<%= ''.join(table.caption) %>\strut}<%= labels %>\\*[\sphinxlongtablecapskipadjust] -<% endif -%> \hline +<% elif labels -%> +\hline\noalign{\phantomsection<%= labels %>}% +<% else -%> +\hline +<% endif -%> <%= ''.join(table.header) %> \endfirsthead diff --git a/sphinx/templates/latex/tabular.tex_t b/sphinx/templates/latex/tabular.tex_t index a35d2b2cb..cd4031e8c 100644 --- a/sphinx/templates/latex/tabular.tex_t +++ b/sphinx/templates/latex/tabular.tex_t @@ -14,6 +14,8 @@ \sphinxcapstartof{table} \sphinxcaption{<%= ''.join(table.caption) %>}<%= labels %> \sphinxaftercaption +<% elif labels -%> +\phantomsection<%= labels %>\nobreak <% endif -%> \begin{tabular}[t]<%= table.get_colspec() -%> \hline diff --git a/sphinx/templates/latex/tabulary.tex_t b/sphinx/templates/latex/tabulary.tex_t index 331ef845d..bf31b7a58 100644 --- a/sphinx/templates/latex/tabulary.tex_t +++ b/sphinx/templates/latex/tabulary.tex_t @@ -14,6 +14,8 @@ \sphinxcapstartof{table} \sphinxcaption{<%= ''.join(table.caption) %>}<%= labels %> \sphinxaftercaption +<% elif labels -%> +\phantomsection<%= labels %>\nobreak <% endif -%> \begin{tabulary}{\linewidth}[t]<%= table.get_colspec() -%> \hline diff --git a/sphinx/testing/fixtures.py b/sphinx/testing/fixtures.py index 94ac9a6e7..fcf1028fd 100644 --- a/sphinx/testing/fixtures.py +++ b/sphinx/testing/fixtures.py @@ -42,7 +42,10 @@ def app_params(request, test_params, shared_result, sphinx_test_tempdir, rootdir # ##### process pytest.mark.sphinx - markers = request.node.get_marker("sphinx") + if hasattr(request.node, 'iter_markers'): # pytest-3.6.0 or newer + markers = request.node.iter_markers("sphinx") + else: + markers = request.node.get_marker("sphinx") pargs = {} kwargs = {} # type: Dict[str, str] @@ -89,7 +92,10 @@ def test_params(request): have same 'shared_result' value. **NOTE**: You can not specify shared_result and srcdir in same time. """ - env = request.node.get_marker('test_params') + if hasattr(request.node, 'get_closest_marker'): # pytest-3.6.0 or newer + env = request.node.get_closest_marker('test_params') + else: + env = request.node.get_marker('test_params') kwargs = env.kwargs if env else {} result = { 'shared_result': None, diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 391ac0089..db58780f1 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -19,7 +19,6 @@ from collections import defaultdict from os import path from docutils import nodes, writers -from docutils.utils.roman import toRoman from docutils.writers.latex2e import Babel from six import itervalues, text_type @@ -35,6 +34,12 @@ from sphinx.util.nodes import clean_astext from sphinx.util.template import LaTeXRenderer from sphinx.util.texescape import tex_escape_map, tex_replace_map +try: + from docutils.utils.roman import toRoman +except ImportError: + # In Debain/Ubuntu, roman package is provided as roman, not as docutils.utils.roman + from roman import toRoman + if False: # For type annotation from typing import Any, Callable, Dict, Iterator, List, Pattern, Tuple, Set, Union # NOQA diff --git a/tests/roots/test-latex-table/expects/longtable_having_widths.tex b/tests/roots/test-latex-table/expects/longtable_having_widths.tex index d41a87586..505ae4d70 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_widths.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_widths.tex @@ -1,7 +1,7 @@ \label{\detokenize{longtable:longtable-having-widths-option}} \begin{savenotes}\sphinxatlongtablestart\begin{longtable}{|\X{30}{100}|\X{70}{100}|} -\hline +\hline\noalign{\phantomsection\label{\detokenize{longtable:namedlongtable}}\label{\detokenize{longtable:mylongtable}}}% \sphinxstyletheadfamily header1 &\sphinxstyletheadfamily @@ -43,3 +43,5 @@ cell3-2 \\ \hline \end{longtable}\sphinxatlongtableend\end{savenotes} + +See {\hyperref[\detokenize{longtable:mylongtable}]{\sphinxcrossref{mylongtable}}}, same as {\hyperref[\detokenize{longtable:namedlongtable}]{\sphinxcrossref{\DUrole{std,std-ref}{this one}}}}. diff --git a/tests/roots/test-latex-table/expects/table_having_widths.tex b/tests/roots/test-latex-table/expects/table_having_widths.tex index 914793181..b4fcea04e 100644 --- a/tests/roots/test-latex-table/expects/table_having_widths.tex +++ b/tests/roots/test-latex-table/expects/table_having_widths.tex @@ -2,6 +2,7 @@ \begin{savenotes}\sphinxattablestart \centering +\phantomsection\label{\detokenize{tabular:namedtabular}}\label{\detokenize{tabular:mytabular}}\nobreak \begin{tabular}[t]{|\X{30}{100}|\X{70}{100}|} \hline \sphinxstyletheadfamily @@ -28,3 +29,5 @@ cell3-2 \end{tabular} \par \sphinxattableend\end{savenotes} + +See {\hyperref[\detokenize{tabular:mytabular}]{\sphinxcrossref{\DUrole{std,std-ref}{this}}}}, same as {\hyperref[\detokenize{tabular:namedtabular}]{\sphinxcrossref{namedtabular}}}. diff --git a/tests/roots/test-latex-table/longtable.rst b/tests/roots/test-latex-table/longtable.rst index 370226f21..bace9d4d2 100644 --- a/tests/roots/test-latex-table/longtable.rst +++ b/tests/roots/test-latex-table/longtable.rst @@ -18,9 +18,12 @@ longtable longtable having :widths: option -------------------------------- +.. _mylongtable: + .. table:: :class: longtable :widths: 30,70 + :name: namedlongtable ======= ======= header1 header2 @@ -30,6 +33,8 @@ longtable having :widths: option cell3-1 cell3-2 ======= ======= +See mylongtable_, same as :ref:`this one `. + longtable having :align: option ------------------------------- diff --git a/tests/roots/test-latex-table/tabular.rst b/tests/roots/test-latex-table/tabular.rst index b28add3d3..7f0909540 100644 --- a/tests/roots/test-latex-table/tabular.rst +++ b/tests/roots/test-latex-table/tabular.rst @@ -1,4 +1,4 @@ -taburar and taburary +tabular and tabulary ==================== simple table @@ -15,8 +15,11 @@ cell3-1 cell3-2 table having :widths: option ---------------------------- +.. _mytabular: + .. table:: :widths: 30,70 + :name: namedtabular ======= ======= header1 header2 @@ -26,6 +29,8 @@ table having :widths: option cell3-1 cell3-2 ======= ======= +See :ref:`this `, same as namedtabular_. + table having :align: option (tabulary) -------------------------------------- diff --git a/tests/test_ext_apidoc.py b/tests/test_ext_apidoc.py index d3d61d1e0..8c81a6e12 100644 --- a/tests/test_ext_apidoc.py +++ b/tests/test_ext_apidoc.py @@ -32,7 +32,10 @@ def apidoc(rootdir, tempdir, apidoc_params): @pytest.fixture def apidoc_params(request): - markers = request.node.get_marker("apidoc") + if hasattr(request.node, 'iter_markers'): # pytest-3.6.0 or newer + markers = request.node.iter_markers("apidoc") + else: + markers = request.node.get_marker("apidoc") pargs = {} kwargs = {} diff --git a/tests/test_setup_command.py b/tests/test_setup_command.py index facb8879d..cd1f89c0c 100644 --- a/tests/test_setup_command.py +++ b/tests/test_setup_command.py @@ -27,7 +27,10 @@ def setup_command(request, tempdir, rootdir): Run `setup.py build_sphinx` with args and kwargs, pass it to the test and clean up properly. """ - marker = request.node.get_marker('setup_command') + if hasattr(request.node, 'get_closest_marker'): # pytest-3.6.0 or newer + marker = request.node.get_closest_marker('setup_command') + else: + marker = request.node.get_marker('setup_command') args = marker.args if marker else [] pkgrootdir = tempdir / 'test-setup' diff --git a/tests/test_toctree.py b/tests/test_toctree.py index 42ec0ce89..e37862ae0 100644 --- a/tests/test_toctree.py +++ b/tests/test_toctree.py @@ -8,6 +8,8 @@ :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ +import re + import pytest @@ -35,3 +37,12 @@ def test_singlehtml_toctree(app, status, warning): app.builder._get_local_toctree('index') except AttributeError: pytest.fail('Unexpected AttributeError in app.builder.fix_refuris') + + +@pytest.mark.sphinx(testroot='toctree', srcdir="numbered-toctree") +def test_numbered_toctree(app, status, warning): + # give argument to :numbered: option + index = (app.srcdir / 'index.rst').text() + index = re.sub(':numbered:.*', ':numbered: 1', index) + (app.srcdir / 'index.rst').write_text(index, encoding='utf-8') + app.builder.build_all()