Exemplo n.º 1
1
            def method(data: Any) -> Any:
                if not isinstance(data, dict):
                    raise bad_type(data, dict)
                values: Dict[str, Any] = {}
                aliases: List[str] = []
                errors = list(
                    constraint_errors(data)) if constraint_errors else []
                field_errors: Dict[ErrorKey, ValidationError] = OrderedDict()
                for (
                        name,
                        alias,
                        field_method,
                        required,
                        fall_back_on_default,
                ) in normal_fields:
                    if alias in data:
                        aliases.append(alias)
                        try:
                            values[name] = field_method(data[alias])
                        except ValidationError as err:
                            if not fall_back_on_default:
                                field_errors[alias] = err
                    elif not required:
                        pass
                    elif required is True:
                        field_errors[alias] = MISSING_PROPERTY
                    else:
                        assert isinstance(required, AbstractSet)
                        requiring = required & data.keys()
                        if requiring:
                            msg = f"missing property (required by {sorted(requiring)})"
                            field_errors[alias] = ValidationError([msg])
                if has_aggregate_field:
                    for (
                            name,
                            flattened_alias,
                            field_method,
                            fall_back_on_default,
                    ) in flattened_fields:

                        flattened = {
                            alias: data[alias]
                            for alias in flattened_alias if alias in data
                        }
                        aliases.extend(flattened)
                        try:
                            values[name] = field_method(flattened)
                        except ValidationError as err:
                            if not fall_back_on_default:
                                errors.extend(err.messages)
                                field_errors.update(err.children)
                    if len(data) != len(aliases):
                        remain = data.keys() - set(aliases)
                    else:
                        remain = set()
                    for (
                            name,
                            pattern,
                            field_method,
                            fall_back_on_default,
                    ) in pattern_fields:
                        matched = {
                            key: data[key]
                            for key in remain if pattern.match(key)
                        }
                        remain -= matched.keys()
                        try:
                            values[name] = field_method(matched)
                        except ValidationError as err:
                            if not fall_back_on_default:
                                errors.extend(err.messages)
                                field_errors.update(err.children)
                    if additional_field is not None:
                        name, field_method, fall_back_on_default = additional_field
                        additional = {key: data[key] for key in remain}
                        try:
                            values[name] = field_method(additional)
                        except ValidationError as err:
                            if not fall_back_on_default:
                                errors.extend(err.messages)
                                field_errors.update(err.children)
                    elif remain and not additional_properties:
                        for key in remain:
                            field_errors[key] = UNEXPECTED_PROPERTY
                elif len(data) != len(aliases) and not additional_properties:
                    for key in data.keys() - set(aliases):
                        field_errors[key] = UNEXPECTED_PROPERTY

                validators2: Sequence[Validator]
                if validators:
                    init: Dict[str, Any] = {}
                    for name, default_factory in init_defaults:
                        if name in values:
                            init[name] = values[name]
                        elif name not in field_errors:
                            assert default_factory is not None
                            init[name] = default_factory()
                    # Don't keep validators when all dependencies are default
                    validators2 = [
                        v for v in validators
                        if v.dependencies & values.keys()
                    ]
                    if field_errors or errors:
                        error = ValidationError(errors, field_errors)
                        invalid_fields = field_errors.keys(
                        ) | post_init_modified
                        validators2 = [
                            v for v in validators2
                            if not v.dependencies & invalid_fields
                        ]
                        try:
                            validate(
                                ValidatorMock(cls, values),
                                validators2,
                                init,
                                aliaser=aliaser,
                            )
                        except ValidationError as err:
                            error = merge_errors(error, err)
                        raise error
                elif field_errors or errors:
                    raise ValidationError(errors, field_errors)
                else:
                    validators2, init = (
                    ), ...  # type: ignore # only for linter
                try:
                    res = cls(**values)
                except (AssertionError, ValidationError):
                    raise
                except TypeError as err:
                    if str(err).startswith("__init__() got"):
                        raise Unsupported(cls)
                    else:
                        raise ValidationError([str(err)])
                except Exception as err:
                    raise ValidationError([str(err)])
                if validators2:
                    validate(res, validators2, init, aliaser=aliaser)
                return res
Exemplo n.º 2
0
def validate(
    obj: T,
    validators: Iterable[Validator] = None,
    kwargs: Mapping[str, Any] = None,
    *,
    aliaser: Aliaser = lambda s: s,
) -> T:
    if validators is None:
        validators = get_validators(type(obj))
    error: Optional[ValidationError] = None
    validators = iter(validators)
    for validator in validators:
        try:
            if not kwargs:
                validator.validate(obj)
            elif validator.params == kwargs.keys():
                validator.validate(obj, **kwargs)
            else:
                if any(k not in kwargs for k in validator.params):
                    raise RuntimeError(
                        f"Missing parameters {kwargs.keys() - validator.params}"
                        f" for validator {validator.func}")
                validator.validate(obj,
                                   **{k: kwargs[k]
                                      for k in validator.params})
        except ValidationError as e:
            err = apply_aliaser(e, aliaser)
        except NonTrivialDependency as exc:
            exc.validator = validator
            raise
        except AssertionError:
            raise
        except Exception as e:
            err = ValidationError([str(e)])
        else:
            continue
        if validator.field is not None:
            alias = getattr(get_alias(validator.owner),
                            get_field_name(validator.field))
            err = ValidationError(children={aliaser(alias): err})
        error = merge_errors(error, err)
        if validator.discard:
            try:
                discarded = set(map(get_field_name, validator.discard))
                next_validators = (v for v in validators
                                   if not discarded & v.dependencies)
                validate(obj, next_validators, kwargs, aliaser=aliaser)
            except ValidationError as err:
                error = merge_errors(error, err)
    if error is not None:
        raise error
    return obj
Exemplo n.º 3
0
 def method(data: Any) -> Any:
     # Optional optimization
     if data is none_check:
         return None
     error: Optional[ValidationError] = None
     for deserialize_alt in alt_deserializers:
         try:
             return deserialize_alt(data)
         except ValidationError as err:
             error = merge_errors(error, err)
     if none_check is None:
         error = merge_errors(error, bad_type(data, NoneType))
     if error is None:  # empty union
         return data
     else:
         raise error
Exemplo n.º 4
0
def validate(__obj: T, __validators: Iterable[Validator] = None, **kwargs) -> T:
    if __validators is None:
        __validators = get_validators(__obj)
    if not __validators:
        return __obj
    error: Optional[ValidationError] = None
    __validators = iter(__validators)
    while True:
        for validator in __validators:
            try:
                if kwargs and validator.params != kwargs.keys():
                    assert all(k in kwargs for k in validator.params)
                    validator.validate(
                        __obj, **{k: kwargs[k] for k in validator.params}
                    )
                else:
                    validator.validate(__obj, **kwargs)
            except ValidationError as err:
                error = merge_errors(error, err)
            except Discard as err:
                error = merge_errors(error, err.error)
                discarded = {f.name for f in err.fields}
                __validators = iter(
                    v for v in __validators if not discarded & v.dependencies
                )
                break
            except NonTrivialDependency as exc:
                exc.validator = validator
                raise
            except AssertionError:
                raise
            except Exception as err:
                error = merge_errors(error, ValidationError([str(err)]))
        else:
            break
    if error is not None:
        raise error
    return __obj
Exemplo n.º 5
0
 def method(data: Any) -> Any:
     error: Optional[ValidationError] = None
     for deserialize_conv, converter in conv_deserializers:
         try:
             value = deserialize_conv(data)
             break
         except ValidationError as err:
             error = merge_errors(error, err)
     else:
         assert error is not None
         raise error
     try:
         return converter(value)  # type: ignore
     except (ValidationError, AssertionError):
         raise
     except Exception as err:
         raise ValidationError([str(err)])