Skip to content

Commit

Permalink
Warn on deprecated Python-specific index types (#11412)
Browse files Browse the repository at this point in the history
  • Loading branch information
AA-Turner committed May 9, 2023
1 parent db54618 commit 706f5f9
Show file tree
Hide file tree
Showing 14 changed files with 91 additions and 71 deletions.
5 changes: 5 additions & 0 deletions CHANGES
Expand Up @@ -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
--------------

Expand Down
5 changes: 5 additions & 0 deletions doc/usage/configuration.rst
Expand Up @@ -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``
Expand Down Expand Up @@ -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
Expand Down
71 changes: 55 additions & 16 deletions doc/usage/restructuredtext/directives.rst
Expand Up @@ -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
---------------------
Expand All @@ -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
Expand Down
5 changes: 0 additions & 5 deletions sphinx/builders/gettext.py
Expand Up @@ -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
Expand Down Expand Up @@ -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)


Expand Down
18 changes: 9 additions & 9 deletions sphinx/domains/python.py
Expand Up @@ -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',
}


Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 0 additions & 6 deletions sphinx/locale/__init__.py
Expand Up @@ -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] = {}
24 changes: 14 additions & 10 deletions sphinx/util/nodes.py
Expand Up @@ -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:
Expand Down
7 changes: 0 additions & 7 deletions tests/roots/test-intl/index_entries.txt
Expand Up @@ -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.
1 change: 0 additions & 1 deletion tests/roots/test-root/markup.txt
Expand Up @@ -373,7 +373,6 @@ Index markup
pair: entry; pair
double: entry; double
triple: index; entry; triple
keyword: with
see: from; to
seealso: fromalso; toalso

Expand Down
2 changes: 1 addition & 1 deletion tests/roots/test-warnings/index.rst
Expand Up @@ -27,7 +27,7 @@ Don't download :download:`this <nonexisting.png>`.
.. index::
single:
pair:
keyword:
seealso:

.. Invalid code-block
.. code-block:: c
Expand Down
7 changes: 0 additions & 7 deletions tests/test_build_gettext.py
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion tests/test_environment_indexentries.py
@@ -1,4 +1,4 @@
"""Test the sphinx.environment.managers.indexentries."""
"""Test the sphinx.environment.adapters.indexentries."""

import pytest

Expand Down
2 changes: 1 addition & 1 deletion 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
Expand Down
7 changes: 0 additions & 7 deletions tests/test_intl.py
Expand Up @@ -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)
Expand Down

0 comments on commit 706f5f9

Please sign in to comment.