sphinx
sphinx copied to clipboard
Nested toc produces multiply-defined labels in LaTeX output
Describe the bug
If you have a toctree that includes another toctree, then run make latexpdf, you will get a warning that there are multiply-defined labels.
How to Reproduce
Starting from a conf.py generated by running sphinx-quickstart, create subindex.rst which will have a toctree and be included in the toctree of index.rst. In the subindex.rst toctree, reference another document, page1.rst.
index.rst
Abbreviated file contents.
.. toctree::
:maxdepth: 2
:caption: Contents:
subindex.rst
subindex.rst
Full file contents.
.. toctree::
page1.rst
page1.rst
Full file contents.
Hello
tex Output
\label{\detokenize{page1:page-one}}\label{\detokenize{page1::doc}}\label{\detokenize{page1::doc}}
Proposed Fix
In writers/latex.py change this:
def hypertarget_to(self, node: Element, anchor: bool = False) -> str:
labels = ''.join(self.hypertarget(node_id, anchor=False) for node_id in node['ids'])
to this:
def hypertarget_to(self, node: Element, anchor: bool = False) -> str:
labels = ''.join(self.hypertarget(node_id, anchor=False) for node_id in {*node['ids']})
Environment Information
Python 3.12.2
Sphinx 7.2.6
Sphinx extensions
No response
Additional context
No response
Just wondering but does this also happen with HTML? or is it only with the latex build?
Also, your fix makes builds nonreproducible due to the arbitrary order of a set. In addition, I'm not sure that it would work if you end up with nested labels that could then collapse to a top-label.
I cannot check this this week though so it'll need to wait a bit.
If the order is important, then how about something like
labels = ''.join(self.hypertarget(node_id, anchor=False) for node_id in {k: None for k in node['ids']})
I don't know if it also happens in HTML. I'll check when I get a minute.
I don't know enough to comment about collapsing.
I don't see it happening in HTML.
Thank you. This needs investigation on our side then to make the fix as smooth as possible.