buildframework/helium/external/python/lib/common/docutils-0.5-py2.5.egg/docutils/transforms/misc.py
author wbernard
Wed, 23 Dec 2009 19:29:07 +0200
changeset 179 d8ac696cc51f
permissions -rw-r--r--
helium_7.0-r14027
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
179
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     1
# $Id: misc.py 4564 2006-05-21 20:44:42Z wiemann $
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     2
# Author: David Goodger <goodger@python.org>
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     3
# Copyright: This module has been placed in the public domain.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     4
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     5
"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     6
Miscellaneous transforms.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     7
"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     8
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     9
__docformat__ = 'reStructuredText'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    10
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    11
from docutils import nodes
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    12
from docutils.transforms import Transform, TransformError
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    13
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    14
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    15
class CallBack(Transform):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    16
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    17
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    18
    Inserts a callback into a document.  The callback is called when the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    19
    transform is applied, which is determined by its priority.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    20
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    21
    For use with `nodes.pending` elements.  Requires a ``details['callback']``
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    22
    entry, a bound method or function which takes one parameter: the pending
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    23
    node.  Other data can be stored in the ``details`` attribute or in the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    24
    object hosting the callback method.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    25
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    26
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    27
    default_priority = 990
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    28
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    29
    def apply(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    30
        pending = self.startnode
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    31
        pending.details['callback'](pending)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    32
        pending.parent.remove(pending)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    33
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    34
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    35
class ClassAttribute(Transform):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    36
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    37
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    38
    Move the "class" attribute specified in the "pending" node into the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    39
    immediately following non-comment element.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    40
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    41
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    42
    default_priority = 210
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    43
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    44
    def apply(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    45
        pending = self.startnode
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    46
        parent = pending.parent
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    47
        child = pending
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    48
        while parent:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    49
            # Check for appropriate following siblings:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    50
            for index in range(parent.index(child) + 1, len(parent)):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    51
                element = parent[index]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    52
                if (isinstance(element, nodes.Invisible) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    53
                    isinstance(element, nodes.system_message)):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    54
                    continue
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    55
                element['classes'] += pending.details['class']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    56
                pending.parent.remove(pending)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    57
                return
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    58
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    59
                # At end of section or container; apply to sibling
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    60
                child = parent
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    61
                parent = parent.parent
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    62
        error = self.document.reporter.error(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    63
            'No suitable element following "%s" directive'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    64
            % pending.details['directive'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    65
            nodes.literal_block(pending.rawsource, pending.rawsource),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    66
            line=pending.line)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    67
        pending.replace_self(error)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    68
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    69
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    70
class Transitions(Transform):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    71
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    72
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    73
    Move transitions at the end of sections up the tree.  Complain
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    74
    on transitions after a title, at the beginning or end of the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    75
    document, and after another transition.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    76
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    77
    For example, transform this::
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    78
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    79
        <section>
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    80
            ...
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    81
            <transition>
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    82
        <section>
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    83
            ...
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    84
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    85
    into this::
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    86
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    87
        <section>
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    88
            ...
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    89
        <transition>
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    90
        <section>
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    91
            ...
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    92
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    93
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    94
    default_priority = 830
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    95
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    96
    def apply(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    97
        for node in self.document.traverse(nodes.transition):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    98
            self.visit_transition(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    99
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   100
    def visit_transition(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   101
        index = node.parent.index(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   102
        error = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   103
        if (index == 0 or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   104
            isinstance(node.parent[0], nodes.title) and
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   105
            (index == 1 or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   106
             isinstance(node.parent[1], nodes.subtitle) and
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   107
             index == 2)):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   108
            assert (isinstance(node.parent, nodes.document) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   109
                    isinstance(node.parent, nodes.section))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   110
            error = self.document.reporter.error(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   111
                'Document or section may not begin with a transition.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   112
                line=node.line)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   113
        elif isinstance(node.parent[index - 1], nodes.transition):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   114
            error = self.document.reporter.error(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   115
                'At least one body element must separate transitions; '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   116
                'adjacent transitions are not allowed.', line=node.line)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   117
        if error:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   118
            # Insert before node and update index.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   119
            node.parent.insert(index, error)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   120
            index += 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   121
        assert index < len(node.parent)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   122
        if index != len(node.parent) - 1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   123
            # No need to move the node.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   124
            return
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   125
        # Node behind which the transition is to be moved.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   126
        sibling = node
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   127
        # While sibling is the last node of its parent.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   128
        while index == len(sibling.parent) - 1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   129
            sibling = sibling.parent
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   130
            # If sibling is the whole document (i.e. it has no parent).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   131
            if sibling.parent is None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   132
                # Transition at the end of document.  Do not move the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   133
                # transition up, and place an error behind.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   134
                error = self.document.reporter.error(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   135
                    'Document may not end with a transition.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   136
                    line=node.line)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   137
                node.parent.insert(node.parent.index(node) + 1, error)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   138
                return
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   139
            index = sibling.parent.index(sibling)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   140
        # Remove the original transition node.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   141
        node.parent.remove(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   142
        # Insert the transition after the sibling.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   143
        sibling.parent.insert(index + 1, node)