def test_conf_defval(self): defs = (('mutable:dict', {'doc': 'some dictionary', 'defval': {}}), ) with s_config.Config(defs=defs) as conf: md = conf.getConfOpt('mutable:dict') md['key'] = 1 md = conf.getConfOpt('mutable:dict') self.eq(md.get('key'), 1) # Ensure the mutable:dict defval content is not changed with s_config.Config(defs=defs) as conf2: md = conf2.getConfOpt('mutable:dict') self.eq(md, {})
async def test_config_base(self): confdefs = (('foo', 20, int), ) conf = s_config.Config(confdefs) with self.raises(s_exc.NoSuchName): await conf.set('hehe', 'haha') await conf.loadConfDict({'foo': 30}) self.eq(conf.get('foo'), 30) with self.getTestDir() as dirn: path = os.path.join(dirn, 'foo.yaml') with s_common.genfile(path) as fd: fd.write(b'foo: 8080') await conf.loadConfYaml(path) self.eq(conf.get('foo'), 8080) with self.setTstEnvars(SYN_CONF_TEST_FOO='31337'): await conf.loadConfEnvs('SYN_CONF_TEST') self.eq(conf.get('foo'), 31337) info = dict(iter(conf)) self.eq(31337, info.get('foo'))
def test_lib_config_req(self): defs = (('foo', {'type': 'int', 'req': True}), ) with s_config.Config(defs=defs) as conf: self.raises(ReqConfOpt, conf.reqConfOpts) conf.setConfOpt('foo', 20) conf.reqConfOpts()
def test_conf_base(self): defs = ( ('fooval', { 'type': 'int', 'doc': 'what is foo val?', 'defval': 99 }), ('enabled', { 'type': 'bool', 'doc': 'is thing enabled?', 'defval': 0 }), ) data = {} def callback(v): data['woot'] = v with s_config.Config(defs=defs) as conf: conf.onConfOptSet('enabled', callback) conf.setConfOpt('enabled', 'true') self.eq(data.get('woot'), 1) conf.setConfOpts({'fooval': '0x20'}) self.eq(conf.getConfOpt('fooval'), 0x20) conf.setConfOpts({'fooval': 0x30}) self.eq(conf.getConfOpt('fooval'), 0x30) self.assertRaises(NoSuchOpt, conf.setConfOpts, {'newp': 'hehe'})
def initCellConf(cls): ''' Create a Config object for the Cell. Notes: The Config object has a ``envar_prefix`` set according to the results of ``cls.getEnvPrefix()``. Returns: s_config.Config: A Config helper object. ''' prefix = cls.getEnvPrefix() schema = s_config.getJsSchema(cls.confbase, cls.confdefs) return s_config.Config(schema, envar_prefix=prefix)
def test_conf_base(self): defs = ( ('fooval', { 'type': 'int', 'doc': 'what is foo val?', 'defval': 99 }), ('enabled', { 'type': 'bool', 'doc': 'is thing enabled?', 'defval': 0 }), ) data = {} def callback(v): data['woot'] = v with s_config.Config(defs=defs) as conf: self.eq(conf.getConfOpt('enabled'), 0) self.eq(conf.getConfOpt('fooval'), 99) conf.onConfOptSet('enabled', callback) conf.setConfOpt('enabled', 'true') self.eq(data.get('woot'), 1) conf.setConfOpts({'fooval': '0x20'}) self.eq(conf.getConfOpt('fooval'), 0x20) conf.setConfOpts({'fooval': 0x30}) self.eq(conf.getConfOpt('fooval'), 0x30) self.raises(NoSuchOpt, conf.setConfOpts, {'newp': 'hehe'}) instance_defs = conf.getConfDefs() self.eq(len(instance_defs), 2) self.isin('enabled', instance_defs) self.isin('fooval', instance_defs) edict = instance_defs.get('enabled') self.eq(edict.get('type'), 'bool') self.eq(edict.get('defval'), 0) self.eq(edict.get('doc'), 'is thing enabled?') opts = conf.getConfOpts() self.eq(opts, {'enabled': 1, 'fooval': 0x30})
def test_hideconf(self): hide_schema = { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": False, "properties": { 'key:string': { 'description': 'Key String. I have a defval!', 'type': 'string', 'default': 'Default string!' }, 'key:integer': { 'description': 'Key Integer', 'type': 'integer', 'hideconf': True, }, } } conf = s_config.Config(hide_schema) pars = argparse.ArgumentParser('synapse.tests.test_lib_config.test_hideconf') for optname, optinfo in conf.getArgParseArgs(): pars.add_argument(optname, **optinfo) hmsg = pars.format_help() self.isin('--key-string', hmsg) self.notin('--key-integer', hmsg) s1 = yaml.safe_dump('We all float down here') i1 = yaml.safe_dump(8675309) # Load data from envars next - this shows precedence as well # where data already set won't be set again via this method. with self.setTstEnvars(KEY_STRING=s1, KEY_INTEGER=i1, ): conf.setConfFromEnvs() self.eq(conf.get('key:string'), 'We all float down here') self.none(conf.get('key:integer'))
async def test_config_basics(self): conf = s_config.Config(s_test.test_schema) # Start out empty self.eq(conf.asDict(), {}) # We can make an argparser that has config options populated in it # We explicitly skip boolean options without a default value so we # done end up in a ambiguous toggle case down the road. mesg = 'Boolean type is missing default information. ' \ 'Will not form argparse for [key:bool:nodefval]' pars = argparse.ArgumentParser('synapse.tests.test_lib_config.basics') pars.add_argument('--beep', type=str, help='beep option', default='beep.sys') with self.getLoggerStream('synapse.lib.config', mesg) as stream: for optname, optinfo in conf.getArgParseArgs(): pars.add_argument(optname, **optinfo) self.true(stream.wait(3)) hmsg = pars.format_help() # Undo pretty-printing hmsg = regex.sub(r'\s\s+', ' ', hmsg) # Multiple types are supported for argparse and descriptions # are used to generate the argparse help self.isin('--key-string KEY_STRING', hmsg) self.isin('Key String. I have a defval!', hmsg) self.isin('--key-integer KEY_INTEGER', hmsg) self.isin('--key-number KEY_NUMBER', hmsg) self.isin('--key-bool-defvalfalse', hmsg) self.isin('--key-bool-defvaltrue', hmsg) # The pre-existing parse is modified self.isin('--beep', hmsg) # We do not populate options for complex types self.notin('Key Array', hmsg) self.notin('Key Object', hmsg) # We do not populate options for bools with missing defaults self.notin('Key Bool, no default', hmsg) # And we can get the data too! Unspecified values are set to # s_common.novalu so we know that they were NOT set at all. # This differs from the default argparse case of defaults being # set to None, and allows us to defer the injection of default # values to the jsonschema validation phase. args = ['--key-number', '1234.5678', '--key-bool-defvaltrue', 'false'] opts = pars.parse_args(args) vopts = vars(opts) edata = { 'key_bool_defvalfalse': None, 'key_bool_defvaltrue': False, 'key_integer': None, 'key_number': 1234.5678, 'key_string': None, 'beep': 'beep.sys' } self.eq(edata, vopts) # We can re-inject the opts back into the config object. # The s_common.novalu data is skipped, as are opts which # were not set by the schema data. conf.setConfFromOpts(opts) self.eq(conf.asDict(), { 'key:bool:defvaltrue': False, 'key:number': 1234.5678, }) # We can also get and load confdef data from environment # variables. These must be safe to decode as yaml. This # is mainly to faciliate machine base management of envars. a1 = yaml.safe_dump(['firetruck', 'spaceship']) i1 = yaml.safe_dump(8675309) n1 = yaml.safe_dump(9.813) # Load data from envars next - this shows precedence as well # where data already set won't be set again via this method. with self.setTstEnvars(KEY_ARRAY=a1, KEY_NUMBER=n1, KEY_INTEGER=i1, ): conf.setConfFromEnvs() self.eq(conf.asDict(), { 'key:bool:defvaltrue': False, 'key:number': 1234.5678, 'key:integer': 8675309, 'key:array': ['firetruck', 'spaceship'] }) # we can set some remaining values directly conf.setdefault('key:object', {'rubber': 'ducky'}) conf.setdefault('key:string', 'Funky string time!') self.eq(conf.asDict(), { 'key:bool:defvaltrue': False, 'key:number': 1234.5678, 'key:integer': 8675309, 'key:array': ['firetruck', 'spaceship'], 'key:object': {'rubber': 'ducky'}, 'key:string': 'Funky string time!', }) # Once we've built up our config, we can then ensure that it is valid. # This validation step also sets vars with defaults. Keys without defaults # are not set at all. self.none(conf.reqConfValid()) self.eq(conf.asDict(), { 'key:bool:defvalfalse': False, 'key:bool:defvaltrue': False, 'key:number': 1234.5678, 'key:integer': 8675309, 'key:array': ['firetruck', 'spaceship'], 'key:object': {'rubber': 'ducky'}, 'key:string': 'Funky string time!', }) # We can ensure that certain vars are loaded self.eq('Funky string time!', conf.reqConfValu('key:string')) # And throw if they are not, or if the requested key isn't even schema valid self.raises(s_exc.NeedConfValu, conf.reqConfValu, 'key:bool:nodefval') self.raises(s_exc.BadArg, conf.reqConfValu, 'key:newp') # Since we're an Mutable mapping, we have some dict methods available to us self.len(7, conf) # __len__ self.eq(set(conf.keys()), # __iter__ {'key:bool:defvalfalse', 'key:bool:defvaltrue', 'key:number', 'key:integer', 'key:string', 'key:array', 'key:object', }) del conf['key:object'] # __delitem__ self.eq(conf.asDict(), { 'key:bool:defvalfalse': False, 'key:bool:defvaltrue': False, 'key:number': 1234.5678, 'key:integer': 8675309, 'key:array': ['firetruck', 'spaceship'], 'key:string': 'Funky string time!', }) # We have a convenience __repr__ :) valu = repr(conf) self.isin('<synapse.lib.config.Config at 0x', valu) self.isin('conf={', valu) # We can set invalid items and ensure the config is no longer valid. conf['key:array'] = 'Totally not an array.' self.raises(s_exc.BadConfValu, conf.reqConfValid) del conf['key:array'] # We can do prefix-bassed collection of envar data. conf2 = s_config.Config(s_test.test_schema, envar_prefix='beeper') with self.setTstEnvars(BEEPER_KEY_ARRAY=a1, KEY_INTEGER=i1, ): conf2.setConfFromEnvs() # key:array is set, key:integer is not set. self.eq(conf2.asDict(), { 'key:array': ['firetruck', 'spaceship'] })
def test_conf_asloc(self): with s_config.Config() as conf: conf.addConfDef('foo', type='int', defval=0, asloc='_foo_valu') self.eq(conf._foo_valu, 0) conf.setConfOpt('foo', '0x20') self.eq(conf._foo_valu, 0x20)
def reqValidTdef(conf): s_config.Config(TrigSchema, conf=conf).reqConfValid()