def test_loop_in_config(self): experiment1 = { 'item1': { 'item': '$item2' }, 'item2': { 'item': '$item3' }, 'item3': { 'item': '$item1', }, } experiment2 = { 'item': { 'key': [ { 'key': '$item' } ] } } self.assertRaises(LoopInConfigError, lambda: ExperimentConfig(experiment1)) self.assertRaises(LoopInConfigError, lambda: ExperimentConfig(experiment2))
def test_unsubstituted_param(self): experiment = { "bar": 'foo', "item": { "_name": "DemoWithStr", "strval": "$bar" } } e = ExperimentConfig(experiment) self.assertEqual(e['item'].strval, 'foo') ######### experiment = { "item": { "_name": "DemoWithStr", "strval": "$bar" } } with self.assertRaises(UnknownReferenceError) as cm: ExperimentConfig(experiment) self.assertEqual("item.strval", cm.exception.obj_name) self.assertEqual('$bar', cm.exception.reference_name) ######### experiment = { 'demo': { '_name': 'DemoWithDict', 'simple_int': 22, 'children': { 'child0': "$demo3" } } } with self.assertRaises(UnknownReferenceError) as cm: ExperimentConfig(experiment) self.assertEqual('demo.children.child0', cm.exception.obj_name) self.assertEqual('$demo3', cm.exception.reference_name) ######### experiment = { 'demo': { '_name': 'DemoWithList', 'simple_int': 22, 'children': ["$demo3"] } } with self.assertRaises(UnknownReferenceError) as cm: ExperimentConfig(experiment) self.assertEqual('demo.children.0', cm.exception.obj_name) self.assertEqual('$demo3', cm.exception.reference_name)
def test_bad_plugin(self): experiment = { "item": { "_name": "NoConfig", } } with self.assertRaises(UnknownPluginException) as cm: ExperimentConfig(experiment) self.assertEqual('NoConfig', cm.exception.registrable) self.assertEqual('item', cm.exception.obj_name) ######### experiment = { "item": { "_name": "DemoWithDict", 'children': { 'child': { "_name": "NoConfig" } } } } with self.assertRaises(UnknownPluginException) as cm: ExperimentConfig(experiment) self.assertEqual('NoConfig', cm.exception.registrable) self.assertEqual('item.children.child', cm.exception.obj_name) ######### experiment = { "item": { "_name": "DemoWithList", 'children': [ { "_name": "NoConfig" } ] } } with self.assertRaises(UnknownPluginException) as cm: ExperimentConfig(experiment) self.assertEqual('NoConfig', cm.exception.registrable) self.assertEqual('item.children.0', cm.exception.obj_name)
def test_unsubstituted_param(self): experiment = { "bar": 'foo', "item": { "_name": "DemoWithStr", "strval": "$bar" } } e = ExperimentConfig(experiment) self.assertEqual(e['item'].strval, 'foo') experiment = {"item": {"_name": "DemoWithStr", "strval": "$bar"}} try: ExperimentConfig(experiment) self.fail() except UnconfiguredItemsException as e: self.assertEqual(len(e.items), 1) self.assertEqual({'strval'}, e.items['item']) experiment = { 'demo': { '_name': 'DemoWithDict', 'simple_int': 22, 'children': { 'child0': "$demo3" } } } try: ExperimentConfig(experiment) self.fail() except UnconfiguredItemsException as e: self.assertEqual(len(e.items), 1) self.assertEqual({'$demo3'}, e.items['demo.children.child0']) experiment = { 'demo': { '_name': 'DemoWithList', 'simple_int': 22, 'children': ["$demo3"] } } try: ExperimentConfig(experiment) self.fail() except UnconfiguredItemsException as e: self.assertEqual(len(e.items), 1) self.assertEqual({'$demo3'}, e.items['demo.children.0'])
def test_env(self): experiment = { 'path': "$HOME/foo/bar", 'path2': "$HOMEPATH/foo/bar", 'data': { '_name': "DemoWithStr", 'strval': "$HOME/foo/bar/bis" }, 'data2': { '_name': "DemoDefaults", 'strval': "foo", 'intval1': "$SVAL" } } e = ExperimentConfig(experiment, HOME='/tmp', HOMEPATH=Path('/tmp2'), SVAL=7) self.assertEqual(e['path'], '/tmp/foo/bar') self.assertEqual(e['path2'], '/tmp2/foo/bar') self.assertEqual(e['data'].strval, '/tmp/foo/bar/bis') self.assertEqual(e['data2'].strval, 'foo') self.assertEqual(e['data2'].intval1, 7) self.assertIsNone(e['data2'].intval2) experiment = { 'path': "$HOME/foo/bar", 'path2': "$HOMEPATH/foo/bar", 'data': { '_name': "DemoWithStr", 'strval': "$HOME/foo/bar/bis" }, 'data2': { '_name': "DemoDefaultsList", 'strval': "foo", 'intval1': "$SVAL", 'param_list': [ { "_name": "DemoIsAvailable", "is_available": "$HOME"}, { "_name": "DemoIsAvailable", "is_available": "$VAL"}, "$HOMEPATH" ] } } e = ExperimentConfig(experiment, HOME='/tmp', HOMEPATH=Path('/tmp2'), SVAL=7, VAL=True) self.assertEqual(e['data2'].param_list[0].is_available, '/tmp') self.assertEqual(e['data2'].param_list[1].is_available, True) self.assertEqual(e['data2'].param_list[2], Path('/tmp2'))
def test_list_of_registrables(self): experiment = { "first_object": { "_name": "DemoWithVal", "val": 2 }, "list_of_objects": [ { "_name": "DemoWithVal", "val": 1 }, { "_name": "DemoWithStr", "strval": "foo" }, 4, "$first_object", "feedly", "$mock_function", "$mock_function2" ] } e = ExperimentConfig(experiment) self.assertEqual(len(e['list_of_objects']), 7) self.assertEqual(e['list_of_objects'][0].val, 1) self.assertEqual(e['list_of_objects'][1].strval, "foo") self.assertEqual(e['list_of_objects'][2], 4) self.assertIsInstance(e['list_of_objects'][3], DemoWithVal) self.assertEqual(e['list_of_objects'][3].val, 2) self.assertEqual(e['list_of_objects'][4], 'feedly') self.assertEqual(e['list_of_objects'][5](), 5) self.assertEqual(e['list_of_objects'][6](), 2)
def test_dict_of_registrables(self): experiment = { "first_object": { "_name": "DemoWithVal", "val": 2 }, "dict_of_objects": { "first_object": { "_name": "DemoWithVal", "val": 1 }, "second_object": { "_name": "DemoWithStr", "strval": "foo" }, "simple_object": 1, "last_object": "$first_object" } } e = ExperimentConfig(experiment) self.assertEqual(e['dict_of_objects']['first_object'].val, 1) self.assertEqual(e['dict_of_objects']['second_object'].strval, 'foo') self.assertEqual(e['dict_of_objects']['simple_object'], 1) self.assertEqual(e['dict_of_objects']['last_object'].val, 2)
def test_config(self): e = copy.deepcopy(EXPERIMENT) e = ExperimentConfig(e) trainer = e.experiment['trainer'] self.assertIsInstance(trainer.model, TestModel) self.assertIsInstance(trainer.dataset_splits, TestDataset) self.assertIsInstance(trainer.loss, torch.nn.modules.loss.CrossEntropyLoss) self.assertIsInstance(trainer.optimizer, torch.optim.Adam) self.assertEqual(len(trainer.metrics), 2) self.assertEqual(trainer.device, torch.device(type='cpu')) self.assertEqual(trainer.seed, 1337) self.assertEqual(trainer.loss_accumulation_steps, 4) self.assertIsInstance(trainer.scheduler, torch.optim.lr_scheduler.ReduceLROnPlateau) self.assertEqual(trainer.num_epochs, 5) self.assertIsInstance(trainer.regularizer, L1) self.assertEqual(trainer.gradient_clipping, 0.25) self.assertEqual(trainer.embeddings_name, None) self.assertEqual(trainer.forward_params, ['x_in', 'apply_softmax']) # trainer.train() # Test factories optimizer = trainer.experiment_config.factories['optimizer'].create() self.assertIsInstance(optimizer, torch.optim.Adam) trainer = trainer.experiment_config.factories['trainer'].create() self.assertIsInstance(trainer, SingleTaskTrainer)
def test_complex_defaults(self): ### test that demod gets created first and then is used to create demo instead of the None default experiment = { 'demo': { '_name': 'DemoComplexDefaults', 'strval': 'foo' }, 'obj': { '_name': 'DemoDefaults', 'strval': 'bar', 'intval1': 20 } } e = ExperimentConfig(experiment) self.assertTrue(isinstance(e['demo'], DemoComplexDefaults)) self.assertTrue(isinstance(e['obj'], DemoDefaults)) self.assertEqual(e['obj'].strval, 'bar') self.assertEqual(e['obj'].intval1, 20) self.assertEqual(e['obj'].intval2, None) self.assertEqual(e['demo'].simple, 'foo') self.assertEqual(e['demo'].complex.strval, 'bar') self.assertEqual(e['demo'].complex.intval1, 20) self.assertEqual(e['demo'].complex.intval2, None)
def test_recursive_dict(self): experiment = { 'demo': { '_name': 'DemoWithDict', 'simple_int': 22, 'children': { 'child0': { '_name': 'DemoWithStr', 'strval': 'foo' }, 'child1': "$demo3" } }, 'demo3': { '_name': 'DemoWithInt', 'intval': 2 } } e = ExperimentConfig(experiment) demo: DemoWithDict = e.experiment['demo'] self.assertEqual(22, demo.simple_int) self.assertIsInstance(demo.children['child0'], DemoWithStr) self.assertEqual(demo.children['child0'].strval, 'foo') self.assertIsInstance(demo.children['child1'], DemoWithInt) self.assertEqual(demo.children['child1'].intval, 2)
def test_recursive_list(self): experiment = { 'demo': { '_name': 'DemoWithList', 'simple_int': 22, 'children': [ { '_name': 'DemoWithStr', 'strval': 'foo' }, '$demo3'] }, 'demo3': { '_name': 'DemoWithInt', 'intval': 2 } } e = ExperimentConfig(experiment) demo: DemoWithList = e.experiment['demo'] self.assertEqual(22, demo.simple_int) self.assertIsInstance(demo.children[0], DemoWithStr) self.assertEqual(demo.children[0].strval, 'foo') self.assertIsInstance(demo.children[1], DemoWithInt) self.assertEqual(demo.children[1].intval, 2)
def test_with_config(self): experiment = { 'demo2': { '_name': 'DemoWithInt' }, 'with_config': { '_name': 'DemoWithConfig', 'intval': 10 }, 'intval': 5 } e = ExperimentConfig(experiment) d = e['with_config'] self.assertEqual(10, d.intval) self.assertEqual(5, d.demo2.intval) self.assertTrue(d.experiment_config is e) self.assertEqual({'demo2', 'with_config', 'intval'}, e.factories.keys()) self.assertEqual(5, e.factories['intval'].create()) d = e.factories['with_config'].create() self.assertEqual(10, d.intval) self.assertEqual(5, d.demo2.intval) self.assertTrue(d.experiment_config is e)
def test_env(self): experiment = { 'path': "$HOME/foo/bar", 'path2': "$HOMEPATH/foo/bar", 'data': { '_name': "DemoWithStr", 'strval': "$HOME/foo/bar/bis" }, 'data2': { '_name': "DemoDefaults", 'strval': "foo", 'intval1': "$SVAL" } } e = ExperimentConfig(experiment, HOME='/tmp', HOMEPATH=Path('/tmp2'), SVAL=7) self.assertEqual(e['path'], '/tmp/foo/bar') self.assertEqual(e['path2'], '/tmp2/foo/bar') self.assertEqual(e['data'].strval, '/tmp/foo/bar/bis') self.assertEqual(e['data2'].strval, 'foo') self.assertEqual(e['data2'].intval1, 7) self.assertIsNone(e['data2'].intval2)
def test_child_named_injection(self): experiment = { 'demo': { '_name': 'Demo', 'demo3': '$demo3a' }, 'demo2': { '_name': 'DemoWithStr' }, 'demo3': { '_name': 'DemoWithInt' }, 'demo3a': { '_name': 'DemoWithInt', 'intval': '$simple_inta' }, 'strval': 'dummy', 'intval': 5, 'simple_inta': 6, } e = ExperimentConfig(experiment) self.assertTrue(isinstance(e['demo'], Demo)) self.assertTrue(isinstance(e['demo2'], DemoWithStr)) self.assertTrue(isinstance(e['demo3'], DemoWithInt)) self.assertTrue(isinstance(e['demo3a'], DemoWithInt)) self.assertEqual(e['demo2'].strval, 'dummy') self.assertEqual(e['demo3'].intval, 5) self.assertEqual(e['demo3a'].intval, 6) self.assertEqual(e['demo'].demo3.intval, 6)
def test_class_method(self): experiment = { "my_object": { "_name": "from_example_alias_name" } } e = ExperimentConfig(experiment) self.assertEqual(e['my_object'].param, 1)
def test_run_all(self): pkg_dir = Path(__file__).parent ExperimentRunner.run_all(experiment=pkg_dir / 'test_experiment.json', experiment_config=pkg_dir / 'test_experiment.cfg', report_dir=self.test_dir + '/reports', trainer_config_name='the_trainer', reporter_config_name='the_reporter', ENV_PARAM='my_env_param') self.assertEqual(2, ExperimentRunnerTest._reporter_calls) self.assertEqual(2, ExperimentRunnerTest._trainer_calls) self.assertEqual(2, len(ExperimentRunnerTest._configs)) for name, bparam, iparam, fparam, sparam in [ ('config1', True, 1, 1.5, 'hello'), ('config2', False, 2, 2.5, 'world') ]: # assert params where substituted into the experiment properly cfg = ExperimentRunnerTest._configs[name]['the_trainer'] self.assertEqual(bparam, cfg.bool_param) self.assertEqual(iparam, cfg.int_param) self.assertEqual(fparam, cfg.float_param) self.assertEqual(sparam, cfg.str_param) self.assertEqual('my_env_param', cfg.env_param) # assert params were recorded in the reports directory cp = configparser.ConfigParser() cp.read(f'{self.test_dir}/reports/{name}/experiment.cfg') self.assertEqual(1, len(cp.sections())) self.assertEqual(bparam, cp.getboolean(name, 'bparam')) self.assertEqual(iparam, cp.getint(name, 'iparam')) self.assertEqual(fparam, cp.getfloat(name, 'fparam')) self.assertEqual(sparam, cp.get(name, 'sparam')) self.assertEqual('my_env_param', cp.get(name, 'ENV_PARAM')) self.assertEqual( ExperimentConfig.load_experiment_json(pkg_dir / 'test_experiment.json'), ExperimentConfig.load_experiment_json( f'{self.test_dir}/reports/{name}/experiment.json'))
def test_nested_lists_dicts(self): experiment = { 'pipeline': { '_name': 'Pipeline', 'steps': [ [['first', '$first'], '$first'], ['second', '$second'], ] }, 'first': { '_name': 'DemoWithInt', "intval": 2 }, 'second': { '_name': 'DemoWithInt', "intval": 1 }, 'pipeline_list_of_dict_objects': { "_name": "Pipeline", "steps": [{ '_name': 'DemoWithInt', "intval": 10 }, { '_name': 'DemoWithInt', "intval": 20 }, { "k1": "v1", "k2": { "_name": "DemoWithInt", "intval": 0 }, "k3": ['second', '$second']}, { "k1": 1, "k2": 2}, [1, 2, 3] ] } } e = ExperimentConfig(experiment) self.assertEqual(e['pipeline'].steps[0][0][0], 'first') self.assertIsInstance(e['pipeline'].steps[0][0][1], DemoWithInt) self.assertIsInstance(e['pipeline'].steps[0][1], DemoWithInt) self.assertIsInstance(e['pipeline'].steps[1][1], DemoWithInt) self.assertEqual(e['pipeline'].steps[1][0], 'second') self.assertIsInstance(e['pipeline_list_of_dict_objects'].steps[0], DemoWithInt) self.assertIsInstance(e['pipeline_list_of_dict_objects'].steps[1], DemoWithInt) self.assertIsInstance(e['pipeline_list_of_dict_objects'].steps[2]['k2'], DemoWithInt) self.assertEqual(e['pipeline_list_of_dict_objects'].steps[3], { "k1": 1, "k2": 2})
def test_bad_plugin(self): experiment = { "item": { "_name": "NoConfig", } } try: ExperimentConfig(experiment) self.fail() except UnknownPluginException as e: self.assertEqual(e.clazz, 'NoConfig') experiment = { "item": { "_name": "DemoWithDict", 'children': { 'child': { "_name": "NoConfig" } } } } try: ExperimentConfig(experiment) self.fail() except UnknownPluginException as e: self.assertEqual(e.clazz, 'NoConfig') experiment = { "item": { "_name": "DemoWithList", 'children': [{ "_name": "NoConfig" }] } } try: ExperimentConfig(experiment) self.fail() except UnknownPluginException as e: self.assertEqual(e.clazz, 'NoConfig')
def run_all(experiment: Union[str, Path, Dict], experiment_config: Union[str, Path], report_dir: Union[str, Path], trainer_config_name: str = 'trainer', reporter_config_name: str = 'reporter', **env_vars) -> None: """ :param experiment: the experiment config :param experiment_config: the experiment config file. The cfg file should be defined in `ConfigParser <https://docs.python.org/3/library/configparser.html#module-configparser>`_ format such that each section is an experiment configuration. :param report_dir: the directory in which to produce the reports. It's recommended to include a timestamp your report directory so you can preserve previous reports across code changes. E.g. $HOME/reports/run_2019_02_22. :param trainer_config_name: the name of the trainer configuration object. The referenced object should implement `TrainerABC`. :param reporter_config_name: the name of the reporter configuration object. The referenced object should implement `ReporterABC`. :param env_vars: any additional environment variables, like file system paths :return: None """ envs: Dict[str, ConfigEnv] = load_config(Path(experiment_config)) report_path = Path(report_dir) report_path.mkdir(parents=True) for exp_name, env in envs.items(): exp_report_path = report_path / exp_name exp_report_path.mkdir() log_handler = ExperimentRunner._capture_logs(exp_report_path) try: logging.info('running %s', exp_name) all_vars = dict(env_vars) all_vars.update(env) experiment_config = ExperimentConfig(experiment, **all_vars) trainer: TrainerABC = experiment_config[trainer_config_name] reporter: ReporterABC = experiment_config[reporter_config_name] trainer.train() exp_json = ExperimentConfig.load_experiment_json(experiment) ExperimentRunner._write_config(exp_name, exp_json, all_vars, exp_report_path) reporter.report(exp_name, experiment_config, exp_report_path) finally: ExperimentRunner._stop_log_capture(log_handler)
def test_uninstantiated_registrable(self): experiment = { "my_registrable": { "_name": "ClassWithUnInstantiatedObject", "my_function": "$mock_function" } } e = ExperimentConfig(experiment) self.assertEqual(e['my_registrable'].my_function, mock_function) self.assertEqual(e['my_registrable'].my_function(), 5)
def test_forward(self): e = copy.deepcopy(EXPERIMENT) e = ExperimentConfig(e) trainer = e.experiment['trainer'] trainer.setup(training_metrics=trainer.training_metrics) batch = next(iter(trainer.dataset_splits.train_data_loader())) self.assertEqual(list(batch.keys()), ['x_in', 'y_target']) output = trainer._forward(batch=batch) self.assertEqual(output.size()[0], min(len(trainer.dataset_splits.train_set), 128)) self.assertEqual(output.size()[1], trainer.model.output_dim)
def test_setup(self): e = copy.deepcopy(EXPERIMENT) e = ExperimentConfig(e) trainer = e.experiment['trainer'] trainer.setup(training_metrics=trainer.training_metrics) self.assertEqual(len(trainer.trainer._event_handlers[ignite.engine.Events.EPOCH_COMPLETED]), 6) self.assertEqual(len(trainer.trainer._event_handlers[ignite.engine.Events.ITERATION_COMPLETED]), 16) self.assertEqual(len(trainer.trainer._event_handlers[ignite.engine.Events.COMPLETED]), 2) self.assertEqual(len(trainer.trainer._event_handlers[ignite.engine.Events.STARTED]), 0) self.assertEqual(len(trainer.trainer._event_handlers[ignite.engine.Events.EPOCH_STARTED]), 8) self.assertEqual(len(trainer.trainer._event_handlers[ignite.engine.Events.ITERATION_STARTED]), 0)
def test_recursive_dict(self): experiment = { 'demo': { '_name': 'DemoWithDict', 'simple_int': 22, 'children': { 'child0': { '_name': 'DemoWithStr', 'strval': 'foo' }, 'child1': "$demo3" } }, 'demo3': { '_name': 'DemoWithInt', 'intval': 2 } } e = ExperimentConfig(experiment) demo: DemoWithDict = e.experiment['demo'] self.assertEqual(22, demo.simple_int) self.assertIsInstance(demo.children['child0'], DemoWithStr) self.assertEqual(demo.children['child0'].strval, 'foo') self.assertIsInstance(demo.children['child1'], DemoWithInt) self.assertEqual(demo.children['child1'].intval, 2) self.assertEqual( e.factories.keys(), { 'demo', 'demo3', 'demo.children', 'demo.children.child0', 'demo.children.child1' }) copy = e.factories['demo.children'].create() self.assertIsInstance(copy['child0'], DemoWithStr) self.assertEqual(copy['child0'].strval, 'foo') self.assertIsInstance(copy['child1'], DemoWithInt) self.assertEqual(copy['child1'].intval, 2) copy = e.factories['demo.children.child0'].create() self.assertIsInstance(copy, DemoWithStr) self.assertEqual(copy.strval, 'foo') copy = e.factories['demo.children.child1'].create() self.assertIsInstance(copy, DemoWithInt) self.assertEqual(copy.intval, 2)
def test_defaults(self): experiment = { 'demoa': { '_name': 'DemoDefaults', 'strval': 'a', }, 'demob': { '_name': 'DemoDefaults', 'strval': 'b', 'intval1': 1 }, 'democ': { '_name': 'DemoDefaults', 'strval': 'c', 'intval2': 2 }, 'demod': { '_name': 'DemoDefaults', 'strval': 'd', 'intval1': 3, 'intval2': 4 }, 'demoe': { '_name': 'DemoDefaults', 'strval': 'e', 'intval1': None, 'intval2': None }, } e = ExperimentConfig(experiment) for c in 'abcde': self.assertTrue(isinstance(e[f'demo{c}'], DemoDefaults)) self.assertEqual(e[f'demo{c}'].strval, c) self.assertEqual(e['demoa'].intval1, 5) self.assertEqual(e['demoa'].intval2, None) self.assertEqual(e['demob'].intval1, 1) self.assertEqual(e['demob'].intval2, None) self.assertEqual(e['democ'].intval1, 5) self.assertEqual(e['democ'].intval2, 2) self.assertEqual(e['demod'].intval1, 3) self.assertEqual(e['demod'].intval2, 4) self.assertEqual(e['demoe'].intval1, None) self.assertEqual(e['demoe'].intval2, None)
def test_additional_params(self): experiment = { "bar": 5, "item": { "_name": "DemoWithInt", "intval": "$bar", "bad_param": 2 } } try: ExperimentConfig(experiment) self.fail() except BadParameter as b: self.assertEqual(b.param, 'bad_param') self.assertEqual(b.clazz, 'DemoWithInt')
def test_method_config(self): experiment = { 'demo': { '_name': 'DemoWithStr', 'strval': "foo", }, "object_from_method": { "_name": "demo_method_with_str", "str_val": 5 } } # Test that the initialization is correct e = ExperimentConfig(experiment) self.assertIsInstance(e['object_from_method'], DemoWithStr) self.assertEqual(e['object_from_method'].strval, 5)
def test_additional_params(self): experiment = { "bar": 5, "item": { "_name": "DemoWithInt", "intval": "$bar", "bad_param": 2 } } with self.assertRaises(CallableInstantiationError) as cm: ExperimentConfig(experiment) self.assertEqual('item', cm.exception.obj_name) self.assertEqual('DemoWithInt', cm.exception.callable_name) self.assertListEqual(['intval', 'bad_param'], cm.exception.arg_names)
def test_all_string_with_dollars(self): experiment = { "first_object": { "_name": "DemoWithVal", "val": 2 }, "list_of_objects": [ "$mock_function", "$mock_function2", "$first_object" ] } e = ExperimentConfig(experiment) self.assertEqual(len(e['list_of_objects']), 3) self.assertEqual(e['list_of_objects'][0](), 5) self.assertEqual(e['list_of_objects'][1](), 2) self.assertEqual(e['list_of_objects'][2].val, 2)
def test_literal_injection(self): experiment = { 'demo2': { '_name': 'DemoWithStr', 'strval': 'dummy' }, 'demo3': { '_name': 'DemoWithInt', 'intval': 5 } } e = ExperimentConfig(experiment) self.assertTrue(isinstance(e['demo2'], DemoWithStr)) self.assertTrue(isinstance(e['demo3'], DemoWithInt)) self.assertEqual(e['demo2'].strval, 'dummy') self.assertEqual(e['demo3'].intval, 5)
def test_nesting_two_levels(self): experiment = { 'democ': { '_name': 'DemoC', 'demob': { '_name': 'DemoB', 'attrb': 10, 'demoa': { '_name': 'DemoA' } } }, 'simple_int': 2 } e = ExperimentConfig(experiment) self.assertEqual(e['democ'].demob.attrb, 10) self.assertEqual(e['democ'].attrc, 3) self.assertEqual(e['democ'].demob.demoa.simple_int, 2)