diff options
| author | goodger <goodger@929543f6-e4f2-0310-98a6-ba3bd3dd1d04> | 2005-12-28 23:48:48 +0000 |
|---|---|---|
| committer | goodger <goodger@929543f6-e4f2-0310-98a6-ba3bd3dd1d04> | 2005-12-28 23:48:48 +0000 |
| commit | a4dc6c54aafa689141243e1e837dc2bc3b236939 (patch) | |
| tree | c4c6ea7309df89b448703233339ac003d112d150 /docutils/transforms | |
| parent | fd5c42c0f1b05949777718b6d033af521c5f3e70 (diff) | |
| download | docutils-a4dc6c54aafa689141243e1e837dc2bc3b236939.tar.gz | |
Fixed bug with circular substitution definitions that put Docutils into an infinite loop. Circular substitution definitions are now detected & reported.
git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@4233 929543f6-e4f2-0310-98a6-ba3bd3dd1d04
Diffstat (limited to 'docutils/transforms')
| -rw-r--r-- | docutils/transforms/references.py | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/docutils/transforms/references.py b/docutils/transforms/references.py index c3de8e3f1..c7e17b50e 100644 --- a/docutils/transforms/references.py +++ b/docutils/transforms/references.py @@ -625,6 +625,9 @@ class Footnotes(Transform): note.resolved = 1 +class CircularSubstitutionDefinitionError(Exception): pass + + class Substitutions(Transform): """ @@ -661,6 +664,7 @@ class Substitutions(Transform): defs = self.document.substitution_defs normed = self.document.substitution_names subreflist = self.document.traverse(nodes.substitution_reference) + nested = {} for ref in subreflist: refname = ref['refname'] key = None @@ -697,9 +701,37 @@ class Substitutions(Transform): parent.replace(parent[index + 1], parent[index + 1].lstrip()) subdef_copy = subdef.deepcopy() - # Take care of nested substitution references. - subreflist.extend(subdef_copy.traverse(nodes.substitution_reference)) - ref.replace_self(subdef_copy.children) + try: + # Take care of nested substitution references: + for nested_ref in subdef_copy.traverse( + nodes.substitution_reference): + nested_name = normed[nested_ref['refname'].lower()] + if nested_name in nested.setdefault(nested_name, []): + raise CircularSubstitutionDefinitionError + else: + nested[nested_name].append(key) + subreflist.append(nested_ref) + except CircularSubstitutionDefinitionError: + parent = ref.parent + if isinstance(parent, nodes.substitution_definition): + msg = self.document.reporter.error( + 'Circular substitution definition detected:', + nodes.literal_block(parent.rawsource, + parent.rawsource), + line=parent.line, base_node=parent) + parent.replace_self(msg) + else: + msg = self.document.reporter.error( + 'Circular substitution definition referenced: "%s".' + % refname, base_node=ref) + msgid = self.document.set_id(msg) + prb = nodes.problematic( + ref.rawsource, ref.rawsource, refid=msgid) + prbid = self.document.set_id(prb) + msg.add_backref(prbid) + ref.replace_self(prb) + else: + ref.replace_self(subdef_copy.children) class TargetNotes(Transform): |
