Source code for swh.model.fields.compound
# Copyright (C) 2015 The Software Heritage developers
# See the AUTHORS file at the top-level directory of this distribution
# License: GNU General Public License version 3, or any later version
# See top-level LICENSE file for more information
from collections import defaultdict
import itertools
from ..exceptions import NON_FIELD_ERRORS, ValidationError
[docs]
def validate_against_schema(model, schema, value):
"""Validate a value for the given model against the given schema.
Args:
model: the name of the model
schema: the schema to validate against
value: the value to validate
Returns:
True if the value is correct against the schema
Raises:
ValidationError if the value does not validate against the schema
"""
if not isinstance(value, dict):
raise ValidationError(
"Unexpected type %(type)s for %(model)s, expected dict",
params={
"model": model,
"type": value.__class__.__name__,
},
code="model-unexpected-type",
)
errors = defaultdict(list)
for key, (mandatory, validators) in itertools.chain(
((k, v) for k, v in schema.items() if k != NON_FIELD_ERRORS),
[(NON_FIELD_ERRORS, (False, schema.get(NON_FIELD_ERRORS, [])))],
):
if not validators:
continue
if not isinstance(validators, list):
validators = [validators]
validated_value = value
if key != NON_FIELD_ERRORS:
try:
validated_value = value[key]
except KeyError:
if mandatory:
errors[key].append(
ValidationError(
"Field %(field)s is mandatory",
params={"field": key},
code="model-field-mandatory",
)
)
continue
else:
if errors:
# Don't validate the whole object if some fields are broken
continue
for validator in validators:
try:
valid = validator(validated_value)
except ValidationError as e:
errors[key].append(e)
else:
if not valid:
errdata = {
"validator": validator.__name__,
}
if key == NON_FIELD_ERRORS:
errmsg = (
"Validation of model %(model)s failed in " "%(validator)s"
)
errdata["model"] = model
errcode = "model-validation-failed"
else:
errmsg = (
"Validation of field %(field)s failed in " "%(validator)s"
)
errdata["field"] = key
errcode = "field-validation-failed"
errors[key].append(
ValidationError(errmsg, params=errdata, code=errcode)
)
if errors:
raise ValidationError(dict(errors))
return True
[docs]
def validate_all_keys(value, keys):
"""Validate that all the given keys are present in value"""
missing_keys = set(keys) - set(value)
if missing_keys:
missing_fields = ", ".join(sorted(missing_keys))
raise ValidationError(
"Missing mandatory fields %(missing_fields)s",
params={"missing_fields": missing_fields},
code="missing-mandatory-field",
)
return True
[docs]
def validate_any_key(value, keys):
"""Validate that any of the given keys is present in value"""
present_keys = set(keys) & set(value)
if not present_keys:
missing_fields = ", ".join(sorted(keys))
raise ValidationError(
"Must contain one of the alternative fields %(missing_fields)s",
params={"missing_fields": missing_fields},
code="missing-alternative-field",
)
return True