diff --git a/CHANGES b/CHANGES index 631ec3b7b00..cbc9d348c17 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,11 @@ Incompatible changes Deprecated ---------- +* #11412: Emit warnings on using a deprecated Python-specific index entry type + (namely, ``module``, ``keyword``, ``operator``, ``object``, ``exception``, + ``statement``, and ``builtin``) in the :rst:dir:`index` directive, and + set the removal version to Sphinx 9. Patch by Adam Turner. + Features added -------------- diff --git a/doc/usage/configuration.rst b/doc/usage/configuration.rst index 11cd2be31dd..23e9ba7ab36 100644 --- a/doc/usage/configuration.rst +++ b/doc/usage/configuration.rst @@ -337,6 +337,7 @@ General configuration * ``epub.unknown_project_files`` * ``epub.duplicated_toc_entry`` * ``i18n.inconsistent_references`` + * ``index`` * ``image.not_readable`` * ``ref.term`` * ``ref.ref`` @@ -388,6 +389,10 @@ General configuration Added ``i18n.inconsistent_references`` + .. versionadded:: 7.1 + + Added ``index`` warning type. + .. confval:: needs_sphinx If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will diff --git a/doc/usage/restructuredtext/directives.rst b/doc/usage/restructuredtext/directives.rst index c9152d1b18b..7082af04622 100644 --- a/doc/usage/restructuredtext/directives.rst +++ b/doc/usage/restructuredtext/directives.rst @@ -896,9 +896,10 @@ mainly contained in information units, such as the language reference. .. index:: single: execution; context - module: __main__ - module: sys + pair: module; __main__ + pair: module; sys triple: module; search; path + seealso: scope The execution context --------------------- @@ -916,25 +917,63 @@ mainly contained in information units, such as the language reference. The possible entry types are: single - Creates a single index entry. Can be made a subentry by separating the - subentry text with a semicolon (this notation is also used below to - describe what entries are created). + Creates a single index entry. + Can be made a sub-entry by separating the sub-entry text with a semicolon + (this notation is also used below to describe what entries are created). + Examples: + + .. code:: reStructuredText + + .. index:: single: execution + single: execution; context + + - ``single: execution`` creates an index entry labelled ``execution``. + - ``single: execution; context`` creates an sub-entry of ``execution`` + labelled ``context``. pair - ``pair: loop; statement`` is a shortcut that creates two index entries, - namely ``loop; statement`` and ``statement; loop``. + A shortcut to create two index entries. + The pair of values must be separated by a semicolon. + Example: + + .. code:: reStructuredText + + .. index:: pair: loop; statement + + This would create two index entries; ``loop; statement`` and ``statement; loop``. triple - Likewise, ``triple: module; search; path`` is a shortcut that creates - three index entries, which are ``module; search path``, ``search; path, - module`` and ``path; module search``. + A shortcut to create three index entries. + All three values must be separated by a semicolon. + Example: + + .. code:: reStructuredText + + .. index:: triple: module; search; path + + This would create three index entries; ``module; search path``, + ``search; path, module``, and ``path; module search``. see - ``see: entry; other`` creates an index entry that refers from ``entry`` to - ``other``. + A shortcut to create an index entry that refers to another entry. + Example: + + .. code:: reStructuredText + + .. index:: see: entry; other + + This would create an index entry referring from ``entry`` to ``other`` + (i.e. 'entry': See 'other'). seealso - Like ``see``, but inserts "see also" instead of "see". + Like ``see``, but inserts 'see also' instead of 'see'. module, keyword, operator, object, exception, statement, builtin - These all create two index entries. For example, ``module: hashlib`` - creates the entries ``module; hashlib`` and ``hashlib; module``. (These - are Python-specific and therefore deprecated.) + These **deprecated** shortcuts all create two index entries. + For example, ``module: hashlib`` creates the entries ``module; hashlib`` + and ``hashlib; module``. + + .. deprecated:: 1.0 + These Python-specific entry types are deprecated. + + .. versionchanged:: 7.1 + Removal version set to Sphinx 9.0. + Using these entry types will now emit warnings with the ``index`` category. You can mark up "main" index entries by prefixing them with an exclamation mark. The references to "main" entries are emphasized in the generated diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py index 4d460109b30..697b75e4053 100644 --- a/sphinx/builders/gettext.py +++ b/sphinx/builders/gettext.py @@ -16,7 +16,6 @@ from sphinx import addnodes, package_dir from sphinx.application import Sphinx from sphinx.builders import Builder -from sphinx.domains.python import pairindextypes from sphinx.errors import ThemeError from sphinx.locale import __ from sphinx.util import logging, split_index_msg @@ -159,10 +158,6 @@ def write_doc(self, docname: str, doctree: nodes.document) -> None: for node, entries in traverse_translatable_index(doctree): for typ, msg, _tid, _main, _key in entries: for m in split_index_msg(typ, msg): - if typ == 'pair' and m in pairindextypes.values(): - # avoid built-in translated message was incorporated - # in 'sphinx.util.nodes.process_index_entry' - continue catalog.add(m, node) diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index c461cc311fd..eef78aa8052 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -50,13 +50,13 @@ pairindextypes = { - 'module': _('module'), - 'keyword': _('keyword'), - 'operator': _('operator'), - 'object': _('object'), - 'exception': _('exception'), - 'statement': _('statement'), - 'builtin': _('built-in function'), + 'module': 'module', + 'keyword': 'keyword', + 'operator': 'operator', + 'object': 'object', + 'exception': 'exception', + 'statement': 'statement', + 'builtin': 'built-in function', } @@ -729,7 +729,7 @@ def add_target_and_index(self, name_cls: tuple[str, str], sig: str, text = _('%s() (in module %s)') % (name, modname) self.indexnode['entries'].append(('single', text, node_id, '', None)) else: - text = f'{pairindextypes["builtin"]}; {name}()' + text = f'built-in function; {name}()' self.indexnode['entries'].append(('pair', text, node_id, '', None)) def get_index_text(self, modname: str, name_cls: tuple[str, str]) -> str | None: @@ -1058,7 +1058,7 @@ def run(self) -> list[Node]: # the platform and synopsis aren't printed; in fact, they are only # used in the modindex currently ret.append(target) - indextext = f'{pairindextypes["module"]}; {modname}' + indextext = f'module; {modname}' inode = addnodes.index(entries=[('pair', indextext, node_id, '', None)]) ret.append(inode) ret.extend(content_node.children) diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py index c92640576ab..8ab90d19120 100644 --- a/sphinx/locale/__init__.py +++ b/sphinx/locale/__init__.py @@ -223,9 +223,3 @@ def gettext(message: str) -> str: 'tip': _('Tip'), 'warning': _('Warning'), } - -# Moved to sphinx.directives.other (will be overridden later) -versionlabels: dict[str, str] = {} - -# Moved to sphinx.domains.python (will be overridden later) -pairindextypes: dict[str, str] = {} diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py index 1b43bd72ed8..3dfdd4f2642 100644 --- a/sphinx/util/nodes.py +++ b/sphinx/util/nodes.py @@ -365,19 +365,23 @@ def process_index_entry(entry: str, targetid: str, if entry.startswith('!'): main = 'main' entry = entry[1:].lstrip() - for type in pairindextypes: - if entry.startswith(type + ':'): - value = entry[len(type) + 1:].strip() - value = pairindextypes[type] + '; ' + value + for index_type in pairindextypes: + if entry.startswith(f'{index_type}:'): + value = entry[len(index_type) + 1:].strip() + value = f'{pairindextypes[index_type]}; {value}' + # xref RemovedInSphinx90Warning + logger.warning(__('%r is deprecated for index entries (from entry %r). ' + "Use 'pair: %s' instead."), + index_type, entry, value, type='index') indexentries.append(('pair', value, targetid, main, None)) break else: - for type in indextypes: - if entry.startswith(type + ':'): - value = entry[len(type) + 1:].strip() - if type == 'double': - type = 'pair' - indexentries.append((type, value, targetid, main, None)) + for index_type in indextypes: + if entry.startswith(f'{index_type}:'): + value = entry[len(index_type) + 1:].strip() + if index_type == 'double': + index_type = 'pair' + indexentries.append((index_type, value, targetid, main, None)) break # shorthand notation for single entries else: diff --git a/tests/roots/test-intl/index_entries.txt b/tests/roots/test-intl/index_entries.txt index c914a4b4328..e9300d0ef94 100644 --- a/tests/roots/test-intl/index_entries.txt +++ b/tests/roots/test-intl/index_entries.txt @@ -20,12 +20,5 @@ various index entries triple: First; Second; Third see: Entry; Mailing List seealso: See; Newsletter - module: Module - keyword: Keyword - operator: Operator - object: Object - exception: Exception - statement: Statement - builtin: Builtin That's all. diff --git a/tests/roots/test-root/markup.txt b/tests/roots/test-root/markup.txt index 41a2fa58310..b59a652ee13 100644 --- a/tests/roots/test-root/markup.txt +++ b/tests/roots/test-root/markup.txt @@ -373,7 +373,6 @@ Index markup pair: entry; pair double: entry; double triple: index; entry; triple - keyword: with see: from; to seealso: fromalso; toalso diff --git a/tests/roots/test-warnings/index.rst b/tests/roots/test-warnings/index.rst index 4110e93d04f..8c4f6bb8a16 100644 --- a/tests/roots/test-warnings/index.rst +++ b/tests/roots/test-warnings/index.rst @@ -27,7 +27,7 @@ Don't download :download:`this `. .. index:: single: pair: - keyword: + seealso: .. Invalid code-block .. code-block:: c diff --git a/tests/test_build_gettext.py b/tests/test_build_gettext.py index ebd46275af5..dee9757b024 100644 --- a/tests/test_build_gettext.py +++ b/tests/test_build_gettext.py @@ -117,13 +117,6 @@ def msgid_getter(msgid): "Third", "Entry", "See", - "Module", - "Keyword", - "Operator", - "Object", - "Exception", - "Statement", - "Builtin", ] for expect in expected_msgids: assert expect in msgids diff --git a/tests/test_environment_indexentries.py b/tests/test_environment_indexentries.py index 2fb7faee0e7..4cfdc282336 100644 --- a/tests/test_environment_indexentries.py +++ b/tests/test_environment_indexentries.py @@ -1,4 +1,4 @@ -"""Test the sphinx.environment.managers.indexentries.""" +"""Test the sphinx.environment.adapters.indexentries.""" import pytest diff --git a/tests/test_environment_toctree.py b/tests/test_environment_toctree.py index 3488fe138f5..9b0047bedd3 100644 --- a/tests/test_environment_toctree.py +++ b/tests/test_environment_toctree.py @@ -1,4 +1,4 @@ -"""Test the sphinx.environment.managers.toctree.""" +"""Test the sphinx.environment.adapters.toctree.""" import pytest from docutils import nodes diff --git a/tests/test_intl.py b/tests/test_intl.py index feabe0e62de..54fa113c183 100644 --- a/tests/test_intl.py +++ b/tests/test_intl.py @@ -727,13 +727,6 @@ def wrap_nest(parenttag, childtag, keyword): wrap('a', 'THIRD, FIRST'), wrap_nest('li', 'ul', 'ENTRY'), wrap_nest('li', 'ul', 'SEE'), - wrap('a', 'MODULE'), - wrap('a', 'KEYWORD'), - wrap('a', 'OPERATOR'), - wrap('a', 'OBJECT'), - wrap('a', 'EXCEPTION'), - wrap('a', 'STATEMENT'), - wrap('a', 'BUILTIN'), ] for expr in expected_exprs: assert_re_search(expr, result, re.M)