summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2012-01-29 11:13:49 +0100
committerGeorg Brandl <georg@python.org>2012-01-29 11:13:49 +0100
commit413081a6c950798fefe3254fc4e70ed69eb7990a (patch)
tree64507be46d9ce16e9983c7f05025d1413b8f7822
parent6fc317cc28ac3ba1491521ecf3f42058cad6e6d1 (diff)
downloadsphinx-413081a6c950798fefe3254fc4e70ed69eb7990a.tar.gz
Closes #851: Recognize and warn about circular toctrees, instead of running into recursion errors.
-rw-r--r--CHANGES3
-rw-r--r--sphinx/environment.py28
2 files changed, 24 insertions, 7 deletions
diff --git a/CHANGES b/CHANGES
index 5fb0efb0..baff2755 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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):