def test_list_errors(self): raw_config = data.pets.build_config() raw_config["playgrounds"] = [{"name": "faulty grounds"}] config_suite = configsuite.ConfigSuite(raw_config, data.pets.build_schema()) self.assertFalse(config_suite.valid) self.assertEqual(1, len(config_suite.errors)) err = config_suite.errors[0] self.assertIsInstance(err, configsuite.MissingKeyError) self.assertEqual(("playgrounds", 0), err.key_path)
def test_favourite_numbers_accepted(self): raw_config = data.favourite_numbers.build_config() schema = data.favourite_numbers.build_schema() config_suite = configsuite.ConfigSuite(raw_config, schema) self.assertTrue(config_suite.valid) config = config_suite.snapshot self.assertEqual(raw_config["favourite_uint4"], config.favourite_uint4) self.assertEqual(raw_config["favourite_uint8"], config.favourite_uint8) self.assertEqual(raw_config["favourite_int"], config.favourite_int)
def test_invalid_dict_keys(self): invalid_keys = ["1monkey", "monkey-donkey", "a b c"] raw_config = data.candy_bag.build_story_config() schema = data.candy_bag.build_schema() for inv_key in invalid_keys: schema[MK.Content][MK.Item][MK.Content][inv_key] = { MK.Type: types.String } with self.assertRaises(KeyError): configsuite.ConfigSuite(raw_config, schema)
def test_context_validator_no_context_data_no_crash(self): raw_config = transactions.build_config() raw_config["exchange_rates"] = "Tulips is all you need!" config_suite = configsuite.ConfigSuite( raw_config, transactions.build_schema(), extract_validation_context=transactions.extract_validation_context, ) self.assertFalse(config_suite.valid) self.assertEqual(1, len(config_suite.errors)) self.assertIsInstance(config_suite.errors[0], configsuite.InvalidTypeError)
def test_allow_none_no_default_not_required(self): schema = { MK.Type: types.NamedDict, MK.Content: { "my_value": { MK.Type: types.Integer, MK.AllowNone: True, MK.Required: False, }, }, } for value in (-1, 4, 1000, None): suite = configsuite.ConfigSuite({"my_value": value}, schema) self.assertTrue(suite.valid) self.assertEqual(value, suite.snapshot.my_value) suite = configsuite.ConfigSuite({}, schema) self.assertTrue(suite.valid) self.assertEqual(None, suite.snapshot.my_value)
def _setup_configuration(self, config_data): """ Creates a ConfigSuite instance and inserts default values """ schema = job_config.build_schema() config_dict = find_and_expand_wildcards(self._obs_keys, config_data) default_layer = job_config.get_default_values() config = configsuite.ConfigSuite(config_dict, schema, layers=(default_layer, )) return config
def test_transformation_prior_to_validation(self): schema = favourite_numbers.build_schema() schema[MK.Transformation] = _sort_favourites raw_config = { "favourite_uint4": 1024, "favourite_uint8": 2**4, "favourite_int": 42, } suite = configsuite.ConfigSuite(raw_config, schema) self.assertFalse(suite.valid)
def test_invalid_dict(self): for pet in [14, None, [{"name": "Markus"}], ()]: raw_config = data.pets.build_config() raw_config["pet"] = pet config_suite = configsuite.ConfigSuite(raw_config, data.pets.build_schema()) self.assertFalse(config_suite.valid) self.assertEqual(1, len(config_suite.errors)) err = config_suite.errors[0] self.assertIsInstance(err, configsuite.InvalidTypeError) self.assertEqual(("pet",), err.key_path)
def test_basictype_implicit_none(self): schema = computers.build_schema() config = computers.build_config() schema[MK.Content]["OS"][MK.AllowNone] = True schema[MK.Content]["OS"][MK.Required] = False config.pop("OS") config_suite = configsuite.ConfigSuite(config, schema) self.assertTrue(config_suite.valid) self.assertIsNone(config_suite.snapshot.OS)
def test_missing_key(self): raw_config = data.candidate.build_config() raw_config.pop("name") config_suite = configsuite.ConfigSuite( raw_config, data.candidate.build_schema() ) self.assertFalse(config_suite.valid) self.assertEqual(1, len(config_suite.errors)) err = config_suite.errors[0] self.assertIsInstance(err, configsuite.MissingKeyError) self.assertEqual((), err.key_path)
def test_unknown_key(self): raw_config = data.candidate.build_config() raw_config["favourite_food"] = "bibimpap" config_suite = configsuite.ConfigSuite( raw_config, data.candidate.build_schema() ) self.assertFalse(config_suite.valid) self.assertEqual(1, len(config_suite.errors)) err = config_suite.errors[0] self.assertIsInstance(err, configsuite.UnknownKeyError) self.assertEqual((), err.key_path)
def test_name_pet_accepted(self): raw_config = data.pets.build_config() config_suite = configsuite.ConfigSuite(raw_config, data.pets.build_schema()) self.assertTrue(config_suite.valid) config = config_suite.snapshot self.assertEqual(raw_config["name"], config.name) self.assertEqual(raw_config["pet"]["name"], config.pet.name) self.assertEqual(raw_config["pet"]["favourite_food"], config.pet.favourite_food)
def test_context_validator_faulty_container(self): config = special_numbers.build_config() config["others"]["self"] = "I'm a snow flake" suite = configsuite.ConfigSuite( config, special_numbers.build_schema(), extract_validation_context=special_numbers.extract_context, ) self.assertFalse(suite.readable) self.assertFalse(suite.valid)
def _setup_configuration(self, config_data): """ Creates a ConfigSuite instance and inserts default values """ schema = job_config.build_schema() config_dict = find_and_expand_wildcards(self._obs_keys, config_data) config = configsuite.ConfigSuite( config_dict, schema, deduce_required=True, ) return config
def test_required_child(self): raw_config = data.candidate.build_config() raw_config["current_job"].pop("company_name") config_suite = configsuite.ConfigSuite( raw_config, data.candidate.build_schema() ) self.assertFalse(config_suite.valid) self.assertEqual(1, len(config_suite.errors)) err = config_suite.errors[0] self.assertIsInstance(err, configsuite.MissingKeyError) self.assertEqual(("current_job",), err.key_path)
def test_element_validator_double_fail(self): raw_config = data.candy_bag.build_config() raw_config[0]["name"] = "" raw_config[1]["name"] = "" config_suite = configsuite.ConfigSuite(raw_config, data.candy_bag.build_schema()) self.assertFalse(config_suite.valid) self.assertEqual(2, len(config_suite.errors)) for idx, err in enumerate(config_suite.errors): self.assertIsInstance(err, configsuite.InvalidValueError) self.assertEqual((idx, "name"), err.key_path)
def test_explicit_required_is_deprecated(self): schema = { MK.Type: types.NamedDict, MK.Content: {"some_key": {MK.Type: types.String, MK.Required: True}}, } with warnings.catch_warnings(record=True) as wc: configsuite.ConfigSuite({}, schema) self.assertEqual(1, len(wc)) self.assertEqual(__file__, wc[0].filename) self.assertIn( "Use `ConfigSuite(..., deduce_required=True)`", str(wc[0].message) )
def test_invalid_config_setup(test_input, expected_errors): schema = _CORRELATED_OBSERVATIONS_SCHEMA config = configsuite.ConfigSuite( test_input, schema, deduce_required=True, ) assert not config.valid msgs = [e.msg for e in config.errors] assert len(expected_errors) == len(msgs) assert all([any(exp in msg for msg in msgs) for exp in expected_errors])
def test_dict_cannot_spec_required(self): schema = { MK.Type: configsuite.types.Dict, MK.Content: { MK.Key: { MK.Type: configsuite.types.String }, MK.Value: { MK.Type: configsuite.types.String }, }, } config_suite = configsuite.ConfigSuite({}, schema) self.assertTrue(config_suite.valid) for req in (True, False): schema[MK.Required] = req with self.assertRaises(ValueError) as err: configsuite.ConfigSuite({}, schema) self.assertIn("Required can only be used for BasicType", str(err.exception))
def test_invalid_config_setup(test_input, expected_errors): schema = build_schema() config = configsuite.ConfigSuite( test_input, schema, deduce_required=True, ) assert not config.valid msgs = [e.msg for e in config.errors] assert len(expected_errors) == len(msgs) assert all([any(exp in msg for msg in msgs) for exp in expected_errors])
def test_transformation_non_readable_results(self): raw_config = templating.build_config_no_definitions() @configsuite.transformation_msg("Deforming elements") def _deformer(elem): return {"unexpected_nesting": elem} schema = templating.build_schema_no_definitions() schema[MK.Transformation] = _deformer suite = configsuite.ConfigSuite(raw_config, schema) self.assertFalse(suite.readable, suite.errors)
def test_invalid_layer_inside_list(self): schema = data.hero.build_schema() dummy_layer = {"heroes": [{"name": "Batman"}]} real_layer = { "heroes": [{ "name": "Batman", "strength": 10 }], "villains": { "The Joker": 9 }, } layered_config = configsuite.ConfigSuite(real_layer, schema, layers=(dummy_layer, )) self.assertTrue(layered_config.readable) self.assertFalse(layered_config.valid) self.assertTrue(len(layered_config.errors) > 0) combined = { "heroes": [{ "name": "Batman" }, { "name": "Batman", "strength": 10 }], "villains": { "The Joker": 9 }, } combined_config = configsuite.ConfigSuite(combined, schema) self.assertTrue(combined_config.readable) self.assertFalse(combined_config.valid) self.assertEqualSnapshots(combined_config.snapshot, layered_config.snapshot)
def test_element_validator_single_fail(self): raw_config = data.candy_bag.build_config() raw_config[0]["name"] = "" config_suite = configsuite.ConfigSuite(raw_config, data.candy_bag.build_schema()) self.assertFalse(config_suite.valid) self.assertEqual(1, len(config_suite.errors)) err = config_suite.errors[0] self.assertIsInstance(err, configsuite.InvalidValueError) self.assertEqual((0, "name"), err.key_path) self.assertEqual("Name should not be empty is false on input ''", err.msg)
def test_dict_disallow_empty(self): schema = { MK.Type: configsuite.types.Dict, MK.AllowEmpty: False, MK.Content: { MK.Key: { MK.Type: configsuite.types.String }, MK.Value: { MK.Type: configsuite.types.Integer }, }, } non_empty_suite = configsuite.ConfigSuite({"a": 1, "b": 2}, schema) self.assertTrue(non_empty_suite.valid) empty_suite = configsuite.ConfigSuite({}, schema) self.assertFalse(empty_suite.valid) self.assertEqual(1, len(empty_suite.errors)) self.assertIn("Expected non-empty container", empty_suite.errors[0].msg)
def test_readable_missing_container(self): schema = data.hero.build_schema() heroes = { "heroes": [ {"name": "Batman", "strength": 10}, {"name": "Flash", "strength": 12}, {"name": "Dirk Gently", "strength": 7}, ] } config = configsuite.ConfigSuite(heroes, schema) self.assertTrue(config.readable) self.assertFalse(config.valid)
def test_no_deprecation_warning_when_deducing(self): schema = { MK.Type: types.NamedDict, MK.Content: { "some_key": { MK.Type: types.String } }, } with warnings.catch_warnings(record=True) as wc: suite = configsuite.ConfigSuite({}, schema, deduce_required=True) self.assertFalse(suite.valid) self.assertEqual(0, len(wc))
def test_valid_examples(input_config): default_values = { "CALCULATE_KEYS": {"std_cutoff": 1.0e-6, "alpha": 3}, "UPDATE_KEYS": {}, } schema = job_config._CORRELATED_OBSERVATIONS_SCHEMA config = configsuite.ConfigSuite( input_config, schema, layers=(default_values,), deduce_required=True, ) assert config.valid
def test_context_transformation_applied(self): raw_config = car.build_all_default_config() car_schema = car.build_schema() tire_schema = car_schema[MK.Content]["tire"] tire_schema[MK.Content]["dimension"][ MK.ContextTransformation] = car.inch_to_cm_context_based config_suite = configsuite.ConfigSuite( raw_config, car_schema, extract_validation_context=lambda snapshot: None) self.assertTrue(config_suite.valid) self.assertAlmostEqual(17 * 2.54, config_suite.snapshot.tire.dimension)
def test_transformation_nameddict(self): schema = favourite_numbers.build_schema() schema[MK.Transformation] = _sort_favourites raw_config = { "favourite_uint4": 1024, "favourite_uint8": 7, "favourite_int": 42, } suite = configsuite.ConfigSuite(raw_config, schema) self.assertTrue(suite.valid, suite.errors) self.assertEqual(7, suite.snapshot.favourite_uint4) self.assertEqual(42, suite.snapshot.favourite_uint8) self.assertEqual(1024, suite.snapshot.favourite_int)
def test_context_validator_layers(self): bottom_layer = transactions.build_config() top_layer = { "exchange_rates": {"gold": 4.39695731e6}, "transactions": ({"source": "NOK", "target": "gold", "amount": 0.5},), } suite = configsuite.ConfigSuite( top_layer, transactions.build_schema(), layers=(bottom_layer,), extract_validation_context=transactions.extract_validation_context, ) self.assertTrue(suite.valid)