summaryrefslogtreecommitdiff
path: root/sphinx/environment.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/environment.py')
-rw-r--r--sphinx/environment.py171
1 files changed, 102 insertions, 69 deletions
diff --git a/sphinx/environment.py b/sphinx/environment.py
index fe4cba6bb..d28043326 100644
--- a/sphinx/environment.py
+++ b/sphinx/environment.py
@@ -205,8 +205,8 @@ class BuildEnvironment:
self.set_warnfunc(None)
values = self.config.values
del self.config.values
- # first write to a temporary file, so that if dumping fails, the existing
- # environment won't be overwritten
+ # first write to a temporary file, so that if dumping fails,
+ # the existing environment won't be overwritten
picklefile = open(filename + '.tmp', 'wb')
# remove potentially pickling-problematic values from config
for key, val in vars(self.config).items():
@@ -244,13 +244,14 @@ class BuildEnvironment:
# this is to invalidate old pickles
self.version = ENV_VERSION
- # All "docnames" here are /-separated and relative and exclude the source suffix.
+ # 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.dependencies = {} # docname -> set of dependent file
+ # names, relative to documentation root
# File metadata
self.metadata = {} # docname -> dict of metadata items
@@ -259,30 +260,34 @@ class BuildEnvironment:
self.titles = {} # docname -> title node
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)
+ # used to determine when to show the TOC
+ # in a sidebar (don't show if it's only one item)
+
self.toctree_includes = {} # docname -> list of toctree includefiles
- self.files_to_rebuild = {} # docname -> set of files (containing its TOCs)
- # to rebuild too
+ self.files_to_rebuild = {} # docname -> set of files
+ # (containing its TOCs) to rebuild too
self.glob_toctrees = set() # docnames that have :glob: toctrees
# X-ref target inventory
self.descrefs = {} # fullname -> docname, desctype
self.filemodules = {} # docname -> [modules]
- self.modules = {} # modname -> docname, synopsis, platform, deprecated
+ self.modules = {} # modname -> docname, synopsis,
+ # platform, deprecated
self.labels = {} # labelname -> docname, labelid, sectionname
self.anonlabels = {} # labelname -> docname, labelid
self.progoptions = {} # (program, name) -> docname, labelid
self.reftargets = {} # (type, name) -> docname, labelid
- # where type is term, token, envvar, citation
+ # type: term, token, envvar, citation
# Other inventories
self.indexentries = {} # docname -> list of
# (type, string, target, aliasname)
- self.versionchanges = {} # version -> list of
- # (type, docname, lineno, module, descname, content)
- self.images = FilenameUniqDict() # absolute path -> (docnames, unique filename)
- self.dlfiles = FilenameUniqDict() # absolute path -> (docnames, unique filename)
+ self.versionchanges = {} # version -> list of (type, docname,
+ # lineno, module, descname, content)
+
+ # these map absolute path -> (docnames, unique filename)
+ self.images = FilenameUniqDict()
+ self.dlfiles = FilenameUniqDict()
# These are set while parsing a file
self.docname = None # current document name
@@ -362,7 +367,8 @@ class BuildEnvironment:
"""
suffix = suffix or self.config.source_suffix
if base is True:
- return path.join(self.srcdir, docname.replace(SEP, path.sep)) + suffix
+ return path.join(self.srcdir,
+ docname.replace(SEP, path.sep)) + suffix
elif base is None:
return docname.replace(SEP, path.sep) + suffix
else:
@@ -375,8 +381,10 @@ class BuildEnvironment:
exclude_dirs = [d.replace(SEP, path.sep) for d in config.exclude_dirs]
exclude_trees = [d.replace(SEP, path.sep) for d in config.exclude_trees]
self.found_docs = set(get_matching_docs(
- self.srcdir, config.source_suffix, exclude_docs=set(config.unused_docs),
- exclude_dirs=exclude_dirs, exclude_trees=exclude_trees,
+ self.srcdir, config.source_suffix,
+ exclude_docs=set(config.unused_docs),
+ exclude_dirs=exclude_dirs,
+ exclude_trees=exclude_trees,
exclude_dirnames=['_sources'] + config.exclude_dirnames))
def get_outdated_files(self, config_changed):
@@ -428,16 +436,17 @@ class BuildEnvironment:
return added, changed, removed
def update(self, config, srcdir, doctreedir, app=None):
- """(Re-)read all files new or changed since last update. Yields a summary
- and then 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)."""
+ """(Re-)read all files new or changed since last update.
+ Yields a summary and then 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
+ # check if a config value was changed that affects how
+ # doctrees are read
for key, descr in config.config_values.iteritems():
if not descr[1]:
continue
@@ -577,7 +586,8 @@ class BuildEnvironment:
if save_parsed:
# save the parsed doctree
- doctree_filename = self.doc2path(docname, self.doctreedir, '.doctree')
+ doctree_filename = self.doc2path(docname, self.doctreedir,
+ '.doctree')
dirname = path.dirname(doctree_filename)
if not path.isdir(dirname):
os.makedirs(dirname)
@@ -638,7 +648,8 @@ class BuildEnvironment:
node['candidates'] = candidates = {}
imguri = node['uri']
if imguri.find('://') != -1:
- self.warn(docname, 'Nonlocal image URI found: %s' % imguri, node.line)
+ self.warn(docname, 'Nonlocal image URI found: %s' % imguri,
+ node.line)
candidates['?'] = imguri
continue
# imgpath is the image path *from srcdir*
@@ -660,7 +671,8 @@ class BuildEnvironment:
finally:
f.close()
except (OSError, IOError):
- self.warn(docname, 'Image file %s not readable' % filename)
+ self.warn(docname,
+ 'Image file %s not readable' % filename)
if imgtype:
candidates['image/' + imgtype] = new_imgpath
else:
@@ -725,7 +737,8 @@ class BuildEnvironment:
continue
if name in self.labels:
self.warn(docname, 'duplicate label %s, ' % name +
- 'other instance in %s' % self.doc2path(self.labels[name][0]),
+ 'other instance in ' +
+ self.doc2path(self.labels[name][0]),
node.line)
self.anonlabels[name] = docname, labelid
if node.tagname == 'section':
@@ -835,7 +848,8 @@ class BuildEnvironment:
if fullname in self.descrefs:
self.warn(self.docname,
'duplicate canonical description name %s, ' % fullname +
- 'other instance in %s' % self.doc2path(self.descrefs[fullname][0]),
+ 'other instance in ' +
+ self.doc2path(self.descrefs[fullname][0]),
line)
self.descrefs[fullname] = (self.docname, desctype)
@@ -851,7 +865,8 @@ class BuildEnvironment:
def note_versionchange(self, type, version, node, lineno):
self.versionchanges.setdefault(version, []).append(
- (type, self.docname, lineno, self.currmodule, self.currdesc, node.astext()))
+ (type, self.docname, lineno, self.currmodule, self.currdesc,
+ node.astext()))
def note_dependency(self, filename):
basename = path.dirname(self.doc2path(self.docname, base=None))
@@ -915,7 +930,8 @@ class BuildEnvironment:
def _walk_depth(node, depth, maxdepth, titleoverrides):
"""Utility: Cut a TOC at a specified depth."""
for subnode in node.children[:]:
- if isinstance(subnode, (addnodes.compact_paragraph, nodes.list_item)):
+ if isinstance(subnode, (addnodes.compact_paragraph,
+ nodes.list_item)):
subnode['classes'].append('toctree-l%d' % (depth-1))
_walk_depth(subnode, depth, maxdepth, titleoverrides)
elif isinstance(subnode, nodes.bullet_list):
@@ -934,27 +950,30 @@ class BuildEnvironment:
toc = self.tocs[includefile].deepcopy()
if not toc.children:
# empty toc means: no titles will show up in the toctree
- self.warn(docname, 'toctree contains reference to document '
- '%r that doesn\'t have a title: no link will be '
- 'generated' % includefile)
+ self.warn(docname,
+ 'toctree contains reference to document '
+ '%r that doesn\'t have a title: no link '
+ 'will be generated' % includefile)
except KeyError:
# this is raised if the included file does not exist
- self.warn(docname, 'toctree contains reference to nonexisting '
- 'document %r' % includefile)
+ self.warn(docname, 'toctree contains reference to '
+ 'nonexisting document %r' % includefile)
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
+ # 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:
- subtoctrees = toplevel.traverse(addnodes.toctree)
- toplevel[1][:] = subtoctrees
+ subtrees = toplevel.traverse(addnodes.toctree)
+ toplevel[1][:] = subtrees
# resolve all sub-toctrees
for toctreenode in toc.traverse(addnodes.toctree):
i = toctreenode.parent.index(toctreenode) + 1
- for item in _entries_from_toctree(toctreenode, subtree=True):
+ for item in _entries_from_toctree(toctreenode,
+ subtree=True):
toctreenode.parent.insert(i, item)
i += 1
toctreenode.parent.remove(toctreenode)
@@ -993,8 +1012,9 @@ class BuildEnvironment:
refnode.children = [nodes.Text(newtitle)]
return newnode
- descroles = frozenset(('data', 'exc', 'func', 'class', 'const', 'attr', 'obj',
- 'meth', 'cfunc', 'cmember', 'cdata', 'ctype', 'cmacro'))
+ descroles = frozenset(('data', 'exc', 'func', 'class', 'const',
+ 'attr', 'obj', 'meth', 'cfunc', 'cmember',
+ 'cdata', 'ctype', 'cmacro'))
def resolve_references(self, doctree, fromdocname, builder):
reftarget_roles = set(('token', 'term', 'citation'))
@@ -1011,30 +1031,32 @@ class BuildEnvironment:
try:
if typ == 'ref':
if node['refcaption']:
- # reference to anonymous label; the reference uses the supplied
- # link caption
+ # reference to anonymous label; the reference uses
+ # the supplied link caption
docname, labelid = self.anonlabels.get(target, ('',''))
sectname = node.astext()
if not docname:
newnode = doctree.reporter.system_message(
2, 'undefined label: %s' % target)
else:
- # reference to the named label; the final node will contain the
- # section name after the label
- docname, labelid, sectname = self.labels.get(target, ('','',''))
+ # reference to the named label; the final node will
+ # contain the section name after the label
+ docname, labelid, sectname = self.labels.get(target,
+ ('','',''))
if not docname:
newnode = doctree.reporter.system_message(
- 2, 'undefined label: %s -- if you don\'t ' % target +
- 'give a link caption the label must precede a section '
- 'header.')
+ 2, 'undefined label: %s' % target +
+ ' -- if you don\'t give a link caption '
+ 'the label must precede a section header.')
if docname:
newnode = nodes.reference('', '')
innernode = nodes.emphasis(sectname, sectname)
if docname == fromdocname:
newnode['refid'] = labelid
else:
- # set more info in contnode in case the get_relative_uri call
- # raises NoUri, the builder will then have to resolve these
+ # set more info in contnode; in case the
+ # get_relative_uri call raises NoUri,
+ # the builder will then have to resolve these
contnode = addnodes.pending_xref('')
contnode['refdocname'] = docname
contnode['refsectname'] = sectname
@@ -1044,8 +1066,8 @@ class BuildEnvironment:
newnode['refuri'] += '#' + labelid
newnode.append(innernode)
elif typ == 'doc':
- # directly reference to document by source name; can be absolute
- # or relative
+ # directly reference to document by source name;
+ # can be absolute or relative
docname = docname_join(fromdocname, target)
if docname not in self.all_docs:
newnode = doctree.reporter.system_message(
@@ -1077,7 +1099,8 @@ class BuildEnvironment:
newnode.append(contnode)
elif typ == 'option':
progname = node['refprogram']
- docname, labelid = self.progoptions.get((progname, target), ('', ''))
+ docname, labelid = self.progoptions.get((progname, target),
+ ('', ''))
if not docname:
newnode = contnode
else:
@@ -1089,13 +1112,16 @@ class BuildEnvironment:
fromdocname, docname) + '#' + labelid
newnode.append(contnode)
elif typ in reftarget_roles:
- docname, labelid = self.reftargets.get((typ, target), ('', ''))
+ docname, labelid = self.reftargets.get((typ, target),
+ ('', ''))
if not docname:
if typ == 'term':
- self.warn(fromdocname, 'term not in glossary: %s' % target,
+ self.warn(fromdocname,
+ 'term not in glossary: %s' % target,
node.line)
elif typ == 'citation':
- self.warn(fromdocname, 'citation not found: %s' % target,
+ self.warn(fromdocname,
+ 'citation not found: %s' % target,
node.line)
newnode = contnode
else:
@@ -1110,8 +1136,8 @@ class BuildEnvironment:
docname, synopsis, platform, deprecated = \
self.modules.get(target, ('','','', ''))
if not docname:
- newnode = builder.app.emit_firstresult('missing-reference',
- self, node, contnode)
+ newnode = builder.app.emit_firstresult(
+ 'missing-reference', self, node, contnode)
if not newnode:
newnode = contnode
elif docname == fromdocname:
@@ -1133,8 +1159,8 @@ class BuildEnvironment:
name, desc = self.find_desc(modname, clsname,
target, typ, searchorder)
if not desc:
- newnode = builder.app.emit_firstresult('missing-reference',
- self, node, contnode)
+ newnode = builder.app.emit_firstresult(
+ 'missing-reference', self, node, contnode)
if not newnode:
newnode = contnode
else:
@@ -1148,7 +1174,8 @@ class BuildEnvironment:
newnode['reftitle'] = name
newnode.append(contnode)
else:
- raise RuntimeError('unknown xfileref node encountered: %s' % node)
+ raise RuntimeError('unknown xfileref node encountered: %s'
+ % node)
except NoUri:
newnode = contnode
if newnode:
@@ -1232,8 +1259,10 @@ class BuildEnvironment:
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)
+ # 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)
@@ -1253,7 +1282,8 @@ class BuildEnvironment:
else:
# get all other symbols under one heading
return 'Symbols'
- return [(key, list(group)) for (key, group) in groupby(newlist, keyfunc)]
+ return [(key, list(group))
+ for (key, group) in groupby(newlist, keyfunc)]
def collect_relations(self):
relations = {}
@@ -1292,7 +1322,8 @@ class BuildEnvironment:
# else it will stay None
# same for children
if includes:
- for subindex, args in enumerate(izip(includes, [None] + includes,
+ for subindex, args in enumerate(izip(includes,
+ [None] + includes,
includes[1:] + [None])):
collect([(docname, subindex)] + parents, *args)
relations[docname] = [parents[0][0], previous, next]
@@ -1360,14 +1391,16 @@ class BuildEnvironment:
def find_keyword(self, keyword, avoid_fuzzy=False, cutoff=0.6, n=20):
"""
- Find keyword matches for a keyword. If there's an exact match, just return
- it, else return a list of fuzzy matches if avoid_fuzzy isn't True.
+ Find keyword matches for a keyword. If there's an exact match,
+ just return it, else return a list of fuzzy matches if avoid_fuzzy
+ isn't True.
Keywords searched are: first modules, then descrefs.
Returns: None if nothing found
(type, docname, anchorname) if exact match found
- list of (quality, type, docname, anchorname, description) if fuzzy
+ list of (quality, type, docname, anchorname, description)
+ if fuzzy
"""
if keyword in self.modules: