buildframework/helium/external/python/lib/common/docutils-0.5-py2.5.egg/docutils/frontend.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: frontend.py 4913 2007-02-12 04:05:20Z 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
Command-line and common processing for Docutils front-end tools.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     7
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     8
Exports the following classes:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     9
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    10
* `OptionParser`: Standard Docutils command-line processing.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    11
* `Option`: Customized version of `optparse.Option`; validation support.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    12
* `Values`: Runtime settings; objects are simple structs
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    13
  (``object.attribute``).  Supports cumulative list settings (attributes).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    14
* `ConfigParser`: Standard Docutils config file processing.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    15
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    16
Also exports the following functions:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    17
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    18
* Option callbacks: `store_multiple`, `read_config_file`.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    19
* Setting validators: `validate_encoding`,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    20
  `validate_encoding_error_handler`,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    21
  `validate_encoding_and_error_handler`, `validate_boolean`,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    22
  `validate_threshold`, `validate_colon_separated_string_list`,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    23
  `validate_dependency_file`.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    24
* `make_paths_absolute`.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    25
"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    26
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    27
__docformat__ = 'reStructuredText'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    28
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    29
import os
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    30
import os.path
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    31
import sys
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    32
import types
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    33
import warnings
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    34
import ConfigParser as CP
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    35
import codecs
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    36
import docutils
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    37
import docutils.utils
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    38
import docutils.nodes
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    39
try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    40
    import optparse
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    41
    from optparse import SUPPRESS_HELP
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    42
except ImportError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    43
    import optik as optparse
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    44
    from optik import SUPPRESS_HELP
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    45
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    46
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    47
def store_multiple(option, opt, value, parser, *args, **kwargs):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    48
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    49
    Store multiple values in `parser.values`.  (Option callback.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    50
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    51
    Store `None` for each attribute named in `args`, and store the value for
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    52
    each key (attribute name) in `kwargs`.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    53
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    54
    for attribute in args:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    55
        setattr(parser.values, attribute, None)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    56
    for key, value in kwargs.items():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    57
        setattr(parser.values, key, value)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    58
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    59
def read_config_file(option, opt, value, parser):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    60
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    61
    Read a configuration file during option processing.  (Option callback.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    62
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    63
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    64
        new_settings = parser.get_config_file_settings(value)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    65
    except ValueError, error:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    66
        parser.error(error)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    67
    parser.values.update(new_settings, parser)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    68
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    69
def validate_encoding(setting, value, option_parser,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    70
                      config_parser=None, config_section=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    71
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    72
        codecs.lookup(value)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    73
    except LookupError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    74
        raise (LookupError('setting "%s": unknown encoding: "%s"'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    75
                           % (setting, value)),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    76
               None, sys.exc_info()[2])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    77
    return value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    78
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    79
def validate_encoding_error_handler(setting, value, option_parser,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    80
                                    config_parser=None, config_section=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    81
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    82
        codecs.lookup_error(value)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    83
    except AttributeError:              # prior to Python 2.3
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    84
        if value not in ('strict', 'ignore', 'replace', 'xmlcharrefreplace'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    85
            raise (LookupError(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    86
                'unknown encoding error handler: "%s" (choices: '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    87
                '"strict", "ignore", "replace", or "xmlcharrefreplace")' % value),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    88
                   None, sys.exc_info()[2])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    89
    except LookupError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    90
        raise (LookupError(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    91
            'unknown encoding error handler: "%s" (choices: '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    92
            '"strict", "ignore", "replace", "backslashreplace", '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    93
            '"xmlcharrefreplace", and possibly others; see documentation for '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    94
            'the Python ``codecs`` module)' % value),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    95
               None, sys.exc_info()[2])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    96
    return value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    97
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    98
def validate_encoding_and_error_handler(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    99
    setting, value, option_parser, config_parser=None, config_section=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   100
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   101
    Side-effect: if an error handler is included in the value, it is inserted
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   102
    into the appropriate place as if it was a separate setting/option.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   103
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   104
    if ':' in value:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   105
        encoding, handler = value.split(':')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   106
        validate_encoding_error_handler(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   107
            setting + '_error_handler', handler, option_parser,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   108
            config_parser, config_section)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   109
        if config_parser:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   110
            config_parser.set(config_section, setting + '_error_handler',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   111
                              handler)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   112
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   113
            setattr(option_parser.values, setting + '_error_handler', handler)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   114
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   115
        encoding = value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   116
    validate_encoding(setting, encoding, option_parser,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   117
                      config_parser, config_section)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   118
    return encoding
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   119
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   120
def validate_boolean(setting, value, option_parser,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   121
                     config_parser=None, config_section=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   122
    if isinstance(value, types.UnicodeType):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   123
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   124
            return option_parser.booleans[value.strip().lower()]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   125
        except KeyError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   126
            raise (LookupError('unknown boolean value: "%s"' % value),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   127
                   None, sys.exc_info()[2])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   128
    return value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   129
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   130
def validate_nonnegative_int(setting, value, option_parser,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   131
                             config_parser=None, config_section=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   132
    value = int(value)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   133
    if value < 0:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   134
        raise ValueError('negative value; must be positive or zero')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   135
    return value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   136
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   137
def validate_threshold(setting, value, option_parser,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   138
                       config_parser=None, config_section=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   139
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   140
        return int(value)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   141
    except ValueError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   142
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   143
            return option_parser.thresholds[value.lower()]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   144
        except (KeyError, AttributeError):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   145
            raise (LookupError('unknown threshold: %r.' % value),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   146
                   None, sys.exc_info[2])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   147
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   148
def validate_colon_separated_string_list(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   149
    setting, value, option_parser, config_parser=None, config_section=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   150
    if isinstance(value, types.UnicodeType):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   151
        value = value.split(':')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   152
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   153
        last = value.pop()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   154
        value.extend(last.split(':'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   155
    return value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   156
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   157
def validate_url_trailing_slash(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   158
    setting, value, option_parser, config_parser=None, config_section=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   159
    if not value:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   160
        return './'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   161
    elif value.endswith('/'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   162
        return value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   163
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   164
        return value + '/'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   165
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   166
def validate_dependency_file(setting, value, option_parser,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   167
                             config_parser=None, config_section=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   168
    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   169
        return docutils.utils.DependencyList(value)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   170
    except IOError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   171
        return docutils.utils.DependencyList(None)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   172
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   173
def validate_strip_class(setting, value, option_parser,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   174
                         config_parser=None, config_section=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   175
    if config_parser:                   # validate all values
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   176
        class_values = value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   177
    else:                               # just validate the latest value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   178
        class_values = [value[-1]]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   179
    for class_value in class_values:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   180
        normalized = docutils.nodes.make_id(class_value)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   181
        if class_value != normalized:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   182
            raise ValueError('invalid class value %r (perhaps %r?)'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   183
                             % (class_value, normalized))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   184
    return value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   185
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   186
def make_paths_absolute(pathdict, keys, base_path=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   187
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   188
    Interpret filesystem path settings relative to the `base_path` given.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   189
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   190
    Paths are values in `pathdict` whose keys are in `keys`.  Get `keys` from
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   191
    `OptionParser.relative_path_settings`.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   192
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   193
    if base_path is None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   194
        base_path = os.getcwd()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   195
    for key in keys:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   196
        if pathdict.has_key(key):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   197
            value = pathdict[key]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   198
            if isinstance(value, types.ListType):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   199
                value = [make_one_path_absolute(base_path, path)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   200
                         for path in value]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   201
            elif value:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   202
                value = make_one_path_absolute(base_path, value)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   203
            pathdict[key] = value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   204
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   205
def make_one_path_absolute(base_path, path):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   206
    return os.path.abspath(os.path.join(base_path, path))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   207
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   208
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   209
class Values(optparse.Values):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   210
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   211
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   212
    Updates list attributes by extension rather than by replacement.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   213
    Works in conjunction with the `OptionParser.lists` instance attribute.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   214
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   215
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   216
    def __init__(self, *args, **kwargs):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   217
        optparse.Values.__init__(self, *args, **kwargs)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   218
        if (not hasattr(self, 'record_dependencies')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   219
            or self.record_dependencies is None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   220
            # Set up dependency list, in case it is needed.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   221
            self.record_dependencies = docutils.utils.DependencyList()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   222
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   223
    def update(self, other_dict, option_parser):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   224
        if isinstance(other_dict, Values):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   225
            other_dict = other_dict.__dict__
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   226
        other_dict = other_dict.copy()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   227
        for setting in option_parser.lists.keys():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   228
            if (hasattr(self, setting) and other_dict.has_key(setting)):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   229
                value = getattr(self, setting)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   230
                if value:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   231
                    value += other_dict[setting]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   232
                    del other_dict[setting]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   233
        self._update_loose(other_dict)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   234
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   235
    def copy(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   236
        """Return a shallow copy of `self`."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   237
        return self.__class__(defaults=self.__dict__)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   238
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   239
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   240
class Option(optparse.Option):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   241
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   242
    ATTRS = optparse.Option.ATTRS + ['validator', 'overrides']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   243
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   244
    def process(self, opt, value, values, parser):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   245
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   246
        Call the validator function on applicable settings and
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   247
        evaluate the 'overrides' option.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   248
        Extends `optparse.Option.process`.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   249
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   250
        result = optparse.Option.process(self, opt, value, values, parser)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   251
        setting = self.dest
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   252
        if setting:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   253
            if self.validator:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   254
                value = getattr(values, setting)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   255
                try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   256
                    new_value = self.validator(setting, value, parser)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   257
                except Exception, error:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   258
                    raise (optparse.OptionValueError(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   259
                        'Error in option "%s":\n    %s: %s'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   260
                        % (opt, error.__class__.__name__, error)),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   261
                           None, sys.exc_info()[2])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   262
                setattr(values, setting, new_value)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   263
            if self.overrides:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   264
                setattr(values, self.overrides, None)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   265
        return result
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
class OptionParser(optparse.OptionParser, docutils.SettingsSpec):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   269
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   270
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   271
    Parser for command-line and library use.  The `settings_spec`
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   272
    specification here and in other Docutils components are merged to build
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   273
    the set of command-line options and runtime settings for this process.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   274
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   275
    Common settings (defined below) and component-specific settings must not
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   276
    conflict.  Short options are reserved for common settings, and components
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   277
    are restrict to using long options.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   278
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   279
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   280
    standard_config_files = [
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   281
        '/etc/docutils.conf',           # system-wide
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   282
        './docutils.conf',              # project-specific
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   283
        '~/.docutils']                  # user-specific
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   284
    """Docutils configuration files, using ConfigParser syntax.  Filenames
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   285
    will be tilde-expanded later.  Later files override earlier ones."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   286
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   287
    threshold_choices = 'info 1 warning 2 error 3 severe 4 none 5'.split()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   288
    """Possible inputs for for --report and --halt threshold values."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   289
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   290
    thresholds = {'info': 1, 'warning': 2, 'error': 3, 'severe': 4, 'none': 5}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   291
    """Lookup table for --report and --halt threshold values."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   292
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   293
    booleans={'1': 1, 'on': 1, 'yes': 1, 'true': 1,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   294
              '0': 0, 'off': 0, 'no': 0, 'false': 0, '': 0}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   295
    """Lookup table for boolean configuration file settings."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   296
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   297
    if hasattr(codecs, 'backslashreplace_errors'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   298
        default_error_encoding_error_handler = 'backslashreplace'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   299
    else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   300
        default_error_encoding_error_handler = 'replace'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   301
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   302
    settings_spec = (
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   303
        'General Docutils Options',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   304
        None,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   305
        (('Specify the document title as metadata.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   306
          ['--title'], {}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   307
         ('Include a "Generated by Docutils" credit and link.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   308
          ['--generator', '-g'], {'action': 'store_true',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   309
                                  'validator': validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   310
         ('Do not include a generator credit.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   311
          ['--no-generator'], {'action': 'store_false', 'dest': 'generator'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   312
         ('Include the date at the end of the document (UTC).',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   313
          ['--date', '-d'], {'action': 'store_const', 'const': '%Y-%m-%d',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   314
                             'dest': 'datestamp'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   315
         ('Include the time & date (UTC).',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   316
          ['--time', '-t'], {'action': 'store_const',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   317
                             'const': '%Y-%m-%d %H:%M UTC',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   318
                             'dest': 'datestamp'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   319
         ('Do not include a datestamp of any kind.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   320
          ['--no-datestamp'], {'action': 'store_const', 'const': None,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   321
                               'dest': 'datestamp'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   322
         ('Include a "View document source" link.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   323
          ['--source-link', '-s'], {'action': 'store_true',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   324
                                    'validator': validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   325
         ('Use <URL> for a source link; implies --source-link.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   326
          ['--source-url'], {'metavar': '<URL>'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   327
         ('Do not include a "View document source" link.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   328
          ['--no-source-link'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   329
          {'action': 'callback', 'callback': store_multiple,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   330
           'callback_args': ('source_link', 'source_url')}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   331
         ('Link from section headers to TOC entries.  (default)',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   332
          ['--toc-entry-backlinks'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   333
          {'dest': 'toc_backlinks', 'action': 'store_const', 'const': 'entry',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   334
           'default': 'entry'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   335
         ('Link from section headers to the top of the TOC.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   336
          ['--toc-top-backlinks'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   337
          {'dest': 'toc_backlinks', 'action': 'store_const', 'const': 'top'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   338
         ('Disable backlinks to the table of contents.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   339
          ['--no-toc-backlinks'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   340
          {'dest': 'toc_backlinks', 'action': 'store_false'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   341
         ('Link from footnotes/citations to references. (default)',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   342
          ['--footnote-backlinks'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   343
          {'action': 'store_true', 'default': 1,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   344
           'validator': validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   345
         ('Disable backlinks from footnotes and citations.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   346
          ['--no-footnote-backlinks'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   347
          {'dest': 'footnote_backlinks', 'action': 'store_false'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   348
         ('Enable section numbering.  (default)',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   349
          ['--section-numbering'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   350
          {'action': 'store_true', 'dest': 'sectnum_xform',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   351
           'default': 1, 'validator': validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   352
         ('Disable section numbering.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   353
          ['--no-section-numbering'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   354
          {'action': 'store_false', 'dest': 'sectnum_xform'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   355
         ('Remove comment elements from the document tree.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   356
          ['--strip-comments'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   357
          {'action': 'store_true', 'validator': validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   358
         ('Leave comment elements in the document tree. (default)',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   359
          ['--leave-comments'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   360
          {'action': 'store_false', 'dest': 'strip_comments'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   361
         ('Remove all elements with classes="<class>" from the document tree. '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   362
          '(Multiple-use option.)',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   363
          ['--strip-elements-with-class'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   364
          {'action': 'append', 'dest': 'strip_elements_with_classes',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   365
           'metavar': '<class>', 'validator': validate_strip_class}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   366
         ('Remove all classes="<class>" attributes from elements in the '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   367
          'document tree. (Multiple-use option.)',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   368
          ['--strip-class'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   369
          {'action': 'append', 'dest': 'strip_classes',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   370
           'metavar': '<class>', 'validator': validate_strip_class}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   371
         ('Report system messages at or higher than <level>: "info" or "1", '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   372
          '"warning"/"2" (default), "error"/"3", "severe"/"4", "none"/"5"',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   373
          ['--report', '-r'], {'choices': threshold_choices, 'default': 2,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   374
                               'dest': 'report_level', 'metavar': '<level>',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   375
                               'validator': validate_threshold}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   376
         ('Report all system messages.  (Same as "--report=1".)',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   377
          ['--verbose', '-v'], {'action': 'store_const', 'const': 1,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   378
                                'dest': 'report_level'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   379
         ('Report no system messages.  (Same as "--report=5".)',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   380
          ['--quiet', '-q'], {'action': 'store_const', 'const': 5,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   381
                              'dest': 'report_level'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   382
         ('Halt execution at system messages at or above <level>.  '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   383
          'Levels as in --report.  Default: 4 (severe).',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   384
          ['--halt'], {'choices': threshold_choices, 'dest': 'halt_level',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   385
                       'default': 4, 'metavar': '<level>',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   386
                       'validator': validate_threshold}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   387
         ('Halt at the slightest problem.  Same as "--halt=info".',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   388
          ['--strict'], {'action': 'store_const', 'const': 'info',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   389
                         'dest': 'halt_level'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   390
         ('Enable a non-zero exit status for non-halting system messages at '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   391
          'or above <level>.  Default: 5 (disabled).',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   392
          ['--exit-status'], {'choices': threshold_choices,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   393
                              'dest': 'exit_status_level',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   394
                              'default': 5, 'metavar': '<level>',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   395
                              'validator': validate_threshold}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   396
         ('Enable debug-level system messages and diagnostics.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   397
          ['--debug'], {'action': 'store_true', 'validator': validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   398
         ('Disable debug output.  (default)',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   399
          ['--no-debug'], {'action': 'store_false', 'dest': 'debug'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   400
         ('Send the output of system messages to <file>.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   401
          ['--warnings'], {'dest': 'warning_stream', 'metavar': '<file>'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   402
         ('Enable Python tracebacks when Docutils is halted.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   403
          ['--traceback'], {'action': 'store_true', 'default': None,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   404
                            'validator': validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   405
         ('Disable Python tracebacks.  (default)',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   406
          ['--no-traceback'], {'dest': 'traceback', 'action': 'store_false'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   407
         ('Specify the encoding and optionally the '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   408
          'error handler of input text.  Default: <locale-dependent>:strict.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   409
          ['--input-encoding', '-i'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   410
          {'metavar': '<name[:handler]>',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   411
           'validator': validate_encoding_and_error_handler}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   412
         ('Specify the error handler for undecodable characters.  '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   413
          'Choices: "strict" (default), "ignore", and "replace".',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   414
          ['--input-encoding-error-handler'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   415
          {'default': 'strict', 'validator': validate_encoding_error_handler}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   416
         ('Specify the text encoding and optionally the error handler for '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   417
          'output.  Default: UTF-8:strict.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   418
          ['--output-encoding', '-o'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   419
          {'metavar': '<name[:handler]>', 'default': 'utf-8',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   420
           'validator': validate_encoding_and_error_handler}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   421
         ('Specify error handler for unencodable output characters; '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   422
          '"strict" (default), "ignore", "replace", '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   423
          '"xmlcharrefreplace", "backslashreplace" (Python 2.3+).',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   424
          ['--output-encoding-error-handler'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   425
          {'default': 'strict', 'validator': validate_encoding_error_handler}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   426
         ('Specify text encoding and error handler for error output.  '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   427
          'Default: ASCII:%s.'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   428
          % default_error_encoding_error_handler,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   429
          ['--error-encoding', '-e'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   430
          {'metavar': '<name[:handler]>', 'default': 'ascii',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   431
           'validator': validate_encoding_and_error_handler}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   432
         ('Specify the error handler for unencodable characters in '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   433
          'error output.  Default: %s.'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   434
          % default_error_encoding_error_handler,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   435
          ['--error-encoding-error-handler'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   436
          {'default': default_error_encoding_error_handler,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   437
           'validator': validate_encoding_error_handler}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   438
         ('Specify the language (as 2-letter code).  Default: en.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   439
          ['--language', '-l'], {'dest': 'language_code', 'default': 'en',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   440
                                 'metavar': '<name>'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   441
         ('Write output file dependencies to <file>.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   442
          ['--record-dependencies'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   443
          {'metavar': '<file>', 'validator': validate_dependency_file,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   444
           'default': None}),           # default set in Values class
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   445
         ('Read configuration settings from <file>, if it exists.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   446
          ['--config'], {'metavar': '<file>', 'type': 'string',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   447
                         'action': 'callback', 'callback': read_config_file}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   448
         ("Show this program's version number and exit.",
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   449
          ['--version', '-V'], {'action': 'version'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   450
         ('Show this help message and exit.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   451
          ['--help', '-h'], {'action': 'help'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   452
         # Typically not useful for non-programmatical use:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   453
         (SUPPRESS_HELP, ['--id-prefix'], {'default': ''}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   454
         (SUPPRESS_HELP, ['--auto-id-prefix'], {'default': 'id'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   455
         # Hidden options, for development use only:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   456
         (SUPPRESS_HELP, ['--dump-settings'], {'action': 'store_true'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   457
         (SUPPRESS_HELP, ['--dump-internals'], {'action': 'store_true'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   458
         (SUPPRESS_HELP, ['--dump-transforms'], {'action': 'store_true'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   459
         (SUPPRESS_HELP, ['--dump-pseudo-xml'], {'action': 'store_true'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   460
         (SUPPRESS_HELP, ['--expose-internal-attribute'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   461
          {'action': 'append', 'dest': 'expose_internals',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   462
           'validator': validate_colon_separated_string_list}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   463
         (SUPPRESS_HELP, ['--strict-visitor'], {'action': 'store_true'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   464
         ))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   465
    """Runtime settings and command-line options common to all Docutils front
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   466
    ends.  Setting specs specific to individual Docutils components are also
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   467
    used (see `populate_from_components()`)."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   468
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   469
    settings_defaults = {'_disable_config': None,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   470
                         '_source': None,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   471
                         '_destination': None,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   472
                         '_config_files': None}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   473
    """Defaults for settings that don't have command-line option equivalents."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   474
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   475
    relative_path_settings = ('warning_stream',)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   476
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   477
    config_section = 'general'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   478
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   479
    version_template = ('%%prog (Docutils %s [%s])'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   480
                        % (docutils.__version__, docutils.__version_details__))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   481
    """Default version message."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   482
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   483
    def __init__(self, components=(), defaults=None, read_config_files=None,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   484
                 *args, **kwargs):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   485
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   486
        `components` is a list of Docutils components each containing a
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   487
        ``.settings_spec`` attribute.  `defaults` is a mapping of setting
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   488
        default overrides.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   489
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   490
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   491
        self.lists = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   492
        """Set of list-type settings."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   493
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   494
        self.config_files = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   495
        """List of paths of applied configuration files."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   496
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   497
        optparse.OptionParser.__init__(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   498
            self, option_class=Option, add_help_option=None,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   499
            formatter=optparse.TitledHelpFormatter(width=78),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   500
            *args, **kwargs)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   501
        if not self.version:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   502
            self.version = self.version_template
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   503
        # Make an instance copy (it will be modified):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   504
        self.relative_path_settings = list(self.relative_path_settings)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   505
        self.components = (self,) + tuple(components)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   506
        self.populate_from_components(self.components)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   507
        self.set_defaults_from_dict(defaults or {})
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   508
        if read_config_files and not self.defaults['_disable_config']:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   509
            try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   510
                config_settings = self.get_standard_config_settings()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   511
            except ValueError, error:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   512
                self.error(error)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   513
            self.set_defaults_from_dict(config_settings.__dict__)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   514
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   515
    def populate_from_components(self, components):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   516
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   517
        For each component, first populate from the `SettingsSpec.settings_spec`
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   518
        structure, then from the `SettingsSpec.settings_defaults` dictionary.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   519
        After all components have been processed, check for and populate from
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   520
        each component's `SettingsSpec.settings_default_overrides` dictionary.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   521
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   522
        for component in components:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   523
            if component is None:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   524
                continue
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   525
            settings_spec = component.settings_spec
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   526
            self.relative_path_settings.extend(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   527
                component.relative_path_settings)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   528
            for i in range(0, len(settings_spec), 3):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   529
                title, description, option_spec = settings_spec[i:i+3]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   530
                if title:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   531
                    group = optparse.OptionGroup(self, title, description)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   532
                    self.add_option_group(group)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   533
                else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   534
                    group = self        # single options
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   535
                for (help_text, option_strings, kwargs) in option_spec:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   536
                    option = group.add_option(help=help_text, *option_strings,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   537
                                              **kwargs)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   538
                    if kwargs.get('action') == 'append':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   539
                        self.lists[option.dest] = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   540
                if component.settings_defaults:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   541
                    self.defaults.update(component.settings_defaults)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   542
        for component in components:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   543
            if component and component.settings_default_overrides:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   544
                self.defaults.update(component.settings_default_overrides)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   545
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   546
    def get_standard_config_files(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   547
        """Return list of config files, from environment or standard."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   548
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   549
            config_files = os.environ['DOCUTILSCONFIG'].split(os.pathsep)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   550
        except KeyError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   551
            config_files = self.standard_config_files
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   552
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   553
        # If 'HOME' is not set, expandvars() requires the 'pwd' module which is
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   554
        # not available under certain environments, for example, within
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   555
        # mod_python.  The publisher ends up in here, and we need to publish
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   556
        # from within mod_python.  Therefore we need to avoid expanding when we
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   557
        # are in those environments.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   558
        expand = os.path.expanduser
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   559
        if 'HOME' not in os.environ:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   560
            try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   561
                import pwd
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   562
            except ImportError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   563
                expand = lambda x: x
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   564
        return [expand(f) for f in config_files if f.strip()]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   565
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   566
    def get_standard_config_settings(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   567
        settings = Values()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   568
        for filename in self.get_standard_config_files():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   569
            settings.update(self.get_config_file_settings(filename), self)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   570
        return settings
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   571
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   572
    def get_config_file_settings(self, config_file):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   573
        """Returns a dictionary containing appropriate config file settings."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   574
        parser = ConfigParser()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   575
        parser.read(config_file, self)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   576
        self.config_files.extend(parser._files)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   577
        base_path = os.path.dirname(config_file)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   578
        applied = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   579
        settings = Values()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   580
        for component in self.components:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   581
            if not component:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   582
                continue
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   583
            for section in (tuple(component.config_section_dependencies or ())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   584
                            + (component.config_section,)):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   585
                if applied.has_key(section):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   586
                    continue
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   587
                applied[section] = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   588
                settings.update(parser.get_section(section), self)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   589
        make_paths_absolute(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   590
            settings.__dict__, self.relative_path_settings, base_path)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   591
        return settings.__dict__
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   592
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   593
    def check_values(self, values, args):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   594
        """Store positional arguments as runtime settings."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   595
        values._source, values._destination = self.check_args(args)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   596
        make_paths_absolute(values.__dict__, self.relative_path_settings,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   597
                            os.getcwd())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   598
        values._config_files = self.config_files
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   599
        return values
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   600
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   601
    def check_args(self, args):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   602
        source = destination = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   603
        if args:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   604
            source = args.pop(0)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   605
            if source == '-':           # means stdin
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   606
                source = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   607
        if args:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   608
            destination = args.pop(0)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   609
            if destination == '-':      # means stdout
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   610
                destination = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   611
        if args:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   612
            self.error('Maximum 2 arguments allowed.')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   613
        if source and source == destination:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   614
            self.error('Do not specify the same file for both source and '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   615
                       'destination.  It will clobber the source file.')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   616
        return source, destination
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   617
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   618
    def set_defaults_from_dict(self, defaults):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   619
        self.defaults.update(defaults)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   620
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   621
    def get_default_values(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   622
        """Needed to get custom `Values` instances."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   623
        defaults = Values(self.defaults)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   624
        defaults._config_files = self.config_files
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   625
        return defaults
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   626
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   627
    def get_option_by_dest(self, dest):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   628
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   629
        Get an option by its dest.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   630
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   631
        If you're supplying a dest which is shared by several options,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   632
        it is undefined which option of those is returned.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   633
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   634
        A KeyError is raised if there is no option with the supplied
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   635
        dest.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   636
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   637
        for group in self.option_groups + [self]:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   638
            for option in group.option_list:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   639
                if option.dest == dest:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   640
                    return option
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   641
        raise KeyError('No option with dest == %r.' % dest)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   642
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   643
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   644
class ConfigParser(CP.ConfigParser):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   645
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   646
    old_settings = {
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   647
        'pep_stylesheet': ('pep_html writer', 'stylesheet'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   648
        'pep_stylesheet_path': ('pep_html writer', 'stylesheet_path'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   649
        'pep_template': ('pep_html writer', 'template')}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   650
    """{old setting: (new section, new setting)} mapping, used by
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   651
    `handle_old_config`, to convert settings from the old [options] section."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   652
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   653
    old_warning = """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   654
The "[option]" section is deprecated.  Support for old-format configuration
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   655
files may be removed in a future Docutils release.  Please revise your
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   656
configuration files.  See <http://docutils.sf.net/docs/user/config.html>,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   657
section "Old-Format Configuration Files".
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   658
"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   659
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   660
    not_utf8_error = """\
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   661
Unable to read configuration file "%s": content not encoded as UTF-8.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   662
Skipping "%s" configuration file.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   663
"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   664
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   665
    def __init__(self, *args, **kwargs):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   666
        CP.ConfigParser.__init__(self, *args, **kwargs)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   667
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   668
        self._files = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   669
        """List of paths of configuration files read."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   670
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   671
    def read(self, filenames, option_parser):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   672
        if type(filenames) in (types.StringType, types.UnicodeType):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   673
            filenames = [filenames]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   674
        for filename in filenames:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   675
            try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   676
                # Config files must be UTF-8-encoded:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   677
                fp = codecs.open(filename, 'r', 'utf-8')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   678
            except IOError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   679
                continue
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   680
            try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   681
                CP.ConfigParser.readfp(self, fp, filename)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   682
            except UnicodeDecodeError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   683
                sys.stderr.write(self.not_utf8_error % (filename, filename))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   684
                fp.close()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   685
                continue
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   686
            fp.close()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   687
            self._files.append(filename)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   688
            if self.has_section('options'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   689
                self.handle_old_config(filename)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   690
            self.validate_settings(filename, option_parser)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   691
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   692
    def handle_old_config(self, filename):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   693
        warnings.warn_explicit(self.old_warning, ConfigDeprecationWarning,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   694
                               filename, 0)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   695
        options = self.get_section('options')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   696
        if not self.has_section('general'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   697
            self.add_section('general')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   698
        for key, value in options.items():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   699
            if self.old_settings.has_key(key):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   700
                section, setting = self.old_settings[key]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   701
                if not self.has_section(section):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   702
                    self.add_section(section)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   703
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   704
                section = 'general'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   705
                setting = key
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   706
            if not self.has_option(section, setting):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   707
                self.set(section, setting, value)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   708
        self.remove_section('options')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   709
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   710
    def validate_settings(self, filename, option_parser):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   711
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   712
        Call the validator function and implement overrides on all applicable
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   713
        settings.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   714
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   715
        for section in self.sections():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   716
            for setting in self.options(section):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   717
                try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   718
                    option = option_parser.get_option_by_dest(setting)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   719
                except KeyError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   720
                    continue
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   721
                if option.validator:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   722
                    value = self.get(section, setting, raw=1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   723
                    try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   724
                        new_value = option.validator(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   725
                            setting, value, option_parser,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   726
                            config_parser=self, config_section=section)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   727
                    except Exception, error:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   728
                        raise (ValueError(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   729
                            'Error in config file "%s", section "[%s]":\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   730
                            '    %s: %s\n        %s = %s'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   731
                            % (filename, section, error.__class__.__name__,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   732
                               error, setting, value)), None, sys.exc_info()[2])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   733
                    self.set(section, setting, new_value)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   734
                if option.overrides:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   735
                    self.set(section, option.overrides, None)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   736
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   737
    def optionxform(self, optionstr):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   738
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   739
        Transform '-' to '_' so the cmdline form of option names can be used.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   740
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   741
        return optionstr.lower().replace('-', '_')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   742
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   743
    def get_section(self, section):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   744
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   745
        Return a given section as a dictionary (empty if the section
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   746
        doesn't exist).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   747
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   748
        section_dict = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   749
        if self.has_section(section):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   750
            for option in self.options(section):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   751
                section_dict[option] = self.get(section, option, raw=1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   752
        return section_dict
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   753
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   754
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   755
class ConfigDeprecationWarning(DeprecationWarning):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   756
    """Warning for deprecated configuration file features."""