From d081ea3dec0b69028155918280420d68f33572ed Mon Sep 17 00:00:00 2001 From: Doug Hellmann Date: Fri, 20 May 2022 10:02:03 -0400 Subject: [PATCH] logging: always show source locations as absolute paths Nodes attached to the parse tree via the `include` directive have their `source` attribute set to the relative path of the included file. Other nodes in the tree use the full absolute path. For consistent logging, ensure that the node location is always expressed as an absolute path, when the filename is known. See https://github.com/sphinx-contrib/spelling/issues/153 for an example of the effect of the original problem. --- sphinx/util/logging.py | 3 +++ tests/test_util_logging.py | 21 ++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/sphinx/util/logging.py b/sphinx/util/logging.py index 37fa672afbf..4c6cb29018e 100644 --- a/sphinx/util/logging.py +++ b/sphinx/util/logging.py @@ -12,6 +12,7 @@ from sphinx.errors import SphinxWarning from sphinx.util.console import colorize +from sphinx.util.osutil import abspath if TYPE_CHECKING: from sphinx.application import Sphinx @@ -514,6 +515,8 @@ class WarningLogRecordTranslator(SphinxLogRecordTranslator): def get_node_location(node: Node) -> Optional[str]: (source, line) = get_source_line(node) + if source: + source = abspath(source) if source and line: return "%s:%s" % (source, line) elif source: diff --git a/tests/test_util_logging.py b/tests/test_util_logging.py index 49cd2c11e0c..436479f7129 100644 --- a/tests/test_util_logging.py +++ b/tests/test_util_logging.py @@ -2,13 +2,14 @@ import codecs import os +import os.path import pytest from docutils import nodes from sphinx.errors import SphinxWarning from sphinx.testing.util import strip_escseq -from sphinx.util import logging +from sphinx.util import logging, osutil from sphinx.util.console import colorize from sphinx.util.logging import is_suppressed_warning, prefixed_warnings from sphinx.util.parallel import ParallelTasks @@ -379,3 +380,21 @@ def test_prefixed_warnings(app, status, warning): assert 'WARNING: Another PREFIX: message3' in warning.getvalue() assert 'WARNING: PREFIX: message4' in warning.getvalue() assert 'WARNING: message5' in warning.getvalue() + + +def test_get_node_location(): + # Ensure that node locations are reported as an absolute path, + # even if the source attribute is a relative path. + + relative_filename = os.path.join('relative', 'path.txt') + absolute_filename = osutil.abspath(relative_filename) + + n = nodes.Node() + n.source = relative_filename + n.line = 100 + + location = logging.get_node_location(n) + source, line = location.split(':') + + assert source == absolute_filename + assert line == '100'