From 104a27fbdbb0fd8efcae227472b317aa015fea19 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Wed, 3 May 2023 17:16:59 +0100 Subject: [PATCH 1/9] Cease special-casing the deprecated Python-specific index types --- sphinx/builders/gettext.py | 5 ----- sphinx/domains/python.py | 18 +++++++++--------- sphinx/locale/__init__.py | 6 ------ sphinx/util/nodes.py | 20 ++++++++++---------- 4 files changed, 19 insertions(+), 30 deletions(-) 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..4b1a9e75d7b 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..ecb976cbb9a 100644 --- a/sphinx/util/nodes.py +++ b/sphinx/util/nodes.py @@ -365,19 +365,19 @@ 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}' 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: From a7d8df08e9b81aae983c53d3aa715b465d6cd686 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Wed, 3 May 2023 17:50:16 +0100 Subject: [PATCH 2/9] Warn on using Python-specific index entry types --- doc/usage/configuration.rst | 5 +++++ doc/usage/restructuredtext/directives.rst | 10 ++++++++-- sphinx/util/nodes.py | 3 +++ 3 files changed, 16 insertions(+), 2 deletions(-) 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..8b74ad9823c 100644 --- a/doc/usage/restructuredtext/directives.rst +++ b/doc/usage/restructuredtext/directives.rst @@ -933,8 +933,14 @@ mainly contained in information units, such as the language reference. 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.) + 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/util/nodes.py b/sphinx/util/nodes.py index ecb976cbb9a..0dd52159c0c 100644 --- a/sphinx/util/nodes.py +++ b/sphinx/util/nodes.py @@ -369,6 +369,9 @@ def process_index_entry(entry: str, targetid: str, if entry.startswith(f'{index_type}:'): value = entry[len(index_type) + 1:].strip() value = f'{pairindextypes[index_type]}; {value}' + 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: From 7628628d4b69959555f90f0e4e221e4baa3b729f Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Wed, 3 May 2023 18:44:44 +0100 Subject: [PATCH 3/9] Update tests --- tests/roots/test-intl/index_entries.txt | 7 ------- tests/roots/test-root/markup.txt | 1 - tests/roots/test-warnings/index.rst | 2 +- tests/test_build_gettext.py | 14 +++++++------- tests/test_environment_indexentries.py | 2 +- tests/test_intl.py | 14 +++++++------- 6 files changed, 16 insertions(+), 24 deletions(-) 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..4127eab4525 100644 --- a/tests/test_build_gettext.py +++ b/tests/test_build_gettext.py @@ -117,13 +117,13 @@ def msgid_getter(msgid): "Third", "Entry", "See", - "Module", - "Keyword", - "Operator", - "Object", - "Exception", - "Statement", - "Builtin", + # "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_intl.py b/tests/test_intl.py index feabe0e62de..29c38fb51e3 100644 --- a/tests/test_intl.py +++ b/tests/test_intl.py @@ -727,13 +727,13 @@ 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'), + # 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) From f2335d6546ea55ad36016ed5023a1d67e101335d Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Thu, 4 May 2023 10:32:47 +0100 Subject: [PATCH 4/9] Expand index documentation --- doc/usage/restructuredtext/directives.rst | 63 +++++++++++++++++------ 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/doc/usage/restructuredtext/directives.rst b/doc/usage/restructuredtext/directives.rst index 8b74ad9823c..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,24 +917,56 @@ 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 **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. From 9b70d152c7beed5cb7510f63cb315fb24756d85d Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Tue, 9 May 2023 21:59:43 +0100 Subject: [PATCH 5/9] whitespace --- sphinx/domains/python.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index 4b1a9e75d7b..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', + 'module': 'module', + 'keyword': 'keyword', + 'operator': 'operator', + 'object': 'object', 'exception': 'exception', 'statement': 'statement', - 'builtin': 'built-in function', + 'builtin': 'built-in function', } From 4cfa33766693725173fe6dcc37d699250eb96798 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Tue, 9 May 2023 22:04:44 +0100 Subject: [PATCH 6/9] eradicate --- tests/test_build_gettext.py | 7 ------- tests/test_intl.py | 7 ------- 2 files changed, 14 deletions(-) diff --git a/tests/test_build_gettext.py b/tests/test_build_gettext.py index 4127eab4525..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_intl.py b/tests/test_intl.py index 29c38fb51e3..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) From 64a2c44aec7882146f96340300754df90ae332a5 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Tue, 9 May 2023 22:07:11 +0100 Subject: [PATCH 7/9] warning notice --- sphinx/util/nodes.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py index 0dd52159c0c..3dfdd4f2642 100644 --- a/sphinx/util/nodes.py +++ b/sphinx/util/nodes.py @@ -369,6 +369,7 @@ def process_index_entry(entry: str, targetid: str, 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') From cb120ef4d4d06b860ff09acfe6da0c21043a8ead Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Tue, 9 May 2023 22:10:22 +0100 Subject: [PATCH 8/9] adapters --- tests/test_environment_toctree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 55face2e50be0a1108750c313873a6b3bb65baf4 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Tue, 9 May 2023 22:44:00 +0100 Subject: [PATCH 9/9] Add CHANGES note --- CHANGES | 5 +++++ 1 file changed, 5 insertions(+) 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 --------------