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