diff --git a/CHANGES.rst b/CHANGES.rst index 8ffe9365d..047336578 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -22,6 +22,9 @@ Deprecated Features added -------------- +* #12131: Added :confval:`show_warning_types` configuration option. + Patch by Chris Sewell. + * #11701: HTML Search: Adopt the new ``_ element. Patch by Bénédikt Tran. diff --git a/doc/conf.py b/doc/conf.py index 37f86232d..2816935e6 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -23,6 +23,7 @@ version = sphinx.__display_version__ release = version show_authors = True nitpicky = True +show_warning_types = True html_theme = 'sphinx13' html_theme_path = ['_themes'] diff --git a/doc/usage/configuration.rst b/doc/usage/configuration.rst index c7b30d054..b5a2b8493 100644 --- a/doc/usage/configuration.rst +++ b/doc/usage/configuration.rst @@ -326,11 +326,19 @@ General configuration .. versionadded:: 0.5 +.. confval:: show_warning_types + + If ``True``, the type of each warning is added as a suffix to the warning message, + e.g., ``WARNING: [...] [index]`` or ``WARNING: [...] [toc.circular]``. + The default is ``False``. + + .. versionadded:: 7.3.0 + .. confval:: suppress_warnings A list of warning types to suppress arbitrary warning messages. - Sphinx supports following warning types: + Sphinx core supports following warning types: * ``app.add_node`` * ``app.add_directive`` @@ -359,11 +367,11 @@ General configuration * ``toc.not_readable`` * ``toc.secnum`` + Then extensions can also define their own warning types. + You can choose from these types. You can also give only the first component to exclude all warnings attached to it. - Now, this option should be considered *experimental*. - .. versionadded:: 1.4 .. versionchanged:: 1.5 diff --git a/sphinx/config.py b/sphinx/config.py index e90c7ebfc..dc8c1c11d 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -227,6 +227,7 @@ class Config: 'template_bridge': _Opt(None, 'html', frozenset((str,))), 'keep_warnings': _Opt(False, 'env', ()), 'suppress_warnings': _Opt([], 'env', ()), + 'show_warning_types': _Opt(False, 'env', frozenset((bool,))), 'modindex_common_prefix': _Opt([], 'html', ()), 'rst_epilog': _Opt(None, 'env', frozenset((str,))), 'rst_prolog': _Opt(None, 'env', frozenset((str,))), diff --git a/sphinx/util/logging.py b/sphinx/util/logging.py index baff07325..a74369862 100644 --- a/sphinx/util/logging.py +++ b/sphinx/util/logging.py @@ -480,6 +480,7 @@ class SphinxLogRecordTranslator(logging.Filter): * Make a instance of SphinxLogRecord * docname to path if location given + * append warning type/subtype to message if :confval:`show_warning_types` is ``True`` """ LogRecordClass: type[logging.LogRecord] @@ -522,6 +523,23 @@ class WarningLogRecordTranslator(SphinxLogRecordTranslator): LogRecordClass = SphinxWarningLogRecord + def filter(self, record: SphinxWarningLogRecord) -> bool: # type: ignore[override] + ret = super().filter(record) + + try: + show_warning_types = self.app.config.show_warning_types + except AttributeError: + # config is not initialized yet (ex. in conf.py) + show_warning_types = False + if show_warning_types: + if log_type := getattr(record, 'type', ''): + if log_subtype := getattr(record, 'subtype', ''): + record.msg += f' [{log_type}.{log_subtype}]' + else: + record.msg += f' [{log_type}]' + + return ret + def get_node_location(node: Node) -> str | None: source, line = get_source_line(node) diff --git a/tests/test_util/test_util_logging.py b/tests/test_util/test_util_logging.py index 4d506a8a8..8c6218803 100644 --- a/tests/test_util/test_util_logging.py +++ b/tests/test_util/test_util_logging.py @@ -10,7 +10,7 @@ from docutils import nodes from sphinx.errors import SphinxWarning from sphinx.testing.util import strip_escseq from sphinx.util import logging, osutil -from sphinx.util.console import colorize +from sphinx.util.console import colorize, strip_colors from sphinx.util.logging import is_suppressed_warning, prefixed_warnings from sphinx.util.parallel import ParallelTasks @@ -396,3 +396,20 @@ def test_get_node_location_abspath(): location = logging.get_node_location(n) assert location == absolute_filename + ':' + + +@pytest.mark.sphinx(confoverrides={'show_warning_types': True}) +def test_show_warning_types(app, status, warning): + logging.setup(app, status, warning) + logger = logging.getLogger(__name__) + logger.warning('message2') + logger.warning('message3', type='test') + logger.warning('message4', type='test', subtype='logging') + + warnings = strip_colors(warning.getvalue()).splitlines() + + assert warnings == [ + 'WARNING: message2', + 'WARNING: message3 [test]', + 'WARNING: message4 [test.logging]', + ]