Update of /cvs-repository/Zope/lib/python/docutils/transforms
In directory cvs.zope.org:/tmp/cvs-serv26422/transforms

Modified Files:
      Tag: Zope-2_7-branch
        __init__.py components.py frontmatter.py misc.py parts.py 
        peps.py references.py universal.py 
Log Message:
upgrade to docutils 0.3.9


=== Zope/lib/python/docutils/transforms/__init__.py 1.2.10.6 => 1.2.10.7 ===
--- Zope/lib/python/docutils/transforms/__init__.py:1.2.10.6    Fri Jan  7 
08:26:05 2005
+++ Zope/lib/python/docutils/transforms/__init__.py     Sun Oct  9 10:43:46 2005
@@ -59,7 +59,7 @@
         self.language = languages.get_language(
             document.settings.language_code)
         """Language module local to this document."""
-        
+
 
     def apply(self):
         """Override to apply the transform to the document tree."""
@@ -163,7 +163,6 @@
         decorated_list = [(f.priority, f) for f in unknown_reference_resolvers]
         decorated_list.sort()
         self.unknown_reference_resolvers.extend([f[1] for f in decorated_list])
-
 
     def apply_transforms(self):
         """Apply all of the stored transforms, in priority order."""


=== Zope/lib/python/docutils/transforms/components.py 1.2.10.6 => 1.2.10.7 ===


=== Zope/lib/python/docutils/transforms/frontmatter.py 1.2.10.6 => 1.2.10.7 ===
--- Zope/lib/python/docutils/transforms/frontmatter.py:1.2.10.6 Fri Jan  7 
08:26:06 2005
+++ Zope/lib/python/docutils/transforms/frontmatter.py  Sun Oct  9 10:43:46 2005
@@ -5,13 +5,15 @@
 # Copyright: This module has been placed in the public domain.
 
 """
-Transforms related to the front matter of a document (information
-found before the main text):
+Transforms related to the front matter of a document or a section
+(information found before the main text):
 
 - `DocTitle`: Used to transform a lone top level section's title to
   the document title, and promote a remaining lone top-level section's
   title to the document subtitle.
 
+- `SectionTitle`: Used to transform a lone subsection into a subtitle.
+
 - `DocInfo`: Used to transform a bibliographic field list into docinfo
   elements.
 """
@@ -23,7 +25,100 @@
 from docutils.transforms import TransformError, Transform
 
 
-class DocTitle(Transform):
+class TitlePromoter(Transform):
+
+    """
+    Abstract base class for DocTitle and SectionSubTitle transforms.
+    """
+
+    def promote_title(self, node):
+        """
+        Transform the following tree::
+
+            <node>
+                <section>
+                    <title>
+                    ...
+
+        into ::
+
+            <node>
+                <title>
+                ...
+
+        `node` is normally a document.
+        """
+        # `node` must not have a title yet.
+        assert not (len(node) and isinstance(node[0], nodes.title))
+        section, index = self.candidate_index(node)
+        if index is None:
+            return None
+        # Transfer the section's attributes to the node:
+        node.attributes.update(section.attributes)
+        # setup_child is called automatically for all nodes.
+        node[:] = (section[:1]        # section title
+                   + node[:index]     # everything that was in the
+                                      # node before the section
+                   + section[1:])     # everything that was in the section
+        assert isinstance(node[0], nodes.title)
+        return 1
+
+    def promote_subtitle(self, node):
+        """
+        Transform the following node tree::
+
+            <node>
+                <title>
+                <section>
+                    <title>
+                    ...
+
+        into ::
+
+            <node>
+                <title>
+                <subtitle>
+                ...
+        """
+        subsection, index = self.candidate_index(node)
+        if index is None:
+            return None
+        subtitle = nodes.subtitle()
+        # Transfer the subsection's attributes to the new subtitle:
+        # This causes trouble with list attributes!  To do: Write a
+        # test case which catches direct access to the `attributes`
+        # dictionary and/or write a test case which shows problems in
+        # this particular case.
+        subtitle.attributes.update(subsection.attributes)
+        # We're losing the subtitle's attributes here!  To do: Write a
+        # test case which shows this behavior.
+        # Transfer the contents of the subsection's title to the
+        # subtitle:
+        subtitle[:] = subsection[0][:]
+        node[:] = (node[:1]       # title
+                   + [subtitle]
+                   # everything that was before the section:
+                   + node[1:index]
+                   # everything that was in the subsection:
+                   + subsection[1:])
+        return 1
+
+    def candidate_index(self, node):
+        """
+        Find and return the promotion candidate and its index.
+
+        Return (None, None) if no valid candidate was found.
+        """
+        index = node.first_child_not_matching_class(
+            nodes.PreBibliographic)
+        if index is None or len(node) > (index + 1) or \
+               not isinstance(node[index], nodes.section):
+            return None, None
+        else:
+            return node[index], index
+
+
+class DocTitle(TitlePromoter):
 
     """
     In reStructuredText_, there is no way to specify a document title
@@ -50,7 +145,7 @@
        Once parsed, it looks like this::
 
            <document>
-               <section name="top-level title">
+               <section names="top-level title">
                    <title>
                        Top-Level Title
                    <paragraph>
@@ -58,7 +153,7 @@
 
        After running the DocTitle transform, we have::
 
-           <document name="top-level title">
+           <document names="top-level title">
                <title>
                    Top-Level Title
                <paragraph>
@@ -85,10 +180,10 @@
        After parsing and running the Section Promotion transform, the
        result is::
 
-           <document name="top-level title">
+           <document names="top-level title">
                <title>
                    Top-Level Title
-               <subtitle name="second-level title">
+               <subtitle names="second-level title">
                    Second-Level Title
                <paragraph>
                    A paragraph.
@@ -107,54 +202,47 @@
     def apply(self):
         if not getattr(self.document.settings, 'doctitle_xform', 1):
             return
-        if self.promote_document_title():
-            self.promote_document_subtitle()
+        if self.promote_title(self.document):
+            self.promote_subtitle(self.document)
 
-    def promote_document_title(self):
-        section, index = self.candidate_index()
-        if index is None:
-            return None
-        document = self.document
-        # Transfer the section's attributes to the document element (at root):
-        document.attributes.update(section.attributes)
-        document[:] = (section[:1]        # section title
-                       + document[:index] # everything that was in the
-                                          # document before the section
-                       + section[1:])     # everything that was in the section
-        return 1
 
-    def promote_document_subtitle(self):
-        subsection, index = self.candidate_index()
-        if index is None:
-            return None
-        subtitle = nodes.subtitle()
-        # Transfer the subsection's attributes to the new subtitle:
-        subtitle.attributes.update(subsection.attributes)
-        # Transfer the contents of the subsection's title to the subtitle:
-        subtitle[:] = subsection[0][:]
-        document = self.document
-        document[:] = (document[:1]       # document title
-                       + [subtitle]
-                       # everything that was before the section:
-                       + document[1:index]
-                       # everything that was in the subsection:
-                       + subsection[1:])
-        return 1
+class SectionSubTitle(TitlePromoter):
 
-    def candidate_index(self):
-        """
-        Find and return the promotion candidate and its index.
+    """
+    This works like document subtitles, but for sections.  For example, ::
 
-        Return (None, None) if no valid candidate was found.
-        """
-        document = self.document
-        index = document.first_child_not_matching_class(
-              nodes.PreBibliographic)
-        if index is None or len(document) > (index + 1) or \
-              not isinstance(document[index], nodes.section):
-            return None, None
-        else:
-            return document[index], index
+        <section>
+            <title>
+                Title
+            <section>
+                <title>
+                    Subtitle
+                ...
+
+    is transformed into ::
+
+        <section>
+            <title>
+                Title
+            <subtitle>
+                Subtitle
+            ...
+
+    For details refer to the docstring of DocTitle.
+    """
+
+    default_priority = 350
+
+    def apply(self):
+        if not getattr(self.document.settings, 'sectsubtitle_xform', 1):
+            return
+        for section in self.document.traverse(lambda n:
+                                              isinstance(n, nodes.section)):
+            # On our way through the node tree, we are deleting
+            # sections, but we call self.promote_subtitle for those
+            # sections nonetheless.  To do: Write a test case which
+            # shows the problem and discuss on Docutils-develop.
+            self.promote_subtitle(section)
 
 
 class DocInfo(Transform):
@@ -258,11 +346,10 @@
         candidate = document[index]
         if isinstance(candidate, nodes.field_list):
             biblioindex = document.first_child_not_matching_class(
-                  nodes.Titular)
+                  (nodes.Titular, nodes.Decorative))
             nodelist = self.extract_bibliographic(candidate)
             del document[index]         # untransformed field list (candidate)
             document[biblioindex:biblioindex] = nodelist
-        return
 
     def extract_bibliographic(self, field_list):
         docinfo = nodes.docinfo()
@@ -294,7 +381,7 @@
                         raise TransformError
                     title = nodes.title(name, labels[canonical])
                     topics[canonical] = biblioclass(
-                        '', title, CLASS=canonical, *field[1].children)
+                        '', title, classes=[canonical], *field[1].children)
                 else:
                     docinfo.append(biblioclass('', *field[1].children))
             except TransformError:


=== Zope/lib/python/docutils/transforms/misc.py 1.2.10.6 => 1.2.10.7 ===
--- Zope/lib/python/docutils/transforms/misc.py:1.2.10.6        Fri Jan  7 
08:26:06 2005
+++ Zope/lib/python/docutils/transforms/misc.py Sun Oct  9 10:43:46 2005
@@ -45,7 +45,6 @@
 
     def apply(self):
         pending = self.startnode
-        class_value = pending.details['class']
         parent = pending.parent
         child = pending
         while parent:
@@ -55,7 +54,7 @@
                 if (isinstance(element, nodes.Invisible) or
                     isinstance(element, nodes.system_message)):
                     continue
-                element.set_class(class_value)
+                element['classes'] += pending.details['class']
                 pending.parent.remove(pending)
                 return
             else:


=== Zope/lib/python/docutils/transforms/parts.py 1.2.10.6 => 1.2.10.7 ===
--- Zope/lib/python/docutils/transforms/parts.py:1.2.10.6       Fri Jan  7 
08:26:06 2005
+++ Zope/lib/python/docutils/transforms/parts.py        Sun Oct  9 10:43:46 2005
@@ -54,7 +54,7 @@
                 generated = nodes.generated(
                     '', (self.prefix + '.'.join(numbers) + self.suffix
                          +  u'\u00a0' * 3),
-                    CLASS='sectnum')
+                    classes=['sectnum'])
                 title.insert(0, generated)
                 title['auto'] = 1
                 if depth < self.maxdepth:
@@ -84,14 +84,13 @@
         details = self.startnode.details
         if details.has_key('local'):
             startnode = self.startnode.parent.parent
-            # @@@ generate an error if the startnode (directive) not at
-            # section/document top-level? Drag it up until it is?
-            while not isinstance(startnode, nodes.Structural):
+            while not (isinstance(startnode, nodes.section)
+                       or isinstance(startnode, nodes.document)):
+                # find the ToC root: a direct ancestor of startnode
                 startnode = startnode.parent
         else:
             startnode = self.document
-
-        self.toc_id = self.startnode.parent['id']
+        self.toc_id = self.startnode.parent['ids'][0]
         if details.has_key('backlinks'):
             self.backlinks = details['backlinks']
         else:
@@ -117,15 +116,17 @@
             title = section[0]
             auto = title.get('auto')    # May be set by SectNum.
             entrytext = self.copy_and_filter(title)
-            reference = nodes.reference('', '', refid=section['id'],
+            reference = nodes.reference('', '', refid=section['ids'][0],
                                         *entrytext)
             ref_id = self.document.set_id(reference)
             entry = nodes.paragraph('', '', reference)
             item = nodes.list_item('', entry)
-            if self.backlinks == 'entry':
-                title['refid'] = ref_id
-            elif self.backlinks == 'top':
-                title['refid'] = self.toc_id
+            if (self.backlinks in ('entry', 'top') and title.next_node(
+                lambda n: isinstance(n, nodes.reference)) is None):
+                if self.backlinks == 'entry':
+                    title['refid'] = ref_id
+                elif self.backlinks == 'top':
+                    title['refid'] = self.toc_id
             if level < depth:
                 subsects = self.build_contents(section, level)
                 item += subsects
@@ -133,7 +134,7 @@
         if entries:
             contents = nodes.bullet_list('', *entries)
             if auto:
-                contents.set_class('auto-toc')
+                contents['classes'].append('auto-toc')
             return contents
         else:
             return []
@@ -148,7 +149,7 @@
 class ContentsFilter(nodes.TreeCopyVisitor):
 
     def get_entry_text(self):
-        return self.get_tree_copy().get_children()
+        return self.get_tree_copy().children
 
     def visit_citation_reference(self, node):
         raise nodes.SkipNode


=== Zope/lib/python/docutils/transforms/peps.py 1.2.10.7 => 1.2.10.8 ===
--- Zope/lib/python/docutils/transforms/peps.py:1.2.10.7        Fri Jan  7 
08:26:06 2005
+++ Zope/lib/python/docutils/transforms/peps.py Sun Oct  9 10:43:46 2005
@@ -46,7 +46,7 @@
             raise DataError('Document tree is empty.')
         header = self.document[0]
         if not isinstance(header, nodes.field_list) or \
-              header.get('class') != 'rfc2822':
+              'rfc2822' not in header['classes']:
             raise DataError('Document does not begin with an RFC-2822 '
                             'header; it is not a PEP.')
         pep = None
@@ -149,10 +149,10 @@
         language = languages.get_language(self.document.settings.language_code)
         name = language.labels['contents']
         title = nodes.title('', name)
-        topic = nodes.topic('', title, CLASS='contents')
+        topic = nodes.topic('', title, classes=['contents'])
         name = nodes.fully_normalize_name(name)
         if not self.document.has_name(name):
-            topic['name'] = name
+            topic['names'].append(name)
         self.document.note_implicit_target(topic)
         pending = nodes.pending(parts.Contents)
         topic += pending
@@ -244,7 +244,7 @@
         node.parent.replace(node, mask_email(node))
 
     def visit_field_list(self, node):
-        if node.hasattr('class') and node['class'] == 'rfc2822':
+        if 'rfc2822' in node['classes']:
             raise nodes.SkipNode
 
     def visit_tgroup(self, node):
@@ -254,7 +254,7 @@
     def visit_colspec(self, node):
         self.entry += 1
         if self.pep_table and self.entry == 2:
-            node['class'] = 'num'
+            node['classes'].append('num')
 
     def visit_row(self, node):
         self.entry = 0
@@ -262,7 +262,7 @@
     def visit_entry(self, node):
         self.entry += 1
         if self.pep_table and self.entry == 2 and len(node) == 1:
-            node['class'] = 'num'
+            node['classes'].append('num')
             p = node[0]
             if isinstance(p, nodes.paragraph) and len(p) == 1:
                 text = p.astext()


=== Zope/lib/python/docutils/transforms/references.py 1.2.10.6 => 1.2.10.7 ===
--- Zope/lib/python/docutils/transforms/references.py:1.2.10.6  Fri Jan  7 
08:26:06 2005
+++ Zope/lib/python/docutils/transforms/references.py   Sun Oct  9 10:43:46 2005
@@ -16,87 +16,75 @@
 from docutils.transforms import TransformError, Transform
 
 
-indices = xrange(sys.maxint)
-
-
-class ChainedTargets(Transform):
+class PropagateTargets(Transform):
 
     """
-    Attributes "refuri" and "refname" are migrated from the final direct
-    target up the chain of contiguous adjacent internal targets, using
-    `ChainedTargetResolver`.
-    """
-
-    default_priority = 420
-
-    def apply(self):
-        visitor = ChainedTargetResolver(self.document)
-        self.document.walk(visitor)
-
+    Propagate empty internal targets to the next element.
 
-class ChainedTargetResolver(nodes.SparseNodeVisitor):
+    Given the following nodes::
 
-    """
-    Copy reference attributes up the length of a hyperlink target chain.
-
-    "Chained targets" are multiple adjacent internal hyperlink targets which
-    "point to" an external or indirect target.  After the transform, all
-    chained targets will effectively point to the same place.
-
-    Given the following ``document`` as input::
-
-        <document>
-            <target id="a" name="a">
-            <target id="b" name="b">
-            <target id="c" name="c" refuri="http://chained.external.targets";>
-            <target id="d" name="d">
-            <paragraph>
-                I'm known as "d".
-            <target id="e" name="e">
-            <target id="id1">
-            <target id="f" name="f" refname="d">
+        <target ids="internal1" names="internal1">
+        <target anonymous="1" ids="id1">
+        <target ids="internal2" names="internal2">
+        <paragraph>
+            This is a test.
 
-    ``ChainedTargetResolver(document).walk()`` will transform the above into::
+    PropagateTargets propagates the ids and names of the internal
+    targets preceding the paragraph to the paragraph itself::
 
-        <document>
-            <target id="a" name="a" refuri="http://chained.external.targets";>
-            <target id="b" name="b" refuri="http://chained.external.targets";>
-            <target id="c" name="c" refuri="http://chained.external.targets";>
-            <target id="d" name="d">
-            <paragraph>
-                I'm known as "d".
-            <target id="e" name="e" refname="d">
-            <target id="id1" refname="d">
-            <target id="f" name="f" refname="d">
+        <target refid="internal1">
+        <target anonymous="1" refid="id1">
+        <target refid="internal2">
+        <paragraph ids="internal2 id1 internal1" names="internal2 internal1">
+            This is a test.
     """
 
-    def unknown_visit(self, node):
-        pass
+    default_priority = 260
 
-    def visit_target(self, node):
-        if node.hasattr('refuri'):
-            attname = 'refuri'
-            call_if_named = self.document.note_external_target
-        elif node.hasattr('refname'):
-            attname = 'refname'
-            call_if_named = self.document.note_indirect_target
-        elif node.hasattr('refid'):
-            attname = 'refid'
-            call_if_named = None
-        else:
-            return
-        attval = node[attname]
-        index = node.parent.index(node)
-        for i in range(index - 1, -1, -1):
-            sibling = node.parent[i]
-            if not isinstance(sibling, nodes.target) \
-                  or sibling.hasattr('refuri') \
-                  or sibling.hasattr('refname') \
-                  or sibling.hasattr('refid'):
-                break
-            sibling[attname] = attval
-            if sibling.hasattr('name') and call_if_named:
-                call_if_named(sibling)
+    def apply(self):
+        for target in self.document.internal_targets:
+            if not (len(target) == 0 and
+                    not (target.attributes.has_key('refid') or
+                         target.attributes.has_key('refuri') or
+                         target.attributes.has_key('refname'))):
+                continue
+            next_node = target.next_node(ascend=1)
+            # Do not move names and ids into Invisibles (we'd lose the
+            # attributes) or different Targetables (e.g. footnotes).
+            if (next_node is not None and
+                ((not isinstance(next_node, nodes.Invisible) and
+                  not isinstance(next_node, nodes.Targetable)) or
+                 isinstance(next_node, nodes.target))):
+                next_node['ids'].extend(target['ids'])
+                next_node['names'].extend(target['names'])
+                # Set defaults for next_node.expect_referenced_by_name/id.
+                if not hasattr(next_node, 'expect_referenced_by_name'):
+                    next_node.expect_referenced_by_name = {}
+                if not hasattr(next_node, 'expect_referenced_by_id'):
+                    next_node.expect_referenced_by_id = {}
+                for id in target['ids']:
+                    # Update IDs to node mapping.
+                    self.document.ids[id] = next_node
+                    # If next_node is referenced by id ``id``, this
+                    # target shall be marked as referenced.
+                    next_node.expect_referenced_by_id[id] = target
+                for name in target['names']:
+                    next_node.expect_referenced_by_name[name] = target
+                # If there are any expect_referenced_by_... attributes
+                # in target set, copy them to next_node.
+                next_node.expect_referenced_by_name.update(
+                    getattr(target, 'expect_referenced_by_name', {}))
+                next_node.expect_referenced_by_id.update(
+                    getattr(target, 'expect_referenced_by_id', {}))
+                # Set refid to point to the first former ID of target
+                # which is now an ID of next_node.
+                target['refid'] = target['ids'][0]
+                # Clear ids and names; they have been moved to
+                # next_node.
+                target['ids'] = []
+                target['names'] = []
+                self.document.note_refid(target)
+                self.document.note_internal_target(next_node)
 
 
 class AnonymousHyperlinks(Transform):
@@ -109,8 +97,8 @@
                 internal
             <reference anonymous="1">
                 external
-        <target anonymous="1" id="id1">
-        <target anonymous="1" id="id2" refuri="http://external";>
+        <target anonymous="1" ids="id1">
+        <target anonymous="1" ids="id2" refuri="http://external";>
 
     Corresponding references are linked via "refid" or resolved via "refuri"::
 
@@ -119,8 +107,8 @@
                 text
             <reference anonymous="1" refuri="http://external";>
                 external
-        <target anonymous="1" id="id1">
-        <target anonymous="1" id="id2" refuri="http://external";>
+        <target anonymous="1" ids="id1">
+        <target anonymous="1" ids="id2" refuri="http://external";>
     """
 
     default_priority = 440
@@ -140,16 +128,28 @@
                 prbid = self.document.set_id(prb)
                 msg.add_backref(prbid)
                 ref.parent.replace(ref, prb)
+            for target in self.document.anonymous_targets:
+                # Assume that all anonymous targets have been
+                # referenced to avoid generating lots of
+                # system_messages.
+                target.referenced = 1
             return
         for ref, target in zip(self.document.anonymous_refs,
                                self.document.anonymous_targets):
-            if target.hasattr('refuri'):
-                ref['refuri'] = target['refuri']
-                ref.resolved = 1
-            else:
-                ref['refid'] = target['id']
-                self.document.note_refid(ref)
             target.referenced = 1
+            while 1:
+                if target.hasattr('refuri'):
+                    ref['refuri'] = target['refuri']
+                    ref.resolved = 1
+                    break
+                else:
+                    if not target['ids']:
+                        # Propagated target.
+                        target = self.document.ids[target['refid']]
+                        continue
+                    ref['refid'] = target['ids'][0]
+                    self.document.note_refid(ref)
+                    break
 
 
 class IndirectHyperlinks(Transform):
@@ -213,20 +213,24 @@
             self.resolve_indirect_references(target)
 
     def resolve_indirect_target(self, target):
-        refname = target['refname']
-        reftarget_id = self.document.nameids.get(refname)
-        if not reftarget_id:
-            # Check the unknown_reference_resolvers
-            for resolver_function in (self.document.transformer
-                                      .unknown_reference_resolvers):
-                if resolver_function(target):
-                    break
-            else:
-                self.nonexistent_indirect_target(target)
-            return
+        refname = target.get('refname')
+        if refname is None:
+            reftarget_id = target['refid']
+        else:
+            reftarget_id = self.document.nameids.get(refname)
+            if not reftarget_id:
+                # Check the unknown_reference_resolvers
+                for resolver_function in \
+                        self.document.transformer.unknown_reference_resolvers:
+                    if resolver_function(target):
+                        break
+                else:
+                    self.nonexistent_indirect_target(target)
+                return
         reftarget = self.document.ids[reftarget_id]
+        reftarget.note_referenced_by(id=reftarget_id)
         if isinstance(reftarget, nodes.target) \
-              and not reftarget.resolved and reftarget.hasattr('refname'):
+               and not reftarget.resolved and reftarget.hasattr('refname'):
             if hasattr(target, 'multiply_indirect'):
                 #and target.multiply_indirect):
                 #del target.multiply_indirect
@@ -237,21 +241,23 @@
             del target.multiply_indirect
         if reftarget.hasattr('refuri'):
             target['refuri'] = reftarget['refuri']
-            if target.hasattr('name'):
+            if target['names']:
                 self.document.note_external_target(target)
+            if target.has_key('refid'):
+                del target['refid']
         elif reftarget.hasattr('refid'):
             target['refid'] = reftarget['refid']
             self.document.note_refid(target)
         else:
-            try:
-                target['refid'] = reftarget['id']
+            if reftarget['ids']:
+                target['refid'] = reftarget_id
                 self.document.note_refid(target)
-            except KeyError:
+            else:
                 self.nonexistent_indirect_target(target)
                 return
-        del target['refname']
+        if refname is not None:
+            del target['refname']
         target.resolved = 1
-        reftarget.referenced = 1
 
     def nonexistent_indirect_target(self, target):
         if self.document.nameids.has_key(target['refname']):
@@ -265,18 +271,19 @@
 
     def indirect_target_error(self, target, explanation):
         naming = ''
-        if target.hasattr('name'):
-            naming = '"%s" ' % target['name']
-            reflist = self.document.refnames.get(target['name'], [])
-        else:
-            reflist = self.document.refids.get(target['id'], [])
-        naming += '(id="%s")' % target['id']
+        reflist = []
+        if target['names']:
+            naming = '"%s" ' % target['names'][0]
+        for name in target['names']:
+            reflist.extend(self.document.refnames.get(name, []))
+        for id in target['ids']:
+            reflist.extend(self.document.refids.get(id, []))
+        naming += '(id="%s")' % target['ids'][0]
         msg = self.document.reporter.error(
               'Indirect hyperlink target %s refers to target "%s", %s.'
-              % (naming, target['refname'], explanation),
-              base_node=target)
+              % (naming, target['refname'], explanation), base_node=target)
         msgid = self.document.set_id(msg)
-        for ref in reflist:
+        for ref in uniq(reflist):
             prb = nodes.problematic(
                   ref.rawsource, ref.rawsource, refid=msgid)
             prbid = self.document.set_id(prb)
@@ -296,43 +303,34 @@
         else:
             return
         attval = target[attname]
-        if target.hasattr('name'):
-            name = target['name']
-            try:
-                reflist = self.document.refnames[name]
-            except KeyError, instance:
-                if target.referenced:
-                    return
-                msg = self.document.reporter.info(
-                      'Indirect hyperlink target "%s" is not referenced.'
-                      % name, base_node=target)
-                target.referenced = 1
-                return
-            delatt = 'refname'
-        else:
-            id = target['id']
-            try:
-                reflist = self.document.refids[id]
-            except KeyError, instance:
-                if target.referenced:
-                    return
-                msg = self.document.reporter.info(
-                      'Indirect hyperlink target id="%s" is not referenced.'
-                      % id, base_node=target)
-                target.referenced = 1
-                return
-            delatt = 'refid'
-        for ref in reflist:
-            if ref.resolved:
-                continue
-            del ref[delatt]
-            ref[attname] = attval
-            if not call_if_named or ref.hasattr('name'):
-                call_method(ref)
-            ref.resolved = 1
-            if isinstance(ref, nodes.target):
-                self.resolve_indirect_references(ref)
-        target.referenced = 1
+        for name in target['names']:
+            reflist = self.document.refnames.get(name, [])
+            if reflist:
+                target.note_referenced_by(name=name)
+            for ref in reflist:
+                if ref.resolved:
+                    continue
+                del ref['refname']
+                ref[attname] = attval
+                if not call_if_named or ref['names']:
+                    call_method(ref)
+                ref.resolved = 1
+                if isinstance(ref, nodes.target):
+                    self.resolve_indirect_references(ref)
+        for id in target['ids']:
+            reflist = self.document.refids.get(id, [])
+            if reflist:
+                target.note_referenced_by(id=id)
+            for ref in reflist:
+                if ref.resolved:
+                    continue
+                del ref['refid']
+                ref[attname] = attval
+                if not call_if_named or ref['names']:
+                    call_method(ref)
+                ref.resolved = 1
+                if isinstance(ref, nodes.target):
+                    self.resolve_indirect_references(ref)
 
 
 class ExternalTargets(Transform):
@@ -357,74 +355,59 @@
 
     def apply(self):
         for target in self.document.external_targets:
-            if target.hasattr('refuri') and target.hasattr('name'):
-                name = target['name']
+            if target.hasattr('refuri'):
                 refuri = target['refuri']
-                try:
-                    reflist = self.document.refnames[name]
-                except KeyError, instance:
-                    # @@@ First clause correct???
-                    if not isinstance(target, nodes.target) or 
target.referenced:
-                        continue
-                    msg = self.document.reporter.info(
-                          'External hyperlink target "%s" is not referenced.'
-                          % name, base_node=target)
-                    target.referenced = 1
-                    continue
-                for ref in reflist:
-                    if ref.resolved:
-                        continue
-                    del ref['refname']
-                    ref['refuri'] = refuri
-                    ref.resolved = 1
-                target.referenced = 1
+                for name in target['names']:
+                    reflist = self.document.refnames.get(name, [])
+                    if reflist:
+                        target.note_referenced_by(name=name)
+                    for ref in reflist:
+                        if ref.resolved:
+                            continue
+                        del ref['refname']
+                        ref['refuri'] = refuri
+                        ref.resolved = 1
 
 
 class InternalTargets(Transform):
 
-    """
-    Given::
+    default_priority = 660
 
-        <paragraph>
-            <reference refname="direct internal">
-                direct internal
-        <target id="id1" name="direct internal">
+    def apply(self):
+        for target in self.document.internal_targets:
+            self.resolve_reference_ids(target)
 
-    The "refname" attribute is replaced by "refid" linking to the target's
-    "id"::
+    def resolve_reference_ids(self, target):
+        """
+        Given::
 
-        <paragraph>
-            <reference refid="id1">
-                direct internal
-        <target id="id1" name="direct internal">
-    """
+            <paragraph>
+                <reference refname="direct internal">
+                    direct internal
+            <target id="id1" name="direct internal">
 
-    default_priority = 660
+        The "refname" attribute is replaced by "refid" linking to the target's
+        "id"::
 
-    def apply(self):
-        for target in self.document.internal_targets:
-            if target.hasattr('refuri') or target.hasattr('refid') \
-                  or not target.hasattr('name'):
-                continue
-            name = target['name']
-            refid = target['id']
-            try:
-                reflist = self.document.refnames[name]
-            except KeyError, instance:
-                if target.referenced:
-                    continue
-                msg = self.document.reporter.info(
-                      'Internal hyperlink target "%s" is not referenced.'
-                      % name, base_node=target)
-                target.referenced = 1
-                continue
+            <paragraph>
+                <reference refid="id1">
+                    direct internal
+            <target id="id1" name="direct internal">
+        """
+        if target.hasattr('refuri') or target.hasattr('refid') \
+              or not target['names']:
+            return
+        for name in target['names']:
+            refid = self.document.nameids[name]
+            reflist = self.document.refnames.get(name, [])
+            if reflist:
+                target.note_referenced_by(name=name)
             for ref in reflist:
                 if ref.resolved:
                     continue
                 del ref['refname']
                 ref['refid'] = refid
                 ref.resolved = 1
-            target.referenced = 1
 
 
 class Footnotes(Transform):
@@ -532,19 +515,17 @@
                 if not self.document.nameids.has_key(label):
                     break
             footnote.insert(0, nodes.label('', label))
-            if footnote.hasattr('dupname'):
-                continue
-            if footnote.hasattr('name'):
-                name = footnote['name']
+            for name in footnote['names']:
                 for ref in self.document.footnote_refs.get(name, []):
                     ref += nodes.Text(label)
                     ref.delattr('refname')
-                    ref['refid'] = footnote['id']
-                    footnote.add_backref(ref['id'])
+                    assert len(footnote['ids']) == len(ref['ids']) == 1
+                    ref['refid'] = footnote['ids'][0]
+                    footnote.add_backref(ref['ids'][0])
                     self.document.note_refid(ref)
                     ref.resolved = 1
-            else:
-                footnote['name'] = label
+            if not footnote['names'] and not footnote['dupnames']:
+                footnote['names'].append(label)
                 self.document.note_explicit_target(footnote, footnote)
                 self.autofootnote_labels.append(label)
         return startnum
@@ -577,7 +558,8 @@
             footnote = self.document.ids[id]
             ref['refid'] = id
             self.document.note_refid(ref)
-            footnote.add_backref(ref['id'])
+            assert len(ref['ids']) == 1
+            footnote.add_backref(ref['ids'][0])
             ref.resolved = 1
             i += 1
 
@@ -612,9 +594,10 @@
                     ref.parent.replace(ref, prb)
                 break
             footnote = self.document.symbol_footnotes[i]
-            ref['refid'] = footnote['id']
+            assert len(footnote['ids']) == 1
+            ref['refid'] = footnote['ids'][0]
             self.document.note_refid(ref)
-            footnote.add_backref(ref['id'])
+            footnote.add_backref(ref['ids'][0])
             i += 1
 
     def resolve_footnotes_and_citations(self):
@@ -623,24 +606,26 @@
         references.
         """
         for footnote in self.document.footnotes:
-            label = footnote['name']
-            if self.document.footnote_refs.has_key(label):
-                reflist = self.document.footnote_refs[label]
-                self.resolve_references(footnote, reflist)
+            for label in footnote['names']:
+                if self.document.footnote_refs.has_key(label):
+                    reflist = self.document.footnote_refs[label]
+                    self.resolve_references(footnote, reflist)
         for citation in self.document.citations:
-            label = citation['name']
-            if self.document.citation_refs.has_key(label):
-                reflist = self.document.citation_refs[label]
-                self.resolve_references(citation, reflist)
+            for label in citation['names']:
+                if self.document.citation_refs.has_key(label):
+                    reflist = self.document.citation_refs[label]
+                    self.resolve_references(citation, reflist)
 
     def resolve_references(self, note, reflist):
-        id = note['id']
+        assert len(note['ids']) == 1
+        id = note['ids'][0]
         for ref in reflist:
             if ref.resolved:
                 continue
             ref.delattr('refname')
             ref['refid'] = id
-            note.add_backref(ref['id'])
+            assert len(ref['ids']) == 1
+            note.add_backref(ref['ids'][0])
             ref.resolved = 1
         note.resolved = 1
 
@@ -680,7 +665,9 @@
     def apply(self):
         defs = self.document.substitution_defs
         normed = self.document.substitution_names
-        for refname, refs in self.document.substitution_refs.items():
+        subreflist = self.document.substitution_refs.items()
+        subreflist.sort()
+        for refname, refs in subreflist:
             for ref in refs:
                 key = None
                 if defs.has_key(refname):
@@ -715,7 +702,7 @@
                              and isinstance(parent[index + 1], nodes.Text)):
                             parent.replace(parent[index + 1],
                                            parent[index + 1].lstrip())
-                    parent.replace(ref, subdef.get_children())
+                    parent.replace(ref, subdef.children)
         self.document.substitution_refs = None  # release replaced references
 
 
@@ -734,11 +721,12 @@
         notes = {}
         nodelist = []
         for target in self.document.external_targets:
-            name = target.get('name')
-            if not name:
-                print >>sys.stderr, 'no name on target: %r' % target
-                continue
-            refs = self.document.refnames.get(name, [])
+            names = target['names']
+            # Only named targets.
+            assert names
+            refs = []
+            for name in names:
+                refs.extend(self.document.refnames.get(name, []))
             if not refs:
                 continue
             footnote = self.make_target_footnote(target, refs, notes)
@@ -760,14 +748,16 @@
         refuri = target['refuri']
         if notes.has_key(refuri):  # duplicate?
             footnote = notes[refuri]
-            footnote_name = footnote['name']
+            assert len(footnote['names']) == 1
+            footnote_name = footnote['names'][0]
         else:                           # original
             footnote = nodes.footnote()
             footnote_id = self.document.set_id(footnote)
-            # Use a colon; they can't be produced inside names by the parser:
-            footnote_name = 'target_note: ' + footnote_id
+            # Use uppercase letters and a colon; they can't be
+            # produced inside names by the parser.
+            footnote_name = 'TARGET_NOTE: ' + footnote_id
             footnote['auto'] = 1
-            footnote['name'] = footnote_name
+            footnote['names'] = [footnote_name]
             footnote_paragraph = nodes.paragraph()
             footnote_paragraph += nodes.reference('', refuri, refuri=refuri)
             footnote += footnote_paragraph
@@ -786,3 +776,11 @@
                 reflist.insert(0, nodes.Text(' '))
             ref.parent.insert(index, reflist)
         return footnote
+
+
+def uniq(L):
+     r = []
+     for item in L:
+         if not item in r:
+             r.append(item)
+     return r


=== Zope/lib/python/docutils/transforms/universal.py 1.2.10.6 => 1.2.10.7 ===
--- Zope/lib/python/docutils/transforms/universal.py:1.2.10.6   Fri Jan  7 
08:26:06 2005
+++ Zope/lib/python/docutils/transforms/universal.py    Sun Oct  9 10:43:46 2005
@@ -32,19 +32,16 @@
     default_priority = 820
 
     def apply(self):
-        header = self.generate_header()
-        footer = self.generate_footer()
-        if header or footer:
-            decoration = nodes.decoration()
-            decoration += header
-            decoration += footer
-            document = self.document
-            index = document.first_child_not_matching_class(
-                nodes.PreDecorative)
-            if index is None:
-                document += decoration
-            else:
-                document[index:index] = [decoration]
+        header_nodes = self.generate_header()
+        if header_nodes:
+            decoration = self.document.get_decoration()
+            header = decoration.get_header()
+            header.extend(header_nodes)
+        footer_nodes = self.generate_footer()
+        if footer_nodes:
+            decoration = self.document.get_decoration()
+            footer = decoration.get_footer()
+            footer.extend(footer_nodes)
 
     def generate_header(self):
         return None
@@ -79,9 +76,7 @@
                     nodes.reference('', 'reStructuredText', refuri='http://'
                                     'docutils.sourceforge.net/rst.html'),
                     nodes.Text(' source.\n')])
-            footer = nodes.footer()
-            footer += nodes.paragraph('', '', *text)
-            return footer
+            return [nodes.paragraph('', '', *text)]
         else:
             return None
 
@@ -97,13 +92,13 @@
 
     def apply(self):
         unfiltered = self.document.transform_messages
-        threshold = self.document.reporter['writer'].report_level
+        threshold = self.document.reporter.report_level
         messages = []
         for msg in unfiltered:
             if msg['level'] >= threshold and not msg.parent:
                 messages.append(msg)
         if messages:
-            section = nodes.section(CLASS='system-messages')
+            section = nodes.section(classes=['system-messages'])
             # @@@ get this from the language module?
             section += nodes.title('', 'Docutils System Messages')
             section += messages
@@ -130,7 +125,7 @@
         pass
 
     def visit_system_message(self, node):
-        if node['level'] < self.document.reporter['writer'].report_level:
+        if node['level'] < self.document.reporter.report_level:
             node.parent.remove(node)
 
 
@@ -167,6 +162,21 @@
         if self.document.settings.expose_internals:
             visitor = InternalAttributeExposer(self.document)
             self.document.walk(visitor)
+        # *After* resolving all references, check for unreferenced
+        # targets:
+        for target in self.document.traverse():
+            if isinstance(target, nodes.target) and not target.referenced:
+                if target['names']:
+                    naming = target['names'][0]
+                elif target['ids']:
+                    naming = target['ids'][0]
+                else:
+                    # Hack: Propagated targets always have their refid
+                    # attribute set.
+                    naming = target['refid']
+                self.document.reporter.info(
+                    'Hyperlink target "%s" is not referenced.'
+                    % naming, base_node=target)
 
 
 class FinalCheckVisitor(nodes.SparseNodeVisitor):
@@ -206,7 +216,7 @@
         else:
             del node['refname']
             node['refid'] = id
-            self.document.ids[id].referenced = 1
+            self.document.ids[id].note_referenced_by(id=id)
             node.resolved = 1
 
     visit_footnote_reference = visit_citation_reference = visit_reference

_______________________________________________
Zope-Checkins maillist  -  Zope-Checkins@zope.org
http://mail.zope.org/mailman/listinfo/zope-checkins

Reply via email to