checks: Fix anyOf validator yield ValidationError on ConfigOptionWarning

We have some hooks yield ConfigOptionWarning. When it happens within
anyOf validator, anyOf validator yield ValidationError and reports the
config as incorrect. We need to overwrite it to pass not break.

Fixes: #598
Merges: #599
Signed-off-by: Qixiang Wan <qwan@redhat.com>
This commit is contained in:
Qixiang Wan 2017-04-14 13:12:35 +08:00 committed by Lubomír Sedlář
parent 180a5b94a9
commit 63327e7d88
2 changed files with 74 additions and 2 deletions

View File

@ -349,12 +349,35 @@ def _extend_with_default_and_alias(validator_class):
for error in validate_type(validator, properties, instance, schema): for error in validate_type(validator, properties, instance, schema):
yield error yield error
def _validate_any_of(validator, anyOf, instance, schema):
"""
Overwrite jsonschema's anyOf validator to not yield ValidationError when
ConfigOptionWarning is found.
"""
all_errors = []
for index, subschema in enumerate(anyOf):
errs = list(validator.descend(instance, subschema, schema_path=index))
warnings = [err for err in errs if isinstance(err, ConfigOptionWarning)]
errors = [err for err in errs if err not in warnings]
if not errors:
for warning in warnings:
yield warning
break
all_errors.extend(errors)
else:
yield jsonschema.ValidationError(
"%r is not valid under any of the given schemas" % (instance,),
context=all_errors,
)
return jsonschema.validators.extend( return jsonschema.validators.extend(
validator_class, {"properties": _set_defaults, validator_class, {"properties": _set_defaults,
"deprecated": error_on_deprecated, "deprecated": error_on_deprecated,
"type": validate_regex_type, "type": validate_regex_type,
"required": _validate_required, "required": _validate_required,
"additionalProperties": _validate_additional_properties}, "additionalProperties": _validate_additional_properties,
"anyOf": _validate_any_of},
) )

View File

@ -16,7 +16,6 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from pungi import checks from pungi import checks
class CheckDependenciesTestCase(unittest.TestCase): class CheckDependenciesTestCase(unittest.TestCase):
def dont_find(self, paths): def dont_find(self, paths):
@ -481,6 +480,56 @@ class TestSchemaValidator(unittest.TestCase):
self.assertEqual(config.get("release_name", None), "dummy product") self.assertEqual(config.get("release_name", None), "dummy product")
self.assertEqual(config.get("repo", None), ["http://url/to/repo", "Server", "Client"]) self.assertEqual(config.get("repo", None), ["http://url/to/repo", "Server", "Client"])
@mock.patch('pungi.checks._make_schema')
def test_anyof_validator_not_raise_our_warnings_as_error(self, make_schema):
# https://pagure.io/pungi/issue/598
schema = {
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Pungi Configuration",
"type": "object",
"definitions": {
"live_image_config": {
"type": "object",
"properties": {
"repo": {
"type": "string",
"append": "repo_from",
},
},
},
},
"properties": {
"live_images": checks._variant_arch_mapping({
"anyOf": [
{"$ref": "#/definitions/live_image_config"},
{
"type": "array",
"items": {
"$ref": "#/definitions/live_image_config"
}
}
]
}),
},
}
make_schema.return_value = schema
string = """
live_images = [
('^Spins$', {
'armhfp': {
'repo_from': 'Everything',
}}),
]
"""
config = self._load_conf_from_string(string)
errors, warnings = checks.validate(config)
self.assertEqual(len(errors), 0)
self.assertEqual(len(warnings), 2)
self.assertRegexpMatches(warnings[0], r"^WARNING: Config option 'repo_from' is deprecated, its value will be appended to option 'repo'.*")
self.assertRegexpMatches(warnings[1], r"^WARNING: Config option 'repo' is not found, but 'repo_from' is specified, value from 'repo_from' is now added as 'repo'.*")
self.assertEqual(config.get("live_images")[0][1]['armhfp']['repo'], 'Everything')
class TestUmask(unittest.TestCase): class TestUmask(unittest.TestCase):
def setUp(self): def setUp(self):