def test_default_config_exists_config_required_overridden_correctly( self ): temp_config_dir = '/tmp' with open('/tmp/dwight.ini', 'w') as f: f.write('[x]\n size=42') try: with open('/tmp/wilma.ini', 'w') as f: f.write('[x]\n size=666') try: cm = ConfigurationManager( definition_source=self._some_namespaces(), values_source_list=[ ConfigFileFutureProxy, command_line ], argv_source=['--admin.conf=/tmp/wilma.ini'], app_name='dwight', config_pathname=temp_config_dir, config_optional=False, ) self.assertEqual(cm.get_config()['x.size'], 666) finally: os.unlink('/tmp/wilma.ini') finally: os.unlink('/tmp/dwight.ini')
def test_write_json(self): n = Namespace(doc='top') n.add_option( 'aaa', '2011-05-04T15:10:00', 'the a', short_form='a', from_string_converter=datetime_from_ISO_string ) c = ConfigurationManager( [n], use_admin_controls=True, use_auto_help=False, argv_source=[] ) out = StringIO() c.write_conf(for_json, opener=stringIO_context_wrapper(out)) received = out.getvalue() out.close() jrec = json.loads(received) expect_to_find = { "short_form": "a", "default": "2011-05-04T15:10:00", "doc": "the a", "value": "2011-05-04T15:10:00", "from_string_converter": "configman.datetime_util.datetime_from_ISO_string", "name": "aaa" } for key, value in expect_to_find.items(): self.assertEqual(jrec['aaa'][key], value)
def test_write_json(self): n = Namespace(doc='top') n.add_option('aaa', '2011-05-04T15:10:00', 'the a', short_form='a', from_string_converter=datetime_from_ISO_string) c = ConfigurationManager([n], use_admin_controls=True, use_auto_help=False, argv_source=[]) out = StringIO() c.write_conf(for_json, opener=stringIO_context_wrapper(out)) received = out.getvalue() out.close() jrec = json.loads(received) expect_to_find = { "short_form": "a", "default": "2011-05-04T15:10:00", "doc": "the a", "value": "2011-05-04T15:10:00", "from_string_converter": "configman.datetime_util.datetime_from_ISO_string", "name": "aaa" } for key, value in expect_to_find.items(): self.assertEqual(jrec['aaa'][key], value)
def test_write_ini_with_custom_converters(self): def dict_encoder(dict_): return ','.join('%s:%s' % (k, v) for (k, v) in dict_.items()) def dict_decoder(string): return dict(x.split(':') for x in string.split(',')) n = Namespace(doc='top') n.add_option( 'a', default={'one': 'One'}, doc='the doc string', to_string_converter=dict_encoder, from_string_converter=dict_decoder, ) c = ConfigurationManager( [n], use_admin_controls=True, use_auto_help=False, argv_source=[] ) expected = "# the doc string\n#a=one:One\n" out = StringIO() c.write_conf(for_configobj, opener=stringIO_context_wrapper(out)) received = out.getvalue() out.close() self.assertEqual(expected.strip(), received.strip())
def test_write_ini_with_custom_converters(self): def dict_encoder(dict_): return ','.join('%s:%s' % (k, v) for (k, v) in dict_.items()) def dict_decoder(string): return dict(x.split(':') for x in string.split(',')) n = Namespace(doc='top') n.add_option( 'a', default={'one': 'One'}, doc='the doc string', to_string_converter=dict_encoder, from_string_converter=dict_decoder, ) c = ConfigurationManager([n], use_admin_controls=True, use_auto_help=False, argv_source=[]) expected = "# the doc string\n#a=one:One\n" out = StringIO() c.write_conf(for_configobj, opener=stringIO_context_wrapper(out)) received = out.getvalue() out.close() self.assertEqual(expected.strip(), received.strip())
def configuration(*args, **kwargs): """this function just instantiates a ConfigurationManager and returns the configuration dictionary. It accepts all the same parameters as the constructor for the ConfigurationManager class.""" try: config_kwargs = {'mapping_class': kwargs.pop('mapping_class')} except KeyError: config_kwargs = {} cm = ConfigurationManager(*args, **kwargs) return cm.get_config(**config_kwargs)
def test_json_round_trip(self): n = Namespace(doc='top') n.add_option( 'aaa', '2011-05-04T15:10:00', 'the a', short_form='a', from_string_converter=datetime_from_ISO_string ) expected_date = datetime_from_ISO_string('2011-05-04T15:10:00') n.add_option( 'bbb', '37', 'the a', short_form='a', from_string_converter=int ) n.add_option('write', 'json') n.add_aggregation('bbb_minus_one', bbb_minus_one) name = '/tmp/test.json' import functools opener = functools.partial(open, name, 'w') c1 = ConfigurationManager( [n], [], use_admin_controls=True, use_auto_help=False, app_name='/tmp/test', app_version='0', app_description='', argv_source=[] ) c1.write_conf('json', opener) d1 = {'bbb': 88} d2 = {'bbb': '-99'} try: with open(name) as jfp: j = json.load(jfp) c2 = ConfigurationManager( (j,), (d1, d2), use_admin_controls=True, use_auto_help=False, argv_source=[] ) config = c2.get_config() self.assertEqual(config.aaa, expected_date) self.assertEqual(config.bbb, -99) self.assertEqual(config.bbb_minus_one, -100) finally: os.unlink(name)
def parse_args(self, args=None, namespace=None): """this method hijacks the normal argparse Namespace generation, shimming configman into the process. The return value will be a configman DotDict rather than an argparse Namespace.""" # load the config_manager within the scope of the method that uses it # so that we avoid circular references in the outer scope from configman.config_manager import ConfigurationManager configuration_manager = ConfigurationManager( definition_source=[self.get_required_config()], values_source_list=self.value_source_list, argv_source=args, app_name=self.prog, app_version=self.version, app_description=self.description, use_auto_help=False, ) # it is apparent a common idiom that commandline options may have # embedded '-' characters in them. Configman requires that option # follow the Python Identifier rules. Fortunately, Configman has a # class that will perform dynamic translation of keys. In this # code fragment, we fetch the final configuration from configman # using a Mapping that will translate keys with '-' into keys with # '_' instead. conf = configuration_manager.get_config( mapping_class=create_key_translating_dot_dict( "HyphenUnderscoreDict", (('-', '_'),) ) ) # here is where we add the values given to "set_defaults" method # of argparse. if self.configman_subparsers_option: subparser_name = conf[self.configman_subparsers_option.name] try: conf.update( self.configman_subparsers_option.foreign_data.argparse .subparsers[subparser_name].subparser .extra_defaults ) except (AttributeError, KeyError): # no extra_defaults skip on pass if hasattr(self, 'extra_defaults'): conf.update(self.extra_defaults) return conf
def test_configdir_default_config_config_required_overridden_correctly_2( self ): temp_config_dir = '/tmp' with open('/tmp/dwight.ini', 'w') as f: f.write('') try: with open('./wilma.ini', 'w') as f: f.write('') try: ConfigurationManager( definition_source=self._some_namespaces(), values_source_list=[ ConfigFileFutureProxy, command_line ], argv_source=['--admin.conf=./wilma.ini'], app_name='dwight', config_pathname=temp_config_dir, config_optional=False, ) finally: os.unlink('./wilma.ini') finally: os.unlink('/tmp/dwight.ini')
def test_configdir_exists_and_default_config_exists_and_config_required( self): temp_config_dir = '/tmp' with open('/tmp/dwight.ini', 'w') as f: f.write('[x]\n size=42') try: cm = ConfigurationManager( definition_source=self._some_namespaces(), values_source_list=[ConfigFileFutureProxy], app_name='dwight', config_pathname=temp_config_dir, config_optional=False, ) self.assertEqual(cm.get_config()['x.size'], 42) finally: os.unlink('/tmp/dwight.ini')
def test_configdir_exists_and_default_config_exists_and_config_required( self ): temp_config_dir = '/tmp' with open('/tmp/dwight.ini', 'w') as f: f.write('[x]\n size=42') try: cm = ConfigurationManager( definition_source=self._some_namespaces(), values_source_list=[ConfigFileFutureProxy], app_name='dwight', config_pathname=temp_config_dir, config_optional=False, ) self.assertEqual(cm.get_config()['x.size'], 42) finally: os.unlink('/tmp/dwight.ini')
def test_no_config_and_not_required(self): ConfigurationManager( definition_source=self._some_namespaces(), values_source_list=[ConfigFileFutureProxy], app_name='dwight', config_pathname='.', config_optional=True, )
def parse_args(self, args=None, namespace=None): """this method hijacks the normal argparse Namespace generation, shimming configman into the process. The return value will be a configman DotDict rather than an argparse Namespace.""" # load the config_manager within the scope of the method that uses it # so that we avoid circular references in the outer scope from configman.config_manager import ConfigurationManager configuration_manager = ConfigurationManager( definition_source=[self.get_required_config()], values_source_list=self.value_source_list, argv_source=args, app_name=self.prog, app_version=self.version, app_description=self.description, use_auto_help=False, ) # it is apparent a common idiom that commandline options may have # embedded '-' characters in them. Configman requires that option # follow the Python Identifier rules. Fortunately, Configman has a # class that will perform dynamic translation of keys. In this # code fragment, we fetch the final configuration from configman # using a Mapping that will translate keys with '-' into keys with # '_' instead. conf = configuration_manager.get_config( mapping_class=create_key_translating_dot_dict( "HyphenUnderscoreDict", (('-', '_'), ))) # here is where we add the values given to "set_defaults" method # of argparse. if self.configman_subparsers_option: subparser_name = conf[self.configman_subparsers_option.name] try: conf.update( self.configman_subparsers_option.foreign_data.argparse. subparsers[subparser_name].subparser.extra_defaults) except (AttributeError, KeyError): # no extra_defaults skip on pass if hasattr(self, 'extra_defaults'): conf.update(self.extra_defaults) return conf
def test_configdir_exists_but_no_config_and_not_required(self): temp_config_dir = '/tmp' ConfigurationManager( definition_source=self._some_namespaces(), values_source_list=[ConfigFileFutureProxy], app_name='dwight', config_pathname=temp_config_dir, config_optional=True, )
def test_write_ini(self): n = self._some_namespaces() c = ConfigurationManager( [n], [{ "c.fred": "just like George Jetson", }], use_admin_controls=True, #use_config_files=False, use_auto_help=False, argv_source=[] ) expected = """# the a #aaa=2011-05-04T15:10:00 [c] # husband from Flintstones fred=just like George Jetson # wife from Flintstones #wilma=waspish's [d] # female neighbor from I Love Lucy #ethel=silly # male neighbor from I Love Lucy #fred=crabby [x] # the password #password=secret "message" # how big in tons #size=100 """ out = StringIO() c.write_conf(for_configobj, opener=stringIO_context_wrapper(out)) received = out.getvalue() out.close() self.assertEqual(expected.strip(), received.strip())
def test_write_ini(self): n = self._some_namespaces() c = ConfigurationManager( [n], [{ "c.fred": "just like George Jetson", }], use_admin_controls=True, #use_config_files=False, use_auto_help=False, argv_source=[]) expected = """# the a #aaa=2011-05-04T15:10:00 [c] # husband from Flintstones fred=just like George Jetson # wife from Flintstones #wilma=waspish's [d] # female neighbor from I Love Lucy #ethel=silly # male neighbor from I Love Lucy #fred=crabby [x] # the password #password=secret "message" # how big in tons #size=100 """ out = StringIO() c.write_conf(for_configobj, opener=stringIO_context_wrapper(out)) received = out.getvalue() out.close() self.assertEqual(expected.strip(), received.strip())
def parse_known_args(self, args=None, namespace=None): """this method hijacks the normal argparse Namespace generation, shimming configman into the process. The return value will be a configman DotDict rather than an argparse Namespace.""" # load the config_manager within the scope of the method that uses it # so that we avoid circular references in the outer scope from configman.config_manager import ConfigurationManager configuration_manager = ConfigurationManager( definition_source=[self.get_required_config()], values_source_list=self.value_source_list, argv_source=args, app_name=self.prog, app_version=self.version, app_description=self.description, use_auto_help=False, ) conf = configuration_manager.get_config( mapping_class=create_key_translating_dot_dict( "HyphenUnderscoreDict", (('-', '_'), ))) return conf
def parse_known_args(self, args=None, namespace=None): """this method hijacks the normal argparse Namespace generation, shimming configman into the process. The return value will be a configman DotDict rather than an argparse Namespace.""" # load the config_manager within the scope of the method that uses it # so that we avoid circular references in the outer scope from configman.config_manager import ConfigurationManager configuration_manager = ConfigurationManager( definition_source=[self.get_required_config()], values_source_list=self.value_source_list, argv_source=args, app_name=self.prog, app_version=self.version, app_description=self.description, use_auto_help=False, ) conf = configuration_manager.get_config( mapping_class=create_key_translating_dot_dict( "HyphenUnderscoreDict", (('-', '_'),) ) ) return conf
def test_configdir_and_default_config_exists_and_config_not_required(self): temp_config_dir = '/tmp' with open('/tmp/dwight.ini', 'w') as f: f.write('') try: ConfigurationManager( definition_source=self._some_namespaces(), values_source_list=[ConfigFileFutureProxy], app_name='dwight', config_pathname=temp_config_dir, config_optional=True, ) finally: os.unlink('/tmp/dwight.ini')
def test_json_round_trip(self): n = Namespace(doc='top') n.add_option('aaa', '2011-05-04T15:10:00', 'the a', short_form='a', from_string_converter=datetime_from_ISO_string) expected_date = datetime_from_ISO_string('2011-05-04T15:10:00') n.add_option('bbb', '37', 'the a', short_form='a', from_string_converter=int) n.add_option('write', 'json') n.add_aggregation('bbb_minus_one', bbb_minus_one) name = '/tmp/test.json' import functools opener = functools.partial(open, name, 'w') c1 = ConfigurationManager([n], [], use_admin_controls=True, use_auto_help=False, app_name='/tmp/test', app_version='0', app_description='', argv_source=[]) c1.write_conf('json', opener) d1 = {'bbb': 88} d2 = {'bbb': '-99'} try: with open(name) as jfp: j = json.load(jfp) c2 = ConfigurationManager((j, ), (d1, d2), use_admin_controls=True, use_auto_help=False, argv_source=[]) config = c2.get_config() self.assertEqual(config.aaa, expected_date) self.assertEqual(config.bbb, -99) self.assertEqual(config.bbb_minus_one, -100) finally: os.unlink(name)
def test_for_configobj_basics_2(self): tmp_filename = os.path.join(tempfile.gettempdir(), 'test.ini') open(tmp_filename, 'w').write(""" # comment name=Peter awesome= # comment [othersection] foo=bar # other comment """) try: o = for_configobj.ValueSource(tmp_filename) c = ConfigurationManager( [], use_admin_controls=True, #use_config_files=False, use_auto_help=False, argv_source=[]) self.assertEqual(o.get_values(c, False), { 'othersection': { 'foo': 'bar' }, 'name': 'Peter', 'awesome': '' }) self.assertEqual(o.get_values(c, True), { 'othersection': { 'foo': 'bar' }, 'name': 'Peter', 'awesome': '' }) finally: if os.path.isfile(tmp_filename): os.remove(tmp_filename)
def test_write_ini_with_reference_value_froms( self ): n = self._some_namespaces() n.namespace('x1') n.x1.add_option( 'password', default='secret "message"', doc='the password', likely_to_be_changed=True, reference_value_from='xxx.yyy' ) n.namespace('x2') n.x2.add_option( 'password', default='secret "message"', doc='the password', reference_value_from='xxx.yyy' ) external_values = { 'xxx': { 'yyy': { 'password': '******' } }, } c = ConfigurationManager( [n], values_source_list=[external_values], use_admin_controls=True, use_auto_help=False, argv_source=[] ) expected = ("""# the a #aaa=2011-05-04T15:10:00 [xxx] #+include ./common_xxx.ini [[yyy]] #+include ./common_yyy.ini # the password password=dwight and wilma [c] # husband from Flintstones #fred="stupid, deadly" # wife from Flintstones #wilma=waspish's [d] # female neighbor from I Love Lucy #ethel=silly # male neighbor from I Love Lucy #fred=crabby [x] # the password #password=secret "message" # how big in tons #size=100 [x1] # the password # see "xxx.yyy.password" for the default or override it here password=dwight and wilma [x2] # the password # see "xxx.yyy.password" for the default or override it here password=dwight and wilma """) out = StringIO() c.write_conf(for_configobj, opener=stringIO_context_wrapper(out)) received = out.getvalue() out.close() self.assertEqual(expected.strip(), received.strip())
def donttest_for_conf_nested_namespaces(self): n = self._some_namespaces() cm = ConfigurationManager( n, values_source_list=[], ) out = StringIO() cm.write_conf(for_conf, opener=stringIO_context_wrapper(out)) received = out.getvalue() out.close() expected = """# name: aaa # doc: the a aaa=2011-05-04T15:10:00 #------------------------------------------------------------------------------ # c - c space # name: c.dwight # doc: your uncle c.dwight=98 # name: c.fred # doc: husband from Flintstones c.fred=stupid # name: c.wilma # doc: wife from Flintstones c.wilma=waspish #------------------------------------------------------------------------------ # e - e space # name: c.e.dwight # doc: my uncle c.e.dwight=97 #------------------------------------------------------------------------------ # d - d space # name: d.ethel # doc: female neighbor from I Love Lucy d.ethel=silly # name: d.fred # doc: male neighbor from I Love Lucy d.fred=crabby #------------------------------------------------------------------------------ # x - x space # name: x.password # doc: the password x.password=secret # name: x.size # doc: how big in tons x.size=100""" self.assertEqual(received.strip(), expected) strio = StringIO(expected) n.c.dwight.default = 3823 n.c.e.dwight = 'fred' cm2 = ConfigurationManager( n, [stringIO_context_wrapper(strio)], use_admin_controls=False, use_auto_help=False ) result = cm2.get_config() self.assertEqual(len(result), 4) self.assertEqual(sorted(result.keys()), ['aaa', 'c', 'd', 'x']) self.assertEqual(len(result.c), 4) self.assertEqual( sorted(result.c.keys()), ['dwight', 'e', 'fred', 'wilma'] ) self.assertEqual(result.c.dwight, 98) self.assertEqual(len(result.c.e), 1) self.assertEqual(result.c.e.dwight, '97')
def donttest_for_conf_nested_namespaces(self): n = self._some_namespaces() cm = ConfigurationManager( n, values_source_list=[], ) out = StringIO() cm.write_conf(for_conf, opener=stringIO_context_wrapper(out)) received = out.getvalue() out.close() expected = """# name: aaa # doc: the a aaa=2011-05-04T15:10:00 #------------------------------------------------------------------------------ # c - c space # name: c.dwight # doc: your uncle c.dwight=98 # name: c.fred # doc: husband from Flintstones c.fred=stupid # name: c.wilma # doc: wife from Flintstones c.wilma=waspish #------------------------------------------------------------------------------ # e - e space # name: c.e.dwight # doc: my uncle c.e.dwight=97 #------------------------------------------------------------------------------ # d - d space # name: d.ethel # doc: female neighbor from I Love Lucy d.ethel=silly # name: d.fred # doc: male neighbor from I Love Lucy d.fred=crabby #------------------------------------------------------------------------------ # x - x space # name: x.password # doc: the password x.password=secret # name: x.size # doc: how big in tons x.size=100""" self.assertEqual(received.strip(), expected) strio = StringIO(expected) n.c.dwight.default = 3823 n.c.e.dwight = 'fred' cm2 = ConfigurationManager(n, [stringIO_context_wrapper(strio)], use_admin_controls=False, use_auto_help=False) result = cm2.get_config() self.assertEqual(len(result), 4) self.assertEqual(sorted(result.keys()), ['aaa', 'c', 'd', 'x']) self.assertEqual(len(result.c), 4) self.assertEqual(sorted(result.c.keys()), ['dwight', 'e', 'fred', 'wilma']) self.assertEqual(result.c.dwight, 98) self.assertEqual(len(result.c.e), 1) self.assertEqual(result.c.e.dwight, '97')
def test_write_ini_with_reference_value_froms(self): n = self._some_namespaces() n.namespace('x1') n.x1.add_option('password', default='secret "message"', doc='the password', likely_to_be_changed=True, reference_value_from='xxx.yyy') n.namespace('x2') n.x2.add_option('password', default='secret "message"', doc='the password', reference_value_from='xxx.yyy') external_values = { 'xxx': { 'yyy': { 'password': '******' } }, } c = ConfigurationManager([n], values_source_list=[external_values], use_admin_controls=True, use_auto_help=False, argv_source=[]) expected = ("""# the a #aaa=2011-05-04T15:10:00 [xxx] #+include ./common_xxx.ini [[yyy]] #+include ./common_yyy.ini # the password password=dwight and wilma [c] # husband from Flintstones #fred="stupid, deadly" # wife from Flintstones #wilma=waspish's [d] # female neighbor from I Love Lucy #ethel=silly # male neighbor from I Love Lucy #fred=crabby [x] # the password #password=secret "message" # how big in tons #size=100 [x1] # the password # see "xxx.yyy.password" for the default or override it here password=dwight and wilma [x2] # the password # see "xxx.yyy.password" for the default or override it here password=dwight and wilma """) out = StringIO() c.write_conf(for_configobj, opener=stringIO_context_wrapper(out)) received = out.getvalue() out.close() self.assertEqual(expected.strip(), received.strip())