buildframework/helium/external/python/lib/common/docutils-0.5-py2.5.egg/docutils/parsers/rst/__init__.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: __init__.py 4802 2006-11-12 18:02:17Z goodger $
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
This is ``docutils.parsers.rst`` package. It exports a single class, `Parser`,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     7
the reStructuredText parser.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     8
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     9
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    10
Usage
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    11
=====
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    12
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    13
1. Create a parser::
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    14
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    15
       parser = docutils.parsers.rst.Parser()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    16
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    17
   Several optional arguments may be passed to modify the parser's behavior.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    18
   Please see `Customizing the Parser`_ below for details.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    19
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    20
2. Gather input (a multi-line string), by reading a file or the standard
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    21
   input::
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    22
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    23
       input = sys.stdin.read()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    24
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    25
3. Create a new empty `docutils.nodes.document` tree::
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    26
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    27
       document = docutils.utils.new_document(source, settings)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    28
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    29
   See `docutils.utils.new_document()` for parameter details.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    30
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    31
4. Run the parser, populating the document tree::
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    32
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    33
       parser.parse(input, document)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    34
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    35
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    36
Parser Overview
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    37
===============
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    38
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    39
The reStructuredText parser is implemented as a state machine, examining its
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    40
input one line at a time. To understand how the parser works, please first
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    41
become familiar with the `docutils.statemachine` module, then see the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    42
`states` module.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    43
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    44
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    45
Customizing the Parser
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    46
----------------------
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    47
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    48
Anything that isn't already customizable is that way simply because that type
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    49
of customizability hasn't been implemented yet.  Patches welcome!
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    50
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    51
When instantiating an object of the `Parser` class, two parameters may be
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    52
passed: ``rfc2822`` and ``inliner``.  Pass ``rfc2822=1`` to enable an initial
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    53
RFC-2822 style header block, parsed as a "field_list" element (with "class"
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    54
attribute set to "rfc2822").  Currently this is the only body-level element
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    55
which is customizable without subclassing.  (Tip: subclass `Parser` and change
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    56
its "state_classes" and "initial_state" attributes to refer to new classes.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    57
Contact the author if you need more details.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    58
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    59
The ``inliner`` parameter takes an instance of `states.Inliner` or a subclass.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    60
It handles inline markup recognition.  A common extension is the addition of
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    61
further implicit hyperlinks, like "RFC 2822".  This can be done by subclassing
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    62
`states.Inliner`, adding a new method for the implicit markup, and adding a
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    63
``(pattern, method)`` pair to the "implicit_dispatch" attribute of the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    64
subclass.  See `states.Inliner.implicit_inline()` for details.  Explicit
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    65
inline markup can be customized in a `states.Inliner` subclass via the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    66
``patterns.initial`` and ``dispatch`` attributes (and new methods as
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    67
appropriate).
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
__docformat__ = 'reStructuredText'
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
import docutils.parsers
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    74
import docutils.statemachine
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    75
from docutils.parsers.rst import states
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    76
from docutils import frontend, nodes
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    77
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    78
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    79
class Parser(docutils.parsers.Parser):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    80
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    81
    """The reStructuredText parser."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    82
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    83
    supported = ('restructuredtext', 'rst', 'rest', 'restx', 'rtxt', 'rstx')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    84
    """Aliases this parser supports."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    85
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    86
    settings_spec = (
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    87
        'reStructuredText Parser Options',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    88
        None,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    89
        (('Recognize and link to standalone PEP references (like "PEP 258").',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    90
          ['--pep-references'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    91
          {'action': 'store_true', 'validator': frontend.validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    92
         ('Base URL for PEP references '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    93
          '(default "http://www.python.org/dev/peps/").',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    94
          ['--pep-base-url'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    95
          {'metavar': '<URL>', 'default': 'http://www.python.org/dev/peps/',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    96
           'validator': frontend.validate_url_trailing_slash}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    97
         ('Template for PEP file part of URL. (default "pep-%04d")',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    98
          ['--pep-file-url-template'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    99
          {'metavar': '<URL>', 'default': 'pep-%04d'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   100
         ('Recognize and link to standalone RFC references (like "RFC 822").',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   101
          ['--rfc-references'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   102
          {'action': 'store_true', 'validator': frontend.validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   103
         ('Base URL for RFC references (default "http://www.faqs.org/rfcs/").',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   104
          ['--rfc-base-url'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   105
          {'metavar': '<URL>', 'default': 'http://www.faqs.org/rfcs/',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   106
           'validator': frontend.validate_url_trailing_slash}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   107
         ('Set number of spaces for tab expansion (default 8).',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   108
          ['--tab-width'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   109
          {'metavar': '<width>', 'type': 'int', 'default': 8,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   110
           'validator': frontend.validate_nonnegative_int}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   111
         ('Remove spaces before footnote references.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   112
          ['--trim-footnote-reference-space'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   113
          {'action': 'store_true', 'validator': frontend.validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   114
         ('Leave spaces before footnote references.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   115
          ['--leave-footnote-reference-space'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   116
          {'action': 'store_false', 'dest': 'trim_footnote_reference_space'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   117
         ('Disable directives that insert the contents of external file '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   118
          '("include" & "raw"); replaced with a "warning" system message.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   119
          ['--no-file-insertion'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   120
          {'action': 'store_false', 'default': 1,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   121
           'dest': 'file_insertion_enabled',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   122
           'validator': frontend.validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   123
         ('Enable directives that insert the contents of external file '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   124
          '("include" & "raw").  Enabled by default.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   125
          ['--file-insertion-enabled'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   126
          {'action': 'store_true'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   127
         ('Disable the "raw" directives; replaced with a "warning" '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   128
          'system message.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   129
          ['--no-raw'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   130
          {'action': 'store_false', 'default': 1, 'dest': 'raw_enabled',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   131
           'validator': frontend.validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   132
         ('Enable the "raw" directive.  Enabled by default.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   133
          ['--raw-enabled'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   134
          {'action': 'store_true'}),))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   135
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   136
    config_section = 'restructuredtext parser'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   137
    config_section_dependencies = ('parsers',)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   138
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   139
    def __init__(self, rfc2822=None, inliner=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   140
        if rfc2822:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   141
            self.initial_state = 'RFC2822Body'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   142
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   143
            self.initial_state = 'Body'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   144
        self.state_classes = states.state_classes
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   145
        self.inliner = inliner
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   146
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   147
    def parse(self, inputstring, document):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   148
        """Parse `inputstring` and populate `document`, a document tree."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   149
        self.setup_parse(inputstring, document)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   150
        self.statemachine = states.RSTStateMachine(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   151
              state_classes=self.state_classes,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   152
              initial_state=self.initial_state,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   153
              debug=document.reporter.debug_flag)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   154
        inputlines = docutils.statemachine.string2lines(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   155
              inputstring, tab_width=document.settings.tab_width,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   156
              convert_whitespace=1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   157
        self.statemachine.run(inputlines, document, inliner=self.inliner)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   158
        self.finish_parse()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   159
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   160
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   161
class DirectiveError(Exception):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   162
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   163
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   164
    Store a message and a system message level.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   165
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   166
    To be thrown from inside directive code.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   167
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   168
    Do not instantiate directly -- use `Directive.directive_error()`
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   169
    instead!
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   170
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   171
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   172
    def __init__(self, level, message):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   173
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   174
        Initialize with message `message`.  `level` is a system message level.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   175
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   176
        Exception.__init__(self)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   177
        self.level = level
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   178
        self.message = message
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   179
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   180
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   181
class Directive:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   182
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   183
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   184
    Base class for reStructuredText directives.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   185
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   186
    The following attributes may be set by subclasses.  They are
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   187
    interpreted by the directive parser (which runs the directive
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   188
    class):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   189
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   190
    - `required_arguments`: The number of required arguments (default:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   191
      0).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   192
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   193
    - `optional_arguments`: The number of optional arguments (default:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   194
      0).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   195
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   196
    - `final_argument_whitespace`: A boolean, indicating if the final
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   197
      argument may contain whitespace (default: False).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   198
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   199
    - `option_spec`: A dictionary, mapping known option names to
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   200
      conversion functions such as `int` or `float` (default: {}, no
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   201
      options).  Several conversion functions are defined in the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   202
      directives/__init__.py module.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   203
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   204
      Option conversion functions take a single parameter, the option
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   205
      argument (a string or ``None``), validate it and/or convert it
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   206
      to the appropriate form.  Conversion functions may raise
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   207
      `ValueError` and `TypeError` exceptions.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   208
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   209
    - `has_content`: A boolean; True if content is allowed.  Client
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   210
      code must handle the case where content is required but not
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   211
      supplied (an empty content list will be supplied).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   212
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   213
    Arguments are normally single whitespace-separated words.  The
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   214
    final argument may contain whitespace and/or newlines if
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   215
    `final_argument_whitespace` is True.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   216
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   217
    If the form of the arguments is more complex, specify only one
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   218
    argument (either required or optional) and set
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   219
    `final_argument_whitespace` to True; the client code must do any
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   220
    context-sensitive parsing.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   221
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   222
    When a directive implementation is being run, the directive class
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   223
    is instantiated, and the `run()` method is executed.  During
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   224
    instantiation, the following instance variables are set:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   225
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   226
    - ``name`` is the directive type or name (string).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   227
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   228
    - ``arguments`` is the list of positional arguments (strings).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   229
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   230
    - ``options`` is a dictionary mapping option names (strings) to
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   231
      values (type depends on option conversion functions; see
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   232
      `option_spec` above).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   233
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   234
    - ``content`` is a list of strings, the directive content line by line.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   235
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   236
    - ``lineno`` is the line number of the first line of the directive.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   237
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   238
    - ``content_offset`` is the line offset of the first line of the content from
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   239
      the beginning of the current input.  Used when initiating a nested parse.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   240
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   241
    - ``block_text`` is a string containing the entire directive.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   242
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   243
    - ``state`` is the state which called the directive function.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   244
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   245
    - ``state_machine`` is the state machine which controls the state which called
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   246
      the directive function.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   247
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   248
    Directive functions return a list of nodes which will be inserted
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   249
    into the document tree at the point where the directive was
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   250
    encountered.  This can be an empty list if there is nothing to
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   251
    insert.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   252
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   253
    For ordinary directives, the list must contain body elements or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   254
    structural elements.  Some directives are intended specifically
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   255
    for substitution definitions, and must return a list of `Text`
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   256
    nodes and/or inline elements (suitable for inline insertion, in
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   257
    place of the substitution reference).  Such directives must verify
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   258
    substitution definition context, typically using code like this::
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   259
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   260
        if not isinstance(state, states.SubstitutionDef):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   261
            error = state_machine.reporter.error(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   262
                'Invalid context: the "%s" directive can only be used '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   263
                'within a substitution definition.' % (name),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   264
                nodes.literal_block(block_text, block_text), line=lineno)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   265
            return [error]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   266
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   267
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   268
    # There is a "Creating reStructuredText Directives" how-to at
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   269
    # <http://docutils.sf.net/docs/howto/rst-directives.html>.  If you
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   270
    # update this docstring, please update the how-to as well.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   271
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   272
    required_arguments = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   273
    """Number of required directive arguments."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   274
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   275
    optional_arguments = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   276
    """Number of optional arguments after the required arguments."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   277
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   278
    final_argument_whitespace = False
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   279
    """May the final argument contain whitespace?"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   280
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   281
    option_spec = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   282
    """Mapping of option names to validator functions."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   283
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   284
    has_content = False
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   285
    """May the directive have content?"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   286
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   287
    def __init__(self, name, arguments, options, content, lineno,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   288
                 content_offset, block_text, state, state_machine):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   289
        self.name = name
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   290
        self.arguments = arguments
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   291
        self.options = options
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   292
        self.content = content
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   293
        self.lineno = lineno
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   294
        self.content_offset = content_offset
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   295
        self.block_text = block_text
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   296
        self.state = state
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   297
        self.state_machine = state_machine
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   298
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   299
    def run(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   300
        raise NotImplementedError('Must override run() is subclass.')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   301
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   302
    # Directive errors:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   303
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   304
    def directive_error(self, level, message):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   305
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   306
        Return a DirectiveError suitable for being thrown as an exception.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   307
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   308
        Call "raise self.directive_error(level, message)" from within
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   309
        a directive implementation to return one single system message
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   310
        at level `level`, which automatically gets the directive block
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   311
        and the line number added.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   312
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   313
        You'd often use self.error(message) instead, which will
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   314
        generate an ERROR-level directive error.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   315
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   316
        return DirectiveError(level, message)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   317
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   318
    def debug(self, message):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   319
        return self.directive_error(0, message)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   320
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   321
    def info(self, message):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   322
        return self.directive_error(1, message)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   323
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   324
    def warning(self, message):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   325
        return self.directive_error(2, message)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   326
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   327
    def error(self, message):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   328
        return self.directive_error(3, message)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   329
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   330
    def severe(self, message):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   331
        return self.directive_error(4, message)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   332
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   333
    # Convenience methods:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   334
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   335
    def assert_has_content(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   336
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   337
        Throw an ERROR-level DirectiveError if the directive doesn't
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   338
        have contents.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   339
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   340
        if not self.content:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   341
            raise self.error('Content block expected for the "%s" directive; '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   342
                             'none found.' % self.name)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   343
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   344
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   345
def convert_directive_function(directive_fn):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   346
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   347
    Define & return a directive class generated from `directive_fn`.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   348
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   349
    `directive_fn` uses the old-style, functional interface.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   350
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   351
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   352
    class FunctionalDirective(Directive):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   353
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   354
        option_spec = getattr(directive_fn, 'options', None)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   355
        has_content = getattr(directive_fn, 'content', False)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   356
        _argument_spec = getattr(directive_fn, 'arguments', (0, 0, False))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   357
        required_arguments, optional_arguments, final_argument_whitespace \
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   358
            = _argument_spec
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   359
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   360
        def run(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   361
            return directive_fn(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   362
                self.name, self.arguments, self.options, self.content,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   363
                self.lineno, self.content_offset, self.block_text,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   364
                self.state, self.state_machine)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   365
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   366
    # Return new-style directive.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   367
    return FunctionalDirective