view configuration/config.py @ 18:d8871956536e

remove cruft and start to organize
author Jeff Hammel <jhammel@mozilla.com>
date Mon, 26 Mar 2012 13:19:55 -0700
parents a78ab14ae376
children cadc9514f60a
line wrap: on
line source

#!/usr/bin/env python

"""
multi-level unified configuration
"""

import sys
import optparse

# imports for contigent configuration providers
try:
    import json
except ImportError:
    try:
        import simplejson as json
    except ImportError:
        json = None
try:
    import yaml
except ImportError:
    yaml = None

__all__ = ['Configuration', 'configuration_providers']

configuration_providers = []
if json:
    class JSON(object):
        extensions = ['json']
        def read(self, filename):
            return json.loads(file(filename).read())
    configuration_providers.append(JSON)

if yaml:
    class YAML(object):
        extensions = ['yml']
        def read(self, filename):
            f = file(filename)
            config = yaml.load(f)
            f.close()
            return config

    configuration_providers.append(YAML)


class Configuration(object):
    options = {}

    def __init__(self, configuration_providers=configuration_providers):
        self.config = {}
        self.configuration_providers = configuration_providers

    def items(self):
        # TODO: allow options to be a list of 2-tuples
        return self.options.items()

    def check(self, config):
        """check validity of configuration"""

        # TODO: ensure options in configuration are in self.options
        unknown_options = []

        # TODO: ensure options are of the right type (if specified)

    def __call__(self, *args):
        """add items to configuration and check it"""

    def add(self, config):
        """update configuration: not undoable"""

        self.check(config)

        self.config.update(config)
        # TODO: option to extend; augment lists/dicts

    ### methods for optparse
    ### XXX could go in a subclass

    def optparse_options(self, parser):
        """add optparse options to a OptionParser instance"""
        for key, value in self.items():
            # TODO: move adding options to a separate function

            # CLI arguments
            args = value.get('flags', ['--%s' % key])
            if not args:
                continue

            kw = {'dest': key}
            help = value.get('help', key)
            if 'default' in value:

                kw['default'] = value['default']
                # TODO: use default pattern a la
                # - http://hg.mozilla.org/build/talos/file/c6013a2f09ce/talos/PerfConfigurator.py#l358
                # - http://k0s.org/mozilla/hg/bzconsole/file/d5e88dadde69/bzconsole/command.py#l12

                help += ' [DEFAULT: %s]' % value['default']
            kw['help'] = help
            kw['action'] = 'store' # TODO: types
            parser.add_option(*args, **kw)

    def parser(self, configuration_provider_option=None, **parser_args):
        """
        return OptionParser for this Configuration instance
        - configuration_provider_options : option for configuration files [TODO]
        (also TODO: a special value that equates to the first file extension value
        for the configuration_providers)
        - parser_args : arguments to the OptionParser constructor
        """
        if 'description' not in parser_args:
            parser_args['description'] = getattr(self, '__doc__', '')
            if 'formatter' not in parser_args:
                class PlainDescriptionFormatter(optparse.IndentedHelpFormatter):
                    """description formatter for console script entry point"""
                    def format_description(self, description):
                        if description:
                            return description.strip() + '\n'
                        else:
                            return ''
                parser_args['formatter'] = PlainDescriptionFormatter()
        parser = optparse.OptionParser(**parser_args)
        self.optparse_options(parser)
        return parser