diff options
| author | Georg Brandl <georg@python.org> | 2009-12-28 19:49:57 +0100 |
|---|---|---|
| committer | Georg Brandl <georg@python.org> | 2009-12-28 19:49:57 +0100 |
| commit | 6b954328bea16abf763a2d829471d6565747f1a4 (patch) | |
| tree | 17299e304c5608d335c88e2eb26780ba14fafecc /sphinx/ext | |
| parent | 2637a7b44ad5b68412d14da5ff64b0f8ee88512f (diff) | |
| parent | a3cd1ee676757c69ae30f401b62b7a055f1e3f1a (diff) | |
| download | sphinx-6b954328bea16abf763a2d829471d6565747f1a4.tar.gz | |
merge with trunk
Diffstat (limited to 'sphinx/ext')
| -rw-r--r-- | sphinx/ext/autodoc.py | 30 | ||||
| -rw-r--r-- | sphinx/ext/autosummary/__init__.py | 10 | ||||
| -rw-r--r-- | sphinx/ext/coverage.py | 14 | ||||
| -rw-r--r-- | sphinx/ext/inheritance_diagram.py | 7 | ||||
| -rw-r--r-- | sphinx/ext/intersphinx.py | 133 | ||||
| -rw-r--r-- | sphinx/ext/refcounting.py | 2 | ||||
| -rw-r--r-- | sphinx/ext/todo.py | 4 |
7 files changed, 126 insertions, 74 deletions
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index b5c59ec5..70d03f59 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -392,9 +392,11 @@ class Documenter(object): def add_directive_header(self, sig): """Add the directive header and options to the generated content.""" + domain = getattr(self, 'domain', 'py') directive = getattr(self, 'directivetype', self.objtype) name = self.format_name() - self.add_line(u'.. %s:: %s%s' % (directive, name, sig), '<autodoc>') + self.add_line(u'.. %s:%s:: %s%s' % (domain, directive, name, sig), + '<autodoc>') if self.options.noindex: self.add_line(u' :noindex:', '<autodoc>') if self.objpath: @@ -548,9 +550,9 @@ class Documenter(object): do all members, else those given by *self.options.members*. """ # set current namespace for finding members - self.env.autodoc_current_module = self.modname + self.env.doc_read_data['autodoc_module'] = self.modname if self.objpath: - self.env.autodoc_current_class = self.objpath[0] + self.env.doc_read_data['autodoc_class'] = self.objpath[0] want_all = all_members or self.options.inherited_members or \ self.options.members is ALL @@ -591,8 +593,8 @@ class Documenter(object): check_module=members_check_module) # reset current objects - self.env.autodoc_current_module = None - self.env.autodoc_current_class = None + self.env.doc_read_data['autodoc_module'] = None + self.env.doc_read_data['autodoc_class'] = None def generate(self, more_content=None, real_modname=None, check_module=False, all_members=False): @@ -750,11 +752,10 @@ class ModuleLevelDocumenter(Documenter): else: # if documenting a toplevel object without explicit module, # it can be contained in another auto directive ... - if hasattr(self.env, 'autodoc_current_module'): - modname = self.env.autodoc_current_module + modname = self.env.doc_read_data.get('autodoc_module') # ... or in the scope of a module directive if not modname: - modname = self.env.currmodule + modname = self.env.doc_read_data.get('py_module') # ... else, it stays None, which means invalid return modname, parents + [base] @@ -773,21 +774,20 @@ class ClassLevelDocumenter(Documenter): # if documenting a class-level object without path, # there must be a current class, either from a parent # auto directive ... - if hasattr(self.env, 'autodoc_current_class'): - mod_cls = self.env.autodoc_current_class + mod_cls = self.env.doc_read_data.get('autodoc_class') # ... or from a class directive if mod_cls is None: - mod_cls = self.env.currclass + mod_cls = self.env.doc_read_data.get('py_class') # ... if still None, there's no way to know if mod_cls is None: return None, [] modname, cls = rpartition(mod_cls, '.') parents = [cls] # if the module name is still missing, get it like above - if not modname and hasattr(self.env, 'autodoc_current_module'): - modname = self.env.autodoc_current_module if not modname: - modname = self.env.currmodule + modname = self.env.doc_read_data.get('autodoc_module') + if not modname: + modname = self.env.doc_read_data.get('py_module') # ... else, it stays None, which means invalid return modname, parents + [base] @@ -1091,7 +1091,7 @@ class AutoDirective(Directive): # record all filenames as dependencies -- this will at least # partially make automatic invalidation possible for fn in self.filename_set: - self.env.note_dependency(fn) + self.state.document.settings.record_dependencies.add(fn) # use a custom reporter that correctly assigns lines to source # filename/description and lineno diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 3c9ff466..0569b75d 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -228,8 +228,9 @@ class Autosummary(Directive): env = self.state.document.settings.env prefixes = [''] - if env.currmodule: - prefixes.insert(0, env.currmodule) + currmodule = env.doc_read_data.get('py_module') + if currmodule: + prefixes.insert(0, currmodule) items = [] @@ -443,8 +444,9 @@ def autolink_role(typ, rawtext, etext, lineno, inliner, Expands to ':obj:`text`' if `text` is an object that can be imported; otherwise expands to '*text*'. """ - r = roles.xfileref_role('obj', rawtext, etext, lineno, inliner, - options, content) + env = inliner.document.settings.env + r = env.get_domain('py').role('obj')( + 'obj', rawtext, etext, lineno, inliner, options, content) pnode = r[0][0] prefixes = [None] diff --git a/sphinx/ext/coverage.py b/sphinx/ext/coverage.py index 964e58ee..38dabf9f 100644 --- a/sphinx/ext/coverage.py +++ b/sphinx/ext/coverage.py @@ -79,6 +79,7 @@ class CoverageBuilder(Builder): def build_c_coverage(self): # Fetch all the info from the header files + c_objects = self.env.domaindata['c']['objects'] for filename in self.c_sourcefiles: undoc = [] f = open(filename, 'r') @@ -88,7 +89,7 @@ class CoverageBuilder(Builder): match = regex.match(line) if match: name = match.groups()[0] - if name not in self.env.descrefs: + if name not in c_objects: for exp in self.c_ignorexps.get(key, ()): if exp.match(name): break @@ -116,7 +117,10 @@ class CoverageBuilder(Builder): op.close() def build_py_coverage(self): - for mod_name in self.env.modules: + objects = self.env.domaindata['py']['objects'] + modules = self.env.domaindata['py']['modules'] + + for mod_name in modules: ignore = False for exp in self.mod_ignorexps: if exp.match(mod_name): @@ -151,7 +155,7 @@ class CoverageBuilder(Builder): full_name = '%s.%s' % (mod_name, name) if inspect.isfunction(obj): - if full_name not in self.env.descrefs: + if full_name not in objects: for exp in self.fun_ignorexps: if exp.match(name): break @@ -162,7 +166,7 @@ class CoverageBuilder(Builder): if exp.match(name): break else: - if full_name not in self.env.descrefs: + if full_name not in objects: # not documented at all classes[name] = [] continue @@ -176,7 +180,7 @@ class CoverageBuilder(Builder): continue full_attr_name = '%s.%s' % (full_name, attr_name) - if full_attr_name not in self.env.descrefs: + if full_attr_name not in objects: attrs.append(attr_name) if attrs: diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py index 35790731..dc3afa4d 100644 --- a/sphinx/ext/inheritance_diagram.py +++ b/sphinx/ext/inheritance_diagram.py @@ -47,7 +47,6 @@ except ImportError: from docutils import nodes from docutils.parsers.rst import directives -from sphinx.roles import xfileref_role from sphinx.ext.graphviz import render_dot_html, render_dot_latex from sphinx.util.compat import Directive @@ -280,10 +279,12 @@ class InheritanceDiagram(Directive): node.document = self.state.document env = self.state.document.settings.env class_names = self.arguments[0].split() + class_role = env.get_domain('py').role('class') # Create a graph starting with the list of classes try: - graph = InheritanceGraph(class_names, env.currmodule) + graph = InheritanceGraph(class_names, + env.doc_read_data.get('py_module')) except InheritanceException, err: return [node.document.reporter.warning(err.args[0], line=self.lineno)] @@ -293,7 +294,7 @@ class InheritanceDiagram(Directive): # references to real URLs later. These nodes will eventually be # removed from the doctree after we're done with them. for name in graph.get_all_class_names(): - refnodes, x = xfileref_role( + refnodes, x = class_role( 'class', ':class:`%s`' % name, name, 0, self.state) node.extend(refnodes) # Store the graph object so we can use it to generate the diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py index 3c97a734..78a6966b 100644 --- a/sphinx/ext/intersphinx.py +++ b/sphinx/ext/intersphinx.py @@ -3,17 +3,17 @@ sphinx.ext.intersphinx ~~~~~~~~~~~~~~~~~~~~~~ - Insert links to Python objects documented in remote Sphinx documentation. + Insert links to objects documented in remote Sphinx documentation. This works as follows: - * Each Sphinx HTML build creates a file named "objects.inv" that contains - a mapping from Python identifiers to URIs relative to the HTML set's root. + * Each Sphinx HTML build creates a file named "objects.inv" that contains a + mapping from object names to URIs relative to the HTML set's root. * Projects using the Intersphinx extension can specify links to such mapping files in the `intersphinx_mapping` config value. The mapping will then be - used to resolve otherwise missing references to Python objects into links - to the other documentation. + used to resolve otherwise missing references to objects into links to the + other documentation. * By default, the mapping file is assumed to be at the same location as the rest of the documentation; however, the location of the mapping file can @@ -25,6 +25,7 @@ """ import time +import zlib import urllib2 import posixpath from os import path @@ -41,12 +42,68 @@ if hasattr(urllib2, 'HTTPSHandler'): urllib2.install_opener(urllib2.build_opener(*handlers)) +def read_inventory_v1(f, uri, join): + invdata = {} + line = f.next() + projname = line.rstrip()[11:].decode('utf-8') + line = f.next() + version = line.rstrip()[11:] + for line in f: + name, type, location = line.rstrip().split(None, 2) + location = join(uri, location) + # version 1 did not add anchors to the location + if type == 'mod': + type = 'py:module' + location += '#module-' + name + else: + type = 'py:' + type + location += '#' + name + invdata.setdefault(type, {})[name] = (projname, version, location) + return invdata + + +def read_inventory_v2(f, uri, join, bufsize=16*1024): + invdata = {} + line = f.readline() + projname = line.rstrip()[11:].decode('utf-8') + line = f.readline() + version = line.rstrip()[11:] + line = f.readline() + if 'zlib' not in line: + raise ValueError + + def read_chunks(): + decompressor = zlib.decompressobj() + for chunk in iter(lambda: f.read(bufsize), ''): + yield decompressor.decompress(chunk) + yield decompressor.flush() + + def split_lines(iter): + buf = '' + for chunk in iter: + buf += chunk + lineend = buf.find('\n') + while lineend != -1: + yield buf[:lineend] + buf = buf[lineend+1:] + lineend = buf.find('\n') + assert not buf + + for line in split_lines(read_chunks()): + name, type, prio, location = line.rstrip().split(None, 3) + if location.endswith('$'): + location = location[:-1] + name + location = join(uri, location) + invdata.setdefault(type, {})[name] = (projname, version, location) + return invdata + + def fetch_inventory(app, uri, inv): """Fetch, parse and return an intersphinx inventory file.""" - invdata = {} # both *uri* (base URI of the links to generate) and *inv* (actual # location of the inventory file) can be local or remote URIs localuri = uri.find('://') == -1 + join = localuri and path.join or posixpath.join try: if inv.find('://') != -1: f = urllib2.urlopen(inv) @@ -57,24 +114,21 @@ def fetch_inventory(app, uri, inv): '%s: %s' % (inv, err.__class__, err)) return try: - line = f.next() - if line.rstrip() != '# Sphinx inventory version 1': - raise ValueError('unknown or unsupported inventory version') - line = f.next() - projname = line.rstrip()[11:].decode('utf-8') - line = f.next() - version = line.rstrip()[11:] - for line in f: - name, type, location = line.rstrip().split(None, 2) - if localuri: - location = path.join(uri, location) + line = f.readline().rstrip() + try: + if line == '# Sphinx inventory version 1': + invdata = read_inventory_v1(f, uri, join) + elif line == '# Sphinx inventory version 2': + invdata = read_inventory_v2(f, uri, join) else: - location = posixpath.join(uri, location) - invdata[name] = (type, projname, version, location) - f.close() + raise ValueError + f.close() + except ValueError: + f.close() + raise ValueError('unknown or unsupported inventory version') except Exception, err: app.warn('intersphinx inventory %r not readable due to ' - '%s: %s' % (inv, err.__class__, err)) + '%s: %s' % (inv, err.__class__.__name__, err)) else: return invdata @@ -110,31 +164,24 @@ def load_mappings(app): def missing_reference(app, env, node, contnode): """Attempt to resolve a missing reference via intersphinx references.""" - type = node['reftype'] + domain = node.get('refdomain') + if not domain: + # only objects in domains are in the inventory + return target = node['reftarget'] - if type == 'mod': - type, proj, version, uri = env.intersphinx_inventory.get(target, - ('','','','')) - if type != 'mod': - return None - target = 'module-' + target # for link anchor + objtypes = env.domains[domain].objtypes_for_role(node['reftype']) + if not objtypes: + return + for objtype in objtypes: + fulltype = '%s:%s' % (domain, objtype) + if fulltype in env.intersphinx_inventory and \ + target in env.intersphinx_inventory[fulltype]: + break else: - if target[-2:] == '()': - target = target[:-2] - target = target.rstrip(' *') - # special case: exceptions and object methods - if type == 'exc' and '.' not in target and \ - 'exceptions.' + target in env.intersphinx_inventory: - target = 'exceptions.' + target - elif type in ('func', 'meth') and '.' not in target and \ - 'object.' + target in env.intersphinx_inventory: - target = 'object.' + target - if target not in env.intersphinx_inventory: - return None - type, proj, version, uri = env.intersphinx_inventory[target] - # print "Intersphinx hit:", target, uri + return + proj, version, uri = env.intersphinx_inventory[fulltype][target] newnode = nodes.reference('', '') - newnode['refuri'] = uri + '#' + target + newnode['refuri'] = uri newnode['reftitle'] = '(in %s v%s)' % (proj, version) newnode['class'] = 'external-xref' newnode.append(contnode) diff --git a/sphinx/ext/refcounting.py b/sphinx/ext/refcounting.py index cad9d7f1..1845cfab 100644 --- a/sphinx/ext/refcounting.py +++ b/sphinx/ext/refcounting.py @@ -69,7 +69,7 @@ class Refcounts(dict): def add_refcount_annotations(self, app, doctree): for node in doctree.traverse(addnodes.desc_content): par = node.parent - if par['desctype'] != 'cfunction': + if par['domain'] != 'c' or par['objtype'] != 'function': continue if not par[0].has_key('names') or not par[0]['names']: continue diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py index 249fb361..5ab97f40 100644 --- a/sphinx/ext/todo.py +++ b/sphinx/ext/todo.py @@ -34,9 +34,7 @@ class Todo(Directive): def run(self): env = self.state.document.settings.env - - targetid = "todo-%s" % env.index_num - env.index_num += 1 + targetid = 'index-%s' % env.new_serialno('index') targetnode = nodes.target('', '', ids=[targetid]) ad = make_admonition(todo_node, self.name, [_('Todo')], self.options, |
