Skip to content

Commit

Permalink
Add sphinx.util.index_entries (#11528)
Browse files Browse the repository at this point in the history
  • Loading branch information
AA-Turner committed Jul 28, 2023
1 parent fca33a2 commit c9f0e67
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 59 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Expand Up @@ -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
--------------
Expand Down
10 changes: 10 additions & 0 deletions doc/extdev/deprecated.rst
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion sphinx/builders/gettext.py
Expand Up @@ -18,10 +18,11 @@
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
Expand Down
3 changes: 2 additions & 1 deletion sphinx/domains/index.py
Expand Up @@ -11,8 +11,9 @@
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

Expand Down
15 changes: 8 additions & 7 deletions sphinx/environment/adapters/indexentries.py
Expand Up @@ -11,7 +11,8 @@
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__)

Expand Down Expand Up @@ -41,32 +42,32 @@ def create_index(self, builder: Builder, group_entries: bool = True,
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,
dic=new, link=uri, key=category_key)
_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:
Expand Down
2 changes: 1 addition & 1 deletion sphinx/search/__init__.py
Expand Up @@ -16,7 +16,7 @@

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
Expand Down
3 changes: 2 additions & 1 deletion sphinx/transforms/i18n.py
Expand Up @@ -18,8 +18,9 @@
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,
Expand Down
28 changes: 4 additions & 24 deletions sphinx/util/__init__.py
Expand Up @@ -16,6 +16,7 @@
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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -300,6 +277,9 @@ def _xml_name_checker():
'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, ''),
}
Expand Down
25 changes: 25 additions & 0 deletions sphinx/util/index_entries.py
@@ -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
44 changes: 20 additions & 24 deletions sphinx/writers/latex.py
Expand Up @@ -20,8 +20,9 @@
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
Expand Down Expand Up @@ -1688,37 +1689,32 @@ def style(string: str) -> str:
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)
Expand Down

0 comments on commit c9f0e67

Please sign in to comment.