# HG changeset patch # User Jeff Hammel # Date 1274370455 25200 # Node ID 3081763b099bc0ea4c9bd43ed4b5052ba6f5a21d initial commit of ConfigOptionParser diff -r 000000000000 -r 3081763b099b configoptionparser/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configoptionparser/__init__.py Thu May 20 08:47:35 2010 -0700 @@ -0,0 +1,93 @@ +from optparse import OptionParser +from ConfigParser import ConfigParser + +### duplicate/extend ConfigParser functions as we can't use them directly :( + +def getlist(string, separator=','): + """returns a list from a string given a separator""" + string = string.strip() + if not string: + return [] + return [i.strip() for i in string.split(separator)] + +def getboolean(string): + return string.lower() == 'true' + + +class Undefined(object): + def __init__(self, default): + self.default=default + +class ConfigOptionParser(OptionParser): + def __init__(self, defaults_section='DEFAULTS', dict_section=None, + variables=None, **kwargs): + """ + - defaults_section: section of .ini to look for configuration variables + - dict_section: section of .ini to return as a dictionary + - variables: attr on returned options to parse dictionary from command line + """ + self.defaults_section = defaults_section + self.dict_section = dict_section + self.variables = variables + if self.dict_section and not self.variables: + self.variables = dict_section + OptionParser.__init__(self, **kwargs) + OptionParser.add_option(self, + '-c', '--config', dest='config', action='append', + help='ini file to read from') + + def add_option(self, *args, **kwargs): + kwargs['default'] = Undefined(kwargs.get('default')) + OptionParser.add_option(self, *args, **kwargs) + + def parse_args(self, args=None, values=None): + options, args = OptionParser.parse_args(self, args, values) + + # get defaults from the configuration parser + defaults = {} + config = ConfigParser() + if options.config: + config.read(options.config) + if self.defaults_section in config.sections(): + defaults = dict(config.items(self.defaults_section, raw=True)) + + # option dict + option_dict = dict([(i.dest, i) for i in self.option_list + if i.dest not in ('config', 'help')]) + + # conversion functions for .ini data + conversions = { 'store_true': getboolean, + 'store_false': getboolean, + 'append': getlist } + + # fill in the defaults not set from the command line + for key, value in options.__dict__.items(): + + # don't override command line arguments! they win! + if isinstance(value, Undefined): + + if key in defaults and key in option_dict: + # fill in options from .ini files + + option = option_dict[key] + + # converstion function + function = conversions.get(option.action, lambda x: x) + + setattr(options, key, function(defaults[key])) + else: + # set from option defaults + setattr(options, key, value.default) + + # get variables from dict_section and command line arguments + # TODO: could do this first then interpolate the config file from these + variables = {} + if self.dict_section in config.sections(): + variables.update(dict(config.items(self.dict_section, raw=True))) + if self.variables: + variables.update(dict([i.split('=',1) for i in args if '=' in i])) + args = [i for i in args if '=' not in i] + setattr(options, self.variables, variables) + + return (options, args) + diff -r 000000000000 -r 3081763b099b example.ini --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example.ini Thu May 20 08:47:35 2010 -0700 @@ -0,0 +1,9 @@ +[DEFAULTS] +foo = bar +bar = baz +fleem = blah +list = foo, bar, baz +verbose = True + +[variables] +blah = w00t \ No newline at end of file diff -r 000000000000 -r 3081763b099b example.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/example.py Thu May 20 08:47:35 2010 -0700 @@ -0,0 +1,35 @@ +#!/usr/bin/env python + +""" +Example script to illustrate ConfigOptionParser. +Run from the command line and give some arguments to see how this works. + +Read values from .ini file: + python example.py -c example.ini + +Read values from .ini file but override the setting for the foo + python example.py -c example.ini -f blah + +Override/add variables from the command line: + python example.py -c example.ini blah=bleem fargo=bah -f blah +""" + +import sys +from configoptionparser import ConfigOptionParser + +parser = ConfigOptionParser(dict_section='variables') +parser.add_option('-f', dest='foo') +parser.add_option('--baz', default='the baz default string') +parser.add_option('--fleem') +parser.add_option('--list', dest='list', action='append') +parser.add_option('--verbose', dest='verbose', action='store_true', + default=False) + +def main(args=sys.argv[1:]): + options, args = parser.parse_args(args) + for key in sorted(options.__dict__): + print '%s: %s' % (key, options.__dict__[key]) + print 'args: %s' % args + +if __name__ == '__main__': + main() diff -r 000000000000 -r 3081763b099b setup.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/setup.py Thu May 20 08:47:35 2010 -0700 @@ -0,0 +1,25 @@ +from setuptools import setup, find_packages + +version = '0.0' + +setup(name='ConfigOptionParser', + version=version, + description="a version of OptionParser that allows parsing from .ini files", + long_description="""\ +""", + classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers + keywords='ini cli', + author='Jeff Hammel', + author_email='jhammel@mozilla.com', + url='http://k0s.org', + license='MPL', + packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), + include_package_data=True, + zip_safe=False, + install_requires=[ + # -*- Extra requirements: -*- + ], + entry_points=""" + # -*- Entry points: -*- + """, + )