Fix duplicated labels in TeX output (#11093)

This commit is contained in:
Bénédikt Tran
2023-04-17 12:07:32 +02:00
parent 5a6b2b16b6
commit 61576516d4
8 changed files with 111 additions and 1 deletions

View File

@@ -1499,7 +1499,26 @@ class LaTeXTranslator(SphinxTranslator):
pass
else:
add_target(node['refid'])
for id in node['ids']:
# Temporary fix for https://github.com/sphinx-doc/sphinx/issues/11093
# TODO: investigate if a more elegant solution exists (see comments of #11093)
if node.get('ismod', False):
# Detect if the previous nodes are label targets. If so, remove
# the refid thereof from node['ids'] to avoid duplicated ids.
def has_dup_label(sib: Element | None) -> bool:
return isinstance(sib, nodes.target) and sib.get('refid') in node['ids']
prev: Element | None = get_prev_node(node)
if has_dup_label(prev):
ids = node['ids'][:] # copy to avoid side-effects
while has_dup_label(prev):
ids.remove(prev['refid'])
prev = get_prev_node(prev)
else:
ids = iter(node['ids']) # read-only iterator
else:
ids = iter(node['ids']) # read-only iterator
for id in ids:
add_target(id)
def depart_target(self, node: Element) -> None:

View File

@@ -0,0 +1,2 @@
"""docstring"""

View File

@@ -0,0 +1,2 @@
"""docstring"""

View File

@@ -0,0 +1,2 @@
"""docstring"""

View File

@@ -0,0 +1,2 @@
"""docstring"""

View File

@@ -0,0 +1,8 @@
import os
import sys
sys.path.insert(0, os.path.abspath('.'))
extensions = ['sphinx.ext.autodoc']
nitpicky = True

View File

@@ -0,0 +1,48 @@
latex-labels-before-module
==========================
.. _label_1a:
.. _label_1b:
.. module:: module1
text
.. _label_2:
.. module:: module2a
text
.. module:: module2b
text
.. _label_3:
.. module:: module3
text
.. _label_auto_1a:
.. _label_auto_1b:
.. automodule:: automodule1
text
.. _label_auto_2:
.. automodule:: automodule2a
text
.. automodule:: automodule2b
text
.. _label_auto_3:
.. automodule:: automodule3
text

View File

@@ -1708,3 +1708,30 @@ def test_copy_images(app, status, warning):
'rimg.png',
'testimäge.png',
}
@pytest.mark.sphinx('latex', testroot='latex-labels-before-module')
def test_duplicated_labels_before_module(app, status, warning):
app.build()
content: str = (app.outdir / 'python.tex').read_text()
def count_label(name):
text = r'\phantomsection\label{\detokenize{%s}}' % name
return content.count(text)
pattern = r'\\phantomsection\\label\{\\detokenize\{index:label-(?:auto-)?\d+[a-z]*}}'
expect_labels = {match.group() for match in re.finditer(pattern, content)}
result_labels = set()
# iterate over the (explicit) labels in the corresponding index.rst
for rst_label_name in {
'label_1a', 'label_1b', 'label_2', 'label_3',
'label_auto_1a', 'label_auto_1b', 'label_auto_2', 'label_auto_3',
}:
tex_label_name = 'index:' + rst_label_name.replace('_', '-')
tex_label_code = r'\phantomsection\label{\detokenize{%s}}' % tex_label_name
assert content.count(tex_label_code) == 1, f'duplicated label: {tex_label_name!r}'
result_labels.add(tex_label_code)
# sort the labels for a better visual diff, if any
assert sorted(result_labels) == sorted(expect_labels)