Exemple #1
0
 def test_adding_multiple_errors(self):
     builder = ValidationErrorBuilder()
     builder.add_error('foo', 'error 1')
     builder.add_error('bar', 'error 2')
     builder.add_error('bam', 'error 3')
     assert {'foo': 'error 1', 'bar': 'error 2', 'bam': 'error 3'} == \
         builder.errors
Exemple #2
0
    def test_raise_errors_on_non_empty_builder_raises_ValidationError(self):
        builder = ValidationErrorBuilder()
        builder.add_error('foo', 'error 1')
        with pytest.raises(ValidationError) as excinfo:
            builder.raise_errors()

        assert excinfo.value.messages == builder.errors
Exemple #3
0
    def __call__(self, value, context=None):
        if not is_sequence(value):
            self._fail('invalid', data=value)

        error_builder = ValidationErrorBuilder()

        for idx, item in enumerate(value):
            for validator in self.validators:
                try:
                    validator(item)
                except ValidationError as ve:
                    error_builder.add_errors({idx: ve.messages})

        error_builder.raise_errors()
Exemple #4
0
    def load(self, data, *args, **kwargs):
        if data is MISSING or data is None:
            self._fail('required')

        if not is_dict(data):
            self._fail('invalid')

        errors_builder = ValidationErrorBuilder()
        result = {}

        for name, field in iteritems(self.fields):
            try:
                loaded = field.load(name, data, *args, **kwargs)
                if loaded != MISSING:
                    result[name] = loaded
            except ValidationError as ve:
                errors_builder.add_error(name, ve.messages)

        if self.allow_extra_fields is False:
            field_names = [name for name, _ in iteritems(self.fields)]
            for name in data:
                if name not in field_names:
                    errors_builder.add_error(name, self._error_messages['unknown'])

        errors_builder.raise_errors()

        result = super(Object, self).load(result, *args, **kwargs)
        if self.constructor:
            result = self.constructor(**result)
        return result
Exemple #5
0
 def test_adding_multiple_nested_errors(self):
     builder = ValidationErrorBuilder()
     builder.add_error('foo.bar', 'error 1')
     builder.add_error('foo.baz.bam', 'error 2')
     builder.add_error('quux', 'error 3')
     assert {'foo': {'bar': 'error 1', 'baz': {'bam': 'error 2'}},
             'quux': 'error 3'} == builder.errors
Exemple #6
0
    def test_raise_errors_on_non_empty_builder_raises_ValidationError(self):
        builder = ValidationErrorBuilder()
        builder.add_error('foo', 'error 1')
        with pytest.raises(ValidationError) as excinfo:
            builder.raise_errors()

        assert excinfo.value.messages == builder.errors
Exemple #7
0
 def test_adding_multiple_nested_errors(self):
     builder = ValidationErrorBuilder()
     builder.add_error('foo.bar', 'error 1')
     builder.add_error('foo.baz.bam', 'error 2')
     builder.add_error('quux', 'error 3')
     assert {
         'foo': {
             'bar': 'error 1',
             'baz': {
                 'bam': 'error 2'
             }
         },
         'quux': 'error 3'
     } == builder.errors
Exemple #8
0
 def test_adding_multiple_errors(self):
     builder = ValidationErrorBuilder()
     builder.add_error('foo', 'error 1')
     builder.add_error('bar', 'error 2')
     builder.add_error('bam', 'error 3')
     assert {'foo': 'error 1', 'bar': 'error 2', 'bam': 'error 3'} == \
         builder.errors
Exemple #9
0
    def __call__(self, value, context=None):
        if not is_sequence(value):
            self._fail('invalid', data=value)

        error_builder = ValidationErrorBuilder()

        for idx, item in enumerate(value):
            for validator in self.validators:
                try:
                    validator(item)
                except ValidationError as ve:
                    error_builder.add_errors({idx: ve.messages})

        error_builder.raise_errors()
Exemple #10
0
    def dump(self, obj, *args, **kwargs):
        if obj is MISSING or obj is None:
            self._fail('required')

        errors_builder = ValidationErrorBuilder()
        result = OrderedDict() if self.ordered else {}

        for name, field in iteritems(self.fields):
            try:
                dumped = field.dump(name, obj, *args, **kwargs)
                if dumped != MISSING:
                    result[name] = dumped
            except ValidationError as ve:
                errors_builder.add_error(name, ve.messages)
        errors_builder.raise_errors()

        return super(Object, self).dump(result, *args, **kwargs)
Exemple #11
0
    def load(self, data, context=None):
        """Deserialize data from primitive types. Raises
        :exc:`~lollipop.errors.ValidationError` if data is invalid.

        :param data: Data to deserialize.
        :param context: Context data.
        :returns: Loaded data
        :raises: :exc:`~lollipop.errors.ValidationError`
        """
        errors_builder = ValidationErrorBuilder()
        for validator in self._validators:
            try:
                validator(data, context)
            except ValidationError as ve:
                errors_builder.add_errors(ve.messages)
        errors_builder.raise_errors()
        return data
Exemple #12
0
    def dump(self, value, *args, **kwargs):
        if value is MISSING or value is None:
            self._fail('required')

        if not is_list(value):
            self._fail('invalid')

        errors_builder = ValidationErrorBuilder()
        items = []
        for idx, item in enumerate(value):
            try:
                items.append(self.item_type.dump(item, *args, **kwargs))
            except ValidationError as ve:
                errors_builder.add_errors({idx: ve.messages})
        errors_builder.raise_errors()

        return super(List, self).dump(items, *args, **kwargs)
Exemple #13
0
    def load(self, data, *args, **kwargs):
        if data is MISSING or data is None:
            self._fail('required')

        # TODO: Make more intelligent check for collections
        if not is_list(data):
            self._fail('invalid')

        errors_builder = ValidationErrorBuilder()
        items = []
        for idx, item in enumerate(data):
            try:
                items.append(self.item_type.load(item, *args, **kwargs))
            except ValidationError as ve:
                errors_builder.add_errors({idx: ve.messages})
        errors_builder.raise_errors()

        return super(List, self).load(items, *args, **kwargs)
Exemple #14
0
    def dump(self, value, *args, **kwargs):
        if value is MISSING or value is None:
            self._fail('required')

        if not is_dict(value):
            self._fail('invalid')

        errors_builder = ValidationErrorBuilder()
        result = {}
        for k, v in iteritems(value):
            value_type = self.value_types.get(k)
            if value_type is None:
                continue
            try:
                result[k] = value_type.dump(v, *args, **kwargs)
            except ValidationError as ve:
                errors_builder.add_error(k, ve.messages)
        errors_builder.raise_errors()

        return super(Dict, self).dump(result, *args, **kwargs)
Exemple #15
0
    def dump(self, value, *args, **kwargs):
        if value is MISSING or value is None:
            self._fail('required')

        if not is_list(value):
            self._fail('invalid')

        if len(value) != len(self.item_types):
            self._fail('invalid_length', expected_length=len(self.item_types))

        errors_builder = ValidationErrorBuilder()
        result = []
        for idx, (item_type, item) in enumerate(zip(self.item_types, value)):
            try:
                result.append(item_type.dump(item, *args, **kwargs))
            except ValidationError as ve:
                errors_builder.add_errors({idx: ve.messages})
        errors_builder.raise_errors()

        return super(Tuple, self).dump(result, *args, **kwargs)
Exemple #16
0
 def test_empty_errors(self):
     builder = ValidationErrorBuilder()
     assert None == builder.errors
Exemple #17
0
 def test_raise_errors_on_empty_builder_does_nothing(self):
     builder = ValidationErrorBuilder()
     builder.raise_errors()
Exemple #18
0
 def test_adding_merging_errors(self):
     builder = ValidationErrorBuilder()
     builder.add_errors({'foo': {'bar': 'error 1'}})
     builder.add_errors({'foo': {'baz': 'error 2'}})
     assert {'foo': {'bar': 'error 1', 'baz': 'error 2'}} == builder.errors
Exemple #19
0
 def test_adding_nested_errors(self):
     builder = ValidationErrorBuilder()
     builder.add_error('foo.bar', 'error 1')
     assert {'foo': {'bar': 'error 1'}} == builder.errors
Exemple #20
0
 def test_adding_nested_errors(self):
     builder = ValidationErrorBuilder()
     builder.add_error('foo.bar', 'error 1')
     assert {'foo': {'bar': 'error 1'}} == builder.errors
Exemple #21
0
 def test_adding_merging_errors(self):
     builder = ValidationErrorBuilder()
     builder.add_errors({'foo': {'bar': 'error 1'}})
     builder.add_errors({'foo': {'baz': 'error 2'}})
     assert {'foo': {'bar': 'error 1', 'baz': 'error 2'}} == builder.errors
Exemple #22
0
 def test_adding_field_error(self):
     builder = ValidationErrorBuilder()
     builder.add_error('foo', 'error 1')
     assert {'foo': 'error 1'} == builder.errors
Exemple #23
0
 def test_raise_errors_on_empty_builder_does_nothing(self):
     builder = ValidationErrorBuilder()
     builder.raise_errors()
Exemple #24
0
    def load_into(self, obj, data, inplace=True, *args, **kwargs):
        """Load data and update existing object.

        :param obj: Object to update with deserialized data.
        :param data: Raw data to get value to deserialize from.
        :param bool inplace: If True update data inplace;
            otherwise - create new data.
        :param kwargs: Same keyword arguments as for :meth:`Type.load`.
        :returns: Updated object.
        :raises: :exc:`~lollipop.errors.ValidationError`
        """
        if obj is None:
            raise ValueError('Load target should not be None')

        if data is MISSING:
            return

        if data is None:
            self._fail('required')

        if not is_dict(data):
            self._fail('invalid')

        errors_builder = ValidationErrorBuilder()

        data1 = {}
        for name, field in iteritems(self.fields):
            try:
                if name in data:
                    # Load new data
                    value = field.load_into(obj, name, data,
                                            inplace=not self.immutable and inplace)
                else:
                    # Retrive data from existing object
                    value = field.get_value(name, obj, *args, **kwargs)

                if value is not MISSING:
                    data1[name] = value
            except ValidationError as ve:
                errors_builder.add_error(name, ve.messages)

        if self.allow_extra_fields is False:
            field_names = [name for name, _ in iteritems(self.fields)]
            for name in data:
                if name not in field_names:
                    errors_builder.add_error(name, self._error_messages['unknown'])

        errors_builder.raise_errors()

        data2 = super(Object, self).load(data1, *args, **kwargs)

        if self.immutable or not inplace:
            result = data2
            if self.constructor:
                result = self.constructor(**result)
        else:
            for name, field in iteritems(self.fields):
                if name not in data:
                    continue

                try:
                    field.set_value(name, obj, data2.get(name, MISSING))
                except ValidationError as ve:
                    raise ValidationError({name: ve.messages})

            result = obj

        return result
Exemple #25
0
 def test_adding_field_error(self):
     builder = ValidationErrorBuilder()
     builder.add_error('foo', 'error 1')
     assert {'foo': 'error 1'} == builder.errors