buildframework/helium/external/python/lib/common/docutils-0.5-py2.5.egg/docutils/parsers/rst/directives/__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 4667 2006-07-12 21:40:56Z wiemann $
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     2
# Author: David Goodger <goodger@python.org>
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     3
# Copyright: This module has been placed in the public domain.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     4
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     5
"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     6
This package contains directive implementation modules.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     7
"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     8
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     9
__docformat__ = 'reStructuredText'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    10
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    11
import re
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    12
import codecs
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    13
from docutils import nodes
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    14
from docutils.parsers.rst.languages import en as _fallback_language_module
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    15
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    16
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    17
_directive_registry = {
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    18
      'attention': ('admonitions', 'Attention'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    19
      'caution': ('admonitions', 'Caution'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    20
      'danger': ('admonitions', 'Danger'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    21
      'error': ('admonitions', 'Error'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    22
      'important': ('admonitions', 'Important'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    23
      'note': ('admonitions', 'Note'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    24
      'tip': ('admonitions', 'Tip'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    25
      'hint': ('admonitions', 'Hint'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    26
      'warning': ('admonitions', 'Warning'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    27
      'admonition': ('admonitions', 'Admonition'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    28
      'sidebar': ('body', 'Sidebar'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    29
      'topic': ('body', 'Topic'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    30
      'line-block': ('body', 'LineBlock'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    31
      'parsed-literal': ('body', 'ParsedLiteral'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    32
      'rubric': ('body', 'Rubric'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    33
      'epigraph': ('body', 'Epigraph'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    34
      'highlights': ('body', 'Highlights'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    35
      'pull-quote': ('body', 'PullQuote'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    36
      'compound': ('body', 'Compound'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    37
      'container': ('body', 'Container'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    38
      #'questions': ('body', 'question_list'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    39
      'table': ('tables', 'RSTTable'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    40
      'csv-table': ('tables', 'CSVTable'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    41
      'list-table': ('tables', 'ListTable'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    42
      'image': ('images', 'Image'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    43
      'figure': ('images', 'Figure'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    44
      'contents': ('parts', 'Contents'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    45
      'sectnum': ('parts', 'Sectnum'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    46
      'header': ('parts', 'Header'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    47
      'footer': ('parts', 'Footer'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    48
      #'footnotes': ('parts', 'footnotes'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    49
      #'citations': ('parts', 'citations'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    50
      'target-notes': ('references', 'TargetNotes'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    51
      'meta': ('html', 'Meta'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    52
      #'imagemap': ('html', 'imagemap'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    53
      'raw': ('misc', 'Raw'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    54
      'include': ('misc', 'Include'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    55
      'replace': ('misc', 'Replace'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    56
      'unicode': ('misc', 'Unicode'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    57
      'class': ('misc', 'Class'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    58
      'role': ('misc', 'Role'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    59
      'default-role': ('misc', 'DefaultRole'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    60
      'title': ('misc', 'Title'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    61
      'date': ('misc', 'Date'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    62
      'restructuredtext-test-directive': ('misc', 'TestDirective'),}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    63
"""Mapping of directive name to (module name, class name).  The
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    64
directive name is canonical & must be lowercase.  Language-dependent
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    65
names are defined in the ``language`` subpackage."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    66
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    67
_directives = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    68
"""Cache of imported directives."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    69
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    70
def directive(directive_name, language_module, document):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    71
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    72
    Locate and return a directive function from its language-dependent name.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    73
    If not found in the current language, check English.  Return None if the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    74
    named directive cannot be found.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    75
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    76
    normname = directive_name.lower()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    77
    messages = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    78
    msg_text = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    79
    if _directives.has_key(normname):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    80
        return _directives[normname], messages
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    81
    canonicalname = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    82
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    83
        canonicalname = language_module.directives[normname]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    84
    except AttributeError, error:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    85
        msg_text.append('Problem retrieving directive entry from language '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    86
                        'module %r: %s.' % (language_module, error))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    87
    except KeyError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    88
        msg_text.append('No directive entry for "%s" in module "%s".'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    89
                        % (directive_name, language_module.__name__))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    90
    if not canonicalname:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    91
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    92
            canonicalname = _fallback_language_module.directives[normname]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    93
            msg_text.append('Using English fallback for directive "%s".'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    94
                            % directive_name)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    95
        except KeyError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    96
            msg_text.append('Trying "%s" as canonical directive name.'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    97
                            % directive_name)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    98
            # The canonical name should be an English name, but just in case:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    99
            canonicalname = normname
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   100
    if msg_text:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   101
        message = document.reporter.info(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   102
            '\n'.join(msg_text), line=document.current_line)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   103
        messages.append(message)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   104
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   105
        modulename, classname = _directive_registry[canonicalname]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   106
    except KeyError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   107
        # Error handling done by caller.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   108
        return None, messages
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   109
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   110
        module = __import__(modulename, globals(), locals())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   111
    except ImportError, detail:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   112
        messages.append(document.reporter.error(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   113
            'Error importing directive module "%s" (directive "%s"):\n%s'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   114
            % (modulename, directive_name, detail),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   115
            line=document.current_line))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   116
        return None, messages
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   117
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   118
        directive = getattr(module, classname)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   119
        _directives[normname] = directive
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   120
    except AttributeError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   121
        messages.append(document.reporter.error(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   122
            'No directive class "%s" in module "%s" (directive "%s").'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   123
            % (classname, modulename, directive_name),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   124
            line=document.current_line))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   125
        return None, messages
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   126
    return directive, messages
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   127
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   128
def register_directive(name, directive):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   129
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   130
    Register a nonstandard application-defined directive function.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   131
    Language lookups are not needed for such functions.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   132
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   133
    _directives[name] = directive
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   134
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   135
def flag(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   136
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   137
    Check for a valid flag option (no argument) and return ``None``.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   138
    (Directive option conversion function.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   139
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   140
    Raise ``ValueError`` if an argument is found.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   141
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   142
    if argument and argument.strip():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   143
        raise ValueError('no argument is allowed; "%s" supplied' % argument)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   144
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   145
        return None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   146
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   147
def unchanged_required(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   148
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   149
    Return the argument text, unchanged.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   150
    (Directive option conversion function.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   151
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   152
    Raise ``ValueError`` if no argument is found.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   153
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   154
    if argument is None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   155
        raise ValueError('argument required but none supplied')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   156
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   157
        return argument  # unchanged!
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   158
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   159
def unchanged(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   160
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   161
    Return the argument text, unchanged.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   162
    (Directive option conversion function.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   163
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   164
    No argument implies empty string ("").
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   165
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   166
    if argument is None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   167
        return u''
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   168
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   169
        return argument  # unchanged!
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   170
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   171
def path(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   172
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   173
    Return the path argument unwrapped (with newlines removed).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   174
    (Directive option conversion function.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   175
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   176
    Raise ``ValueError`` if no argument is found.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   177
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   178
    if argument is None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   179
        raise ValueError('argument required but none supplied')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   180
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   181
        path = ''.join([s.strip() for s in argument.splitlines()])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   182
        return path
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   183
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   184
def uri(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   185
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   186
    Return the URI argument with whitespace removed.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   187
    (Directive option conversion function.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   188
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   189
    Raise ``ValueError`` if no argument is found.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   190
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   191
    if argument is None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   192
        raise ValueError('argument required but none supplied')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   193
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   194
        uri = ''.join(argument.split())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   195
        return uri
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   196
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   197
def nonnegative_int(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   198
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   199
    Check for a nonnegative integer argument; raise ``ValueError`` if not.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   200
    (Directive option conversion function.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   201
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   202
    value = int(argument)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   203
    if value < 0:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   204
        raise ValueError('negative value; must be positive or zero')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   205
    return value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   206
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   207
length_units = ['em', 'ex', 'px', 'in', 'cm', 'mm', 'pt', 'pc']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   208
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   209
def get_measure(argument, units):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   210
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   211
    Check for a positive argument of one of the units and return a
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   212
    normalized string of the form "<value><unit>" (without space in
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   213
    between).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   214
    
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   215
    To be called from directive option conversion functions.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   216
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   217
    match = re.match(r'^([0-9.]+) *(%s)$' % '|'.join(units), argument)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   218
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   219
        assert match is not None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   220
        float(match.group(1))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   221
    except (AssertionError, ValueError):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   222
        raise ValueError(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   223
            'not a positive measure of one of the following units:\n%s'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   224
            % ' '.join(['"%s"' % i for i in units]))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   225
    return match.group(1) + match.group(2)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   226
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   227
def length_or_unitless(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   228
    return get_measure(argument, length_units + [''])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   229
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   230
def length_or_percentage_or_unitless(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   231
    return get_measure(argument, length_units + ['%', ''])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   232
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   233
def class_option(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   234
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   235
    Convert the argument into a list of ID-compatible strings and return it.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   236
    (Directive option conversion function.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   237
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   238
    Raise ``ValueError`` if no argument is found.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   239
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   240
    if argument is None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   241
        raise ValueError('argument required but none supplied')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   242
    names = argument.split()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   243
    class_names = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   244
    for name in names:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   245
        class_name = nodes.make_id(name)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   246
        if not class_name:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   247
            raise ValueError('cannot make "%s" into a class name' % name)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   248
        class_names.append(class_name)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   249
    return class_names
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   250
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   251
unicode_pattern = re.compile(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   252
    r'(?:0x|x|\\x|U\+?|\\u)([0-9a-f]+)$|&#x([0-9a-f]+);$', re.IGNORECASE)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   253
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   254
def unicode_code(code):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   255
    r"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   256
    Convert a Unicode character code to a Unicode character.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   257
    (Directive option conversion function.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   258
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   259
    Codes may be decimal numbers, hexadecimal numbers (prefixed by ``0x``,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   260
    ``x``, ``\x``, ``U+``, ``u``, or ``\u``; e.g. ``U+262E``), or XML-style
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   261
    numeric character entities (e.g. ``&#x262E;``).  Other text remains as-is.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   262
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   263
    Raise ValueError for illegal Unicode code values.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   264
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   265
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   266
        if code.isdigit():                  # decimal number
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   267
            return unichr(int(code))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   268
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   269
            match = unicode_pattern.match(code)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   270
            if match:                       # hex number
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   271
                value = match.group(1) or match.group(2)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   272
                return unichr(int(value, 16))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   273
            else:                           # other text
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   274
                return code
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   275
    except OverflowError, detail:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   276
        raise ValueError('code too large (%s)' % detail)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   277
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   278
def single_char_or_unicode(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   279
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   280
    A single character is returned as-is.  Unicode characters codes are
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   281
    converted as in `unicode_code`.  (Directive option conversion function.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   282
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   283
    char = unicode_code(argument)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   284
    if len(char) > 1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   285
        raise ValueError('%r invalid; must be a single character or '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   286
                         'a Unicode code' % char)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   287
    return char
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   288
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   289
def single_char_or_whitespace_or_unicode(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   290
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   291
    As with `single_char_or_unicode`, but "tab" and "space" are also supported.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   292
    (Directive option conversion function.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   293
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   294
    if argument == 'tab':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   295
        char = '\t'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   296
    elif argument == 'space':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   297
        char = ' '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   298
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   299
        char = single_char_or_unicode(argument)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   300
    return char
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   301
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   302
def positive_int(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   303
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   304
    Converts the argument into an integer.  Raises ValueError for negative,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   305
    zero, or non-integer values.  (Directive option conversion function.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   306
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   307
    value = int(argument)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   308
    if value < 1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   309
        raise ValueError('negative or zero value; must be positive')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   310
    return value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   311
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   312
def positive_int_list(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   313
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   314
    Converts a space- or comma-separated list of values into a Python list
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   315
    of integers.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   316
    (Directive option conversion function.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   317
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   318
    Raises ValueError for non-positive-integer values.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   319
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   320
    if ',' in argument:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   321
        entries = argument.split(',')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   322
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   323
        entries = argument.split()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   324
    return [positive_int(entry) for entry in entries]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   325
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   326
def encoding(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   327
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   328
    Verfies the encoding argument by lookup.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   329
    (Directive option conversion function.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   330
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   331
    Raises ValueError for unknown encodings.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   332
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   333
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   334
        codecs.lookup(argument)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   335
    except LookupError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   336
        raise ValueError('unknown encoding: "%s"' % argument)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   337
    return argument
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   338
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   339
def choice(argument, values):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   340
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   341
    Directive option utility function, supplied to enable options whose
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   342
    argument must be a member of a finite set of possible values (must be
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   343
    lower case).  A custom conversion function must be written to use it.  For
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   344
    example::
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   345
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   346
        from docutils.parsers.rst import directives
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   347
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   348
        def yesno(argument):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   349
            return directives.choice(argument, ('yes', 'no'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   350
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   351
    Raise ``ValueError`` if no argument is found or if the argument's value is
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   352
    not valid (not an entry in the supplied list).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   353
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   354
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   355
        value = argument.lower().strip()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   356
    except AttributeError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   357
        raise ValueError('must supply an argument; choose from %s'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   358
                         % format_values(values))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   359
    if value in values:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   360
        return value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   361
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   362
        raise ValueError('"%s" unknown; choose from %s'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   363
                         % (argument, format_values(values)))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   364
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   365
def format_values(values):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   366
    return '%s, or "%s"' % (', '.join(['"%s"' % s for s in values[:-1]]),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   367
                            values[-1])