Add `sphinx.util.index_entries` (#11528)

This commit is contained in:
Adam Turner 2023-07-28 07:41:10 +01:00 committed by GitHub
parent fca33a203d
commit c9f0e67cca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 76 additions and 59 deletions

View File

@ -16,6 +16,8 @@ Deprecated
Use ``hashlib`` instead.
* #11526: Deprecate ``sphinx.testing.path``.
Use ``os.path`` or ``pathlib`` instead.
* #11528: Deprecate ``sphinx.util.split_index_msg`` and ``sphinx.util.split_into``.
Use ``sphinx.util.index_entries.split_index_msg`` instead.
Features added
--------------

View File

@ -22,6 +22,16 @@ The following is a list of deprecated interfaces.
- Removed
- Alternatives
* - ``sphinx.util.split_into``
- 7.2
- 9.0
- N/A
* - ``sphinx.util.split_index_msg``
- 7.2
- 9.0
- ``sphinx.util.index_entries.split_index_msg``
* - ``sphinx.testing.path``
- 7.2
- 9.0

View File

@ -18,10 +18,11 @@ from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.errors import ThemeError
from sphinx.locale import __
from sphinx.util import logging, split_index_msg
from sphinx.util import logging
from sphinx.util.console import bold # type: ignore
from sphinx.util.display import status_iterator
from sphinx.util.i18n import CatalogInfo, docname_to_domain
from sphinx.util.index_entries import split_index_msg
from sphinx.util.nodes import extract_messages, traverse_translatable_index
from sphinx.util.osutil import canon_path, ensuredir, relpath
from sphinx.util.tags import Tags

View File

@ -11,8 +11,9 @@ from docutils.parsers.rst import directives
from sphinx import addnodes
from sphinx.domains import Domain
from sphinx.environment import BuildEnvironment
from sphinx.util import logging, split_index_msg
from sphinx.util import logging
from sphinx.util.docutils import ReferenceRole, SphinxDirective
from sphinx.util.index_entries import split_index_msg
from sphinx.util.nodes import process_index_entry
from sphinx.util.typing import OptionSpec

View File

@ -11,7 +11,8 @@ from sphinx.builders import Builder
from sphinx.environment import BuildEnvironment
from sphinx.errors import NoUri
from sphinx.locale import _, __
from sphinx.util import logging, split_into
from sphinx.util import logging
from sphinx.util.index_entries import _split_into
logger = logging.getLogger(__name__)
@ -41,20 +42,20 @@ class IndexEntries:
try:
if entry_type == 'single':
try:
entry, sub_entry = split_into(2, 'single', value)
entry, sub_entry = _split_into(2, 'single', value)
except ValueError:
entry, = split_into(1, 'single', value)
entry, = _split_into(1, 'single', value)
sub_entry = ''
_add_entry(entry, sub_entry, main,
dic=new, link=uri, key=category_key)
elif entry_type == 'pair':
first, second = split_into(2, 'pair', value)
first, second = _split_into(2, 'pair', value)
_add_entry(first, second, main,
dic=new, link=uri, key=category_key)
_add_entry(second, first, main,
dic=new, link=uri, key=category_key)
elif entry_type == 'triple':
first, second, third = split_into(3, 'triple', value)
first, second, third = _split_into(3, 'triple', value)
_add_entry(first, second + ' ' + third, main,
dic=new, link=uri, key=category_key)
_add_entry(second, third + ', ' + first, main,
@ -62,11 +63,11 @@ class IndexEntries:
_add_entry(third, first + ' ' + second, main,
dic=new, link=uri, key=category_key)
elif entry_type == 'see':
first, second = split_into(2, 'see', value)
first, second = _split_into(2, 'see', value)
_add_entry(first, _('see %s') % second, None,
dic=new, link=False, key=category_key)
elif entry_type == 'seealso':
first, second = split_into(2, 'see', value)
first, second = _split_into(2, 'see', value)
_add_entry(first, _('see also %s') % second, None,
dic=new, link=False, key=category_key)
else:

View File

@ -16,7 +16,7 @@ from docutils.nodes import Element, Node
from sphinx import addnodes, package_dir
from sphinx.environment import BuildEnvironment
from sphinx.util import split_index_msg
from sphinx.util.index_entries import split_index_msg
if TYPE_CHECKING:
from collections.abc import Iterable

View File

@ -18,8 +18,9 @@ from sphinx.errors import ConfigError
from sphinx.locale import __
from sphinx.locale import init as init_locale
from sphinx.transforms import SphinxTransform
from sphinx.util import get_filetype, logging, split_index_msg
from sphinx.util import get_filetype, logging
from sphinx.util.i18n import docname_to_domain
from sphinx.util.index_entries import split_index_msg
from sphinx.util.nodes import (
IMAGE_TYPE_NODES,
LITERAL_TYPE_NODES,

View File

@ -16,6 +16,7 @@ from sphinx.locale import __
from sphinx.util import display as _display
from sphinx.util import exceptions as _exceptions
from sphinx.util import http_date as _http_date
from sphinx.util import index_entries as _index_entries
from sphinx.util import logging
from sphinx.util import osutil as _osutil
from sphinx.util.console import strip_colors # NoQA: F401
@ -220,30 +221,6 @@ def parselinenos(spec: str, total: int) -> list[int]:
return items
def split_into(n: int, type: str, value: str) -> list[str]:
"""Split an index entry into a given number of parts at semicolons."""
parts = [x.strip() for x in value.split(';', n - 1)]
if len(list(filter(None, parts))) < n:
raise ValueError(f'invalid {type} index entry {value!r}')
return parts
def split_index_msg(entry_type: str, value: str) -> list[str]:
# new entry types must be listed in util/nodes.py!
if entry_type == 'single':
try:
return split_into(2, 'single', value)
except ValueError:
return split_into(1, 'single', value)
if entry_type == 'pair':
return split_into(2, 'pair', value)
if entry_type == 'triple':
return split_into(3, 'triple', value)
if entry_type in {'see', 'seealso'}:
return split_into(2, 'see', value)
raise ValueError(f'invalid {entry_type} index entry {value!r}')
def import_object(objname: str, source: str | None = None) -> Any:
"""Import python object by qualname."""
try:
@ -300,6 +277,9 @@ _DEPRECATED_OBJECTS = {
'format_exception_cut_frames': (_exceptions.format_exception_cut_frames,
'sphinx.exceptions.format_exception_cut_frames'),
'xmlname_checker': (_xml_name_checker, 'sphinx.builders.epub3._XML_NAME_PATTERN'),
'split_index_msg': (_index_entries.split_index_msg,
'sphinx.util.index_entries.split_index_msg'),
'split_into': (_index_entries.split_index_msg, 'sphinx.util.index_entries.split_into'),
'md5': (_md5, ''),
'sha1': (_sha1, ''),
}

View File

@ -0,0 +1,25 @@
from __future__ import annotations
def split_index_msg(entry_type: str, value: str) -> list[str]:
# new entry types must be listed in util/nodes.py!
if entry_type == 'single':
try:
return _split_into(2, 'single', value)
except ValueError:
return _split_into(1, 'single', value)
if entry_type == 'pair':
return _split_into(2, 'pair', value)
if entry_type == 'triple':
return _split_into(3, 'triple', value)
if entry_type in {'see', 'seealso'}:
return _split_into(2, 'see', value)
raise ValueError(f'invalid {entry_type} index entry {value!r}')
def _split_into(n: int, type: str, value: str) -> list[str]:
"""Split an index entry into a given number of parts at semicolons."""
parts = [x.strip() for x in value.split(';', n - 1)]
if len(list(filter(None, parts))) < n:
raise ValueError(f'invalid {type} index entry {value!r}')
return parts

View File

@ -20,8 +20,9 @@ from sphinx.domains import IndexEntry
from sphinx.domains.std import StandardDomain
from sphinx.errors import SphinxError
from sphinx.locale import _, __, admonitionlabels
from sphinx.util import logging, split_into, texescape
from sphinx.util import logging, texescape
from sphinx.util.docutils import SphinxTranslator
from sphinx.util.index_entries import split_index_msg
from sphinx.util.nodes import clean_astext, get_prev_node
from sphinx.util.template import LaTeXRenderer
from sphinx.util.texescape import tex_replace_map
@ -1688,37 +1689,32 @@ class LaTeXTranslator(SphinxTranslator):
if ismain:
m = '|spxpagem'
try:
parts = tuple(map(escape, split_index_msg(type, string)))
styled = tuple(map(style, parts))
if type == 'single':
try:
p1, p2 = (escape(x) for x in split_into(2, 'single', string))
P1, P2 = style(p1), style(p2)
p1, p2 = parts
P1, P2 = styled
self.body.append(fr'\index{{{p1}@{P1}!{p2}@{P2}{m}}}')
except ValueError:
p = escape(split_into(1, 'single', string)[0])
P = style(p)
p, = parts
P, = styled
self.body.append(fr'\index{{{p}@{P}{m}}}')
elif type == 'pair':
p1, p2 = (escape(x) for x in split_into(2, 'pair', string))
P1, P2 = style(p1), style(p2)
self.body.append(r'\index{%s@%s!%s@%s%s}\index{%s@%s!%s@%s%s}' %
(p1, P1, p2, P2, m, p2, P2, p1, P1, m))
p1, p2 = parts
P1, P2 = styled
self.body.append(fr'\index{{{p1}@{P1}!{p2}@{P2}{m}}}'
fr'\index{{{p2}@{P2}!{p1}@{P1}{m}}}')
elif type == 'triple':
p1, p2, p3 = (escape(x) for x in split_into(3, 'triple', string))
P1, P2, P3 = style(p1), style(p2), style(p3)
p1, p2, p3 = parts
P1, P2, P3 = styled
self.body.append(
r'\index{%s@%s!%s %s@%s %s%s}'
r'\index{%s@%s!%s, %s@%s, %s%s}'
r'\index{%s@%s!%s %s@%s %s%s}' %
(p1, P1, p2, p3, P2, P3, m,
p2, P2, p3, p1, P3, P1, m,
p3, P3, p1, p2, P1, P2, m))
elif type == 'see':
p1, p2 = (escape(x) for x in split_into(2, 'see', string))
P1 = style(p1)
self.body.append(fr'\index{{{p1}@{P1}|see{{{p2}}}}}')
elif type == 'seealso':
p1, p2 = (escape(x) for x in split_into(2, 'seealso', string))
P1 = style(p1)
fr'\index{{{p1}@{P1}!{p2} {p3}@{P2} {P3}{m}}}'
fr'\index{{{p2}@{P2}!{p3}, {p1}@{P3}, {P1}{m}}}'
fr'\index{{{p3}@{P3}!{p1} {p2}@{P1} {P2}{m}}}')
elif type in {'see', 'seealso'}:
p1, p2 = parts
P1, _P2 = styled
self.body.append(fr'\index{{{p1}@{P1}|see{{{p2}}}}}')
else:
logger.warning(__('unknown index entry type %s found'), type)