Skip to content

Commit

Permalink
Merge branch 'master' into issue-11328/messaging-mention-template-eva…
Browse files Browse the repository at this point in the history
…luation
  • Loading branch information
jayaddison authored Aug 8, 2024
2 parents 9935eb2 + 586c0cd commit 0f27a34
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 17 deletions.
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,11 @@ Bugs fixed
:confval:`intersphinx_cache_limit`.
Patch by Shengyu Zhang.

* #12730: The ``UnreferencedFootnotesDetector`` transform has been improved
to more consistently detect unreferenced footnotes.
Note, the priority of the transform has been changed from 200 to 622,
so that it now runs after the docutils ``Footnotes`` resolution transform.
Patch by Chris Sewell.

Testing
-------
44 changes: 31 additions & 13 deletions sphinx/transforms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from docutils import nodes
from docutils.transforms import Transform, Transformer
from docutils.transforms.parts import ContentsFilter
from docutils.transforms.references import Footnotes
from docutils.transforms.universal import SmartQuotes
from docutils.utils import normalize_language_tag
from docutils.utils.smartquotes import smartchars
Expand Down Expand Up @@ -294,23 +295,40 @@ class UnreferencedFootnotesDetector(SphinxTransform):
Detect unreferenced footnotes and emit warnings
"""

default_priority = 200
default_priority = Footnotes.default_priority + 2

def apply(self, **kwargs: Any) -> None:
for node in self.document.footnotes:
if node['names'] == []:
# footnote having duplicated number. It is already warned at parser.
pass
elif node['names'][0] not in self.document.footnote_refs:
logger.warning(__('Footnote [%s] is not referenced.'), node['names'][0],
type='ref', subtype='footnote',
location=node)

# note we do not warn on duplicate footnotes here
# (i.e. where the name has been moved to dupnames)
# since this is already reported by docutils
if not node['backrefs'] and node["names"]:
logger.warning(
__('Footnote [%s] is not referenced.'),
node['names'][0] if node['names'] else node['dupnames'][0],
type='ref',
subtype='footnote',
location=node
)
for node in self.document.symbol_footnotes:
if not node['backrefs']:
logger.warning(
__('Footnote [*] is not referenced.'),
type='ref',
subtype='footnote',
location=node
)
for node in self.document.autofootnotes:
if not any(ref['auto'] == node['auto'] for ref in self.document.autofootnote_refs):
logger.warning(__('Footnote [#] is not referenced.'),
type='ref', subtype='footnote',
location=node)
# note we do not warn on duplicate footnotes here
# (i.e. where the name has been moved to dupnames)
# since this is already reported by docutils
if not node['backrefs'] and node["names"]:
logger.warning(
__('Footnote [#] is not referenced.'),
type='ref',
subtype='footnote',
location=node
)


class DoctestTransform(SphinxTransform):
Expand Down
4 changes: 0 additions & 4 deletions tests/test_builders/test_build_manpage.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
from sphinx.config import Config


@pytest.mark.xfail(docutils.__version_info__[:2] > (0, 21),
reason='Docutils has removed the reference key in master')
@pytest.mark.sphinx('man')
def test_all(app):
app.build(force_all=True)
Expand Down Expand Up @@ -49,8 +47,6 @@ def test_man_make_section_directory(app):
assert (app.outdir / 'man1' / 'projectnamenotset.1').exists()


@pytest.mark.xfail(docutils.__version_info__[:2] > (0, 21),
reason='Docutils has removed the reference key in master')
@pytest.mark.sphinx('man', testroot='directive-code')
def test_captioned_code_block(app):
app.build(force_all=True)
Expand Down
39 changes: 39 additions & 0 deletions tests/test_transforms/test_unreferenced_footnotes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Test the ``UnreferencedFootnotesDetector`` transform."""

from pathlib import Path

from sphinx.testing.util import SphinxTestApp
from sphinx.util.console import strip_colors


def test_warnings(make_app: type[SphinxTestApp], tmp_path: Path) -> None:
"""Test that warnings are emitted for unreferenced footnotes."""
tmp_path.joinpath("conf.py").touch()
tmp_path.joinpath("index.rst").write_text(
"""
Title
=====
[1]_ [#label2]_
.. [1] This is a normal footnote.
.. [2] This is a normal footnote.
.. [2] This is a normal footnote.
.. [3] This is a normal footnote.
.. [*] This is a symbol footnote.
.. [#] This is an auto-numbered footnote.
.. [#label1] This is an auto-numbered footnote with a label.
.. [#label1] This is an auto-numbered footnote with a label.
.. [#label2] This is an auto-numbered footnote with a label.
""", encoding="utf8"
)
app = make_app(srcdir=tmp_path)
app.build()
warnings = strip_colors(app.warning.getvalue()).replace(str(tmp_path / "index.rst"), "source/index.rst")
print(warnings)
assert warnings.strip() == """
source/index.rst:8: WARNING: Duplicate explicit target name: "2". [docutils]
source/index.rst:13: WARNING: Duplicate explicit target name: "label1". [docutils]
source/index.rst:9: WARNING: Footnote [3] is not referenced. [ref.footnote]
source/index.rst:10: WARNING: Footnote [*] is not referenced. [ref.footnote]
source/index.rst:11: WARNING: Footnote [#] is not referenced. [ref.footnote]
""".strip()

0 comments on commit 0f27a34

Please sign in to comment.