# -*- coding: utf-8 -*-
"""
    sphinx.environment
    ~~~~~~~~~~~~~~~~~~

    Global creation environment.

    :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
    :license: BSD, see LICENSE for details.
"""

import re
import os
import sys
import time
import types
import codecs
import imghdr
import string
import unicodedata
from os import path
from glob import glob
from itertools import groupby

from six import iteritems, itervalues, text_type, class_types
from six.moves import cPickle as pickle, zip
from docutils import nodes
from docutils.io import FileInput, NullOutput
from docutils.core import Publisher
from docutils.utils import Reporter, relative_path, get_source_line
from docutils.readers import standalone
from docutils.parsers.rst import roles, directives
from docutils.parsers.rst.languages import en as english
from docutils.parsers.rst.directives.html import MetaBody
from docutils.writers import UnfilteredWriter

from sphinx import addnodes
from sphinx.util import url_re, get_matching_docs, docname_join, split_into, \
    FilenameUniqDict
from sphinx.util.nodes import clean_astext, make_refnode, WarningStream
from sphinx.util.osutil import SEP, find_catalog_files
from sphinx.util.matching import compile_matchers
from sphinx.util.websupport import is_commentable
from sphinx.errors import SphinxError, ExtensionError
from sphinx.locale import _
from sphinx.versioning import add_uids, merge_doctrees
from sphinx.transforms import DefaultSubstitutions, MoveModuleTargets, \
    HandleCodeBlocks, SortIds, CitationReferences, Locale, \
    RemoveTranslatableInline, SphinxContentsFilter


orig_role_function = roles.role
orig_directive_function = directives.directive


class ElementLookupError(Exception):
    pass


default_settings = {
    'embed_stylesheet': False,
    'cloak_email_addresses': True,
    'pep_base_url': 'http://www.python.org/dev/peps/',
    'rfc_base_url': 'http://tools.ietf.org/html/',
    'input_encoding': 'utf-8-sig',
    'doctitle_xform': False,
    'sectsubtitle_xform': False,
    'halt_level': 5,
    'file_insertion_enabled': True,
}

# This is increased every time an environment attribute is added
# or changed to properly invalidate pickle files.
ENV_VERSION = 42 + (sys.version_info[0] - 2)


dummy_reporter = Reporter('', 4, 4)

versioning_conditions = {
    'none': False,
    'text': nodes.TextElement,
    'commentable': is_commentable,
}


class NoUri(Exception):
    """Raised by get_relative_uri if there is no URI available."""
    pass


class SphinxStandaloneReader(standalone.Reader):
    """
    Add our own transforms.
    """
    transforms = [Locale, CitationReferences, DefaultSubstitutions,
                  MoveModuleTargets, HandleCodeBlocks, SortIds,
                  RemoveTranslatableInline]

    def get_transforms(self):
        return standalone.Reader.get_transforms(self) + self.transforms


class SphinxDummyWriter(UnfilteredWriter):
    supported = ('html',)  # needed to keep "meta" nodes

    def translate(self):
        pass


class BuildEnvironment:
    """
    The environment in which the ReST files are translated.
    Stores an inventory of cross-file targets and provides doctree
    transformations to resolve links to them.
    """

    # --------- ENVIRONMENT PERSISTENCE ----------------------------------------

    @staticmethod
    def frompickle(config, filename):
        picklefile = open(filename, 'rb')
        try:
            env = pickle.load(picklefile)
        finally:
            picklefile.close()
        if env.version != ENV_VERSION:
            raise IOError('env version not current')
        env.config.values = config.values
        return env

    def topickle(self, filename):
        # remove unpicklable attributes
        warnfunc = self._warnfunc
        self.set_warnfunc(None)
        values = self.config.values
        del self.config.values
        domains = self.domains
        del self.domains
        picklefile = open(filename, 'wb')
        # remove potentially pickling-problematic values from config
        for key, val in list(vars(self.config).items()):
            if key.startswith('_') or \
               isinstance(val, types.ModuleType) or \
               isinstance(val, types.FunctionType) or \
               isinstance(val, class_types):
                del self.config[key]
        try:
            pickle.dump(self, picklefile, pickle.HIGHEST_PROTOCOL)
        finally:
            picklefile.close()
        # reset attributes
        self.domains = domains
        self.config.values = values
        self.set_warnfunc(warnfunc)

    # --------- ENVIRONMENT INITIALIZATION -------------------------------------

    def __init__(self, srcdir, doctreedir, config):
        self.doctreedir = doctreedir
        self.srcdir = srcdir
        self.config = config

        # the method of doctree versioning; see set_versioning_method
        self.versioning_condition = None

        # the application object; only set while update() runs
        self.app = None

        # all the registered domains, set by the application
        self.domains = {}

        # the docutils settings for building
        self.settings = default_settings.copy()
        self.settings['env'] = self

        # the function to write warning messages with
        self._warnfunc = None

        # this is to invalidate old pickles
        self.version = ENV_VERSION

        # All "docnames" here are /-separated and relative and exclude
        # the source suffix.

        self.found_docs = set()     # contains all existing docnames
        self.all_docs = {}          # docname -> mtime at the time of build
                                    # contains all built docnames
        self.dependencies = {}      # docname -> set of dependent file
                                    # names, relative to documentation root
        self.reread_always = set()  # docnames to re-read unconditionally on
                                    # next build

        # File metadata
        self.metadata = {}          # docname -> dict of metadata items

        # TOC inventory
        self.titles = {}            # docname -> title node
        self.longtitles = {}        # docname -> title node; only different if
                                    # set differently with title directive
        self.tocs = {}              # docname -> table of contents nodetree
        self.toc_num_entries = {}   # docname -> number of real entries
        # used to determine when to show the TOC
        # in a sidebar (don't show if it's only one item)
        self.toc_secnumbers = {}    # docname -> dict of sectionid -> number

        self.toctree_includes = {}  # docname -> list of toctree includefiles
        self.files_to_rebuild = {}  # docname -> set of files
                                    # (containing its TOCs) to rebuild too
        self.glob_toctrees = set()  # docnames that have :glob: toctrees
        self.numbered_toctrees = set() # docnames that have :numbered: toctrees

        # domain-specific inventories, here to be pickled
        self.domaindata = {}        # domainname -> domain-specific dict

        # Other inventories
        self.citations = {}         # citation name -> docname, labelid
        self.indexentries = {}      # docname -> list of
                                    # (type, string, target, aliasname)
        self.versionchanges = {}    # version -> list of (type, docname,
                                    # lineno, module, descname, content)

        # these map absolute path -> (docnames, unique filename)
        self.images = FilenameUniqDict()
        self.dlfiles = FilenameUniqDict()

        # temporary data storage while reading a document
        self.temp_data = {}

    def set_warnfunc(self, func):
        self._warnfunc = func
        self.settings['warning_stream'] = WarningStream(func)

    def set_versioning_method(self, method):
        """This sets the doctree versioning method for this environment.

        Versioning methods are a builder property; only builders with the same
        versioning method can share the same doctree directory.  Therefore, we
        raise an exception if the user tries to use an environment with an
        incompatible versioning method.
        """
        if method not in versioning_conditions:
            raise ValueError('invalid versioning method: %r' % method)
        condition = versioning_conditions[method]
        if self.versioning_condition not in (None, condition):
            raise SphinxError('This environment is incompatible with the '
                              'selected builder, please choose another '
                              'doctree directory.')
        self.versioning_condition = condition

    def warn(self, docname, msg, lineno=None):
        """Emit a warning.

        This differs from using ``app.warn()`` in that the warning may not
        be emitted instantly, but collected for emitting all warnings after
        the update of the environment.
        """
        # strange argument order is due to backwards compatibility
        self._warnfunc(msg, (docname, lineno))

    def warn_node(self, msg, node):
        """Like :meth:`warn`, but with source information taken from *node*."""
        self._warnfunc(msg, '%s:%s' % get_source_line(node))

    def clear_doc(self, docname):
        """Remove all traces of a source file in the inventory."""
        if docname in self.all_docs:
            self.all_docs.pop(docname, None)
            self.reread_always.discard(docname)
            self.metadata.pop(docname, None)
            self.dependencies.pop(docname, None)
            self.titles.pop(docname, None)
            self.longtitles.pop(docname, None)
            self.tocs.pop(docname, None)
            self.toc_secnumbers.pop(docname, None)
            self.toc_num_entries.pop(docname, None)
            self.toctree_includes.pop(docname, None)
            self.indexentries.pop(docname, None)
            self.glob_toctrees.discard(docname)
            self.numbered_toctrees.discard(docname)
            self.images.purge_doc(docname)
            self.dlfiles.purge_doc(docname)

            for subfn, fnset in list(self.files_to_rebuild.items()):
                fnset.discard(docname)
                if not fnset:
                    del self.files_to_rebuild[subfn]
            for key, (fn, _) in list(self.citations.items()):
                if fn == docname:
                    del self.citations[key]
            for version, changes in self.versionchanges.items():
                new = [change for change in changes if change[1] != docname]
                changes[:] = new

        for domain in self.domains.values():
            domain.clear_doc(docname)

    def doc2path(self, docname, base=True, suffix=None):
        """Return the filename for the document name.

        If *base* is True, return absolute path under self.srcdir.
        If *base* is None, return relative path to self.srcdir.
        If *base* is a path string, return absolute path under that.
        If *suffix* is not None, add it instead of config.source_suffix.
        """
        docname = docname.replace(SEP, path.sep)
        suffix = suffix or self.config.source_suffix
        if base is True:
            return path.join(self.srcdir, docname) + suffix
        elif base is None:
            return docname + suffix
        else:
            return path.join(base, docname) + suffix

    def relfn2path(self, filename, docname=None):
        """Return paths to a file referenced from a document, relative to
        documentation root and absolute.

        In the input "filename", absolute filenames are taken as relative to the
        source dir, while relative filenames are relative to the dir of the
        containing document.
        """
        if filename.startswith('/') or filename.startswith(os.sep):
            rel_fn = filename[1:]
        else:
            docdir = path.dirname(self.doc2path(docname or self.docname,
                                                base=None))
            rel_fn = path.join(docdir, filename)
        try:
            # the path.abspath() might seem redundant, but otherwise artifacts
            # such as ".." will remain in the path
            return rel_fn, path.abspath(path.join(self.srcdir, rel_fn))
        except UnicodeDecodeError:
            # the source directory is a bytestring with non-ASCII characters;
            # let's try to encode the rel_fn in the file system encoding
            enc_rel_fn = rel_fn.encode(sys.getfilesystemencoding())
            return rel_fn, path.abspath(path.join(self.srcdir, enc_rel_fn))

    def find_files(self, config):
        """Find all source files in the source dir and put them in
        self.found_docs.
        """
        matchers = compile_matchers(
            config.exclude_patterns[:] +
            config.templates_path +
            config.html_extra_path +
            ['**/_sources', '.#*']
        )
        self.found_docs = set(get_matching_docs(
            self.srcdir, config.source_suffix, exclude_matchers=matchers))

        # add catalog mo file dependency
        for docname in self.found_docs:
            catalog_files = find_catalog_files(
                docname,
                self.srcdir,
                self.config.locale_dirs,
                self.config.language,
                self.config.gettext_compact)
            for filename in catalog_files:
                self.dependencies.setdefault(docname, set()).add(filename)

    def get_outdated_files(self, config_changed):
        """Return (added, changed, removed) sets."""
        # clear all files no longer present
        removed = set(self.all_docs) - self.found_docs

        added = set()
        changed = set()

        if config_changed:
            # config values affect e.g. substitutions
            added = self.found_docs
        else:
            for docname in self.found_docs:
                if docname not in self.all_docs:
                    added.add(docname)
                    continue
                # if the doctree file is not there, rebuild
                if not path.isfile(self.doc2path(docname, self.doctreedir,
                                                 '.doctree')):
                    changed.add(docname)
                    continue
                # check the "reread always" list
                if docname in self.reread_always:
                    changed.add(docname)
                    continue
                # check the mtime of the document
                mtime = self.all_docs[docname]
                newmtime = path.getmtime(self.doc2path(docname))
                if newmtime > mtime:
                    changed.add(docname)
                    continue
                # finally, check the mtime of dependencies
                for dep in self.dependencies.get(docname, ()):
                    try:
                        # this will do the right thing when dep is absolute too
                        deppath = path.join(self.srcdir, dep)
                        if not path.isfile(deppath):
                            changed.add(docname)
                            break
                        depmtime = path.getmtime(deppath)
                        if depmtime > mtime:
                            changed.add(docname)
                            break
                    except EnvironmentError:
                        # give it another chance
                        changed.add(docname)
                        break

        return added, changed, removed

    def update(self, config, srcdir, doctreedir, app=None):
        """(Re-)read all files new or changed since last update.

        Returns a summary, the total count of documents to reread and an
        iterator that yields docnames as it processes them.  Store all
        environment docnames in the canonical format (ie using SEP as a
        separator in place of os.path.sep).
        """
        config_changed = False
        if self.config is None:
            msg = '[new config] '
            config_changed = True
        else:
            # check if a config value was changed that affects how
            # doctrees are read
            for key, descr in iteritems(config.values):
                if descr[1] != 'env':
                    continue
                if self.config[key] != config[key]:
                    msg = '[config changed] '
                    config_changed = True
                    break
            else:
                msg = ''
            # this value is not covered by the above loop because it is handled
            # specially by the config class
            if self.config.extensions != config.extensions:
                msg = '[extensions changed] '
                config_changed = True
        # the source and doctree directories may have been relocated
        self.srcdir = srcdir
        self.doctreedir = doctreedir
        self.find_files(config)
        self.config = config

        # this cache also needs to be updated every time
        self._nitpick_ignore = set(self.config.nitpick_ignore)

        added, changed, removed = self.get_outdated_files(config_changed)

        # allow user intervention as well
        for docs in app.emit('env-get-outdated', self, added, changed, removed):
            changed.update(set(docs) & self.found_docs)

        # if files were added or removed, all documents with globbed toctrees
        # must be reread
        if added or removed:
            # ... but not those that already were removed
            changed.update(self.glob_toctrees & self.found_docs)

        msg += '%s added, %s changed, %s removed' % (len(added), len(changed),
                                                     len(removed))

        def update_generator():
            self.app = app

            # clear all files no longer present
            for docname in removed:
                if app:
                    app.emit('env-purge-doc', self, docname)
                self.clear_doc(docname)

            # read all new and changed files
            for docname in sorted(added | changed):
                yield docname
                self.read_doc(docname, app=app)

            if config.master_doc not in self.all_docs:
                self.warn(None, 'master file %s not found' %
                          self.doc2path(config.master_doc))

            self.app = None
            if app:
                app.emit('env-updated', self)

        return msg, len(added | changed), update_generator()

    def check_dependents(self, already):
        to_rewrite = self.assign_section_numbers()
        for docname in to_rewrite:
            if docname not in already:
                yield docname

    # --------- SINGLE FILE READING --------------------------------------------

    def warn_and_replace(self, error):
        """Custom decoding error handler that warns and replaces."""
        linestart = error.object.rfind(b'\n', 0, error.start)
        lineend = error.object.find(b'\n', error.start)
        if lineend == -1: lineend = len(error.object)
        lineno = error.object.count(b'\n', 0, error.start) + 1
        self.warn(self.docname, 'undecodable source characters, '
                  'replacing with "?": %r' %
                  (error.object[linestart+1:error.start] + b'>>>' +
                   error.object[error.start:error.end] + b'<<<' +
                   error.object[error.end:lineend]), lineno)
        return (u'?', error.end)

    def lookup_domain_element(self, type, name):
        """Lookup a markup element (directive or role), given its name which can
        be a full name (with domain).
        """
        name = name.lower()
        # explicit domain given?
        if ':' in name:
            domain_name, name = name.split(':', 1)
            if domain_name in self.domains:
                domain = self.domains[domain_name]
                element = getattr(domain, type)(name)
                if element is not None:
                    return element, []
        # else look in the default domain
        else:
            def_domain = self.temp_data.get('default_domain')
            if def_domain is not None:
                element = getattr(def_domain, type)(name)
                if element is not None:
                    return element, []
        # always look in the std domain
        element = getattr(self.domains['std'], type)(name)
        if element is not None:
            return element, []
        raise ElementLookupError

    def patch_lookup_functions(self):
        """Monkey-patch directive and role dispatch, so that domain-specific
        markup takes precedence.
        """
        def directive(name, lang_module, document):
            try:
                return self.lookup_domain_element('directive', name)
            except ElementLookupError:
                return orig_directive_function(name, lang_module, document)

        def role(name, lang_module, lineno, reporter):
            try:
                return self.lookup_domain_element('role', name)
            except ElementLookupError:
                return orig_role_function(name, lang_module, lineno, reporter)

        directives.directive = directive
        roles.role = role

    def read_doc(self, docname, src_path=None, save_parsed=True, app=None):
        """Parse a file and add/update inventory entries for the doctree.

        If srcpath is given, read from a different source file.
        """
        # remove all inventory entries for that file
        if app:
            app.emit('env-purge-doc', self, docname)

        self.clear_doc(docname)

        if src_path is None:
            src_path = self.doc2path(docname)

        self.temp_data['docname'] = docname
        # defaults to the global default, but can be re-set in a document
        self.temp_data['default_domain'] = \
            self.domains.get(self.config.primary_domain)

        self.settings['input_encoding'] = self.config.source_encoding
        self.settings['trim_footnote_reference_space'] = \
            self.config.trim_footnote_reference_space
        self.settings['gettext_compact'] = self.config.gettext_compact

        self.patch_lookup_functions()

        if self.config.default_role:
            role_fn, messages = roles.role(self.config.default_role, english,
                                           0, dummy_reporter)
            if role_fn:
                roles._roles[''] = role_fn
            else:
                self.warn(docname, 'default role %s not found' %
                          self.config.default_role)

        codecs.register_error('sphinx', self.warn_and_replace)

        class SphinxSourceClass(FileInput):
            def __init__(self_, *args, **kwds):
                # don't call sys.exit() on IOErrors
                kwds['handle_io_errors'] = False
                kwds['error_handler'] = 'sphinx'  # py3: handle error on open.
                FileInput.__init__(self_, *args, **kwds)

            def decode(self_, data):
                if isinstance(data, text_type):  # py3: `data` already decoded.
                    return data
                return data.decode(self_.encoding, 'sphinx')  # py2: decoding

            def read(self_):
                data = FileInput.read(self_)
                if app:
                    arg = [data]
                    app.emit('source-read', docname, arg)
                    data = arg[0]
                if self.config.rst_epilog:
                    data = data + '\n' + self.config.rst_epilog + '\n'
                if self.config.rst_prolog:
                    data = self.config.rst_prolog + '\n' + data
                return data

        # publish manually
        pub = Publisher(reader=SphinxStandaloneReader(),
                        writer=SphinxDummyWriter(),
                        source_class=SphinxSourceClass,
                        destination_class=NullOutput)
        pub.set_components(None, 'restructuredtext', None)
        pub.process_programmatic_settings(None, self.settings, None)
        pub.set_source(None, src_path)
        pub.set_destination(None, None)
        pub.publish()
        doctree = pub.document

        # post-processing
        self.filter_messages(doctree)
        self.process_dependencies(docname, doctree)
        self.process_images(docname, doctree)
        self.process_downloads(docname, doctree)
        self.process_metadata(docname, doctree)
        self.process_refonly_bullet_lists(docname, doctree)
        self.create_title_from(docname, doctree)
        self.note_indexentries_from(docname, doctree)
        self.note_citations_from(docname, doctree)
        self.build_toc_from(docname, doctree)
        for domain in itervalues(self.domains):
            domain.process_doc(self, docname, doctree)

        # allow extension-specific post-processing
        if app:
            app.emit('doctree-read', doctree)

        # store time of build, for outdated files detection
        # (Some filesystems have coarse timestamp resolution;
        # therefore time.time() can be older than filesystem's timestamp.
        # For example, FAT32 has 2sec timestamp resolution.)
        self.all_docs[docname] = max(
            time.time(), path.getmtime(self.doc2path(docname)))

        if self.versioning_condition:
            # get old doctree
            try:
                f = open(self.doc2path(docname,
                                       self.doctreedir, '.doctree'), 'rb')
                try:
                    old_doctree = pickle.load(f)
                finally:
                    f.close()
            except EnvironmentError:
                old_doctree = None

            # add uids for versioning
            if old_doctree is None:
                list(add_uids(doctree, self.versioning_condition))
            else:
                list(merge_doctrees(
                    old_doctree, doctree, self.versioning_condition))

        # make it picklable
        doctree.reporter = None
        doctree.transformer = None
        doctree.settings.warning_stream = None
        doctree.settings.env = None
        doctree.settings.record_dependencies = None
        for metanode in doctree.traverse(MetaBody.meta):
            # docutils' meta nodes aren't picklable because the class is nested
            metanode.__class__ = addnodes.meta

        # cleanup
        self.temp_data.clear()

        if save_parsed:
            # save the parsed doctree
            doctree_filename = self.doc2path(docname, self.doctreedir,
                                             '.doctree')
            dirname = path.dirname(doctree_filename)
            if not path.isdir(dirname):
                os.makedirs(dirname)
            f = open(doctree_filename, 'wb')
            try:
                pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
            finally:
                f.close()
        else:
            return doctree

    # utilities to use while reading a document

    @property
    def docname(self):
        """Returns the docname of the document currently being parsed."""
        return self.temp_data['docname']

    @property
    def currmodule(self):
        """Backwards compatible alias."""
        return self.temp_data.get('py:module')

    @property
    def currclass(self):
        """Backwards compatible alias."""
        return self.temp_data.get('py:class')

    def new_serialno(self, category=''):
        """Return a serial number, e.g. for index entry targets.

        The number is guaranteed to be unique in the current document.
        """
        key = category + 'serialno'
        cur = self.temp_data.get(key, 0)
        self.temp_data[key] = cur + 1
        return cur

    def note_dependency(self, filename):
        """Add *filename* as a dependency of the current document.

        This means that the document will be rebuilt if this file changes.

        *filename* should be absolute or relative to the source directory.
        """
        self.dependencies.setdefault(self.docname, set()).add(filename)

    def note_reread(self):
        """Add the current document to the list of documents that will
        automatically be re-read at the next build.
        """
        self.reread_always.add(self.docname)

    def note_versionchange(self, type, version, node, lineno):
        self.versionchanges.setdefault(version, []).append(
            (type, self.temp_data['docname'], lineno,
             self.temp_data.get('py:module'),
             self.temp_data.get('object'), node.astext()))

    # post-processing of read doctrees

    def filter_messages(self, doctree):
        """Filter system messages from a doctree."""
        filterlevel = self.config.keep_warnings and 2 or 5
        for node in doctree.traverse(nodes.system_message):
            if node['level'] < filterlevel:
                self.app.debug('%s [filtered system message]', node.astext())
                node.parent.remove(node)

    def process_dependencies(self, docname, doctree):
        """Process docutils-generated dependency info."""
        cwd = os.getcwd()
        frompath = path.join(path.normpath(self.srcdir), 'dummy')
        deps = doctree.settings.record_dependencies
        if not deps:
            return
        for dep in deps.list:
            # the dependency path is relative to the working dir, so get
            # one relative to the srcdir
            relpath = relative_path(frompath,
                                    path.normpath(path.join(cwd, dep)))
            self.dependencies.setdefault(docname, set()).add(relpath)

    def process_downloads(self, docname, doctree):
        """Process downloadable file paths. """
        for node in doctree.traverse(addnodes.download_reference):
            targetname = node['reftarget']
            rel_filename, filename = self.relfn2path(targetname, docname)
            self.dependencies.setdefault(docname, set()).add(rel_filename)
            if not os.access(filename, os.R_OK):
                self.warn_node('download file not readable: %s' % filename,
                               node)
                continue
            uniquename = self.dlfiles.add_file(docname, filename)
            node['filename'] = uniquename

    def process_images(self, docname, doctree):
        """Process and rewrite image URIs."""
        for node in doctree.traverse(nodes.image):
            # Map the mimetype to the corresponding image.  The writer may
            # choose the best image from these candidates.  The special key * is
            # set if there is only single candidate to be used by a writer.
            # The special key ? is set for nonlocal URIs.
            node['candidates'] = candidates = {}
            imguri = node['uri']
            if imguri.find('://') != -1:
                self.warn_node('nonlocal image URI found: %s' % imguri, node)
                candidates['?'] = imguri
                continue
            rel_imgpath, full_imgpath = self.relfn2path(imguri, docname)
            # set imgpath as default URI
            node['uri'] = rel_imgpath
            if rel_imgpath.endswith(os.extsep + '*'):
                for filename in glob(full_imgpath):
                    new_imgpath = relative_path(path.join(self.srcdir, 'dummy'),
                                                filename)
                    if filename.lower().endswith('.pdf'):
                        candidates['application/pdf'] = new_imgpath
                    elif filename.lower().endswith('.svg'):
                        candidates['image/svg+xml'] = new_imgpath
                    else:
                        try:
                            f = open(filename, 'rb')
                            try:
                                imgtype = imghdr.what(f)
                            finally:
                                f.close()
                        except (OSError, IOError) as err:
                            self.warn_node('image file %s not readable: %s' %
                                           (filename, err), node)
                        if imgtype:
                            candidates['image/' + imgtype] = new_imgpath
            else:
                candidates['*'] = rel_imgpath
            # map image paths to unique image names (so that they can be put
            # into a single directory)
            for imgpath in itervalues(candidates):
                self.dependencies.setdefault(docname, set()).add(imgpath)
                if not os.access(path.join(self.srcdir, imgpath), os.R_OK):
                    self.warn_node('image file not readable: %s' % imgpath,
                                   node)
                    continue
                self.images.add_file(docname, imgpath)

    def process_metadata(self, docname, doctree):
        """Process the docinfo part of the doctree as metadata.

        Keep processing minimal -- just return what docutils says.
        """
        self.metadata[docname] = md = {}
        try:
            docinfo = doctree[0]
        except IndexError:
            # probably an empty document
            return
        if docinfo.__class__ is not nodes.docinfo:
            # nothing to see here
            return
        for node in docinfo:
            # nodes are multiply inherited...
            if isinstance(node, nodes.authors):
                md['authors'] = [author.astext() for author in node]
            elif isinstance(node, nodes.TextElement):  # e.g. author
                md[node.__class__.__name__] = node.astext()
            else:
                name, body = node
                md[name.astext()] = body.astext()
        for name, value in md.items():
            if name in ('tocdepth',):
                try:
                    value = int(value)
                except ValueError:
                    value = 0
                md[name] = value

        del doctree[0]

    def process_refonly_bullet_lists(self, docname, doctree):
        """Change refonly bullet lists to use compact_paragraphs.

        Specifically implemented for 'Indices and Tables' section, which looks
        odd when html_compact_lists is false.
        """
        if self.config.html_compact_lists:
            return

        class RefOnlyListChecker(nodes.GenericNodeVisitor):
            """Raise `nodes.NodeFound` if non-simple list item is encountered.

            Here 'simple' means a list item containing only a paragraph with a
            single reference in it.
            """

            def default_visit(self, node):
                raise nodes.NodeFound

            def visit_bullet_list(self, node):
                pass

            def visit_list_item(self, node):
                children = []
                for child in node.children:
                    if not isinstance(child, nodes.Invisible):
                        children.append(child)
                if len(children) != 1:
                    raise nodes.NodeFound
                if not isinstance(children[0], nodes.paragraph):
                    raise nodes.NodeFound
                para = children[0]
                if len(para) != 1:
                    raise nodes.NodeFound
                if not isinstance(para[0], addnodes.pending_xref):
                    raise nodes.NodeFound
                raise nodes.SkipChildren

            def invisible_visit(self, node):
                """Invisible nodes should be ignored."""
                pass

        def check_refonly_list(node):
            """Check for list with only references in it."""
            visitor = RefOnlyListChecker(doctree)
            try:
                node.walk(visitor)
            except nodes.NodeFound:
                return False
            else:
                return True

        for node in doctree.traverse(nodes.bullet_list):
            if check_refonly_list(node):
                for item in node.traverse(nodes.list_item):
                    para = item[0]
                    ref = para[0]
                    compact_para = addnodes.compact_paragraph()
                    compact_para += ref
                    item.replace(para, compact_para)

    def create_title_from(self, docname, document):
        """Add a title node to the document (just copy the first section title),
        and store that title in the environment.
        """
        titlenode = nodes.title()
        longtitlenode = titlenode
        # explicit title set with title directive; use this only for
        # the <title> tag in HTML output
        if 'title' in document:
            longtitlenode = nodes.title()
            longtitlenode += nodes.Text(document['title'])
        # look for first section title and use that as the title
        for node in document.traverse(nodes.section):
            visitor = SphinxContentsFilter(document)
            node[0].walkabout(visitor)
            titlenode += visitor.get_entry_text()
            break
        else:
            # document has no title
            titlenode += nodes.Text('<no title>')
        self.titles[docname] = titlenode
        self.longtitles[docname] = longtitlenode

    def note_indexentries_from(self, docname, document):
        entries = self.indexentries[docname] = []
        for node in document.traverse(addnodes.index):
            entries.extend(node['entries'])

    def note_citations_from(self, docname, document):
        for node in document.traverse(nodes.citation):
            label = node[0].astext()
            if label in self.citations:
                self.warn_node('duplicate citation %s, ' % label +
                               'other instance in %s' % self.doc2path(
                                   self.citations[label][0]), node)
            self.citations[label] = (docname, node['ids'][0])

    def note_toctree(self, docname, toctreenode):
        """Note a TOC tree directive in a document and gather information about
        file relations from it.
        """
        if toctreenode['glob']:
            self.glob_toctrees.add(docname)
        if toctreenode.get('numbered'):
            self.numbered_toctrees.add(docname)
        includefiles = toctreenode['includefiles']
        for includefile in includefiles:
            # note that if the included file is rebuilt, this one must be
            # too (since the TOC of the included file could have changed)
            self.files_to_rebuild.setdefault(includefile, set()).add(docname)
        self.toctree_includes.setdefault(docname, []).extend(includefiles)

    def build_toc_from(self, docname, document):
        """Build a TOC from the doctree and store it in the inventory."""
        numentries = [0]  # nonlocal again...

        def traverse_in_section(node, cls):
            """Like traverse(), but stay within the same section."""
            result = []
            if isinstance(node, cls):
                result.append(node)
            for child in node.children:
                if isinstance(child, nodes.section):
                    continue
                result.extend(traverse_in_section(child, cls))
            return result

        def build_toc(node, depth=1):
            entries = []
            for sectionnode in node:
                # find all toctree nodes in this section and add them
                # to the toc (just copying the toctree node which is then
                # resolved in self.get_and_resolve_doctree)
                if isinstance(sectionnode, addnodes.only):
                    onlynode = addnodes.only(expr=sectionnode['expr'])
                    blist = build_toc(sectionnode, depth)
                    if blist:
                        onlynode += blist.children
                        entries.append(onlynode)
                    continue
                if not isinstance(sectionnode, nodes.section):
                    for toctreenode in traverse_in_section(sectionnode,
                                                           addnodes.toctree):
                        item = toctreenode.copy()
                        entries.append(item)
                        # important: do the inventory stuff
                        self.note_toctree(docname, toctreenode)
                    continue
                title = sectionnode[0]
                # copy the contents of the section title, but without references
                # and unnecessary stuff
                visitor = SphinxContentsFilter(document)
                title.walkabout(visitor)
                nodetext = visitor.get_entry_text()
                if not numentries[0]:
                    # for the very first toc entry, don't add an anchor
                    # as it is the file's title anyway
                    anchorname = ''
                else:
                    anchorname = '#' + sectionnode['ids'][0]
                numentries[0] += 1
                # make these nodes:
                # list_item -> compact_paragraph -> reference
                reference = nodes.reference(
                    '', '', internal=True, refuri=docname,
                    anchorname=anchorname, *nodetext)
                para = addnodes.compact_paragraph('', '', reference)
                item = nodes.list_item('', para)
                sub_item = build_toc(sectionnode, depth + 1)
                item += sub_item
                entries.append(item)
            if entries:
                return nodes.bullet_list('', *entries)
            return []
        toc = build_toc(document)
        if toc:
            self.tocs[docname] = toc
        else:
            self.tocs[docname] = nodes.bullet_list('')
        self.toc_num_entries[docname] = numentries[0]

    def get_toc_for(self, docname, builder):
        """Return a TOC nodetree -- for use on the same page only!"""
        try:
            toc = self.tocs[docname].deepcopy()
        except KeyError:
            # the document does not exist anymore: return a dummy node that
            # renders to nothing
            return nodes.paragraph()
        self.process_only_nodes(toc, builder, docname)
        for node in toc.traverse(nodes.reference):
            node['refuri'] = node['anchorname'] or '#'
        return toc

    def get_toctree_for(self, docname, builder, collapse, **kwds):
        """Return the global TOC nodetree."""
        doctree = self.get_doctree(self.config.master_doc)
        toctrees = []
        if 'includehidden' not in kwds:
            kwds['includehidden'] = True
        if 'maxdepth' not in kwds:
            kwds['maxdepth'] = 0
        kwds['collapse'] = collapse
        for toctreenode in doctree.traverse(addnodes.toctree):
            toctree = self.resolve_toctree(docname, builder, toctreenode,
                                           prune=True, **kwds)
            if toctree:
                toctrees.append(toctree)
        if not toctrees:
            return None
        result = toctrees[0]
        for toctree in toctrees[1:]:
            result.extend(toctree.children)
        return result

    def get_domain(self, domainname):
        """Return the domain instance with the specified name.

        Raises an ExtensionError if the domain is not registered.
        """
        try:
            return self.domains[domainname]
        except KeyError:
            raise ExtensionError('Domain %r is not registered' % domainname)

    # --------- RESOLVING REFERENCES AND TOCTREES ------------------------------

    def get_doctree(self, docname):
        """Read the doctree for a file from the pickle and return it."""
        doctree_filename = self.doc2path(docname, self.doctreedir, '.doctree')
        f = open(doctree_filename, 'rb')
        try:
            doctree = pickle.load(f)
        finally:
            f.close()
        doctree.settings.env = self
        doctree.reporter = Reporter(self.doc2path(docname), 2, 5,
                                    stream=WarningStream(self._warnfunc))
        return doctree

    def get_and_resolve_doctree(self, docname, builder, doctree=None,
                                prune_toctrees=True, includehidden=False):
        """Read the doctree from the pickle, resolve cross-references and
        toctrees and return it.
        """
        if doctree is None:
            doctree = self.get_doctree(docname)

        # resolve all pending cross-references
        self.resolve_references(doctree, docname, builder)

        # now, resolve all toctree nodes
        for toctreenode in doctree.traverse(addnodes.toctree):
            result = self.resolve_toctree(docname, builder, toctreenode,
                                          prune=prune_toctrees,
                                          includehidden=includehidden)
            if result is None:
                toctreenode.replace_self([])
            else:
                toctreenode.replace_self(result)

        return doctree

    def resolve_toctree(self, docname, builder, toctree, prune=True, maxdepth=0,
                        titles_only=False, collapse=False, includehidden=False):
        """Resolve a *toctree* node into individual bullet lists with titles
        as items, returning None (if no containing titles are found) or
        a new node.

        If *prune* is True, the tree is pruned to *maxdepth*, or if that is 0,
        to the value of the *maxdepth* option on the *toctree* node.
        If *titles_only* is True, only toplevel document titles will be in the
        resulting tree.
        If *collapse* is True, all branches not containing docname will
        be collapsed.
        """
        if toctree.get('hidden', False) and not includehidden:
            return None

        # For reading the following two helper function, it is useful to keep
        # in mind the node structure of a toctree (using HTML-like node names
        # for brevity):
        #
        # <ul>
        #   <li>
        #     <p><a></p>
        #     <p><a></p>
        #     ...
        #     <ul>
        #       ...
        #     </ul>
        #   </li>
        # </ul>
        #
        # The transformation is made in two passes in order to avoid
        # interactions between marking and pruning the tree (see bug #1046).

        def _toctree_prune(node, depth, maxdepth):
            """Utility: Cut a TOC at a specified depth."""
            for subnode in node.children[:]:
                if isinstance(subnode, (addnodes.compact_paragraph,
                                        nodes.list_item)):
                    # for <p> and <li>, just recurse
                    _toctree_prune(subnode, depth, maxdepth)
                elif isinstance(subnode, nodes.bullet_list):
                    # for <ul>, determine if the depth is too large or if the
                    # entry is to be collapsed
                    if maxdepth > 0 and depth > maxdepth:
                        subnode.parent.replace(subnode, [])
                    else:
                        # cull sub-entries whose parents aren't 'current'
                        if (collapse and depth > 1 and
                                'iscurrent' not in subnode.parent):
                            subnode.parent.remove(subnode)
                        else:
                            # recurse on visible children
                            _toctree_prune(subnode, depth+1, maxdepth)

        def _toctree_add_classes(node, depth):
            """Add 'toctree-l%d' and 'current' classes to the toctree."""
            for subnode in node.children:
                if isinstance(subnode, (addnodes.compact_paragraph,
                                        nodes.list_item)):
                    # for <p> and <li>, indicate the depth level and recurse
                    subnode['classes'].append('toctree-l%d' % (depth-1))
                    _toctree_add_classes(subnode, depth)
                elif isinstance(subnode, nodes.bullet_list):
                    # for <ul>, just recurse
                    _toctree_add_classes(subnode, depth+1)
                elif isinstance(subnode, nodes.reference):
                    # for <a>, identify which entries point to the current
                    # document and therefore may not be collapsed
                    if subnode['refuri'] == docname:
                        if not subnode['anchorname']:
                            # give the whole branch a 'current' class
                            # (useful for styling it differently)
                            branchnode = subnode
                            while branchnode:
                                branchnode['classes'].append('current')
                                branchnode = branchnode.parent
                        # mark the list_item as "on current page"
                        if subnode.parent.parent.get('iscurrent'):
                            # but only if it's not already done
                            return
                        while subnode:
                            subnode['iscurrent'] = True
                            subnode = subnode.parent

        def _entries_from_toctree(toctreenode, parents,
                                  separate=False, subtree=False):
            """Return TOC entries for a toctree node."""
            refs = [(e[0], e[1]) for e in toctreenode['entries']]
            entries = []
            for (title, ref) in refs:
                try:
                    refdoc = None
                    if url_re.match(ref):
                        if title is None:
                            title = ref
                        reference = nodes.reference('', '', internal=False,
                                                    refuri=ref, anchorname='',
                                                    *[nodes.Text(title)])
                        para = addnodes.compact_paragraph('', '', reference)
                        item = nodes.list_item('', para)
                        toc = nodes.bullet_list('', item)
                    elif ref == 'self':
                        # 'self' refers to the document from which this
                        # toctree originates
                        ref = toctreenode['parent']
                        if not title:
                            title = clean_astext(self.titles[ref])
                        reference = nodes.reference('', '', internal=True,
                                                    refuri=ref,
                                                    anchorname='',
                                                    *[nodes.Text(title)])
                        para = addnodes.compact_paragraph('', '', reference)
                        item = nodes.list_item('', para)
                        # don't show subitems
                        toc = nodes.bullet_list('', item)
                    else:
                        if ref in parents:
                            self.warn(ref, 'circular toctree references '
                                      'detected, ignoring: %s <- %s' %
                                      (ref, ' <- '.join(parents)))
                            continue
                        refdoc = ref
                        toc = self.tocs[ref].deepcopy()
                        maxdepth = self.metadata[ref].get('tocdepth', 0)
                        _toctree_prune(toc, 2, maxdepth)
                        self.process_only_nodes(toc, builder, ref)
                        if title and toc.children and len(toc.children) == 1:
                            child = toc.children[0]
                            for refnode in child.traverse(nodes.reference):
                                if refnode['refuri'] == ref and \
                                   not refnode['anchorname']:
                                    refnode.children = [nodes.Text(title)]
                    if not toc.children:
                        # empty toc means: no titles will show up in the toctree
                        self.warn_node(
                            'toctree contains reference to document %r that '
                            'doesn\'t have a title: no link will be generated'
                            % ref, toctreenode)
                except KeyError:
                    # this is raised if the included file does not exist
                    self.warn_node(
                        'toctree contains reference to nonexisting document %r'
                        % ref, toctreenode)
                else:
                    # if titles_only is given, only keep the main title and
                    # sub-toctrees
                    if titles_only:
                        # delete everything but the toplevel title(s)
                        # and toctrees
                        for toplevel in toc:
                            # nodes with length 1 don't have any children anyway
                            if len(toplevel) > 1:
                                subtrees = toplevel.traverse(addnodes.toctree)
                                toplevel[1][:] = subtrees
                    # resolve all sub-toctrees
                    for toctreenode in toc.traverse(addnodes.toctree):
                        if not (toctreenode.get('hidden', False)
                                and not includehidden):
                            i = toctreenode.parent.index(toctreenode) + 1
                            for item in _entries_from_toctree(
                                    toctreenode, [refdoc] + parents,
                                    subtree=True):
                                toctreenode.parent.insert(i, item)
                                i += 1
                            toctreenode.parent.remove(toctreenode)
                    if separate:
                        entries.append(toc)
                    else:
                        entries.extend(toc.children)
            if not subtree and not separate:
                ret = nodes.bullet_list()
                ret += entries
                return [ret]
            return entries

        maxdepth = maxdepth or toctree.get('maxdepth', -1)
        if not titles_only and toctree.get('titlesonly', False):
            titles_only = True
        if not includehidden and toctree.get('includehidden', False):
            includehidden = True

        # NOTE: previously, this was separate=True, but that leads to artificial
        # separation when two or more toctree entries form a logical unit, so
        # separating mode is no longer used -- it's kept here for history's sake
        tocentries = _entries_from_toctree(toctree, [], separate=False)
        if not tocentries:
            return None

        newnode = addnodes.compact_paragraph('', '', *tocentries)
        newnode['toctree'] = True

        # prune the tree to maxdepth, also set toc depth and current classes
        _toctree_add_classes(newnode, 1)
        _toctree_prune(newnode, 1, prune and maxdepth or 0)

        # set the target paths in the toctrees (they are not known at TOC
        # generation time)
        for refnode in newnode.traverse(nodes.reference):
            if not url_re.match(refnode['refuri']):
                refnode['refuri'] = builder.get_relative_uri(
                    docname, refnode['refuri']) + refnode['anchorname']
        return newnode

    def resolve_references(self, doctree, fromdocname, builder):
        for node in doctree.traverse(addnodes.pending_xref):
            contnode = node[0].deepcopy()
            newnode = None

            typ = node['reftype']
            target = node['reftarget']
            refdoc = node.get('refdoc', fromdocname)
            domain = None

            try:
                if 'refdomain' in node and node['refdomain']:
                    # let the domain try to resolve the reference
                    try:
                        domain = self.domains[node['refdomain']]
                    except KeyError:
                        raise NoUri
                    newnode = domain.resolve_xref(self, fromdocname, builder,
                                                  typ, target, node, contnode)
                # really hardwired reference types
                elif typ == 'doc':
                    # directly reference to document by source name;
                    # can be absolute or relative
                    docname = docname_join(refdoc, target)
                    if docname in self.all_docs:
                        if node['refexplicit']:
                            # reference with explicit title
                            caption = node.astext()
                        else:
                            caption = clean_astext(self.titles[docname])
                        innernode = nodes.emphasis(caption, caption)
                        newnode = nodes.reference('', '', internal=True)
                        newnode['refuri'] = builder.get_relative_uri(
                            fromdocname, docname)
                        newnode.append(innernode)
                elif typ == 'citation':
                    docname, labelid = self.citations.get(target, ('', ''))
                    if docname:
                        try:
                            newnode = make_refnode(builder, fromdocname,
                                                   docname, labelid, contnode)
                        except NoUri:
                            # remove the ids we added in the CitationReferences
                            # transform since they can't be transfered to
                            # the contnode (if it's a Text node)
                            if not isinstance(contnode, nodes.Element):
                                del node['ids'][:]
                            raise
                    elif 'ids' in node:
                        # remove ids attribute that annotated at
                        # transforms.CitationReference.apply.
                        del node['ids'][:]
                # no new node found? try the missing-reference event
                if newnode is None:
                    newnode = builder.app.emit_firstresult(
                        'missing-reference', self, node, contnode)
                    # still not found? warn if in nit-picky mode
                    if newnode is None:
                        self._warn_missing_reference(
                            fromdocname, typ, target, node, domain)
            except NoUri:
                newnode = contnode
            node.replace_self(newnode or contnode)

        # remove only-nodes that do not belong to our builder
        self.process_only_nodes(doctree, builder, fromdocname)

        # allow custom references to be resolved
        builder.app.emit('doctree-resolved', doctree, fromdocname)

    def _warn_missing_reference(self, fromdoc, typ, target, node, domain):
        warn = node.get('refwarn')
        if self.config.nitpicky:
            warn = True
            if self._nitpick_ignore:
                dtype = domain and '%s:%s' % (domain.name, typ) or typ
                if (dtype, target) in self._nitpick_ignore:
                    warn = False
                # for "std" types also try without domain name
                if domain.name == 'std' and (typ, target) in self._nitpick_ignore:
                    warn = False
        if not warn:
            return
        if domain and typ in domain.dangling_warnings:
            msg = domain.dangling_warnings[typ]
        elif typ == 'doc':
            msg = 'unknown document: %(target)s'
        elif typ == 'citation':
            msg = 'citation not found: %(target)s'
        elif node.get('refdomain', 'std') != 'std':
            msg = '%s:%s reference target not found: %%(target)s' % \
                  (node['refdomain'], typ)
        else:
            msg = '%s reference target not found: %%(target)s' % typ
        self.warn_node(msg % {'target': target}, node)

    def process_only_nodes(self, doctree, builder, fromdocname=None):
        # A comment on the comment() nodes being inserted: replacing by [] would
        # result in a "Losing ids" exception if there is a target node before
        # the only node, so we make sure docutils can transfer the id to
        # something, even if it's just a comment and will lose the id anyway...
        for node in doctree.traverse(addnodes.only):
            try:
                ret = builder.tags.eval_condition(node['expr'])
            except Exception as err:
                self.warn_node('exception while evaluating only '
                               'directive expression: %s' % err, node)
                node.replace_self(node.children or nodes.comment())
            else:
                if ret:
                    node.replace_self(node.children or nodes.comment())
                else:
                    node.replace_self(nodes.comment())

    def assign_section_numbers(self):
        """Assign a section number to each heading under a numbered toctree."""
        # a list of all docnames whose section numbers changed
        rewrite_needed = []

        assigned = set()
        old_secnumbers = self.toc_secnumbers
        self.toc_secnumbers = {}

        def _walk_toc(node, secnums, depth, titlenode=None):
            # titlenode is the title of the document, it will get assigned a
            # secnumber too, so that it shows up in next/prev/parent rellinks
            for subnode in node.children:
                if isinstance(subnode, nodes.bullet_list):
                    numstack.append(0)
                    _walk_toc(subnode, secnums, depth-1, titlenode)
                    numstack.pop()
                    titlenode = None
                elif isinstance(subnode, nodes.list_item):
                    _walk_toc(subnode, secnums, depth, titlenode)
                    titlenode = None
                elif isinstance(subnode, addnodes.only):
                    # at this stage we don't know yet which sections are going
                    # to be included; just include all of them, even if it leads
                    # to gaps in the numbering
                    _walk_toc(subnode, secnums, depth, titlenode)
                    titlenode = None
                elif isinstance(subnode, addnodes.compact_paragraph):
                    numstack[-1] += 1
                    if depth > 0:
                        number = tuple(numstack)
                    else:
                        number = None
                    secnums[subnode[0]['anchorname']] = \
                        subnode[0]['secnumber'] = number
                    if titlenode:
                        titlenode['secnumber'] = number
                        titlenode = None
                elif isinstance(subnode, addnodes.toctree):
                    _walk_toctree(subnode, depth)

        def _walk_toctree(toctreenode, depth):
            if depth == 0:
                return
            for (title, ref) in toctreenode['entries']:
                if url_re.match(ref) or ref == 'self' or ref in assigned:
                    # don't mess with those
                    continue
                if ref in self.tocs:
                    secnums = self.toc_secnumbers[ref] = {}
                    assigned.add(ref)
                    _walk_toc(self.tocs[ref], secnums, depth,
                              self.titles.get(ref))
                    if secnums != old_secnumbers.get(ref):
                        rewrite_needed.append(ref)

        for docname in self.numbered_toctrees:
            assigned.add(docname)
            doctree = self.get_doctree(docname)
            for toctreenode in doctree.traverse(addnodes.toctree):
                depth = toctreenode.get('numbered', 0)
                if depth:
                    # every numbered toctree gets new numbering
                    numstack = [0]
                    _walk_toctree(toctreenode, depth)

        return rewrite_needed

    def create_index(self, builder, group_entries=True,
                     _fixre=re.compile(r'(.*) ([(][^()]*[)])')):
        """Create the real index from the collected index entries."""
        new = {}

        def add_entry(word, subword, link=True, dic=new):
            # 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 = [[], {}]
            if subword:
                add_entry(subword, '', link=link, dic=entry[1])
            elif link:
                try:
                    uri = builder.get_relative_uri('genindex', fn) + '#' + tid
                except NoUri:
                    pass
                else:
                    entry[0].append((main, uri))

        for fn, entries in iteritems(self.indexentries):
            # new entry types must be listed in directives/other.py!
            for type, value, tid, main 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)
                    elif type == 'pair':
                        first, second = split_into(2, 'pair', value)
                        add_entry(first, second)
                        add_entry(second, first)
                    elif type == 'triple':
                        first, second, third = split_into(3, 'triple', value)
                        add_entry(first, second+' '+third)
                        add_entry(second, third+', '+first)
                        add_entry(third, first+' '+second)
                    elif type == 'see':
                        first, second = split_into(2, 'see', value)
                        add_entry(first, _('see %s') % second, link=False)
                    elif type == 'seealso':
                        first, second = split_into(2, 'see', value)
                        add_entry(first, _('see also %s') % second, link=False)
                    else:
                        self.warn(fn, 'unknown index entry type %r' % type)
                except ValueError as err:
                    self.warn(fn, str(err))

        # 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 + '_'):
            lckey = unicodedata.normalize('NFD', entry[0].lower())
            if lckey[0:1] in lcletters:
                return chr(127) + lckey
            return lckey
        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 = ''
            oldsubitems = None
            i = 0
            while i < len(newlist):
                key, (targets, subitems) = 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), [[], {}])[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)) in iteritems(v[1]))
            # 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')
        return [(key, list(group))
                for (key, group) in groupby(newlist, keyfunc2)]

    def collect_relations(self):
        relations = {}
        getinc = self.toctree_includes.get

        def collect(parents, parents_set, docname, previous, next):
            # circular relationship?
            if docname in parents_set:
                # we will warn about this in resolve_toctree()
                return
            includes = getinc(docname)
            # previous
            if not previous:
                # if no previous sibling, go to parent
                previous = parents[0][0]
            else:
                # else, go to previous sibling, or if it has children, to
                # the last of its children, or if that has children, to the
                # last of those, and so forth
                while 1:
                    previncs = getinc(previous)
                    if previncs:
                        previous = previncs[-1]
                    else:
                        break
            # next
            if includes:
                # if it has children, go to first of them
                next = includes[0]
            elif next:
                # else, if next sibling, go to it
                pass
            else:
                # else, go to the next sibling of the parent, if present,
                # else the grandparent's sibling, if present, and so forth
                for parname, parindex in parents:
                    parincs = getinc(parname)
                    if parincs and parindex + 1 < len(parincs):
                        next = parincs[parindex+1]
                        break
                # else it will stay None
            # same for children
            if includes:
                for subindex, args in enumerate(zip(includes,
                                                    [None] + includes,
                                                    includes[1:] + [None])):
                    collect([(docname, subindex)] + parents,
                            parents_set.union([docname]), *args)
            relations[docname] = [parents[0][0], previous, next]
        collect([(None, 0)], set(), self.config.master_doc, None, None)
        return relations

    def check_consistency(self):
        """Do consistency checks."""
        for docname in sorted(self.all_docs):
            if docname not in self.files_to_rebuild:
                if docname == self.config.master_doc:
                    # the master file is not included anywhere ;)
                    continue
                if 'orphan' in self.metadata[docname]:
                    continue
                self.warn(docname, 'document isn\'t included in any toctree')
