def test_layered_subsections(self):
        defaults = OrderedDict((('force', False),
                                ('home', 'thisdata'),
                                ('loglevel', 'INFO')))
        cmdline = ['--mymodule-home=thatdata', '--mymodule-force']
        cfg = LayeredConfig(Defaults(defaults), Commandline(cmdline),
                            cascade=True)
        self.assertEqual(cfg.mymodule.force, True)
        self.assertEqual(cfg.mymodule.home, 'thatdata')
        self.assertEqual(cfg.mymodule.loglevel, 'INFO')

        # second test is more difficult: the lower-priority Defaults
        # source only contains a subsection, while the higher-priority
        # Commandline source contains no such subsection. Our
        # sub-LayeredConfig object will only have a Defaults source,
        # not a Commandline source (which will cause the
        # __getattribute__ lookup_resource to look in the Defaults
        # object in the sub-LayeredConfig object, unless we do
        # something smart.
        defaults = {'mymodule': defaults}
        cmdline = ['--home=thatdata', '--force']

        o = Commandline(cmdline)
        o.subsection("mymodule").keys()
        cfg = LayeredConfig(Defaults(defaults), Commandline(cmdline),
                            cascade=True)
        self.assertEqual(cfg.mymodule.force, True)
        self.assertEqual(cfg.mymodule.home, 'thatdata')
        self.assertEqual(cfg.mymodule.loglevel, 'INFO')
        self.assertEqual(['force', 'home', 'loglevel'], list(cfg.mymodule))
Example #2
0
    def test_commandline_implicit_typing(self):
        # The big test here is really the partially-configured
        # ArgumentParser (handles one positional argument but not the
        # optional --force)
        defaults = {'force': False}
        cmdline = ['command', '--force']
        parser = argparse.ArgumentParser()
        parser.add_argument("positional")
        cmdlinesrc = Commandline(cmdline, parser=parser)
        cfg = LayeredConfig(Defaults(defaults), cmdlinesrc)
        self.assertEqual(cfg.force, True)

        # try again with explicit argument
        parser = argparse.ArgumentParser()
        parser.add_argument("positional")
        cmdlinesrc = Commandline(['command', '--force=True'], parser=parser)
        cfg = LayeredConfig(Defaults(defaults), cmdlinesrc)
        self.assertEqual(cfg.force, True)

        # once again without the optional typing source
        parser = argparse.ArgumentParser()
        parser.add_argument("positional")
        cmdlinesrc = Commandline(['command', '--force'], parser=parser)
        cfg = LayeredConfig(Defaults({}), cmdlinesrc)
        self.assertEqual(cfg.force, True)
Example #3
0
class TestCommandline(unittest.TestCase, TestConfigSourceHelper):

    # Note: bool is "half-way" supported. Only value-less parameters
    # are typed as bool (eg "--force", not "--force=True")
    supported_types = (str, list, bool)

    simple_cmdline = [
        '--home=mydata',
        '--processes=4',
        '--force',  # note implicit boolean typing
        '--extra=foo',
        '--extra=bar',
        '--expires=2014-10-15',
        '--lastrun=2014-10-15 14:32:07'
    ]

    complex_cmdline = [
        '--home=mydata', '--processes=4', '--force=True', '--extra=foo',
        '--extra=bar', '--mymodule-force=False', '--mymodule-extra=foo',
        '--mymodule-extra=baz', '--mymodule-expires=2014-10-15',
        '--mymodule-arbitrary-nesting-depth=works', '--extramodule-unique'
    ]

    def setUp(self):
        super(TestCommandline, self).setUp()
        # this means we lack typing information
        self.simple = Commandline(self.simple_cmdline)
        self.complex = Commandline(self.complex_cmdline)

    # Overrides of TestHelper.test_get, .test_typed and and due to
    # limitations of Commandline (carries almost no typeinfo)
    def test_get(self):
        self.assertEqual(self.simple.get("home"), "mydata")
        self.assertEqual(self.simple.get("processes"), "4")
        self.assertEqual(self.simple.get("force"), True)
        self.assertEqual(self.simple.get("extra"),
                         ['foo', 'bar'])  # note typed!
        self.assertEqual(self.simple.get("expires"), "2014-10-15")
        self.assertEqual(self.simple.get("lastrun"), "2014-10-15 14:32:07")

    def test_typed(self):
        for key in self.simple.keys():
            # these should be typed as bool and list, respectively
            if key in ("force", "extra"):
                self.assertTrue(self.simple.typed(key))
            else:
                self.assertFalse(self.simple.typed(key))

    def test_config_subsections(self):
        # this case uses valued parameter for --force et al, which
        # cannot be reliably converted to bools using only intrinsic
        # information
        self.supported_types = (str, list)
        super(TestCommandline, self).test_config_subsections()

    def test_set(self):
        self.simple.set("home", "away from home")
        self.assertEqual(self.simple.get("home"), "away from home")
Example #4
0
 def test_modified_subsections(self):
     defaults = {'force': False, 'home': 'thisdata', 'loglevel': 'INFO'}
     cmdline = ['--mymodule-home=thatdata', '--mymodule-force']
     cfg = LayeredConfig(Defaults(defaults),
                         INIFile("complex.ini"),
                         Commandline(cmdline),
                         cascade=True)
     cfg.mymodule.expires = date(2014, 10, 24)
Example #5
0
    def test_set_novalue(self):
        # it should be possible to set values that are defined in any
        # of the configsources, even though only typing information
        # exists there.
        cfg = LayeredConfig(Defaults({'placeholder': int}), Commandline([]))
        cfg.placeholder = 42

        # but it shouldn't be possible to set values that hasn't been
        # defined anywhere.
        with self.assertRaises(AttributeError):
            cfg.nonexistent = 43
Example #6
0
 def test_typed_commandline(self):
     cmdline = [
         '--home=mydata', '--processes=4', '--force=True', '--extra=foo',
         '--extra=bar', '--implicitboolean', '--mymodule-force=False',
         '--mymodule-extra=foo', '--mymodule-extra=baz',
         '--mymodule-expires=2014-10-15',
         '--mymodule-arbitrary-nesting-depth=works', '--extramodule-unique'
     ]
     cfg = LayeredConfig(Defaults(self.types), Commandline(cmdline))
     self._test_config_subsections(cfg)
     self.assertTrue(cfg.implicitboolean)
     self.assertIs(type(cfg.implicitboolean), bool)
Example #7
0
    def test_layered_subsections(self):
        defaults = OrderedDict(
            (('force', False), ('home', 'thisdata'), ('loglevel', 'INFO')))
        cmdline = ['--mymodule-home=thatdata', '--mymodule-force']
        cfg = LayeredConfig(Defaults(defaults),
                            Commandline(cmdline),
                            cascade=True)
        self.assertEqual(cfg.mymodule.force, True)
        self.assertEqual(cfg.mymodule.home, 'thatdata')
        self.assertEqual(cfg.mymodule.loglevel, 'INFO')

        # second test is more difficult: the lower-priority Defaults
        # source only contains a subsection, while the higher-priority
        # Commandline source contains no such subsection. Our
        # sub-LayeredConfig object will only have a Defaults source,
        # not a Commandline source (which will cause the
        # __getattribute__ lookup_resource to look in the Defaults
        # object in the sub-LayeredConfig object, unless we do
        # something smart.
        defaults = {'mymodule': defaults}
        cmdline = ['--home=thatdata', '--force']

        o = Commandline(cmdline)
        o.subsection("mymodule").keys()
        cfg = LayeredConfig(Defaults(defaults),
                            Commandline(cmdline),
                            cascade=True)
        self.assertEqual(cfg.mymodule.force, True)
        self.assertEqual(cfg.mymodule.home, 'thatdata')
        self.assertEqual(cfg.mymodule.loglevel, 'INFO')
        self.assertEqual(['force', 'home', 'loglevel'], list(cfg.mymodule))
Example #8
0
 def test_typed_novalue(self):
     # this cmdline only sets some of the settings. The test is
     # that the rest should raise AttributeError (not return None,
     # as was the previous behaviour), and that __iter__ should not
     # include them.
     cmdline = ['--processes=4', '--force=False']
     cfg = LayeredConfig(Defaults(self.types), Commandline(cmdline))
     self.assertEqual(4, cfg.processes)
     self.assertIsInstance(cfg.processes, int)
     with self.assertRaises(AttributeError):
         cfg.home
     with self.assertRaises(AttributeError):
         cfg.extra
     self.assertEqual(set(['processes', 'force']), set(list(cfg)))
Example #9
0
    def setUp(self):
        super(TestCommandlineConfigured, self).setUp()
        simp = argparse.ArgumentParser(description="This is a simple program")
        simp.add_argument('--home', help="The home directory of the app")
        simp.add_argument('--processes',
                          type=int,
                          help="Number of simultaneous processes")
        simp.add_argument('--force',
                          type=LayeredConfig.boolconvert,
                          nargs='?',
                          const=True)
        simp.add_argument('--extra', action='append')
        simp.add_argument('--expires', type=LayeredConfig.dateconvert)
        simp.add_argument('--lastrun', type=LayeredConfig.datetimeconvert)
        simp.add_argument('--unused')
        self.simple = Commandline(self.simple_cmdline, parser=simp)

        comp = argparse.ArgumentParser(description="This is a complex program")
        comp.add_argument('--home', help="The home directory of the app")
        comp.add_argument('--processes',
                          type=int,
                          help="Number of simultaneous processes")
        comp.add_argument('--force',
                          type=LayeredConfig.boolconvert,
                          nargs='?',
                          const=True)
        comp.add_argument('--extra', action='append')
        comp.add_argument('--mymodule-force',
                          type=LayeredConfig.boolconvert,
                          nargs='?',
                          const=True)
        comp.add_argument('--mymodule-extra', action='append')
        comp.add_argument('--mymodule-expires', type=LayeredConfig.dateconvert)
        comp.add_argument('--mymodule-arbitrary-nesting-depth')
        comp.add_argument('--extramodule-unique', nargs='?', const=True)
        self.complex = Commandline(self.complex_cmdline, parser=comp)
Example #10
0
 def test_layered(self):
     defaults = {'home': 'someplace'}
     cmdline = ['--home=anotherplace']
     env = {'MYAPP_HOME': 'yourdata'}
     cfg = LayeredConfig(Defaults(defaults))
     self.assertEqual(cfg.home, 'someplace')
     cfg = LayeredConfig(Defaults(defaults), INIFile("simple.ini"))
     self.assertEqual(cfg.home, 'mydata')
     cfg = LayeredConfig(Defaults(defaults), INIFile("simple.ini"),
                         Environment(env, prefix="MYAPP_"))
     self.assertEqual(cfg.home, 'yourdata')
     cfg = LayeredConfig(Defaults(defaults), INIFile("simple.ini"),
                         Environment(env, prefix="MYAPP_"),
                         Commandline(cmdline))
     self.assertEqual(cfg.home, 'anotherplace')
     self.assertEqual(
         ['home', 'processes', 'force', 'extra', 'expires', 'lastrun'],
         list(cfg))
Example #11
0
    def test_typed_commandline_cascade(self):
        # the test here is that __getattribute__ must determine that
        # subconfig.force is not typed in itself, and fetch type
        # information from the root of defaults

        defaults = {'force': True, 'lastdownload': datetime, 'mymodule': {}}
        cmdline = ['--mymodule-force=False']
        cfg = LayeredConfig(Defaults(defaults),
                            Commandline(cmdline),
                            cascade=True)
        subconfig = getattr(cfg, 'mymodule')
        self.assertIs(type(subconfig.force), bool)
        self.assertEqual(subconfig.force, False)

        # test typed config values that have no actual value. Since
        # they have no value, they should raise AtttributeError
        with self.assertRaises(AttributeError):
            self.assertEqual(cfg.lastdownload, None)
        with self.assertRaises(AttributeError):
            self.assertEqual(subconfig.lastdownload, None)
Example #12
0
 def setUp(self):
     super(TestCommandline, self).setUp()
     # this means we lack typing information
     self.simple = Commandline(self.simple_cmdline)
     self.complex = Commandline(self.complex_cmdline)
Example #13
0
 def test_typed_override(self):
     # make sure this auto-typing isn't run for bools
     types = {'logfile': True}
     cmdline = ["--logfile=out.log"]
     cfg = LayeredConfig(Defaults(types), Commandline(cmdline))
     self.assertEqual(cfg.logfile, "out.log")
 def setUp(self):
     super(TestCommandline, self).setUp()
     # this means we lack typing information
     self.simple = Commandline(self.simple_cmdline)
     self.complex = Commandline(self.complex_cmdline)
class TestCommandline(unittest.TestCase, TestConfigSourceHelper):

    # Note: bool is "half-way" supported. Only value-less parameters
    # are typed as bool (eg "--force", not "--force=True")
    supported_types = (str, list, bool)

    simple_cmdline = ['--home=mydata',
                      '--processes=4',
                      '--force',  # note implicit boolean typing
                      '--extra=foo',
                      '--extra=bar',
                      '--expires=2014-10-15',
                      '--lastrun=2014-10-15 14:32:07']

    complex_cmdline = ['--home=mydata',
                       '--processes=4',
                       '--force=True',
                       '--extra=foo',
                       '--extra=bar',
                       '--mymodule-force=False',
                       '--mymodule-extra=foo',
                       '--mymodule-extra=baz',
                       '--mymodule-expires=2014-10-15',
                       '--mymodule-arbitrary-nesting-depth=works',
                       '--extramodule-unique']

    def setUp(self):
        super(TestCommandline, self).setUp()
        # this means we lack typing information
        self.simple = Commandline(self.simple_cmdline)
        self.complex = Commandline(self.complex_cmdline)


    # Overrides of TestHelper.test_get, .test_typed and and due to
    # limitations of Commandline (carries almost no typeinfo)
    def test_get(self):
        self.assertEqual(self.simple.get("home"), "mydata")
        self.assertEqual(self.simple.get("processes"), "4")
        self.assertEqual(self.simple.get("force"), True)
        self.assertEqual(self.simple.get("extra"), ['foo','bar'])  # note typed!
        self.assertEqual(self.simple.get("expires"), "2014-10-15")
        self.assertEqual(self.simple.get("lastrun"), "2014-10-15 14:32:07")

    def test_typed(self):
        for key in self.simple.keys():
            # these should be typed as bool and list, respectively
            if key in ("force", "extra"):
                self.assertTrue(self.simple.typed(key))
            else:
                self.assertFalse(self.simple.typed(key))


    def test_config_subsections(self):
        # this case uses valued parameter for --force et al, which
        # cannot be reliably converted to bools using only intrinsic
        # information
        self.supported_types = (str, list)
        super(TestCommandline, self).test_config_subsections()

    def test_set(self):
        self.simple.set("home", "away from home")
        self.assertEqual(self.simple.get("home"), "away from home")
Example #16
0
inifile = INIFile("myapp.ini")
# end inifile

# begin argparse
parser = argparse.ArgumentParser("This is a simple program")
parser.add_argument("--home", help="The home directory of the app")
parser.add_argument('--dostuff', action="store_true", help="Do some work")
parser.add_argument("-t", "--times", type=int, help="Number of times to do it")
parser.add_argument('--things', action="append", help="Extra things to crunch")
parser.add_argument('--retry', action="store_true", help="Try again")
parser.add_argument("file", metavar="FILE", help="The filename to process")
# end argparse

# begin layeredconfig
sys.argv = ['./myapp.py', '--home=/opt/myapp', '-t=2', '--dostuff', 'file.txt']
cfg = LayeredConfig(defaults, inifile, Commandline(parser=parser))
print("Starting %s in %s for %r times (doing work: %s)" %
      (cfg.name, cfg.home, cfg.times, cfg.dostuff))
# should print "Starting MyApp in /opt/myapp for 2 times (doing work: True)"
# end layeredconfig

# begin showhelp
sys.argv = ['./myapp.py', '-h']
cfg = LayeredConfig(defaults, inifile, Commandline(parser=parser))
# end showhelp

# begin nodefaults

# NOTE: we never reach this because the previous call to -h will have
# called sys.exit
Example #17
0
# 1. hard-coded defaults
defaults = {"hello": "is it me you're looking for?"}

# 2. INI configuration file
with open("myapp.ini", "w") as fp:
    fp.write("""
[__root__]
hello = kitty
""")

# 3. enironment variables
import os
os.environ['MYAPP_HELLO'] = 'goodbye'

# 4.command-line arguments
import sys
sys.argv = ['./myapp.py', '--hello=world']

# Create a config object that gets settings from these four
# sources.
config = LayeredConfig(Defaults(defaults), INIFile("myapp.ini"),
                       Environment(prefix="MYAPP_"), Commandline())

# Prints "Hello world!", i.e the value provided by command-line
# arguments. Latter sources take precedence over earlier sources.
print("Hello %s!" % config.hello)
# end firststep

return_value = True
Example #18
0
        'lastrun': datetime(2014, 10, 30, 16, 40, 22)
    }
})
# end defaults

# begin inifile
myinifile = INIFile("myapp.ini")
# end inifile

# begin environment
env = {'MYAPP_HOME': 'C:\\Progra~1\\MyApp', 'MYAPP_SUBMODULE_RETRY': 'True'}
myenv = Environment(env, prefix="MYAPP_")
# end environment

# begin commandline
mycmdline = Commandline(['-f', '--home=/opt/myapp', '--times=2', '--dostuff'])
rest = mycmdline.rest
# end commandline
assert rest == ['-f']

# begin makeconfig
cfg = LayeredConfig(mydefaults, myinifile, myenv, mycmdline)
# end makeconfig
import os


def do_stuff(action, idx):
    pass


# begin useconfig