buildframework/helium/external/python/lib/common/Sphinx-0.5.1-py2.5.egg/sphinx/ext/intersphinx.py
changeset 179 d8ac696cc51f
equal deleted inserted replaced
1:be27ed110b50 179:d8ac696cc51f
       
     1 # -*- coding: utf-8 -*-
       
     2 """
       
     3     sphinx.ext.intersphinx
       
     4     ~~~~~~~~~~~~~~~~~~~~~~
       
     5 
       
     6     Insert links to Python objects documented in remote Sphinx documentation.
       
     7 
       
     8     This works as follows:
       
     9 
       
    10     * Each Sphinx HTML build creates a file named "objects.inv" that contains
       
    11       a mapping from Python identifiers to URIs relative to the HTML set's root.
       
    12 
       
    13     * Projects using the Intersphinx extension can specify links to such mapping
       
    14       files in the `intersphinx_mapping` config value.  The mapping will then be
       
    15       used to resolve otherwise missing references to Python objects into links
       
    16       to the other documentation.
       
    17 
       
    18     * By default, the mapping file is assumed to be at the same location as the
       
    19       rest of the documentation; however, the location of the mapping file can
       
    20       also be specified individually, e.g. if the docs should be buildable
       
    21       without Internet access.
       
    22 
       
    23     :copyright: 2008 by Georg Brandl.
       
    24     :license: BSD.
       
    25 """
       
    26 
       
    27 import time
       
    28 import urllib
       
    29 import posixpath
       
    30 from os import path
       
    31 
       
    32 from docutils import nodes
       
    33 
       
    34 from sphinx.builder import INVENTORY_FILENAME
       
    35 
       
    36 
       
    37 def fetch_inventory(app, uri, inv):
       
    38     """Fetch, parse and return an intersphinx inventory file."""
       
    39     invdata = {}
       
    40     # both *uri* (base URI of the links to generate) and *inv* (actual
       
    41     # location of the inventory file) can be local or remote URIs
       
    42     localuri = uri.find('://') == -1
       
    43     try:
       
    44         if inv.find('://') != -1:
       
    45             f = urllib.urlopen(inv)
       
    46         else:
       
    47             f = open(path.join(app.srcdir, inv))
       
    48     except Exception, err:
       
    49         app.warn('intersphinx inventory %r not fetchable due to '
       
    50                  '%s: %s' % (inv, err.__class__, err))
       
    51         return
       
    52     try:
       
    53         line = f.next()
       
    54         if line.rstrip() != '# Sphinx inventory version 1':
       
    55             raise ValueError('unknown or unsupported inventory version')
       
    56         line = f.next()
       
    57         projname = line.rstrip()[11:].decode('utf-8')
       
    58         line = f.next()
       
    59         version = line.rstrip()[11:]
       
    60         for line in f:
       
    61             name, type, location = line.rstrip().split(None, 2)
       
    62             if localuri:
       
    63                 location = path.join(uri, location)
       
    64             else:
       
    65                 location = posixpath.join(uri, location)
       
    66             invdata[name] = (type, projname, version, location)
       
    67         f.close()
       
    68     except Exception, err:
       
    69         app.warn('intersphinx inventory %r not readable due to '
       
    70                  '%s: %s' % (inv, err.__class__, err))
       
    71     else:
       
    72         return invdata
       
    73 
       
    74 
       
    75 def load_mappings(app):
       
    76     """Load all intersphinx mappings into the environment."""
       
    77     now = int(time.time())
       
    78     cache_time = now - app.config.intersphinx_cache_limit * 86400
       
    79     env = app.builder.env
       
    80     if not hasattr(env, 'intersphinx_cache'):
       
    81         env.intersphinx_cache = {}
       
    82     cache = env.intersphinx_cache
       
    83     update = False
       
    84     for uri, inv in app.config.intersphinx_mapping.iteritems():
       
    85         # we can safely assume that the uri<->inv mapping is not changed
       
    86         # during partial rebuilds since a changed intersphinx_mapping
       
    87         # setting will cause a full environment reread
       
    88         if not inv:
       
    89             inv = posixpath.join(uri, INVENTORY_FILENAME)
       
    90         # decide whether the inventory must be read: always read local
       
    91         # files; remote ones only if the cache time is expired
       
    92         if '://' not in inv or uri not in cache \
       
    93                or cache[uri][0] < cache_time:
       
    94             invdata = fetch_inventory(app, uri, inv)
       
    95             cache[uri] = (now, invdata)
       
    96             update = True
       
    97     if update:
       
    98         env.intersphinx_inventory = {}
       
    99         for _, invdata in cache.itervalues():
       
   100             if invdata:
       
   101                 env.intersphinx_inventory.update(invdata)
       
   102 
       
   103 
       
   104 def missing_reference(app, env, node, contnode):
       
   105     """Attempt to resolve a missing reference via intersphinx references."""
       
   106     type = node['reftype']
       
   107     target = node['reftarget']
       
   108     if type == 'mod':
       
   109         type, proj, version, uri = env.intersphinx_inventory.get(target,
       
   110                                                                  ('','','',''))
       
   111         if type != 'mod':
       
   112             return None
       
   113         target = 'module-' + target   # for link anchor
       
   114     else:
       
   115         if target[-2:] == '()':
       
   116             target = target[:-2]
       
   117         target = target.rstrip(' *')
       
   118         # special case: exceptions and object methods
       
   119         if type == 'exc' and '.' not in target and \
       
   120            'exceptions.' + target in env.intersphinx_inventory:
       
   121             target = 'exceptions.' + target
       
   122         elif type in ('func', 'meth') and '.' not in target and \
       
   123            'object.' + target in env.intersphinx_inventory:
       
   124             target = 'object.' + target
       
   125         if target not in env.intersphinx_inventory:
       
   126             return None
       
   127         type, proj, version, uri = env.intersphinx_inventory[target]
       
   128     print "Intersphinx hit:", target, uri
       
   129     newnode = nodes.reference('', '')
       
   130     newnode['refuri'] = uri + '#' + target
       
   131     newnode['reftitle'] = '(in %s v%s)' % (proj, version)
       
   132     newnode['class'] = 'external-xref'
       
   133     newnode.append(contnode)
       
   134     return newnode
       
   135 
       
   136 
       
   137 def setup(app):
       
   138     app.add_config_value('intersphinx_mapping', {}, True)
       
   139     app.add_config_value('intersphinx_cache_limit', 5, False)
       
   140     app.connect('missing-reference', missing_reference)
       
   141     app.connect('builder-inited', load_mappings)