summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES1
-rw-r--r--sphinx/builders/_epub_base.py12
-rw-r--r--tests/roots/test-root/index.txt1
-rw-r--r--tests/roots/test-toctree-duplicated/conf.py0
-rw-r--r--tests/roots/test-toctree-duplicated/foo.rst2
-rw-r--r--tests/roots/test-toctree-duplicated/index.rst7
-rw-r--r--tests/test_build_epub.py6
-rw-r--r--tests/test_build_latex.py21
8 files changed, 38 insertions, 12 deletions
diff --git a/CHANGES b/CHANGES
index dae77b2a6..9eb401173 100644
--- a/CHANGES
+++ b/CHANGES
@@ -166,6 +166,7 @@ Features added
* C++: add ``cpp:struct`` to complement ``cpp:class``.
* #1341 the HTML search considers words that contain a search term of length
three or longer a match.
+* #4611: epub: Show warning for duplicated ToC entries
Bugs fixed
----------
diff --git a/sphinx/builders/_epub_base.py b/sphinx/builders/_epub_base.py
index 7038f45f6..5516fdaf8 100644
--- a/sphinx/builders/_epub_base.py
+++ b/sphinx/builders/_epub_base.py
@@ -35,7 +35,7 @@ except ImportError:
if False:
# For type annotation
- from typing import Any, Dict, List, Tuple # NOQA
+ from typing import Any, Dict, List, Set, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
@@ -213,6 +213,15 @@ class EpubBuilder(StandaloneHTMLBuilder):
result = self.get_refnodes(elem, result)
return result
+ def check_refnodes(self, nodes):
+ # type: (List[Dict[str, Any]]) -> None
+ appeared = set() # type: Set[str]
+ for node in nodes:
+ if node['refuri'] in appeared:
+ logger.warning(__('duplicated ToC entry found: %s'), node['refuri'])
+ else:
+ appeared.add(node['refuri'])
+
def get_toc(self):
# type: () -> None
"""Get the total table of contents, containing the master_doc
@@ -726,6 +735,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
else:
# 'includehidden'
refnodes = self.refnodes
+ self.check_refnodes(refnodes)
navpoints = self.build_navpoints(refnodes)
level = max(item['level'] for item in self.refnodes)
level = min(level, self.config.epub_tocdepth)
diff --git a/tests/roots/test-root/index.txt b/tests/roots/test-root/index.txt
index ce0338cf7..27f90f357 100644
--- a/tests/roots/test-root/index.txt
+++ b/tests/roots/test-root/index.txt
@@ -24,7 +24,6 @@ Contents:
math
autodoc
extensions
- extensions
footnote
lists
otherext
diff --git a/tests/roots/test-toctree-duplicated/conf.py b/tests/roots/test-toctree-duplicated/conf.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/roots/test-toctree-duplicated/conf.py
diff --git a/tests/roots/test-toctree-duplicated/foo.rst b/tests/roots/test-toctree-duplicated/foo.rst
new file mode 100644
index 000000000..f23d4ce05
--- /dev/null
+++ b/tests/roots/test-toctree-duplicated/foo.rst
@@ -0,0 +1,2 @@
+foo
+===
diff --git a/tests/roots/test-toctree-duplicated/index.rst b/tests/roots/test-toctree-duplicated/index.rst
new file mode 100644
index 000000000..38a8c44c1
--- /dev/null
+++ b/tests/roots/test-toctree-duplicated/index.rst
@@ -0,0 +1,7 @@
+test-toctree-duplicated
+=======================
+
+.. toctree::
+
+ foo
+ foo
diff --git a/tests/test_build_epub.py b/tests/test_build_epub.py
index 86e40b65d..337363832 100644
--- a/tests/test_build_epub.py
+++ b/tests/test_build_epub.py
@@ -367,6 +367,12 @@ def test_html_download_role(app, status, warning):
'/_static/sphinxheader.png]</span></p></li>' in content)
+@pytest.mark.sphinx('epub', testroot='toctree-duplicated')
+def test_duplicated_toctree_entry(app, status, warning):
+ app.build()
+ assert 'WARNING: duplicated ToC entry found: foo.xhtml' in warning.getvalue()
+
+
@pytest.mark.skipif('DO_EPUBCHECK' not in os.environ,
reason='Skipped because DO_EPUBCHECK is not set')
@pytest.mark.sphinx('epub')
diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py
index 2ce63ae6a..3a31fa586 100644
--- a/tests/test_build_latex.py
+++ b/tests/test_build_latex.py
@@ -23,7 +23,7 @@ from sphinx.config import Config
from sphinx.errors import SphinxError
from sphinx.testing.util import strip_escseq
from sphinx.util import docutils
-from sphinx.util.osutil import ensuredir
+from sphinx.util.osutil import cd, ensuredir
from sphinx.writers.latex import LaTeXTranslator
@@ -54,15 +54,16 @@ def kpsetest(*filenames):
def compile_latex_document(app, filename='python.tex'):
# now, try to run latex over it
try:
- ensuredir(app.config.latex_engine)
- # keep a copy of latex file for this engine in case test fails
- copyfile(filename, app.config.latex_engine + '/' + filename)
- args = [app.config.latex_engine,
- '--halt-on-error',
- '--interaction=nonstopmode',
- '-output-directory=%s' % app.config.latex_engine,
- filename]
- subprocess.run(args, stdout=PIPE, stderr=PIPE, cwd=app.outdir, check=True)
+ with cd(app.outdir):
+ ensuredir(app.config.latex_engine)
+ # keep a copy of latex file for this engine in case test fails
+ copyfile(filename, app.config.latex_engine + '/' + filename)
+ args = [app.config.latex_engine,
+ '--halt-on-error',
+ '--interaction=nonstopmode',
+ '-output-directory=%s' % app.config.latex_engine,
+ filename]
+ subprocess.run(args, stdout=PIPE, stderr=PIPE, check=True)
except OSError: # most likely the latex executable was not found
raise pytest.skip.Exception
except CalledProcessError as exc: