summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakeshi KOMIYA <i.tkomiya@gmail.com>2017-01-11 00:15:34 +0900
committerTakeshi KOMIYA <i.tkomiya@gmail.com>2017-01-28 20:43:54 +0900
commite2c7b1db4206542c72e0dfbfc78bae9a8d153dfd (patch)
tree9a014aff0077ee9408da986e7bf6946a8920de33
parent0b0637deb2f093de80de102348de6c89fe432e11 (diff)
downloadsphinx-git-e2c7b1db4206542c72e0dfbfc78bae9a8d153dfd.tar.gz
Add IndexEntries adapter
-rw-r--r--sphinx/builders/devhelp.py3
-rw-r--r--sphinx/builders/html.py3
-rw-r--r--sphinx/builders/htmlhelp.py3
-rw-r--r--sphinx/builders/qthelp.py3
-rw-r--r--sphinx/environment/__init__.py14
-rw-r--r--sphinx/environment/adapters/indexentries.py157
-rw-r--r--sphinx/environment/managers/indexentries.py134
-rw-r--r--tests/test_environment_indexentries.py2
8 files changed, 177 insertions, 142 deletions
diff --git a/sphinx/builders/devhelp.py b/sphinx/builders/devhelp.py
index af8bcfeed..031c55184 100644
--- a/sphinx/builders/devhelp.py
+++ b/sphinx/builders/devhelp.py
@@ -22,6 +22,7 @@ from sphinx import addnodes
from sphinx.util import logging
from sphinx.util.osutil import make_filename
from sphinx.builders.html import StandaloneHTMLBuilder
+from sphinx.environment.adapters.indexentries import IndexEntries
try:
import xml.etree.ElementTree as etree
@@ -104,7 +105,7 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
# Index
functions = etree.SubElement(root, 'functions')
- index = self.env.create_index(self)
+ index = IndexEntries(self.env).create_index(self)
def write_index(title, refs, subitems):
# type: (unicode, List[Any], Any) -> None
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index 5c3d9601e..062c56669 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -46,6 +46,7 @@ from sphinx.util.console import bold, darkgreen # type: ignore
from sphinx.writers.html import HTMLWriter, HTMLTranslator, \
SmartyPantsHTMLTranslator
from sphinx.environment.adapters.toctree import TocTree
+from sphinx.environment.adapters.indexentries import IndexEntries
if False:
# For type annotation
@@ -542,7 +543,7 @@ class StandaloneHTMLBuilder(Builder):
# type: () -> None
# the total count of lines for each index letter, used to distribute
# the entries into two columns
- genindex = self.env.create_index(self)
+ genindex = IndexEntries(self.env).create_index(self)
indexcounts = []
for _k, entries in genindex:
indexcounts.append(sum(1 + len(subitems)
diff --git a/sphinx/builders/htmlhelp.py b/sphinx/builders/htmlhelp.py
index 08e6f9df4..68fd3b1db 100644
--- a/sphinx/builders/htmlhelp.py
+++ b/sphinx/builders/htmlhelp.py
@@ -19,6 +19,7 @@ from docutils import nodes
from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder
+from sphinx.environment.adapters.indexentries import IndexEntries
from sphinx.util import logging
from sphinx.util.osutil import make_filename
from sphinx.util.pycompat import htmlescape
@@ -281,7 +282,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
f.write(contents_footer)
logger.info('writing index file...')
- index = self.env.create_index(self)
+ index = IndexEntries(self.env).create_index(self)
with self.open_file(outdir, outname + '.hhk') as f:
f.write('<UL>\n')
diff --git a/sphinx/builders/qthelp.py b/sphinx/builders/qthelp.py
index 27178676f..25dec7586 100644
--- a/sphinx/builders/qthelp.py
+++ b/sphinx/builders/qthelp.py
@@ -21,6 +21,7 @@ from docutils import nodes
from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder
+from sphinx.environment.adapters.indexentries import IndexEntries
from sphinx.util import force_decode, logging
from sphinx.util.osutil import make_filename
from sphinx.util.pycompat import htmlescape
@@ -170,7 +171,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
# keywords
keywords = []
- index = self.env.create_index(self, group_entries=False)
+ index = IndexEntries(self.env).create_index(self, group_entries=False)
for (key, group) in index:
for title, (refs, subitems, key_) in group:
keywords.extend(self.build_keywords(title, refs, subitems))
diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py
index 46cdc21ef..d41b90871 100644
--- a/sphinx/environment/__init__.py
+++ b/sphinx/environment/__init__.py
@@ -47,8 +47,9 @@ from sphinx.util.websupport import is_commentable
from sphinx.errors import SphinxError, ExtensionError
from sphinx.versioning import add_uids, merge_doctrees
from sphinx.deprecation import RemovedInSphinx20Warning
+from sphinx.environment.adapters.indexentries import IndexEntries
from sphinx.environment.adapters.toctree import TocTree
-from sphinx.environment.managers.indexentries import IndexEntries
+from sphinx.environment.managers.indexentries import IndexEntries as IndexEntriesManager
if False:
# For type annotation
@@ -247,7 +248,7 @@ class BuildEnvironment(object):
# type: () -> None
managers = {}
manager_class = None # type: Type[EnvironmentManager]
- for manager_class in [IndexEntries]: # type: ignore
+ for manager_class in [IndexEntriesManager]: # type: ignore
managers[manager_class.name] = manager_class(self)
self.attach_managers(managers)
@@ -1070,8 +1071,13 @@ class BuildEnvironment(object):
def create_index(self, builder, group_entries=True,
_fixre=re.compile(r'(.*) ([(][^()]*[)])')):
- # type: (Builder, bool, Pattern) -> Any
- return self.indices.create_index(builder, group_entries=group_entries, _fixre=_fixre) # type: ignore # NOQA
+ # type: (Builder, bool, Pattern) -> List[Tuple[unicode, List[Tuple[unicode, List[unicode]]]]] # NOQA
+ warnings.warn('env.create_index() is deprecated. '
+ 'Use sphinx.environment.adapters.indexentreis.IndexEntries instead.',
+ RemovedInSphinx20Warning)
+ return IndexEntries(self).create_index(builder,
+ group_entries=group_entries,
+ _fixre=_fixre)
def collect_relations(self):
# type: () -> Dict[unicode, List[unicode]]
diff --git a/sphinx/environment/adapters/indexentries.py b/sphinx/environment/adapters/indexentries.py
new file mode 100644
index 000000000..9eeb50833
--- /dev/null
+++ b/sphinx/environment/adapters/indexentries.py
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.environment.adapters.indexentries
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Index entries adapters for sphinx.environment.
+
+ :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+import re
+import bisect
+import unicodedata
+import string
+from itertools import groupby
+
+from six import text_type
+
+from sphinx.locale import _
+from sphinx.util import iteritems, split_into, logging
+
+if False:
+ # For type annotation
+ from typing import Any, Pattern, Tuple # NOQA
+ from sphinx.builders import Builder # NOQA
+ from sphinx.environment import BuildEnvironment # NOQA
+
+logger = logging.getLogger(__name__)
+
+
+class IndexEntries(object):
+ def __init__(self, env):
+ # type: (BuildEnvironment) -> None
+ self.env = env
+
+ def create_index(self, builder, group_entries=True,
+ _fixre=re.compile(r'(.*) ([(][^()]*[)])')):
+ # type: (Builder, bool, Pattern) -> List[Tuple[unicode, List[Tuple[unicode, Any]]]] # NOQA
+ """Create the real index from the collected index entries."""
+ from sphinx.environment import NoUri
+
+ new = {} # type: Dict[unicode, List]
+
+ def add_entry(word, subword, main, link=True, dic=new, key=None):
+ # Force the word to be unicode if it's a ASCII bytestring.
+ # This will solve problems with unicode normalization later.
+ # For instance the RFC role will add bytestrings at the moment
+ word = text_type(word)
+ entry = dic.get(word)
+ if not entry:
+ dic[word] = entry = [[], {}, key]
+ if subword:
+ add_entry(subword, '', main, link=link, dic=entry[1], key=key)
+ elif link:
+ try:
+ uri = builder.get_relative_uri('genindex', fn) + '#' + tid
+ except NoUri:
+ pass
+ else:
+ # maintain links in sorted/deterministic order
+ bisect.insort(entry[0], (main, uri))
+
+ for fn, entries in iteritems(self.env.indexentries):
+ # new entry types must be listed in directives/other.py!
+ for type, value, tid, main, index_key in entries:
+ try:
+ if type == 'single':
+ try:
+ entry, subentry = split_into(2, 'single', value)
+ except ValueError:
+ entry, = split_into(1, 'single', value)
+ subentry = ''
+ add_entry(entry, subentry, main, key=index_key)
+ elif type == 'pair':
+ first, second = split_into(2, 'pair', value)
+ add_entry(first, second, main, key=index_key)
+ add_entry(second, first, main, key=index_key)
+ elif type == 'triple':
+ first, second, third = split_into(3, 'triple', value)
+ add_entry(first, second + ' ' + third, main, key=index_key)
+ add_entry(second, third + ', ' + first, main, key=index_key)
+ add_entry(third, first + ' ' + second, main, key=index_key)
+ elif type == 'see':
+ first, second = split_into(2, 'see', value)
+ add_entry(first, _('see %s') % second, None,
+ link=False, key=index_key)
+ elif type == 'seealso':
+ first, second = split_into(2, 'see', value)
+ add_entry(first, _('see also %s') % second, None,
+ link=False, key=index_key)
+ else:
+ logger.warning('unknown index entry type %r', type, location=fn)
+ except ValueError as err:
+ logger.warning(str(err), location=fn)
+
+ # sort the index entries; put all symbols at the front, even those
+ # following the letters in ASCII, this is where the chr(127) comes from
+ def keyfunc(entry, lcletters=string.ascii_lowercase + '_'):
+ key, (void, void, category_key) = entry
+ if category_key:
+ # using specified category key to sort
+ key = category_key
+ lckey = unicodedata.normalize('NFD', key.lower())
+ if lckey[0:1] in lcletters:
+ lckey = chr(127) + lckey
+ # ensure a determinstic order *within* letters by also sorting on
+ # the entry itself
+ return (lckey, entry[0])
+ newlist = sorted(new.items(), key=keyfunc)
+
+ if group_entries:
+ # fixup entries: transform
+ # func() (in module foo)
+ # func() (in module bar)
+ # into
+ # func()
+ # (in module foo)
+ # (in module bar)
+ oldkey = '' # type: unicode
+ oldsubitems = None # type: Dict[unicode, List]
+ i = 0
+ while i < len(newlist):
+ key, (targets, subitems, _key) = newlist[i]
+ # cannot move if it has subitems; structure gets too complex
+ if not subitems:
+ m = _fixre.match(key)
+ if m:
+ if oldkey == m.group(1):
+ # prefixes match: add entry as subitem of the
+ # previous entry
+ oldsubitems.setdefault(m.group(2), [[], {}, _key])[0].\
+ extend(targets)
+ del newlist[i]
+ continue
+ oldkey = m.group(1)
+ else:
+ oldkey = key
+ oldsubitems = subitems
+ i += 1
+
+ # group the entries by letter
+ def keyfunc2(item, letters=string.ascii_uppercase + '_'):
+ # hack: mutating the subitems dicts to a list in the keyfunc
+ k, v = item
+ v[1] = sorted((si, se) for (si, (se, void, void)) in iteritems(v[1]))
+ if v[2] is None:
+ # now calculate the key
+ letter = unicodedata.normalize('NFD', k[0])[0].upper()
+ if letter in letters:
+ return letter
+ else:
+ # get all other symbols under one heading
+ return _('Symbols')
+ else:
+ return v[2]
+ return [(key_, list(group))
+ for (key_, group) in groupby(newlist, keyfunc2)]
diff --git a/sphinx/environment/managers/indexentries.py b/sphinx/environment/managers/indexentries.py
index cb972b54c..680ef374d 100644
--- a/sphinx/environment/managers/indexentries.py
+++ b/sphinx/environment/managers/indexentries.py
@@ -8,23 +8,14 @@
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
-import re
-import bisect
-import unicodedata
-import string
-from itertools import groupby
-from six import text_type
from sphinx import addnodes
-from sphinx.util import iteritems, split_index_msg, split_into, logging
-from sphinx.locale import _
+from sphinx.util import split_index_msg, logging
from sphinx.environment.managers import EnvironmentManager
if False:
# For type annotation
- from typing import Pattern, Tuple # NOQA
from docutils import nodes # NOQA
- from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
logger = logging.getLogger(__name__)
@@ -68,126 +59,3 @@ class IndexEntries(EnvironmentManager):
def get_updated_docs(self):
# type: () -> List[unicode]
return []
-
- def create_index(self, builder, group_entries=True,
- _fixre=re.compile(r'(.*) ([(][^()]*[)])')):
- # type: (Builder, bool, Pattern) -> List[Tuple[unicode, List[Tuple[unicode, List[unicode]]]]] # NOQA
- """Create the real index from the collected index entries."""
- from sphinx.environment import NoUri
-
- new = {} # type: Dict[unicode, List]
-
- def add_entry(word, subword, main, link=True, dic=new, key=None):
- # Force the word to be unicode if it's a ASCII bytestring.
- # This will solve problems with unicode normalization later.
- # For instance the RFC role will add bytestrings at the moment
- word = text_type(word)
- entry = dic.get(word)
- if not entry:
- dic[word] = entry = [[], {}, key]
- if subword:
- add_entry(subword, '', main, link=link, dic=entry[1], key=key)
- elif link:
- try:
- uri = builder.get_relative_uri('genindex', fn) + '#' + tid
- except NoUri:
- pass
- else:
- # maintain links in sorted/deterministic order
- bisect.insort(entry[0], (main, uri))
-
- for fn, entries in iteritems(self.data):
- # new entry types must be listed in directives/other.py!
- for type, value, tid, main, index_key in entries:
- try:
- if type == 'single':
- try:
- entry, subentry = split_into(2, 'single', value)
- except ValueError:
- entry, = split_into(1, 'single', value)
- subentry = ''
- add_entry(entry, subentry, main, key=index_key)
- elif type == 'pair':
- first, second = split_into(2, 'pair', value)
- add_entry(first, second, main, key=index_key)
- add_entry(second, first, main, key=index_key)
- elif type == 'triple':
- first, second, third = split_into(3, 'triple', value)
- add_entry(first, second + ' ' + third, main, key=index_key)
- add_entry(second, third + ', ' + first, main, key=index_key)
- add_entry(third, first + ' ' + second, main, key=index_key)
- elif type == 'see':
- first, second = split_into(2, 'see', value)
- add_entry(first, _('see %s') % second, None,
- link=False, key=index_key)
- elif type == 'seealso':
- first, second = split_into(2, 'see', value)
- add_entry(first, _('see also %s') % second, None,
- link=False, key=index_key)
- else:
- logger.warning('unknown index entry type %r', type, location=fn)
- except ValueError as err:
- logger.warning(str(err), location=fn)
-
- # sort the index entries; put all symbols at the front, even those
- # following the letters in ASCII, this is where the chr(127) comes from
- def keyfunc(entry, lcletters=string.ascii_lowercase + '_'):
- key, (void, void, category_key) = entry
- if category_key:
- # using specified category key to sort
- key = category_key
- lckey = unicodedata.normalize('NFD', key.lower())
- if lckey[0:1] in lcletters:
- lckey = chr(127) + lckey
- # ensure a determinstic order *within* letters by also sorting on
- # the entry itself
- return (lckey, entry[0])
- newlist = sorted(new.items(), key=keyfunc)
-
- if group_entries:
- # fixup entries: transform
- # func() (in module foo)
- # func() (in module bar)
- # into
- # func()
- # (in module foo)
- # (in module bar)
- oldkey = '' # type: unicode
- oldsubitems = None # type: Dict[unicode, List]
- i = 0
- while i < len(newlist):
- key, (targets, subitems, _key) = newlist[i]
- # cannot move if it has subitems; structure gets too complex
- if not subitems:
- m = _fixre.match(key)
- if m:
- if oldkey == m.group(1):
- # prefixes match: add entry as subitem of the
- # previous entry
- oldsubitems.setdefault(m.group(2), [[], {}, _key])[0].\
- extend(targets)
- del newlist[i]
- continue
- oldkey = m.group(1)
- else:
- oldkey = key
- oldsubitems = subitems
- i += 1
-
- # group the entries by letter
- def keyfunc2(item, letters=string.ascii_uppercase + '_'):
- # hack: mutating the subitems dicts to a list in the keyfunc
- k, v = item
- v[1] = sorted((si, se) for (si, (se, void, void)) in iteritems(v[1]))
- if v[2] is None:
- # now calculate the key
- letter = unicodedata.normalize('NFD', k[0])[0].upper()
- if letter in letters:
- return letter
- else:
- # get all other symbols under one heading
- return _('Symbols')
- else:
- return v[2]
- return [(key_, list(group))
- for (key_, group) in groupby(newlist, keyfunc2)]
diff --git a/tests/test_environment_indexentries.py b/tests/test_environment_indexentries.py
index 57a3cf52f..53e0ad65d 100644
--- a/tests/test_environment_indexentries.py
+++ b/tests/test_environment_indexentries.py
@@ -11,7 +11,7 @@
from collections import namedtuple
from sphinx import locale
-from sphinx.environment.managers.indexentries import IndexEntries
+from sphinx.environment.adapters.indexentries import IndexEntries
import mock