buildframework/helium/external/python/lib/2.5/docutils-0.5-py2.5.egg/docutils/nodes.py
changeset 179 d8ac696cc51f
parent 1 be27ed110b50
child 180 e02a83d4c571
child 592 3215c239276a
equal deleted inserted replaced
1:be27ed110b50 179:d8ac696cc51f
     1 # $Id: nodes.py 5033 2007-03-21 19:51:22Z wiemann $
       
     2 # Author: David Goodger <goodger@python.org>
       
     3 # Copyright: This module has been placed in the public domain.
       
     4 
       
     5 """
       
     6 Docutils document tree element class library.
       
     7 
       
     8 Classes in CamelCase are abstract base classes or auxiliary classes. The one
       
     9 exception is `Text`, for a text (PCDATA) node; uppercase is used to
       
    10 differentiate from element classes.  Classes in lower_case_with_underscores
       
    11 are element classes, matching the XML element generic identifiers in the DTD_.
       
    12 
       
    13 The position of each node (the level at which it can occur) is significant and
       
    14 is represented by abstract base classes (`Root`, `Structural`, `Body`,
       
    15 `Inline`, etc.).  Certain transformations will be easier because we can use
       
    16 ``isinstance(node, base_class)`` to determine the position of the node in the
       
    17 hierarchy.
       
    18 
       
    19 .. _DTD: http://docutils.sourceforge.net/docs/ref/docutils.dtd
       
    20 """
       
    21 
       
    22 __docformat__ = 'reStructuredText'
       
    23 
       
    24 import sys
       
    25 import os
       
    26 import re
       
    27 import warnings
       
    28 from types import IntType, SliceType, StringType, UnicodeType, \
       
    29      TupleType, ListType, ClassType, TypeType
       
    30 from UserString import UserString
       
    31 
       
    32 
       
    33 # ==============================
       
    34 #  Functional Node Base Classes
       
    35 # ==============================
       
    36 
       
    37 class Node:
       
    38 
       
    39     """Abstract base class of nodes in a document tree."""
       
    40 
       
    41     parent = None
       
    42     """Back-reference to the Node immediately containing this Node."""
       
    43 
       
    44     document = None
       
    45     """The `document` node at the root of the tree containing this Node."""
       
    46 
       
    47     source = None
       
    48     """Path or description of the input source which generated this Node."""
       
    49 
       
    50     line = None
       
    51     """The line number (1-based) of the beginning of this Node in `source`."""
       
    52 
       
    53     def __nonzero__(self):
       
    54         """
       
    55         Node instances are always true, even if they're empty.  A node is more
       
    56         than a simple container.  Its boolean "truth" does not depend on
       
    57         having one or more subnodes in the doctree.
       
    58 
       
    59         Use `len()` to check node length.  Use `None` to represent a boolean
       
    60         false value.
       
    61         """
       
    62         return 1
       
    63 
       
    64     def __str__(self):
       
    65         return self.__unicode__().encode('raw_unicode_escape')
       
    66 
       
    67     def __unicode__(self):
       
    68         # Override in subclass.
       
    69         raise NotImplementedError
       
    70 
       
    71     def asdom(self, dom=None):
       
    72         """Return a DOM **fragment** representation of this Node."""
       
    73         if dom is None:
       
    74             import xml.dom.minidom as dom
       
    75         domroot = dom.Document()
       
    76         return self._dom_node(domroot)
       
    77 
       
    78     def pformat(self, indent='    ', level=0):
       
    79         """
       
    80         Return an indented pseudo-XML representation, for test purposes.
       
    81 
       
    82         Override in subclasses.
       
    83         """
       
    84         raise NotImplementedError
       
    85 
       
    86     def copy(self):
       
    87         """Return a copy of self."""
       
    88         raise NotImplementedError
       
    89 
       
    90     def deepcopy(self):
       
    91         """Return a deep copy of self (also copying children)."""
       
    92         raise NotImplementedError
       
    93 
       
    94     def setup_child(self, child):
       
    95         child.parent = self
       
    96         if self.document:
       
    97             child.document = self.document
       
    98             if child.source is None:
       
    99                 child.source = self.document.current_source
       
   100             if child.line is None:
       
   101                 child.line = self.document.current_line
       
   102 
       
   103     def walk(self, visitor):
       
   104         """
       
   105         Traverse a tree of `Node` objects, calling the
       
   106         `dispatch_visit()` method of `visitor` when entering each
       
   107         node.  (The `walkabout()` method is similar, except it also
       
   108         calls the `dispatch_departure()` method before exiting each
       
   109         node.)
       
   110 
       
   111         This tree traversal supports limited in-place tree
       
   112         modifications.  Replacing one node with one or more nodes is
       
   113         OK, as is removing an element.  However, if the node removed
       
   114         or replaced occurs after the current node, the old node will
       
   115         still be traversed, and any new nodes will not.
       
   116 
       
   117         Within ``visit`` methods (and ``depart`` methods for
       
   118         `walkabout()`), `TreePruningException` subclasses may be raised
       
   119         (`SkipChildren`, `SkipSiblings`, `SkipNode`, `SkipDeparture`).
       
   120 
       
   121         Parameter `visitor`: A `NodeVisitor` object, containing a
       
   122         ``visit`` implementation for each `Node` subclass encountered.
       
   123 
       
   124         Return true if we should stop the traversal.
       
   125         """
       
   126         stop = 0
       
   127         visitor.document.reporter.debug(
       
   128             'docutils.nodes.Node.walk calling dispatch_visit for %s'
       
   129             % self.__class__.__name__)
       
   130         try:
       
   131             try:
       
   132                 visitor.dispatch_visit(self)
       
   133             except (SkipChildren, SkipNode):
       
   134                 return stop
       
   135             except SkipDeparture:           # not applicable; ignore
       
   136                 pass
       
   137             children = self.children
       
   138             try:
       
   139                 for child in children[:]:
       
   140                     if child.walk(visitor):
       
   141                         stop = 1
       
   142                         break
       
   143             except SkipSiblings:
       
   144                 pass
       
   145         except StopTraversal:
       
   146             stop = 1
       
   147         return stop
       
   148 
       
   149     def walkabout(self, visitor):
       
   150         """
       
   151         Perform a tree traversal similarly to `Node.walk()` (which
       
   152         see), except also call the `dispatch_departure()` method
       
   153         before exiting each node.
       
   154 
       
   155         Parameter `visitor`: A `NodeVisitor` object, containing a
       
   156         ``visit`` and ``depart`` implementation for each `Node`
       
   157         subclass encountered.
       
   158 
       
   159         Return true if we should stop the traversal.
       
   160         """
       
   161         call_depart = 1
       
   162         stop = 0
       
   163         visitor.document.reporter.debug(
       
   164             'docutils.nodes.Node.walkabout calling dispatch_visit for %s'
       
   165             % self.__class__.__name__)
       
   166         try:
       
   167             try:
       
   168                 visitor.dispatch_visit(self)
       
   169             except SkipNode:
       
   170                 return stop
       
   171             except SkipDeparture:
       
   172                 call_depart = 0
       
   173             children = self.children
       
   174             try:
       
   175                 for child in children[:]:
       
   176                     if child.walkabout(visitor):
       
   177                         stop = 1
       
   178                         break
       
   179             except SkipSiblings:
       
   180                 pass
       
   181         except SkipChildren:
       
   182             pass
       
   183         except StopTraversal:
       
   184             stop = 1
       
   185         if call_depart:
       
   186             visitor.document.reporter.debug(
       
   187                 'docutils.nodes.Node.walkabout calling dispatch_departure '
       
   188                 'for %s' % self.__class__.__name__)
       
   189             visitor.dispatch_departure(self)
       
   190         return stop
       
   191 
       
   192     def traverse(self, condition=None,
       
   193                  include_self=1, descend=1, siblings=0, ascend=0):
       
   194         """
       
   195         Return an iterable containing
       
   196 
       
   197         * self (if include_self is true)
       
   198         * all descendants in tree traversal order (if descend is true)
       
   199         * all siblings (if siblings is true) and their descendants (if
       
   200           also descend is true)
       
   201         * the siblings of the parent (if ascend is true) and their
       
   202           descendants (if also descend is true), and so on
       
   203 
       
   204         If `condition` is not None, the iterable contains only nodes
       
   205         for which ``condition(node)`` is true.  If `condition` is a
       
   206         node class ``cls``, it is equivalent to a function consisting
       
   207         of ``return isinstance(node, cls)``.
       
   208 
       
   209         If ascend is true, assume siblings to be true as well.
       
   210 
       
   211         For example, given the following tree::
       
   212 
       
   213             <paragraph>
       
   214                 <emphasis>      <--- emphasis.traverse() and
       
   215                     <strong>    <--- strong.traverse() are called.
       
   216                         Foo
       
   217                     Bar
       
   218                 <reference name="Baz" refid="baz">
       
   219                     Baz
       
   220 
       
   221         Then list(emphasis.traverse()) equals ::
       
   222 
       
   223             [<emphasis>, <strong>, <#text: Foo>, <#text: Bar>]
       
   224 
       
   225         and list(strong.traverse(ascend=1)) equals ::
       
   226 
       
   227             [<strong>, <#text: Foo>, <#text: Bar>, <reference>, <#text: Baz>]
       
   228         """
       
   229         r = []
       
   230         if ascend:
       
   231             siblings=1
       
   232         # Check if `condition` is a class (check for TypeType for Python
       
   233         # implementations that use only new-style classes, like PyPy).
       
   234         if isinstance(condition, (ClassType, TypeType)):
       
   235             node_class = condition
       
   236             def condition(node, node_class=node_class):
       
   237                 return isinstance(node, node_class)
       
   238         if include_self and (condition is None or condition(self)):
       
   239             r.append(self)
       
   240         if descend and len(self.children):
       
   241             for child in self:
       
   242                 r.extend(child.traverse(
       
   243                     include_self=1, descend=1, siblings=0, ascend=0,
       
   244                     condition=condition))
       
   245         if siblings or ascend:
       
   246             node = self
       
   247             while node.parent:
       
   248                 index = node.parent.index(node)
       
   249                 for sibling in node.parent[index+1:]:
       
   250                     r.extend(sibling.traverse(include_self=1, descend=descend,
       
   251                                               siblings=0, ascend=0,
       
   252                                               condition=condition))
       
   253                 if not ascend:
       
   254                     break
       
   255                 else:
       
   256                     node = node.parent
       
   257         return r
       
   258 
       
   259     def next_node(self, condition=None,
       
   260                   include_self=0, descend=1, siblings=0, ascend=0):
       
   261         """
       
   262         Return the first node in the iterable returned by traverse(),
       
   263         or None if the iterable is empty.
       
   264 
       
   265         Parameter list is the same as of traverse.  Note that
       
   266         include_self defaults to 0, though.
       
   267         """
       
   268         iterable = self.traverse(condition=condition,
       
   269                                  include_self=include_self, descend=descend,
       
   270                                  siblings=siblings, ascend=ascend)
       
   271         try:
       
   272             return iterable[0]
       
   273         except IndexError:
       
   274             return None
       
   275 
       
   276 class Text(Node, UserString):
       
   277 
       
   278     """
       
   279     Instances are terminal nodes (leaves) containing text only; no child
       
   280     nodes or attributes.  Initialize by passing a string to the constructor.
       
   281     Access the text itself with the `astext` method.
       
   282     """
       
   283 
       
   284     tagname = '#text'
       
   285 
       
   286     children = ()
       
   287     """Text nodes have no children, and cannot have children."""
       
   288 
       
   289     def __init__(self, data, rawsource=''):
       
   290         UserString.__init__(self, data)
       
   291 
       
   292         self.rawsource = rawsource
       
   293         """The raw text from which this element was constructed."""
       
   294 
       
   295     def __repr__(self):
       
   296         data = repr(self.data)
       
   297         if len(data) > 70:
       
   298             data = repr(self.data[:64] + ' ...')
       
   299         return '<%s: %s>' % (self.tagname, data)
       
   300 
       
   301     def __len__(self):
       
   302         return len(self.data)
       
   303 
       
   304     def shortrepr(self):
       
   305         data = repr(self.data)
       
   306         if len(data) > 20:
       
   307             data = repr(self.data[:16] + ' ...')
       
   308         return '<%s: %s>' % (self.tagname, data)
       
   309 
       
   310     def _dom_node(self, domroot):
       
   311         return domroot.createTextNode(self.data)
       
   312 
       
   313     def astext(self):
       
   314         return self.data
       
   315 
       
   316     def __unicode__(self):
       
   317         return self.data
       
   318 
       
   319     def copy(self):
       
   320         return self.__class__(self.data)
       
   321 
       
   322     def deepcopy(self):
       
   323         return self.copy()
       
   324 
       
   325     def pformat(self, indent='    ', level=0):
       
   326         result = []
       
   327         indent = indent * level
       
   328         for line in self.data.splitlines():
       
   329             result.append(indent + line + '\n')
       
   330         return ''.join(result)
       
   331 
       
   332 
       
   333 class Element(Node):
       
   334 
       
   335     """
       
   336     `Element` is the superclass to all specific elements.
       
   337 
       
   338     Elements contain attributes and child nodes.  Elements emulate
       
   339     dictionaries for attributes, indexing by attribute name (a string).  To
       
   340     set the attribute 'att' to 'value', do::
       
   341 
       
   342         element['att'] = 'value'
       
   343 
       
   344     There are two special attributes: 'ids' and 'names'.  Both are
       
   345     lists of unique identifiers, and names serve as human interfaces
       
   346     to IDs.  Names are case- and whitespace-normalized (see the
       
   347     fully_normalize_name() function), and IDs conform to the regular
       
   348     expression ``[a-z](-?[a-z0-9]+)*`` (see the make_id() function).
       
   349 
       
   350     Elements also emulate lists for child nodes (element nodes and/or text
       
   351     nodes), indexing by integer.  To get the first child node, use::
       
   352 
       
   353         element[0]
       
   354 
       
   355     Elements may be constructed using the ``+=`` operator.  To add one new
       
   356     child node to element, do::
       
   357 
       
   358         element += node
       
   359 
       
   360     This is equivalent to ``element.append(node)``.
       
   361 
       
   362     To add a list of multiple child nodes at once, use the same ``+=``
       
   363     operator::
       
   364 
       
   365         element += [node1, node2]
       
   366 
       
   367     This is equivalent to ``element.extend([node1, node2])``.
       
   368     """
       
   369 
       
   370     list_attributes = ('ids', 'classes', 'names', 'dupnames', 'backrefs')
       
   371     """List attributes, automatically initialized to empty lists for
       
   372     all nodes."""
       
   373 
       
   374     tagname = None
       
   375     """The element generic identifier. If None, it is set as an instance
       
   376     attribute to the name of the class."""
       
   377 
       
   378     child_text_separator = '\n\n'
       
   379     """Separator for child nodes, used by `astext()` method."""
       
   380 
       
   381     def __init__(self, rawsource='', *children, **attributes):
       
   382         self.rawsource = rawsource
       
   383         """The raw text from which this element was constructed."""
       
   384 
       
   385         self.children = []
       
   386         """List of child nodes (elements and/or `Text`)."""
       
   387 
       
   388         self.extend(children)           # maintain parent info
       
   389 
       
   390         self.attributes = {}
       
   391         """Dictionary of attribute {name: value}."""
       
   392 
       
   393         # Initialize list attributes.
       
   394         for att in self.list_attributes:
       
   395             self.attributes[att] = []
       
   396 
       
   397         for att, value in attributes.items():
       
   398             att = att.lower()
       
   399             if att in self.list_attributes:
       
   400                 # mutable list; make a copy for this node
       
   401                 self.attributes[att] = value[:]
       
   402             else:
       
   403                 self.attributes[att] = value
       
   404 
       
   405         if self.tagname is None:
       
   406             self.tagname = self.__class__.__name__
       
   407 
       
   408     def _dom_node(self, domroot):
       
   409         element = domroot.createElement(self.tagname)
       
   410         for attribute, value in self.attlist():
       
   411             if isinstance(value, ListType):
       
   412                 value = ' '.join([serial_escape('%s' % v) for v in value])
       
   413             element.setAttribute(attribute, '%s' % value)
       
   414         for child in self.children:
       
   415             element.appendChild(child._dom_node(domroot))
       
   416         return element
       
   417 
       
   418     def __repr__(self):
       
   419         data = ''
       
   420         for c in self.children:
       
   421             data += c.shortrepr()
       
   422             if len(data) > 60:
       
   423                 data = data[:56] + ' ...'
       
   424                 break
       
   425         if self['names']:
       
   426             return '<%s "%s": %s>' % (self.__class__.__name__,
       
   427                                       '; '.join(self['names']), data)
       
   428         else:
       
   429             return '<%s: %s>' % (self.__class__.__name__, data)
       
   430 
       
   431     def shortrepr(self):
       
   432         if self['names']:
       
   433             return '<%s "%s"...>' % (self.__class__.__name__,
       
   434                                      '; '.join(self['names']))
       
   435         else:
       
   436             return '<%s...>' % self.tagname
       
   437 
       
   438     def __unicode__(self):
       
   439         if self.children:
       
   440             return u'%s%s%s' % (self.starttag(),
       
   441                                 ''.join([unicode(c) for c in self.children]),
       
   442                                 self.endtag())
       
   443         else:
       
   444             return self.emptytag()
       
   445 
       
   446     def starttag(self):
       
   447         parts = [self.tagname]
       
   448         for name, value in self.attlist():
       
   449             if value is None:           # boolean attribute
       
   450                 parts.append(name)
       
   451             elif isinstance(value, ListType):
       
   452                 values = [serial_escape('%s' % v) for v in value]
       
   453                 parts.append('%s="%s"' % (name, ' '.join(values)))
       
   454             else:
       
   455                 parts.append('%s="%s"' % (name, value))
       
   456         return '<%s>' % ' '.join(parts)
       
   457 
       
   458     def endtag(self):
       
   459         return '</%s>' % self.tagname
       
   460 
       
   461     def emptytag(self):
       
   462         return u'<%s/>' % ' '.join([self.tagname] +
       
   463                                     ['%s="%s"' % (n, v)
       
   464                                      for n, v in self.attlist()])
       
   465 
       
   466     def __len__(self):
       
   467         return len(self.children)
       
   468 
       
   469     def __getitem__(self, key):
       
   470         if isinstance(key, UnicodeType) or isinstance(key, StringType):
       
   471             return self.attributes[key]
       
   472         elif isinstance(key, IntType):
       
   473             return self.children[key]
       
   474         elif isinstance(key, SliceType):
       
   475             assert key.step in (None, 1), 'cannot handle slice with stride'
       
   476             return self.children[key.start:key.stop]
       
   477         else:
       
   478             raise TypeError, ('element index must be an integer, a slice, or '
       
   479                               'an attribute name string')
       
   480 
       
   481     def __setitem__(self, key, item):
       
   482         if isinstance(key, UnicodeType) or isinstance(key, StringType):
       
   483             self.attributes[str(key)] = item
       
   484         elif isinstance(key, IntType):
       
   485             self.setup_child(item)
       
   486             self.children[key] = item
       
   487         elif isinstance(key, SliceType):
       
   488             assert key.step in (None, 1), 'cannot handle slice with stride'
       
   489             for node in item:
       
   490                 self.setup_child(node)
       
   491             self.children[key.start:key.stop] = item
       
   492         else:
       
   493             raise TypeError, ('element index must be an integer, a slice, or '
       
   494                               'an attribute name string')
       
   495 
       
   496     def __delitem__(self, key):
       
   497         if isinstance(key, UnicodeType) or isinstance(key, StringType):
       
   498             del self.attributes[key]
       
   499         elif isinstance(key, IntType):
       
   500             del self.children[key]
       
   501         elif isinstance(key, SliceType):
       
   502             assert key.step in (None, 1), 'cannot handle slice with stride'
       
   503             del self.children[key.start:key.stop]
       
   504         else:
       
   505             raise TypeError, ('element index must be an integer, a simple '
       
   506                               'slice, or an attribute name string')
       
   507 
       
   508     def __add__(self, other):
       
   509         return self.children + other
       
   510 
       
   511     def __radd__(self, other):
       
   512         return other + self.children
       
   513 
       
   514     def __iadd__(self, other):
       
   515         """Append a node or a list of nodes to `self.children`."""
       
   516         if isinstance(other, Node):
       
   517             self.append(other)
       
   518         elif other is not None:
       
   519             self.extend(other)
       
   520         return self
       
   521 
       
   522     def astext(self):
       
   523         return self.child_text_separator.join(
       
   524               [child.astext() for child in self.children])
       
   525 
       
   526     def non_default_attributes(self):
       
   527         atts = {}
       
   528         for key, value in self.attributes.items():
       
   529             if self.is_not_default(key):
       
   530                 atts[key] = value
       
   531         return atts
       
   532 
       
   533     def attlist(self):
       
   534         attlist = self.non_default_attributes().items()
       
   535         attlist.sort()
       
   536         return attlist
       
   537 
       
   538     def get(self, key, failobj=None):
       
   539         return self.attributes.get(key, failobj)
       
   540 
       
   541     def hasattr(self, attr):
       
   542         return self.attributes.has_key(attr)
       
   543 
       
   544     def delattr(self, attr):
       
   545         if self.attributes.has_key(attr):
       
   546             del self.attributes[attr]
       
   547 
       
   548     def setdefault(self, key, failobj=None):
       
   549         return self.attributes.setdefault(key, failobj)
       
   550 
       
   551     has_key = hasattr
       
   552 
       
   553     def append(self, item):
       
   554         self.setup_child(item)
       
   555         self.children.append(item)
       
   556 
       
   557     def extend(self, item):
       
   558         for node in item:
       
   559             self.append(node)
       
   560 
       
   561     def insert(self, index, item):
       
   562         if isinstance(item, Node):
       
   563             self.setup_child(item)
       
   564             self.children.insert(index, item)
       
   565         elif item is not None:
       
   566             self[index:index] = item
       
   567 
       
   568     def pop(self, i=-1):
       
   569         return self.children.pop(i)
       
   570 
       
   571     def remove(self, item):
       
   572         self.children.remove(item)
       
   573 
       
   574     def index(self, item):
       
   575         return self.children.index(item)
       
   576 
       
   577     def is_not_default(self, key):
       
   578         if self[key] == [] and key in self.list_attributes:
       
   579             return 0
       
   580         else:
       
   581             return 1
       
   582 
       
   583     def update_basic_atts(self, dict):
       
   584         """
       
   585         Update basic attributes ('ids', 'names', 'classes',
       
   586         'dupnames', but not 'source') from node or dictionary `dict`.
       
   587         """
       
   588         if isinstance(dict, Node):
       
   589             dict = dict.attributes
       
   590         for att in ('ids', 'classes', 'names', 'dupnames'):
       
   591             for value in dict.get(att, []):
       
   592                 if not value in self[att]:
       
   593                     self[att].append(value)
       
   594 
       
   595     def clear(self):
       
   596         self.children = []
       
   597 
       
   598     def replace(self, old, new):
       
   599         """Replace one child `Node` with another child or children."""
       
   600         index = self.index(old)
       
   601         if isinstance(new, Node):
       
   602             self.setup_child(new)
       
   603             self[index] = new
       
   604         elif new is not None:
       
   605             self[index:index+1] = new
       
   606 
       
   607     def replace_self(self, new):
       
   608         """
       
   609         Replace `self` node with `new`, where `new` is a node or a
       
   610         list of nodes.
       
   611         """
       
   612         update = new
       
   613         if not isinstance(new, Node):
       
   614             # `new` is a list; update first child.
       
   615             try:
       
   616                 update = new[0]
       
   617             except IndexError:
       
   618                 update = None
       
   619         if isinstance(update, Element):
       
   620             update.update_basic_atts(self)
       
   621         else:
       
   622             # `update` is a Text node or `new` is an empty list.
       
   623             # Assert that we aren't losing any attributes.
       
   624             for att in ('ids', 'names', 'classes', 'dupnames'):
       
   625                 assert not self[att], \
       
   626                        'Losing "%s" attribute: %s' % (att, self[att])
       
   627         self.parent.replace(self, new)
       
   628 
       
   629     def first_child_matching_class(self, childclass, start=0, end=sys.maxint):
       
   630         """
       
   631         Return the index of the first child whose class exactly matches.
       
   632 
       
   633         Parameters:
       
   634 
       
   635         - `childclass`: A `Node` subclass to search for, or a tuple of `Node`
       
   636           classes. If a tuple, any of the classes may match.
       
   637         - `start`: Initial index to check.
       
   638         - `end`: Initial index to *not* check.
       
   639         """
       
   640         if not isinstance(childclass, TupleType):
       
   641             childclass = (childclass,)
       
   642         for index in range(start, min(len(self), end)):
       
   643             for c in childclass:
       
   644                 if isinstance(self[index], c):
       
   645                     return index
       
   646         return None
       
   647 
       
   648     def first_child_not_matching_class(self, childclass, start=0,
       
   649                                        end=sys.maxint):
       
   650         """
       
   651         Return the index of the first child whose class does *not* match.
       
   652 
       
   653         Parameters:
       
   654 
       
   655         - `childclass`: A `Node` subclass to skip, or a tuple of `Node`
       
   656           classes. If a tuple, none of the classes may match.
       
   657         - `start`: Initial index to check.
       
   658         - `end`: Initial index to *not* check.
       
   659         """
       
   660         if not isinstance(childclass, TupleType):
       
   661             childclass = (childclass,)
       
   662         for index in range(start, min(len(self), end)):
       
   663             for c in childclass:
       
   664                 if isinstance(self.children[index], c):
       
   665                     break
       
   666             else:
       
   667                 return index
       
   668         return None
       
   669 
       
   670     def pformat(self, indent='    ', level=0):
       
   671         return ''.join(['%s%s\n' % (indent * level, self.starttag())] +
       
   672                        [child.pformat(indent, level+1)
       
   673                         for child in self.children])
       
   674 
       
   675     def copy(self):
       
   676         return self.__class__(**self.attributes)
       
   677 
       
   678     def deepcopy(self):
       
   679         copy = self.copy()
       
   680         copy.extend([child.deepcopy() for child in self.children])
       
   681         return copy
       
   682 
       
   683     def set_class(self, name):
       
   684         """Add a new class to the "classes" attribute."""
       
   685         warnings.warn('docutils.nodes.Element.set_class deprecated; '
       
   686                       "append to Element['classes'] list attribute directly",
       
   687                       DeprecationWarning, stacklevel=2)
       
   688         assert ' ' not in name
       
   689         self['classes'].append(name.lower())
       
   690 
       
   691     def note_referenced_by(self, name=None, id=None):
       
   692         """Note that this Element has been referenced by its name
       
   693         `name` or id `id`."""
       
   694         self.referenced = 1
       
   695         # Element.expect_referenced_by_* dictionaries map names or ids
       
   696         # to nodes whose ``referenced`` attribute is set to true as
       
   697         # soon as this node is referenced by the given name or id.
       
   698         # Needed for target propagation.
       
   699         by_name = getattr(self, 'expect_referenced_by_name', {}).get(name)
       
   700         by_id = getattr(self, 'expect_referenced_by_id', {}).get(id)
       
   701         if by_name:
       
   702             assert name is not None
       
   703             by_name.referenced = 1
       
   704         if by_id:
       
   705             assert id is not None
       
   706             by_id.referenced = 1
       
   707 
       
   708 
       
   709 class TextElement(Element):
       
   710 
       
   711     """
       
   712     An element which directly contains text.
       
   713 
       
   714     Its children are all `Text` or `Inline` subclass nodes.  You can
       
   715     check whether an element's context is inline simply by checking whether
       
   716     its immediate parent is a `TextElement` instance (including subclasses).
       
   717     This is handy for nodes like `image` that can appear both inline and as
       
   718     standalone body elements.
       
   719 
       
   720     If passing children to `__init__()`, make sure to set `text` to
       
   721     ``''`` or some other suitable value.
       
   722     """
       
   723 
       
   724     child_text_separator = ''
       
   725     """Separator for child nodes, used by `astext()` method."""
       
   726 
       
   727     def __init__(self, rawsource='', text='', *children, **attributes):
       
   728         if text != '':
       
   729             textnode = Text(text)
       
   730             Element.__init__(self, rawsource, textnode, *children,
       
   731                               **attributes)
       
   732         else:
       
   733             Element.__init__(self, rawsource, *children, **attributes)
       
   734 
       
   735 
       
   736 class FixedTextElement(TextElement):
       
   737 
       
   738     """An element which directly contains preformatted text."""
       
   739 
       
   740     def __init__(self, rawsource='', text='', *children, **attributes):
       
   741         TextElement.__init__(self, rawsource, text, *children, **attributes)
       
   742         self.attributes['xml:space'] = 'preserve'
       
   743 
       
   744 
       
   745 # ========
       
   746 #  Mixins
       
   747 # ========
       
   748 
       
   749 class Resolvable:
       
   750 
       
   751     resolved = 0
       
   752 
       
   753 
       
   754 class BackLinkable:
       
   755 
       
   756     def add_backref(self, refid):
       
   757         self['backrefs'].append(refid)
       
   758 
       
   759 
       
   760 # ====================
       
   761 #  Element Categories
       
   762 # ====================
       
   763 
       
   764 class Root: pass
       
   765 
       
   766 class Titular: pass
       
   767 
       
   768 class PreBibliographic:
       
   769     """Category of Node which may occur before Bibliographic Nodes."""
       
   770 
       
   771 class Bibliographic: pass
       
   772 
       
   773 class Decorative(PreBibliographic): pass
       
   774 
       
   775 class Structural: pass
       
   776 
       
   777 class Body: pass
       
   778 
       
   779 class General(Body): pass
       
   780 
       
   781 class Sequential(Body):
       
   782     """List-like elements."""
       
   783 
       
   784 class Admonition(Body): pass
       
   785 
       
   786 class Special(Body):
       
   787     """Special internal body elements."""
       
   788 
       
   789 class Invisible(PreBibliographic):
       
   790     """Internal elements that don't appear in output."""
       
   791 
       
   792 class Part: pass
       
   793 
       
   794 class Inline: pass
       
   795 
       
   796 class Referential(Resolvable): pass
       
   797 
       
   798 
       
   799 class Targetable(Resolvable):
       
   800 
       
   801     referenced = 0
       
   802 
       
   803     indirect_reference_name = None
       
   804     """Holds the whitespace_normalized_name (contains mixed case) of a target.
       
   805     Required for MoinMoin/reST compatibility."""
       
   806 
       
   807 
       
   808 class Labeled:
       
   809     """Contains a `label` as its first element."""
       
   810 
       
   811 
       
   812 # ==============
       
   813 #  Root Element
       
   814 # ==============
       
   815 
       
   816 class document(Root, Structural, Element):
       
   817 
       
   818     """
       
   819     The document root element.
       
   820 
       
   821     Do not instantiate this class directly; use
       
   822     `docutils.utils.new_document()` instead.
       
   823     """
       
   824 
       
   825     def __init__(self, settings, reporter, *args, **kwargs):
       
   826         Element.__init__(self, *args, **kwargs)
       
   827 
       
   828         self.current_source = None
       
   829         """Path to or description of the input source being processed."""
       
   830 
       
   831         self.current_line = None
       
   832         """Line number (1-based) of `current_source`."""
       
   833 
       
   834         self.settings = settings
       
   835         """Runtime settings data record."""
       
   836 
       
   837         self.reporter = reporter
       
   838         """System message generator."""
       
   839 
       
   840         self.indirect_targets = []
       
   841         """List of indirect target nodes."""
       
   842 
       
   843         self.substitution_defs = {}
       
   844         """Mapping of substitution names to substitution_definition nodes."""
       
   845 
       
   846         self.substitution_names = {}
       
   847         """Mapping of case-normalized substitution names to case-sensitive
       
   848         names."""
       
   849 
       
   850         self.refnames = {}
       
   851         """Mapping of names to lists of referencing nodes."""
       
   852 
       
   853         self.refids = {}
       
   854         """Mapping of ids to lists of referencing nodes."""
       
   855 
       
   856         self.nameids = {}
       
   857         """Mapping of names to unique id's."""
       
   858 
       
   859         self.nametypes = {}
       
   860         """Mapping of names to hyperlink type (boolean: True => explicit,
       
   861         False => implicit."""
       
   862 
       
   863         self.ids = {}
       
   864         """Mapping of ids to nodes."""
       
   865 
       
   866         self.footnote_refs = {}
       
   867         """Mapping of footnote labels to lists of footnote_reference nodes."""
       
   868 
       
   869         self.citation_refs = {}
       
   870         """Mapping of citation labels to lists of citation_reference nodes."""
       
   871 
       
   872         self.autofootnotes = []
       
   873         """List of auto-numbered footnote nodes."""
       
   874 
       
   875         self.autofootnote_refs = []
       
   876         """List of auto-numbered footnote_reference nodes."""
       
   877 
       
   878         self.symbol_footnotes = []
       
   879         """List of symbol footnote nodes."""
       
   880 
       
   881         self.symbol_footnote_refs = []
       
   882         """List of symbol footnote_reference nodes."""
       
   883 
       
   884         self.footnotes = []
       
   885         """List of manually-numbered footnote nodes."""
       
   886 
       
   887         self.citations = []
       
   888         """List of citation nodes."""
       
   889 
       
   890         self.autofootnote_start = 1
       
   891         """Initial auto-numbered footnote number."""
       
   892 
       
   893         self.symbol_footnote_start = 0
       
   894         """Initial symbol footnote symbol index."""
       
   895 
       
   896         self.id_start = 1
       
   897         """Initial ID number."""
       
   898 
       
   899         self.parse_messages = []
       
   900         """System messages generated while parsing."""
       
   901 
       
   902         self.transform_messages = []
       
   903         """System messages generated while applying transforms."""
       
   904 
       
   905         import docutils.transforms
       
   906         self.transformer = docutils.transforms.Transformer(self)
       
   907         """Storage for transforms to be applied to this document."""
       
   908 
       
   909         self.decoration = None
       
   910         """Document's `decoration` node."""
       
   911 
       
   912         self.document = self
       
   913 
       
   914     def __getstate__(self):
       
   915         """
       
   916         Return dict with unpicklable references removed.
       
   917         """
       
   918         state = self.__dict__.copy()
       
   919         state['reporter'] = None
       
   920         state['transformer'] = None
       
   921         return state
       
   922 
       
   923     def asdom(self, dom=None):
       
   924         """Return a DOM representation of this document."""
       
   925         if dom is None:
       
   926             import xml.dom.minidom as dom
       
   927         domroot = dom.Document()
       
   928         domroot.appendChild(self._dom_node(domroot))
       
   929         return domroot
       
   930 
       
   931     def set_id(self, node, msgnode=None):
       
   932         for id in node['ids']:
       
   933             if self.ids.has_key(id) and self.ids[id] is not node:
       
   934                 msg = self.reporter.severe('Duplicate ID: "%s".' % id)
       
   935                 if msgnode != None:
       
   936                     msgnode += msg
       
   937         if not node['ids']:
       
   938             for name in node['names']:
       
   939                 id = self.settings.id_prefix + make_id(name)
       
   940                 if id and not self.ids.has_key(id):
       
   941                     break
       
   942             else:
       
   943                 id = ''
       
   944                 while not id or self.ids.has_key(id):
       
   945                     id = (self.settings.id_prefix +
       
   946                           self.settings.auto_id_prefix + str(self.id_start))
       
   947                     self.id_start += 1
       
   948             node['ids'].append(id)
       
   949         self.ids[id] = node
       
   950         return id
       
   951 
       
   952     def set_name_id_map(self, node, id, msgnode=None, explicit=None):
       
   953         """
       
   954         `self.nameids` maps names to IDs, while `self.nametypes` maps names to
       
   955         booleans representing hyperlink type (True==explicit,
       
   956         False==implicit).  This method updates the mappings.
       
   957 
       
   958         The following state transition table shows how `self.nameids` ("ids")
       
   959         and `self.nametypes` ("types") change with new input (a call to this
       
   960         method), and what actions are performed ("implicit"-type system
       
   961         messages are INFO/1, and "explicit"-type system messages are ERROR/3):
       
   962 
       
   963         ====  =====  ========  ========  =======  ====  =====  =====
       
   964          Old State    Input          Action        New State   Notes
       
   965         -----------  --------  -----------------  -----------  -----
       
   966         ids   types  new type  sys.msg.  dupname  ids   types
       
   967         ====  =====  ========  ========  =======  ====  =====  =====
       
   968         -     -      explicit  -         -        new   True
       
   969         -     -      implicit  -         -        new   False
       
   970         None  False  explicit  -         -        new   True
       
   971         old   False  explicit  implicit  old      new   True
       
   972         None  True   explicit  explicit  new      None  True
       
   973         old   True   explicit  explicit  new,old  None  True   [#]_
       
   974         None  False  implicit  implicit  new      None  False
       
   975         old   False  implicit  implicit  new,old  None  False
       
   976         None  True   implicit  implicit  new      None  True
       
   977         old   True   implicit  implicit  new      old   True
       
   978         ====  =====  ========  ========  =======  ====  =====  =====
       
   979 
       
   980         .. [#] Do not clear the name-to-id map or invalidate the old target if
       
   981            both old and new targets are external and refer to identical URIs.
       
   982            The new target is invalidated regardless.
       
   983         """
       
   984         for name in node['names']:
       
   985             if self.nameids.has_key(name):
       
   986                 self.set_duplicate_name_id(node, id, name, msgnode, explicit)
       
   987             else:
       
   988                 self.nameids[name] = id
       
   989                 self.nametypes[name] = explicit
       
   990 
       
   991     def set_duplicate_name_id(self, node, id, name, msgnode, explicit):
       
   992         old_id = self.nameids[name]
       
   993         old_explicit = self.nametypes[name]
       
   994         self.nametypes[name] = old_explicit or explicit
       
   995         if explicit:
       
   996             if old_explicit:
       
   997                 level = 2
       
   998                 if old_id is not None:
       
   999                     old_node = self.ids[old_id]
       
  1000                     if node.has_key('refuri'):
       
  1001                         refuri = node['refuri']
       
  1002                         if old_node['names'] \
       
  1003                                and old_node.has_key('refuri') \
       
  1004                                and old_node['refuri'] == refuri:
       
  1005                             level = 1   # just inform if refuri's identical
       
  1006                     if level > 1:
       
  1007                         dupname(old_node, name)
       
  1008                         self.nameids[name] = None
       
  1009                 msg = self.reporter.system_message(
       
  1010                     level, 'Duplicate explicit target name: "%s".' % name,
       
  1011                     backrefs=[id], base_node=node)
       
  1012                 if msgnode != None:
       
  1013                     msgnode += msg
       
  1014                 dupname(node, name)
       
  1015             else:
       
  1016                 self.nameids[name] = id
       
  1017                 if old_id is not None:
       
  1018                     old_node = self.ids[old_id]
       
  1019                     dupname(old_node, name)
       
  1020         else:
       
  1021             if old_id is not None and not old_explicit:
       
  1022                 self.nameids[name] = None
       
  1023                 old_node = self.ids[old_id]
       
  1024                 dupname(old_node, name)
       
  1025             dupname(node, name)
       
  1026         if not explicit or (not old_explicit and old_id is not None):
       
  1027             msg = self.reporter.info(
       
  1028                 'Duplicate implicit target name: "%s".' % name,
       
  1029                 backrefs=[id], base_node=node)
       
  1030             if msgnode != None:
       
  1031                 msgnode += msg
       
  1032 
       
  1033     def has_name(self, name):
       
  1034         return self.nameids.has_key(name)
       
  1035 
       
  1036     # "note" here is an imperative verb: "take note of".
       
  1037     def note_implicit_target(self, target, msgnode=None):
       
  1038         id = self.set_id(target, msgnode)
       
  1039         self.set_name_id_map(target, id, msgnode, explicit=None)
       
  1040 
       
  1041     def note_explicit_target(self, target, msgnode=None):
       
  1042         id = self.set_id(target, msgnode)
       
  1043         self.set_name_id_map(target, id, msgnode, explicit=1)
       
  1044 
       
  1045     def note_refname(self, node):
       
  1046         self.refnames.setdefault(node['refname'], []).append(node)
       
  1047 
       
  1048     def note_refid(self, node):
       
  1049         self.refids.setdefault(node['refid'], []).append(node)
       
  1050 
       
  1051     def note_indirect_target(self, target):
       
  1052         self.indirect_targets.append(target)
       
  1053         if target['names']:
       
  1054             self.note_refname(target)
       
  1055 
       
  1056     def note_anonymous_target(self, target):
       
  1057         self.set_id(target)
       
  1058 
       
  1059     def note_autofootnote(self, footnote):
       
  1060         self.set_id(footnote)
       
  1061         self.autofootnotes.append(footnote)
       
  1062 
       
  1063     def note_autofootnote_ref(self, ref):
       
  1064         self.set_id(ref)
       
  1065         self.autofootnote_refs.append(ref)
       
  1066 
       
  1067     def note_symbol_footnote(self, footnote):
       
  1068         self.set_id(footnote)
       
  1069         self.symbol_footnotes.append(footnote)
       
  1070 
       
  1071     def note_symbol_footnote_ref(self, ref):
       
  1072         self.set_id(ref)
       
  1073         self.symbol_footnote_refs.append(ref)
       
  1074 
       
  1075     def note_footnote(self, footnote):
       
  1076         self.set_id(footnote)
       
  1077         self.footnotes.append(footnote)
       
  1078 
       
  1079     def note_footnote_ref(self, ref):
       
  1080         self.set_id(ref)
       
  1081         self.footnote_refs.setdefault(ref['refname'], []).append(ref)
       
  1082         self.note_refname(ref)
       
  1083 
       
  1084     def note_citation(self, citation):
       
  1085         self.citations.append(citation)
       
  1086 
       
  1087     def note_citation_ref(self, ref):
       
  1088         self.set_id(ref)
       
  1089         self.citation_refs.setdefault(ref['refname'], []).append(ref)
       
  1090         self.note_refname(ref)
       
  1091 
       
  1092     def note_substitution_def(self, subdef, def_name, msgnode=None):
       
  1093         name = whitespace_normalize_name(def_name)
       
  1094         if self.substitution_defs.has_key(name):
       
  1095             msg = self.reporter.error(
       
  1096                   'Duplicate substitution definition name: "%s".' % name,
       
  1097                   base_node=subdef)
       
  1098             if msgnode != None:
       
  1099                 msgnode += msg
       
  1100             oldnode = self.substitution_defs[name]
       
  1101             dupname(oldnode, name)
       
  1102         # keep only the last definition:
       
  1103         self.substitution_defs[name] = subdef
       
  1104         # case-insensitive mapping:
       
  1105         self.substitution_names[fully_normalize_name(name)] = name
       
  1106 
       
  1107     def note_substitution_ref(self, subref, refname):
       
  1108         subref['refname'] = whitespace_normalize_name(refname)
       
  1109 
       
  1110     def note_pending(self, pending, priority=None):
       
  1111         self.transformer.add_pending(pending, priority)
       
  1112 
       
  1113     def note_parse_message(self, message):
       
  1114         self.parse_messages.append(message)
       
  1115 
       
  1116     def note_transform_message(self, message):
       
  1117         self.transform_messages.append(message)
       
  1118 
       
  1119     def note_source(self, source, offset):
       
  1120         self.current_source = source
       
  1121         if offset is None:
       
  1122             self.current_line = offset
       
  1123         else:
       
  1124             self.current_line = offset + 1
       
  1125 
       
  1126     def copy(self):
       
  1127         return self.__class__(self.settings, self.reporter,
       
  1128                               **self.attributes)
       
  1129 
       
  1130     def get_decoration(self):
       
  1131         if not self.decoration:
       
  1132             self.decoration = decoration()
       
  1133             index = self.first_child_not_matching_class(Titular)
       
  1134             if index is None:
       
  1135                 self.append(self.decoration)
       
  1136             else:
       
  1137                 self.insert(index, self.decoration)
       
  1138         return self.decoration
       
  1139 
       
  1140 
       
  1141 # ================
       
  1142 #  Title Elements
       
  1143 # ================
       
  1144 
       
  1145 class title(Titular, PreBibliographic, TextElement): pass
       
  1146 class subtitle(Titular, PreBibliographic, TextElement): pass
       
  1147 class rubric(Titular, TextElement): pass
       
  1148 
       
  1149 
       
  1150 # ========================
       
  1151 #  Bibliographic Elements
       
  1152 # ========================
       
  1153 
       
  1154 class docinfo(Bibliographic, Element): pass
       
  1155 class author(Bibliographic, TextElement): pass
       
  1156 class authors(Bibliographic, Element): pass
       
  1157 class organization(Bibliographic, TextElement): pass
       
  1158 class address(Bibliographic, FixedTextElement): pass
       
  1159 class contact(Bibliographic, TextElement): pass
       
  1160 class version(Bibliographic, TextElement): pass
       
  1161 class revision(Bibliographic, TextElement): pass
       
  1162 class status(Bibliographic, TextElement): pass
       
  1163 class date(Bibliographic, TextElement): pass
       
  1164 class copyright(Bibliographic, TextElement): pass
       
  1165 
       
  1166 
       
  1167 # =====================
       
  1168 #  Decorative Elements
       
  1169 # =====================
       
  1170 
       
  1171 class decoration(Decorative, Element):
       
  1172 
       
  1173     def get_header(self):
       
  1174         if not len(self.children) or not isinstance(self.children[0], header):
       
  1175             self.insert(0, header())
       
  1176         return self.children[0]
       
  1177 
       
  1178     def get_footer(self):
       
  1179         if not len(self.children) or not isinstance(self.children[-1], footer):
       
  1180             self.append(footer())
       
  1181         return self.children[-1]
       
  1182 
       
  1183 
       
  1184 class header(Decorative, Element): pass
       
  1185 class footer(Decorative, Element): pass
       
  1186 
       
  1187 
       
  1188 # =====================
       
  1189 #  Structural Elements
       
  1190 # =====================
       
  1191 
       
  1192 class section(Structural, Element): pass
       
  1193 
       
  1194 
       
  1195 class topic(Structural, Element):
       
  1196 
       
  1197     """
       
  1198     Topics are terminal, "leaf" mini-sections, like block quotes with titles,
       
  1199     or textual figures.  A topic is just like a section, except that it has no
       
  1200     subsections, and it doesn't have to conform to section placement rules.
       
  1201 
       
  1202     Topics are allowed wherever body elements (list, table, etc.) are allowed,
       
  1203     but only at the top level of a section or document.  Topics cannot nest
       
  1204     inside topics, sidebars, or body elements; you can't have a topic inside a
       
  1205     table, list, block quote, etc.
       
  1206     """
       
  1207 
       
  1208 
       
  1209 class sidebar(Structural, Element):
       
  1210 
       
  1211     """
       
  1212     Sidebars are like miniature, parallel documents that occur inside other
       
  1213     documents, providing related or reference material.  A sidebar is
       
  1214     typically offset by a border and "floats" to the side of the page; the
       
  1215     document's main text may flow around it.  Sidebars can also be likened to
       
  1216     super-footnotes; their content is outside of the flow of the document's
       
  1217     main text.
       
  1218 
       
  1219     Sidebars are allowed wherever body elements (list, table, etc.) are
       
  1220     allowed, but only at the top level of a section or document.  Sidebars
       
  1221     cannot nest inside sidebars, topics, or body elements; you can't have a
       
  1222     sidebar inside a table, list, block quote, etc.
       
  1223     """
       
  1224 
       
  1225 
       
  1226 class transition(Structural, Element): pass
       
  1227 
       
  1228 
       
  1229 # ===============
       
  1230 #  Body Elements
       
  1231 # ===============
       
  1232 
       
  1233 class paragraph(General, TextElement): pass
       
  1234 class compound(General, Element): pass
       
  1235 class container(General, Element): pass
       
  1236 class bullet_list(Sequential, Element): pass
       
  1237 class enumerated_list(Sequential, Element): pass
       
  1238 class list_item(Part, Element): pass
       
  1239 class definition_list(Sequential, Element): pass
       
  1240 class definition_list_item(Part, Element): pass
       
  1241 class term(Part, TextElement): pass
       
  1242 class classifier(Part, TextElement): pass
       
  1243 class definition(Part, Element): pass
       
  1244 class field_list(Sequential, Element): pass
       
  1245 class field(Part, Element): pass
       
  1246 class field_name(Part, TextElement): pass
       
  1247 class field_body(Part, Element): pass
       
  1248 
       
  1249 
       
  1250 class option(Part, Element):
       
  1251 
       
  1252     child_text_separator = ''
       
  1253 
       
  1254 
       
  1255 class option_argument(Part, TextElement):
       
  1256 
       
  1257     def astext(self):
       
  1258         return self.get('delimiter', ' ') + TextElement.astext(self)
       
  1259 
       
  1260 
       
  1261 class option_group(Part, Element):
       
  1262 
       
  1263     child_text_separator = ', '
       
  1264 
       
  1265 
       
  1266 class option_list(Sequential, Element): pass
       
  1267 
       
  1268 
       
  1269 class option_list_item(Part, Element):
       
  1270 
       
  1271     child_text_separator = '  '
       
  1272 
       
  1273 
       
  1274 class option_string(Part, TextElement): pass
       
  1275 class description(Part, Element): pass
       
  1276 class literal_block(General, FixedTextElement): pass
       
  1277 class doctest_block(General, FixedTextElement): pass
       
  1278 class line_block(General, Element): pass
       
  1279 
       
  1280 
       
  1281 class line(Part, TextElement):
       
  1282 
       
  1283     indent = None
       
  1284 
       
  1285 
       
  1286 class block_quote(General, Element): pass
       
  1287 class attribution(Part, TextElement): pass
       
  1288 class attention(Admonition, Element): pass
       
  1289 class caution(Admonition, Element): pass
       
  1290 class danger(Admonition, Element): pass
       
  1291 class error(Admonition, Element): pass
       
  1292 class important(Admonition, Element): pass
       
  1293 class note(Admonition, Element): pass
       
  1294 class tip(Admonition, Element): pass
       
  1295 class hint(Admonition, Element): pass
       
  1296 class warning(Admonition, Element): pass
       
  1297 class admonition(Admonition, Element): pass
       
  1298 class comment(Special, Invisible, FixedTextElement): pass
       
  1299 class substitution_definition(Special, Invisible, TextElement): pass
       
  1300 class target(Special, Invisible, Inline, TextElement, Targetable): pass
       
  1301 class footnote(General, BackLinkable, Element, Labeled, Targetable): pass
       
  1302 class citation(General, BackLinkable, Element, Labeled, Targetable): pass
       
  1303 class label(Part, TextElement): pass
       
  1304 class figure(General, Element): pass
       
  1305 class caption(Part, TextElement): pass
       
  1306 class legend(Part, Element): pass
       
  1307 class table(General, Element): pass
       
  1308 class tgroup(Part, Element): pass
       
  1309 class colspec(Part, Element): pass
       
  1310 class thead(Part, Element): pass
       
  1311 class tbody(Part, Element): pass
       
  1312 class row(Part, Element): pass
       
  1313 class entry(Part, Element): pass
       
  1314 
       
  1315 
       
  1316 class system_message(Special, BackLinkable, PreBibliographic, Element):
       
  1317 
       
  1318     """
       
  1319     System message element.
       
  1320 
       
  1321     Do not instantiate this class directly; use
       
  1322     ``document.reporter.info/warning/error/severe()`` instead.
       
  1323     """
       
  1324 
       
  1325     def __init__(self, message=None, *children, **attributes):
       
  1326         if message:
       
  1327             p = paragraph('', message)
       
  1328             children = (p,) + children
       
  1329         try:
       
  1330             Element.__init__(self, '', *children, **attributes)
       
  1331         except:
       
  1332             print 'system_message: children=%r' % (children,)
       
  1333             raise
       
  1334 
       
  1335     def astext(self):
       
  1336         line = self.get('line', '')
       
  1337         return u'%s:%s: (%s/%s) %s' % (self['source'], line, self['type'],
       
  1338                                        self['level'], Element.astext(self))
       
  1339 
       
  1340 
       
  1341 class pending(Special, Invisible, Element):
       
  1342 
       
  1343     """
       
  1344     The "pending" element is used to encapsulate a pending operation: the
       
  1345     operation (transform), the point at which to apply it, and any data it
       
  1346     requires.  Only the pending operation's location within the document is
       
  1347     stored in the public document tree (by the "pending" object itself); the
       
  1348     operation and its data are stored in the "pending" object's internal
       
  1349     instance attributes.
       
  1350 
       
  1351     For example, say you want a table of contents in your reStructuredText
       
  1352     document.  The easiest way to specify where to put it is from within the
       
  1353     document, with a directive::
       
  1354 
       
  1355         .. contents::
       
  1356 
       
  1357     But the "contents" directive can't do its work until the entire document
       
  1358     has been parsed and possibly transformed to some extent.  So the directive
       
  1359     code leaves a placeholder behind that will trigger the second phase of its
       
  1360     processing, something like this::
       
  1361 
       
  1362         <pending ...public attributes...> + internal attributes
       
  1363 
       
  1364     Use `document.note_pending()` so that the
       
  1365     `docutils.transforms.Transformer` stage of processing can run all pending
       
  1366     transforms.
       
  1367     """
       
  1368 
       
  1369     def __init__(self, transform, details=None,
       
  1370                  rawsource='', *children, **attributes):
       
  1371         Element.__init__(self, rawsource, *children, **attributes)
       
  1372 
       
  1373         self.transform = transform
       
  1374         """The `docutils.transforms.Transform` class implementing the pending
       
  1375         operation."""
       
  1376 
       
  1377         self.details = details or {}
       
  1378         """Detail data (dictionary) required by the pending operation."""
       
  1379 
       
  1380     def pformat(self, indent='    ', level=0):
       
  1381         internals = [
       
  1382               '.. internal attributes:',
       
  1383               '     .transform: %s.%s' % (self.transform.__module__,
       
  1384                                           self.transform.__name__),
       
  1385               '     .details:']
       
  1386         details = self.details.items()
       
  1387         details.sort()
       
  1388         for key, value in details:
       
  1389             if isinstance(value, Node):
       
  1390                 internals.append('%7s%s:' % ('', key))
       
  1391                 internals.extend(['%9s%s' % ('', line)
       
  1392                                   for line in value.pformat().splitlines()])
       
  1393             elif value and isinstance(value, ListType) \
       
  1394                   and isinstance(value[0], Node):
       
  1395                 internals.append('%7s%s:' % ('', key))
       
  1396                 for v in value:
       
  1397                     internals.extend(['%9s%s' % ('', line)
       
  1398                                       for line in v.pformat().splitlines()])
       
  1399             else:
       
  1400                 internals.append('%7s%s: %r' % ('', key, value))
       
  1401         return (Element.pformat(self, indent, level)
       
  1402                 + ''.join([('    %s%s\n' % (indent * level, line))
       
  1403                            for line in internals]))
       
  1404 
       
  1405     def copy(self):
       
  1406         return self.__class__(self.transform, self.details, self.rawsource,
       
  1407                               **self.attributes)
       
  1408 
       
  1409 
       
  1410 class raw(Special, Inline, PreBibliographic, FixedTextElement):
       
  1411 
       
  1412     """
       
  1413     Raw data that is to be passed untouched to the Writer.
       
  1414     """
       
  1415 
       
  1416     pass
       
  1417 
       
  1418 
       
  1419 # =================
       
  1420 #  Inline Elements
       
  1421 # =================
       
  1422 
       
  1423 class emphasis(Inline, TextElement): pass
       
  1424 class strong(Inline, TextElement): pass
       
  1425 class literal(Inline, TextElement): pass
       
  1426 class reference(General, Inline, Referential, TextElement): pass
       
  1427 class footnote_reference(Inline, Referential, TextElement): pass
       
  1428 class citation_reference(Inline, Referential, TextElement): pass
       
  1429 class substitution_reference(Inline, TextElement): pass
       
  1430 class title_reference(Inline, TextElement): pass
       
  1431 class abbreviation(Inline, TextElement): pass
       
  1432 class acronym(Inline, TextElement): pass
       
  1433 class superscript(Inline, TextElement): pass
       
  1434 class subscript(Inline, TextElement): pass
       
  1435 
       
  1436 
       
  1437 class image(General, Inline, Element):
       
  1438 
       
  1439     def astext(self):
       
  1440         return self.get('alt', '')
       
  1441 
       
  1442 
       
  1443 class inline(Inline, TextElement): pass
       
  1444 class problematic(Inline, TextElement): pass
       
  1445 class generated(Inline, TextElement): pass
       
  1446 
       
  1447 
       
  1448 # ========================================
       
  1449 #  Auxiliary Classes, Functions, and Data
       
  1450 # ========================================
       
  1451 
       
  1452 node_class_names = """
       
  1453     Text
       
  1454     abbreviation acronym address admonition attention attribution author
       
  1455         authors
       
  1456     block_quote bullet_list
       
  1457     caption caution citation citation_reference classifier colspec comment
       
  1458         compound contact container copyright
       
  1459     danger date decoration definition definition_list definition_list_item
       
  1460         description docinfo doctest_block document
       
  1461     emphasis entry enumerated_list error
       
  1462     field field_body field_list field_name figure footer
       
  1463         footnote footnote_reference
       
  1464     generated
       
  1465     header hint
       
  1466     image important inline
       
  1467     label legend line line_block list_item literal literal_block
       
  1468     note
       
  1469     option option_argument option_group option_list option_list_item
       
  1470         option_string organization
       
  1471     paragraph pending problematic
       
  1472     raw reference revision row rubric
       
  1473     section sidebar status strong subscript substitution_definition
       
  1474         substitution_reference subtitle superscript system_message
       
  1475     table target tbody term tgroup thead tip title title_reference topic
       
  1476         transition
       
  1477     version
       
  1478     warning""".split()
       
  1479 """A list of names of all concrete Node subclasses."""
       
  1480 
       
  1481 
       
  1482 class NodeVisitor:
       
  1483 
       
  1484     """
       
  1485     "Visitor" pattern [GoF95]_ abstract superclass implementation for
       
  1486     document tree traversals.
       
  1487 
       
  1488     Each node class has corresponding methods, doing nothing by
       
  1489     default; override individual methods for specific and useful
       
  1490     behaviour.  The `dispatch_visit()` method is called by
       
  1491     `Node.walk()` upon entering a node.  `Node.walkabout()` also calls
       
  1492     the `dispatch_departure()` method before exiting a node.
       
  1493 
       
  1494     The dispatch methods call "``visit_`` + node class name" or
       
  1495     "``depart_`` + node class name", resp.
       
  1496 
       
  1497     This is a base class for visitors whose ``visit_...`` & ``depart_...``
       
  1498     methods should be implemented for *all* node types encountered (such as
       
  1499     for `docutils.writers.Writer` subclasses).  Unimplemented methods will
       
  1500     raise exceptions.
       
  1501 
       
  1502     For sparse traversals, where only certain node types are of interest,
       
  1503     subclass `SparseNodeVisitor` instead.  When (mostly or entirely) uniform
       
  1504     processing is desired, subclass `GenericNodeVisitor`.
       
  1505 
       
  1506     .. [GoF95] Gamma, Helm, Johnson, Vlissides. *Design Patterns: Elements of
       
  1507        Reusable Object-Oriented Software*. Addison-Wesley, Reading, MA, USA,
       
  1508        1995.
       
  1509     """
       
  1510 
       
  1511     optional = ()
       
  1512     """
       
  1513     Tuple containing node class names (as strings).
       
  1514 
       
  1515     No exception will be raised if writers do not implement visit
       
  1516     or departure functions for these node classes.
       
  1517 
       
  1518     Used to ensure transitional compatibility with existing 3rd-party writers.
       
  1519     """
       
  1520 
       
  1521     def __init__(self, document):
       
  1522         self.document = document
       
  1523 
       
  1524     def dispatch_visit(self, node):
       
  1525         """
       
  1526         Call self."``visit_`` + node class name" with `node` as
       
  1527         parameter.  If the ``visit_...`` method does not exist, call
       
  1528         self.unknown_visit.
       
  1529         """
       
  1530         node_name = node.__class__.__name__
       
  1531         method = getattr(self, 'visit_' + node_name, self.unknown_visit)
       
  1532         self.document.reporter.debug(
       
  1533             'docutils.nodes.NodeVisitor.dispatch_visit calling %s for %s'
       
  1534             % (method.__name__, node_name))
       
  1535         return method(node)
       
  1536 
       
  1537     def dispatch_departure(self, node):
       
  1538         """
       
  1539         Call self."``depart_`` + node class name" with `node` as
       
  1540         parameter.  If the ``depart_...`` method does not exist, call
       
  1541         self.unknown_departure.
       
  1542         """
       
  1543         node_name = node.__class__.__name__
       
  1544         method = getattr(self, 'depart_' + node_name, self.unknown_departure)
       
  1545         self.document.reporter.debug(
       
  1546             'docutils.nodes.NodeVisitor.dispatch_departure calling %s for %s'
       
  1547             % (method.__name__, node_name))
       
  1548         return method(node)
       
  1549 
       
  1550     def unknown_visit(self, node):
       
  1551         """
       
  1552         Called when entering unknown `Node` types.
       
  1553 
       
  1554         Raise an exception unless overridden.
       
  1555         """
       
  1556         if  (node.document.settings.strict_visitor
       
  1557              or node.__class__.__name__ not in self.optional):
       
  1558             raise NotImplementedError(
       
  1559                 '%s visiting unknown node type: %s'
       
  1560                 % (self.__class__, node.__class__.__name__))
       
  1561 
       
  1562     def unknown_departure(self, node):
       
  1563         """
       
  1564         Called before exiting unknown `Node` types.
       
  1565 
       
  1566         Raise exception unless overridden.
       
  1567         """
       
  1568         if  (node.document.settings.strict_visitor
       
  1569              or node.__class__.__name__ not in self.optional):
       
  1570             raise NotImplementedError(
       
  1571                 '%s departing unknown node type: %s'
       
  1572                 % (self.__class__, node.__class__.__name__))
       
  1573 
       
  1574 
       
  1575 class SparseNodeVisitor(NodeVisitor):
       
  1576 
       
  1577     """
       
  1578     Base class for sparse traversals, where only certain node types are of
       
  1579     interest.  When ``visit_...`` & ``depart_...`` methods should be
       
  1580     implemented for *all* node types (such as for `docutils.writers.Writer`
       
  1581     subclasses), subclass `NodeVisitor` instead.
       
  1582     """
       
  1583 
       
  1584 
       
  1585 class GenericNodeVisitor(NodeVisitor):
       
  1586 
       
  1587     """
       
  1588     Generic "Visitor" abstract superclass, for simple traversals.
       
  1589 
       
  1590     Unless overridden, each ``visit_...`` method calls `default_visit()`, and
       
  1591     each ``depart_...`` method (when using `Node.walkabout()`) calls
       
  1592     `default_departure()`. `default_visit()` (and `default_departure()`) must
       
  1593     be overridden in subclasses.
       
  1594 
       
  1595     Define fully generic visitors by overriding `default_visit()` (and
       
  1596     `default_departure()`) only. Define semi-generic visitors by overriding
       
  1597     individual ``visit_...()`` (and ``depart_...()``) methods also.
       
  1598 
       
  1599     `NodeVisitor.unknown_visit()` (`NodeVisitor.unknown_departure()`) should
       
  1600     be overridden for default behavior.
       
  1601     """
       
  1602 
       
  1603     def default_visit(self, node):
       
  1604         """Override for generic, uniform traversals."""
       
  1605         raise NotImplementedError
       
  1606 
       
  1607     def default_departure(self, node):
       
  1608         """Override for generic, uniform traversals."""
       
  1609         raise NotImplementedError
       
  1610 
       
  1611 def _call_default_visit(self, node):
       
  1612     self.default_visit(node)
       
  1613 
       
  1614 def _call_default_departure(self, node):
       
  1615     self.default_departure(node)
       
  1616 
       
  1617 def _nop(self, node):
       
  1618     pass
       
  1619 
       
  1620 def _add_node_class_names(names):
       
  1621     """Save typing with dynamic assignments:"""
       
  1622     for _name in names:
       
  1623         setattr(GenericNodeVisitor, "visit_" + _name, _call_default_visit)
       
  1624         setattr(GenericNodeVisitor, "depart_" + _name, _call_default_departure)
       
  1625         setattr(SparseNodeVisitor, 'visit_' + _name, _nop)
       
  1626         setattr(SparseNodeVisitor, 'depart_' + _name, _nop)
       
  1627 
       
  1628 _add_node_class_names(node_class_names)
       
  1629 
       
  1630 
       
  1631 class TreeCopyVisitor(GenericNodeVisitor):
       
  1632 
       
  1633     """
       
  1634     Make a complete copy of a tree or branch, including element attributes.
       
  1635     """
       
  1636 
       
  1637     def __init__(self, document):
       
  1638         GenericNodeVisitor.__init__(self, document)
       
  1639         self.parent_stack = []
       
  1640         self.parent = []
       
  1641 
       
  1642     def get_tree_copy(self):
       
  1643         return self.parent[0]
       
  1644 
       
  1645     def default_visit(self, node):
       
  1646         """Copy the current node, and make it the new acting parent."""
       
  1647         newnode = node.copy()
       
  1648         self.parent.append(newnode)
       
  1649         self.parent_stack.append(self.parent)
       
  1650         self.parent = newnode
       
  1651 
       
  1652     def default_departure(self, node):
       
  1653         """Restore the previous acting parent."""
       
  1654         self.parent = self.parent_stack.pop()
       
  1655 
       
  1656 
       
  1657 class TreePruningException(Exception):
       
  1658 
       
  1659     """
       
  1660     Base class for `NodeVisitor`-related tree pruning exceptions.
       
  1661 
       
  1662     Raise subclasses from within ``visit_...`` or ``depart_...`` methods
       
  1663     called from `Node.walk()` and `Node.walkabout()` tree traversals to prune
       
  1664     the tree traversed.
       
  1665     """
       
  1666 
       
  1667     pass
       
  1668 
       
  1669 
       
  1670 class SkipChildren(TreePruningException):
       
  1671 
       
  1672     """
       
  1673     Do not visit any children of the current node.  The current node's
       
  1674     siblings and ``depart_...`` method are not affected.
       
  1675     """
       
  1676 
       
  1677     pass
       
  1678 
       
  1679 
       
  1680 class SkipSiblings(TreePruningException):
       
  1681 
       
  1682     """
       
  1683     Do not visit any more siblings (to the right) of the current node.  The
       
  1684     current node's children and its ``depart_...`` method are not affected.
       
  1685     """
       
  1686 
       
  1687     pass
       
  1688 
       
  1689 
       
  1690 class SkipNode(TreePruningException):
       
  1691 
       
  1692     """
       
  1693     Do not visit the current node's children, and do not call the current
       
  1694     node's ``depart_...`` method.
       
  1695     """
       
  1696 
       
  1697     pass
       
  1698 
       
  1699 
       
  1700 class SkipDeparture(TreePruningException):
       
  1701 
       
  1702     """
       
  1703     Do not call the current node's ``depart_...`` method.  The current node's
       
  1704     children and siblings are not affected.
       
  1705     """
       
  1706 
       
  1707     pass
       
  1708 
       
  1709 
       
  1710 class NodeFound(TreePruningException):
       
  1711 
       
  1712     """
       
  1713     Raise to indicate that the target of a search has been found.  This
       
  1714     exception must be caught by the client; it is not caught by the traversal
       
  1715     code.
       
  1716     """
       
  1717 
       
  1718     pass
       
  1719 
       
  1720 
       
  1721 class StopTraversal(TreePruningException):
       
  1722 
       
  1723     """
       
  1724     Stop the traversal alltogether.  The current node's ``depart_...`` method
       
  1725     is not affected.  The parent nodes ``depart_...`` methods are also called
       
  1726     as usual.  No other nodes are visited.  This is an alternative to
       
  1727     NodeFound that does not cause exception handling to trickle up to the
       
  1728     caller.
       
  1729     """
       
  1730 
       
  1731     pass
       
  1732 
       
  1733 
       
  1734 def make_id(string):
       
  1735     """
       
  1736     Convert `string` into an identifier and return it.
       
  1737 
       
  1738     Docutils identifiers will conform to the regular expression
       
  1739     ``[a-z](-?[a-z0-9]+)*``.  For CSS compatibility, identifiers (the "class"
       
  1740     and "id" attributes) should have no underscores, colons, or periods.
       
  1741     Hyphens may be used.
       
  1742 
       
  1743     - The `HTML 4.01 spec`_ defines identifiers based on SGML tokens:
       
  1744 
       
  1745           ID and NAME tokens must begin with a letter ([A-Za-z]) and may be
       
  1746           followed by any number of letters, digits ([0-9]), hyphens ("-"),
       
  1747           underscores ("_"), colons (":"), and periods (".").
       
  1748 
       
  1749     - However the `CSS1 spec`_ defines identifiers based on the "name" token,
       
  1750       a tighter interpretation ("flex" tokenizer notation; "latin1" and
       
  1751       "escape" 8-bit characters have been replaced with entities)::
       
  1752 
       
  1753           unicode     \\[0-9a-f]{1,4}
       
  1754           latin1      [&iexcl;-&yuml;]
       
  1755           escape      {unicode}|\\[ -~&iexcl;-&yuml;]
       
  1756           nmchar      [-a-z0-9]|{latin1}|{escape}
       
  1757           name        {nmchar}+
       
  1758 
       
  1759     The CSS1 "nmchar" rule does not include underscores ("_"), colons (":"),
       
  1760     or periods ("."), therefore "class" and "id" attributes should not contain
       
  1761     these characters. They should be replaced with hyphens ("-"). Combined
       
  1762     with HTML's requirements (the first character must be a letter; no
       
  1763     "unicode", "latin1", or "escape" characters), this results in the
       
  1764     ``[a-z](-?[a-z0-9]+)*`` pattern.
       
  1765 
       
  1766     .. _HTML 4.01 spec: http://www.w3.org/TR/html401
       
  1767     .. _CSS1 spec: http://www.w3.org/TR/REC-CSS1
       
  1768     """
       
  1769     id = _non_id_chars.sub('-', ' '.join(string.lower().split()))
       
  1770     id = _non_id_at_ends.sub('', id)
       
  1771     return str(id)
       
  1772 
       
  1773 _non_id_chars = re.compile('[^a-z0-9]+')
       
  1774 _non_id_at_ends = re.compile('^[-0-9]+|-+$')
       
  1775 
       
  1776 def dupname(node, name):
       
  1777     node['dupnames'].append(name)
       
  1778     node['names'].remove(name)
       
  1779     # Assume that this method is referenced, even though it isn't; we
       
  1780     # don't want to throw unnecessary system_messages.
       
  1781     node.referenced = 1
       
  1782 
       
  1783 def fully_normalize_name(name):
       
  1784     """Return a case- and whitespace-normalized name."""
       
  1785     return ' '.join(name.lower().split())
       
  1786 
       
  1787 def whitespace_normalize_name(name):
       
  1788     """Return a whitespace-normalized name."""
       
  1789     return ' '.join(name.split())
       
  1790 
       
  1791 def serial_escape(value):
       
  1792     """Escape string values that are elements of a list, for serialization."""
       
  1793     return value.replace('\\', r'\\').replace(' ', r'\ ')
       
  1794 
       
  1795 # 
       
  1796 #
       
  1797 # Local Variables:
       
  1798 # indent-tabs-mode: nil
       
  1799 # sentence-end-double-space: t
       
  1800 # fill-column: 78
       
  1801 # End: