1.3.3.8.2. Example with optparse

In this example we’ll show you how to use the ConfigManager to handle defaults, command line arguments and a configuration file. The command line arguments may be used through optparse or argparse module.

Specification file:

# This is an example specification file

# A section with scalar options
[scalars]
    boolean = boolean(default=False) # A boolean value
    integer = integer(default=0, min=-10, max=10) # An integer value between -10 and 10
    float = float(default=0.0, min=-10.0, max=10.0) # A float value between -10.0 and 10.0
    string = string(default='string') # A string value
# A section with list options
[lists]
    booleans = booleans(default=list(False, True)) # A list of booleans
    integers = integers(default=list(0, 1), min=-10, max=10) # A list of integers
    floats = floats(default=list(0.0, 1.0), min=-10.0, max=10.0) # A list of floats
    strings = strings(default=list('foo', 'bar')) # A list of strings

Configuration file:

# This is an example configuration file

# A section with scalar options
[scalars]
    boolean = True
    integer = 1
    float = 1.0
    string = foo
# A section with list options
[lists]
    floats = 0.0, 1.0, 1.0, 0.0
    booleans = False, True, True, False
    integers = 0, 1, 1, 0
    strings = foo, bar, bar, foo, foo bar, ' foo bar '

Sample code using these specification and configuration:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os, os.path as P, pprint, sys
import vacumm.misc.config as C

def main(argv=None):
    specfile = '%s.ini'%(P.splitext(__file__)[0])
    cfgfile = '%s.cfg'%(P.splitext(__file__)[0])
    
    if not '--cfgfile' in argv:
        argv += ['--cfgfile', cfgfile]
    
    cfgm = C.ConfigManager(specfile)
    
    print '***'
    print '*** You can use the --help flag with this script to interact with it'
    print '*** to test setting config values with command line options and/or'
    print '*** the config file'
    print '***'
    
    print '\n### Using the config manager\n'
    
    cfg = cfgm.defaults()
    print '\n*** Default config from specfile %r:\n\n%s\n'%(specfile, pprint.pformat(cfg.dict()))
    
    # FIXME: load method which currently apply defaults, make it as an option ?
    #cfg = cfgm.load(cfgfile)
    # The ConfigManager currently set defaults from its specifications when using its load method.
    # So in this example we'll directly use configobj to show you only the content of the configuration file
    import configobj
    cfg = configobj.ConfigObj(cfgfile)
    print '\n*** Content of the config file %r:\n\n%s\n'%(cfgfile, pprint.pformat(cfg.dict()))
    
    optcfg = argcfg = None
    
    print '\n### Using the config manager with optparse\n'
    
    try:
    
        cfg = optcfg = cfgm.opt_parse(args=argv)
        print '\n*** Command line config only:\n\n%s\n'%(pprint.pformat(cfg.dict()))
        
        cfg = cfgm.opt_parse(args=argv, cfgfilepatch=True)
        print '\n*** Merged config: file and command:\n\n%s\n'%(pprint.pformat(cfg.dict()))
        
        cfg = cfgm.opt_parse(args=argv, patch=True, cfgfilepatch=True)
        print '\n*** Merged config: default, file and command:\n\n%s\n'%(pprint.pformat(cfg.dict()))
        
        # FIXME: because the load method applies defaults, the real order is command, default and file
        #cfg = cfgm.opt_parse(args=argv, patch=True, cfgfilepatch='after')
        #print '\n*** Merged config: default, command and file:\n\n%s\n'%(pprint.pformat(cfg.dict()))
    
    except SystemExit: pass
    
    print '\n### Using the config manager with argparse\n'
    
    try:
    
        cfg = argcfg = cfgm.arg_parse(args=argv)
        print '\n*** Command line config only:\n\n%s\n'%(pprint.pformat(cfg.dict()))
        
        cfg = cfgm.arg_parse(args=argv, cfgfilepatch=True)
        print '\n*** Merged config: file and command:\n\n%s\n'%(pprint.pformat(cfg.dict()))
        
        cfg = cfgm.arg_parse(args=argv, patch=True, cfgfilepatch=True)
        print '\n*** Merged config: default, file and command:\n\n%s\n'%(pprint.pformat(cfg.dict()))
    
    except SystemExit: pass
    
    assert optcfg == argcfg, 'optparse and argparse configurations differ !'

if __name__ =='__main__':
    main(sys.argv[1:])

The help generated is:

$ ../../../scripts/tutorials/misc.config.py --help
/local/tmp/sraynaud/miniconda2/lib/python2.7/site-packages/cmocean/tools.py:76: MatplotlibDeprecationWarning: The is_string_like function was deprecated in version 2.1.
  if not mpl.cbook.is_string_like(rgbin[0]):
***
*** You can use the --help flag with this script to interact with it
*** to test setting config values with command line options and/or
*** the config file
***

### Using the config manager


*** Default config from specfile '../../../scripts/tutorials/misc.config.ini':

{'lists': {'booleans': [False, True],
           'floats': [0.0, 1.0],
           'integers': [0, 1],
           'strings': ['foo', 'bar']},
 'scalars': {'boolean': False, 'float': 0.0, 'integer': 0, 'string': 'string'}}


*** Content of the config file '../../../scripts/tutorials/misc.config.cfg':

{'lists': {'booleans': ['False', 'True', 'True', 'False'],
           'floats': ['0.0', '1.0', '1.0', '0.0'],
           'integers': ['0', '1', '1', '0'],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': 'True',
             'float': '1.0',
             'integer': '1',
             'string': 'foo'}}


### Using the config manager with optparse

Usage: misc.config.py [options]

Options:
  -h, --help            show this help message and exit
  --cfgfile=CFGFILE     Configuration file [default: "config.cfg"]

  Global configuration options:

  Undocumented section:
    --scalars-boolean   A boolean value. [default: 'False']
    --scalars-integer=SCALARS_INTEGER
                        An integer value between -10 and 10. [default: '0']
    --scalars-float=SCALARS_FLOAT
                        A float value between -10.0 and 10.0. [default: '0.0']
    --scalars-string=SCALARS_STRING
                        A string value. [default: 'string']

  Undocumented section:
    --lists-booleans=LISTS_BOOLEANS
                        A list of booleans. [default: 'False,True']
    --lists-integers=LISTS_INTEGERS
                        A list of integers. [default: '0,1']
    --lists-floats=LISTS_FLOATS
                        A list of floats. [default: '0.0,1.0']
    --lists-strings=LISTS_STRINGS
                        A list of strings. [default: 'foo,bar']

### Using the config manager with argparse

usage: misc.config.py [-h] [--long-help] [--short-help] [--cfgfile CFGFILE]
                      [--scalars-boolean] [--scalars-integer SCALARS_INTEGER]
                      [--scalars-float SCALARS_FLOAT]
                      [--scalars-string SCALARS_STRING]
                      [--lists-booleans LISTS_BOOLEANS]
                      [--lists-integers LISTS_INTEGERS]
                      [--lists-floats LISTS_FLOATS]
                      [--lists-strings LISTS_STRINGS]

optional arguments:
  -h, --help         show a reduced help and exit
  --long-help        show an extended help and exit
  --short-help       show a very reduced help and exit
  --cfgfile CFGFILE  user configuration file that overrides defauts [default:
                     "config.cfg"]

The outputs of this code are:

$ ../../../scripts/tutorials/misc.config.py
/local/tmp/sraynaud/miniconda2/lib/python2.7/site-packages/cmocean/tools.py:76: MatplotlibDeprecationWarning: The is_string_like function was deprecated in version 2.1.
  if not mpl.cbook.is_string_like(rgbin[0]):
***
*** You can use the --help flag with this script to interact with it
*** to test setting config values with command line options and/or
*** the config file
***

### Using the config manager


*** Default config from specfile '../../../scripts/tutorials/misc.config.ini':

{'lists': {'booleans': [False, True],
           'floats': [0.0, 1.0],
           'integers': [0, 1],
           'strings': ['foo', 'bar']},
 'scalars': {'boolean': False, 'float': 0.0, 'integer': 0, 'string': 'string'}}


*** Content of the config file '../../../scripts/tutorials/misc.config.cfg':

{'lists': {'booleans': ['False', 'True', 'True', 'False'],
           'floats': ['0.0', '1.0', '1.0', '0.0'],
           'integers': ['0', '1', '1', '0'],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': 'True',
             'float': '1.0',
             'integer': '1',
             'string': 'foo'}}


### Using the config manager with optparse


*** Command line config only:

{'lists': {'booleans': [False, True, True, False],
           'floats': [0.0, 1.0, 1.0, 0.0],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False, 'float': 1.0, 'integer': 1, 'string': 'foo'}}


*** Merged config: file and command:

{'lists': {'booleans': [False, True, True, False],
           'floats': [0.0, 1.0, 1.0, 0.0],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False, 'float': 1.0, 'integer': 1, 'string': 'foo'}}


*** Merged config: default, file and command:

{'lists': {'booleans': [False, True, True, False],
           'floats': [0.0, 1.0, 1.0, 0.0],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False, 'float': 1.0, 'integer': 1, 'string': 'foo'}}


### Using the config manager with argparse


*** Command line config only:

{'lists': {'booleans': [False, True, True, False],
           'floats': [0.0, 1.0, 1.0, 0.0],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False, 'float': 1.0, 'integer': 1, 'string': 'foo'}}


*** Merged config: file and command:

{'lists': {'booleans': [False, True, True, False],
           'floats': [0.0, 1.0, 1.0, 0.0],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False, 'float': 1.0, 'integer': 1, 'string': 'foo'}}


*** Merged config: default, file and command:

{'lists': {'booleans': [False, True, True, False],
           'floats': [0.0, 1.0, 1.0, 0.0],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False, 'float': 1.0, 'integer': 1, 'string': 'foo'}}

The outputs of this code with configuration setup with command line options:

$ ../../../scripts/tutorials/misc.config.py --scalars-string="foo, 'hello world'" --lists-floats="42,3.14"
/local/tmp/sraynaud/miniconda2/lib/python2.7/site-packages/cmocean/tools.py:76: MatplotlibDeprecationWarning: The is_string_like function was deprecated in version 2.1.
  if not mpl.cbook.is_string_like(rgbin[0]):
***
*** You can use the --help flag with this script to interact with it
*** to test setting config values with command line options and/or
*** the config file
***

### Using the config manager


*** Default config from specfile '../../../scripts/tutorials/misc.config.ini':

{'lists': {'booleans': [False, True],
           'floats': [0.0, 1.0],
           'integers': [0, 1],
           'strings': ['foo', 'bar']},
 'scalars': {'boolean': False, 'float': 0.0, 'integer': 0, 'string': 'string'}}


*** Content of the config file '../../../scripts/tutorials/misc.config.cfg':

{'lists': {'booleans': ['False', 'True', 'True', 'False'],
           'floats': ['0.0', '1.0', '1.0', '0.0'],
           'integers': ['0', '1', '1', '0'],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': 'True',
             'float': '1.0',
             'integer': '1',
             'string': 'foo'}}


### Using the config manager with optparse


*** Command line config only:

{'lists': {'booleans': [False, True, True, False],
           'floats': [42.0, 3.14],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False,
             'float': 1.0,
             'integer': 1,
             'string': "foo, 'hello world'"}}


*** Merged config: file and command:

{'lists': {'booleans': [False, True, True, False],
           'floats': [42.0, 3.14],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False,
             'float': 1.0,
             'integer': 1,
             'string': "foo, 'hello world'"}}


*** Merged config: default, file and command:

{'lists': {'booleans': [False, True, True, False],
           'floats': [42.0, 3.14],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False,
             'float': 1.0,
             'integer': 1,
             'string': "foo, 'hello world'"}}


### Using the config manager with argparse


*** Command line config only:

{'lists': {'booleans': [False, True, True, False],
           'floats': [42.0, 3.14],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False,
             'float': 1.0,
             'integer': 1,
             'string': "foo, 'hello world'"}}


*** Merged config: file and command:

{'lists': {'booleans': [False, True, True, False],
           'floats': [42.0, 3.14],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False,
             'float': 1.0,
             'integer': 1,
             'string': "foo, 'hello world'"}}


*** Merged config: default, file and command:

{'lists': {'booleans': [False, True, True, False],
           'floats': [42.0, 3.14],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False,
             'float': 1.0,
             'integer': 1,
             'string': "foo, 'hello world'"}}

The outputs of this code with configuration setup with command line options and a configuration file :

$ ../../../scripts/tutorials/misc.config.py --scalars-string="foo, 'hello world'" --lists-floats="42,3.14" --cfgfile=tutorials/python/misc.config.cfg
/local/tmp/sraynaud/miniconda2/lib/python2.7/site-packages/cmocean/tools.py:76: MatplotlibDeprecationWarning: The is_string_like function was deprecated in version 2.1.
  if not mpl.cbook.is_string_like(rgbin[0]):
***
*** You can use the --help flag with this script to interact with it
*** to test setting config values with command line options and/or
*** the config file
***

### Using the config manager


*** Default config from specfile '../../../scripts/tutorials/misc.config.ini':

{'lists': {'booleans': [False, True],
           'floats': [0.0, 1.0],
           'integers': [0, 1],
           'strings': ['foo', 'bar']},
 'scalars': {'boolean': False, 'float': 0.0, 'integer': 0, 'string': 'string'}}


*** Content of the config file '../../../scripts/tutorials/misc.config.cfg':

{'lists': {'booleans': ['False', 'True', 'True', 'False'],
           'floats': ['0.0', '1.0', '1.0', '0.0'],
           'integers': ['0', '1', '1', '0'],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': 'True',
             'float': '1.0',
             'integer': '1',
             'string': 'foo'}}


### Using the config manager with optparse


*** Command line config only:

{'lists': {'booleans': [False, True, True, False],
           'floats': [42.0, 3.14],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False,
             'float': 1.0,
             'integer': 1,
             'string': "foo, 'hello world'"}}


*** Merged config: file and command:

{'lists': {'booleans': [False, True, True, False],
           'floats': [42.0, 3.14],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False,
             'float': 1.0,
             'integer': 1,
             'string': "foo, 'hello world'"}}


*** Merged config: default, file and command:

{'lists': {'booleans': [False, True, True, False],
           'floats': [42.0, 3.14],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False,
             'float': 1.0,
             'integer': 1,
             'string': "foo, 'hello world'"}}


### Using the config manager with argparse


*** Command line config only:

{'lists': {'booleans': [False, True, True, False],
           'floats': [42.0, 3.14],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False,
             'float': 1.0,
             'integer': 1,
             'string': "foo, 'hello world'"}}


*** Merged config: file and command:

{'lists': {'booleans': [False, True, True, False],
           'floats': [42.0, 3.14],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False,
             'float': 1.0,
             'integer': 1,
             'string': "foo, 'hello world'"}}


*** Merged config: default, file and command:

{'lists': {'booleans': [False, True, True, False],
           'floats': [42.0, 3.14],
           'integers': [0, 1, 1, 0],
           'strings': ['foo', 'bar', 'bar', 'foo', 'foo bar', ' foo bar ']},
 'scalars': {'boolean': False,
             'float': 1.0,
             'integer': 1,
             'string': "foo, 'hello world'"}}