diff options
author | Georg Brandl <georg@python.org> | 2012-01-29 11:13:49 +0100 |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2012-01-29 11:13:49 +0100 |
commit | 413081a6c950798fefe3254fc4e70ed69eb7990a (patch) | |
tree | 64507be46d9ce16e9983c7f05025d1413b8f7822 | |
parent | 6fc317cc28ac3ba1491521ecf3f42058cad6e6d1 (diff) | |
download | sphinx-413081a6c950798fefe3254fc4e70ed69eb7990a.tar.gz |
Closes #851: Recognize and warn about circular toctrees, instead of running into recursion errors.
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | sphinx/environment.py | 28 |
2 files changed, 24 insertions, 7 deletions
@@ -24,6 +24,9 @@ Release 1.1.3 (in development) * #862: Fix handling of ``-D`` and ``-A`` options on Python 3. +* #851: Recognize and warn about circular toctrees, instead of running + into recursion errors. + Release 1.1.2 (Nov 1, 2011) -- 1.1.1 is a silly version number anyway! ====================================================================== diff --git a/sphinx/environment.py b/sphinx/environment.py index 9fd9ff89..6ea1e248 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -1313,12 +1313,14 @@ class BuildEnvironment: subnode['iscurrent'] = True subnode = subnode.parent - def _entries_from_toctree(toctreenode, separate=False, subtree=False): + def _entries_from_toctree(toctreenode, parents, + separate=False, subtree=False): """Return TOC entries for a toctree node.""" refs = [(e[0], str(e[1])) for e in toctreenode['entries']] entries = [] for (title, ref) in refs: try: + refdoc = None if url_re.match(ref): reference = nodes.reference('', '', internal=False, refuri=ref, anchorname='', @@ -1341,6 +1343,12 @@ class BuildEnvironment: # 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() self.process_only_nodes(toc, builder, ref) if title and toc.children and len(toc.children) == 1: @@ -1376,8 +1384,9 @@ class BuildEnvironment: if not (toctreenode.get('hidden', False) and not includehidden): i = toctreenode.parent.index(toctreenode) + 1 - for item in _entries_from_toctree(toctreenode, - subtree=True): + for item in _entries_from_toctree( + toctreenode, [refdoc] + parents, + subtree=True): toctreenode.parent.insert(i, item) i += 1 toctreenode.parent.remove(toctreenode) @@ -1398,7 +1407,7 @@ class BuildEnvironment: # 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) + tocentries = _entries_from_toctree(toctree, [], separate=False) if not tocentries: return None @@ -1686,7 +1695,11 @@ class BuildEnvironment: def collect_relations(self): relations = {} getinc = self.toctree_includes.get - def collect(parents, docname, previous, next): + 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: @@ -1723,9 +1736,10 @@ class BuildEnvironment: for subindex, args in enumerate(izip(includes, [None] + includes, includes[1:] + [None])): - collect([(docname, subindex)] + parents, *args) + collect([(docname, subindex)] + parents, + parents_set.union([docname]), *args) relations[docname] = [parents[0][0], previous, next] - collect([(None, 0)], self.config.master_doc, None, None) + collect([(None, 0)], set(), self.config.master_doc, None, None) return relations def check_consistency(self): |