Exemple #1
0
        class C(Catalyst):
            max_value = IntegerField()
            min_value = IntegerField()

            def pre_dump(self, obj):
                return self.pre_load(obj)

            def post_dump(self, data, original_data):
                assert original_data is not None
                return self.post_load(data)

            def pre_load(self, data):
                keys = {field.key for field in self._load_fields.values()}
                extra_keys = set(data.keys()) - keys
                if extra_keys:
                    raise ValidationError(
                        f'This keys should not be present: {extra_keys}.')
                return data

            def post_load(self, data):
                if data['max_value'] < data['min_value']:
                    raise ValidationError(
                        '"max_value" must be larger than "min_value".')
                return data

            def pre_load_many(self, data):
                assert len(data) < 3
                return data
Exemple #2
0
    def test_field_group(self):
        group = FieldGroup(declared_fields=['num'])

        self.assertFalse(hasattr(group, 'fields'))

        fields = {'num': IntegerField(), 'xxx': IntegerField()}
        group.set_fields(fields)
        self.assertEqual(set(group.fields), {'num'})

        with self.assertRaises(ValueError):
            group.set_fields({})

        with self.assertRaises(TypeError):
            group.set_fields({'num': None})

        self.assertIsNone(group.load(None))
        self.assertIsNone(group.dump(None))

        # test "*" all fields, exclude FieldGroup
        group = FieldGroup(declared_fields='*')
        fields['group'] = group
        group.set_fields(fields)
        self.assertSetEqual(set(group.fields), {'xxx', 'num'})

        # test override method
        @group.set_dump
        @group.set_load
        def test_override(data):
            data['xxx'] = 1
            return data

        self.assertEqual(test_override, group.dump)
        self.assertEqual(test_override, group.load)
        self.assertEqual(group.dump({})['xxx'], 1)
        self.assertEqual(group.load({})['xxx'], 1)

        @group.set_dump
        def self_and_group(self, data, group):
            assert self is group
            assert isinstance(self, FieldGroup)
            data['xxx'] = 1
            return data

        self.assertEqual(group.dump, self_and_group)
        self.assertEqual(group.dump({})['xxx'], 1)
        class C(Catalyst):
            a = IntegerField()
            b = IntegerField()
            no_extra = FieldGroup(declared_fields=('a', 'b'))

            @staticmethod
            @no_extra.set_dump
            def inject_kwargs(data, **kwargs):
                assert set(kwargs) == {'group', 'original_method'}
                return data

            @staticmethod
            @no_extra.set_load
            def check_no_extra(data, original_data, group: FieldGroup = None):
                extra_fields = set(original_data) - set(group.declared_fields)
                if extra_fields:
                    raise ValidationError(f"Invalid fields: '{extra_fields}'.")
                return data
Exemple #4
0
class TestDataCatalyst(Catalyst):
    string = StringField(min_length=2,
                         max_length=12,
                         dump_default='default',
                         load_default='default')
    integer = IntegerField(minimum=0, maximum=12, load_required=True)
    float_field = FloatField(name='float_',
                             key='float',
                             minimum=-1.1,
                             maximum=1.1)
    bool_field = BooleanField(name='bool_', key='bool')
    func = CallableField(name='func', key='func', func_args=(1, 2, 3))
    list_ = ListField(StringField())
Exemple #5
0
    def test_except_exception(self):
        catalyst = Catalyst(schema={'a': IntegerField(minimum=0)},
                            except_exception=(ValueError, ValidationError))

        result = catalyst.load({'a': 'x'})
        self.assertFalse(result.is_valid)
        self.assertIsInstance(result.errors['a'], ValueError)

        result = catalyst.load({'a': -1})
        self.assertFalse(result.is_valid)
        self.assertIsInstance(result.errors['a'], ValidationError)

        with self.assertRaises(TypeError):
            catalyst.load(1)

        with self.assertRaises(TypeError):
            catalyst.load({'a': []})
Exemple #6
0
    def test_nest_field(self):
        with self.assertRaises(TypeError):
            NestedField()

        with self.assertRaises(TypeError):
            field = NestedField(Catalyst)

        fields = {'name': StringField(max_length=3)}
        field = NestedField(Catalyst(fields), name='a', key='a')

        self.assertEqual(field.dump({'name': '1'}), {'name': '1'})
        self.assertEqual(field.dump({'name': '1234'}), {'name': '1234'})
        with self.assertRaises(ValidationError):
            field.dump({'n': 'm'})
        with self.assertRaises(ValidationError):
            field.dump(1)

        self.assertEqual(field.load({'name': '1'}), {'name': '1'})
        self.assertDictEqual(field.load({'n': 'm'}), {})
        with self.assertRaises(ValidationError):
            field.load({'name': '1234'})
        with self.assertRaises(ValidationError):
            field.load(1)

        # list with dict items
        field = NestedField(Catalyst({'x': IntegerField()}), many=True)

        data = [{'x': 1}, {'x': 2}]
        self.assertListEqual(data, field.load(data))

        data = [{'x': 1}, {'x': 'x'}]
        with self.assertRaises(ValidationError) as cm:
            field.load(data)
        result = cm.exception.detail
        self.assertIsInstance(result.errors[1]['x'], ValueError)

        data = [{'x': 1}, None]
        with self.assertRaises(ValidationError) as cm:
            field.load(data)
        result = cm.exception.detail
        self.assertIsInstance(result.errors[1]['load'], TypeError)
Exemple #7
0
    def test_separated_field(self):
        field = SeparatedField(separator=None)
        self.assertEqual(field.load('1 2 3'), ['1', '2', '3'])
        self.assertEqual(field.load('1'), ['1'])
        self.assertEqual(field.load(''), [])
        self.assertEqual(field.load({}), ['{}'])
        self.assertEqual(field.dump([1, '2', 3]), '1 2 3')
        self.assertEqual(field.dump([]), '')
        self.assertEqual(field.dump(None), None)
        with self.assertRaises(ValidationError):
            field.load(None)

        field = SeparatedField(IntegerField())
        self.assertEqual(field.load('1,2,3'), [1, 2, 3])
        self.assertEqual(field.dump([1, '2', 3]), '1,2,3')
        with self.assertRaises(ValidationError):
            field.load('1,a,3')
        with self.assertRaises(ValidationError):
            field.dump([1, 'a', 3])
        with self.assertRaises(ValidationError) as cm:
            field.load({})
        result = cm.exception.detail
        self.assertEqual(result.invalid_data[0], '{}')
Exemple #8
0
 class SumCatalyst(Catalyst):
     a = IntegerField()
     b = IntegerField()
     total = SumFields(decimal_field, declared_fields='*')
Exemple #9
0
 class TransformCatalyst(Catalyst):
     a = IntegerField()
     coordinate = NestedField(coordinate_catalyst)
     transform = TransformNested('coordinate')
Exemple #10
0
    def test_transform_nested(self):
        coordinate_catalyst = Catalyst({
            'x': IntegerField(),
            'y': IntegerField()
        })

        class TransformCatalyst(Catalyst):
            a = IntegerField()
            coordinate = NestedField(coordinate_catalyst)
            transform = TransformNested('coordinate')

        catalyst = TransformCatalyst()

        # test wrong fields
        with self.assertRaises(ValueError):
            catalyst.transform.set_fields(fields={})

        with self.assertRaises(TypeError) as cm:
            catalyst.transform.set_fields(
                fields={'coordinate': IntegerField()})
        self.assertIn('NestedField', str(cm.exception))

        with self.assertRaises(ValueError) as cm:
            catalyst.transform.set_fields(
                fields={
                    'coordinate': NestedField(coordinate_catalyst, many=True)
                })
        self.assertIn('many=True', str(cm.exception))

        # test valid
        loading_data = {'a': 0, 'x': 1, 'y': -1}
        dumping_data = {'a': 0, 'coordinate': {'x': 1, 'y': -1}}

        result = catalyst.load(loading_data)
        self.assertTrue(result.is_valid)
        self.assertDictEqual(result.valid_data, dumping_data)

        result = catalyst.dump(dumping_data)
        self.assertTrue(result.is_valid)
        self.assertDictEqual(result.valid_data, loading_data)

        # test invalid
        invalid_loading_data = {'a': 0, 'x': 'x', 'y': -1}
        result = catalyst.load(invalid_loading_data)
        self.assertFalse(result.is_valid)
        self.assertSetEqual(set(result.errors), {'x'})
        self.assertDictEqual(result.invalid_data, {'x': 'x'})

        invalid_dumping_data = {'a': 0, 'coordinate': {'x': 'x', 'y': -1}}
        result = catalyst.dump(invalid_dumping_data)
        self.assertFalse(result.is_valid)
        self.assertSetEqual(set(result.errors), {'coordinate'})
        self.assertDictEqual(result.invalid_data, {'coordinate': {'x': 'x'}})

        # test change process methods
        fields = {'x': catalyst.coordinate}

        with self.assertRaises(AttributeError):
            TransformNested('x', dump_method='wrong').set_fields(fields)
        with self.assertRaises(AttributeError):
            TransformNested('x', load_method='wrong').set_fields(fields)

        class ReversedTransformCatalyst(TransformCatalyst):
            coordinate = NestedField(coordinate_catalyst, dump_required=False)
            transform = TransformNested('coordinate',
                                        dump_method='flat_to_nested',
                                        load_method='nested_to_flat')

        reversed_catalyst = ReversedTransformCatalyst()

        dumping_data = {'a': 0, 'x': 1, 'y': -1}
        loading_data = {'a': 0, 'coordinate': {'x': 1, 'y': -1}}

        result = reversed_catalyst.dump(dumping_data)
        self.assertTrue(result.is_valid)
        self.assertDictEqual(result.valid_data, loading_data)

        result = reversed_catalyst.load(loading_data)
        self.assertTrue(result.is_valid)
        self.assertDictEqual(result.valid_data, dumping_data)
Exemple #11
0
        class B(A):
            raise_error = True

            b = IntegerField()
            c = FloatField()
Exemple #12
0
 class A(Catalyst):
     a = IntegerField()
     b = IntegerField()
     args = ListField(IntegerField())
     kwargs = NestedField(Kwargs())
Exemple #13
0
 class Kwargs(Catalyst):
     c = IntegerField()
Exemple #14
0
    def test_list_field(self):
        with self.assertRaises(TypeError):
            ListField()

        with self.assertRaises(TypeError):
            field = ListField(FloatField)

        field = ListField(item_field=FloatField())

        # dump
        self.assertListEqual(field.dump([1.0, 2.0, 3.0]), [1.0, 2.0, 3.0])
        self.assertListEqual(field.dump([]), [])
        self.assertEqual(field.dump(None), None)
        with self.assertRaises(TypeError):
            field.dump(1)

        # load
        self.assertListEqual(field.load([1, 2, 3]), [1.0, 2.0, 3.0])
        self.assertListEqual(field.load([]), [])

        with self.assertRaises(ValidationError) as cm:
            field.load([1, 'a', 3])
        result = cm.exception.detail
        self.assertIsInstance(result.errors[1], ValueError)
        self.assertEqual(result.invalid_data[1], 'a')
        self.assertEqual(result.valid_data, [1.0, 3.0])

        with self.assertRaises(TypeError):
            field.load(1)
        with self.assertRaises(ValidationError):
            field.load(None)

        field = ListField(item_field=FloatField(), all_errors=False)
        with self.assertRaises(ValidationError) as cm:
            field.load([1, 'a', 'b'])
        result = cm.exception.detail
        self.assertEqual(set(result.errors), {1})
        self.assertEqual(result.invalid_data[1], 'a')
        self.assertEqual(result.valid_data, [1.0])

        # two-dimensional array
        field = ListField(ListField(IntegerField()))

        data = [[1], [2]]
        self.assertListEqual(data, field.load(data))

        data = [[1], ['x']]
        with self.assertRaises(ValidationError) as cm:
            field.load(data)
        result = cm.exception.detail
        self.assertIsInstance(result.errors[1][0], ValueError)

        data = [[1], None]
        with self.assertRaises(ValidationError) as cm:
            field.load(data)
        result = cm.exception.detail
        self.assertIsInstance(result.errors[1], ValidationError)

        # list with dict items
        field = ListField(NestedField(Catalyst({'x': IntegerField()})))

        data = [{'x': 1}, {'x': 2}]
        self.assertListEqual(data, field.load(data))

        data = [{'x': 1}, {'x': 'x'}]
        with self.assertRaises(ValidationError) as cm:
            field.load(data)
        result = cm.exception.detail
        self.assertIsInstance(result.errors[1]['x'], ValueError)

        data = [{'x': 1}, None]
        with self.assertRaises(ValidationError) as cm:
            field.load(data)
        result = cm.exception.detail
        self.assertIsInstance(result.errors[1], ValidationError)

        field = ListField(IntegerField(), 2, 3)
        self.assertListEqual(field.load(['1', '2']), [1, 2])
        with self.assertRaises(ValidationError):
            field.load(['1'])
        with self.assertRaises(ValidationError):
            field.load(['1', '2', '3', '4'])
Exemple #15
0
 class ComparisonCatalyst(Catalyst):
     lower_limit = IntegerField()
     upper_limit = IntegerField()
     comparison = CompareFields('upper_limit', '>', 'lower_limit')
Exemple #16
0
 class B:
     base = IntegerField()
     a = IntegerField()
     b = IntegerField()
 class C2(Catalyst):
     group = TestSetFields(declared_fields='*')
     field = IntegerField()
 class User(Catalyst):
     uid = IntegerField()
     name = StringField()
 class C(Catalyst):
     nums = ListField(IntegerField())
        class A(Catalyst):
            raise_error = True

            a = IntegerField()
            b = StringField()
Exemple #21
0
    def test_dump_and_load(self):
        # test dump
        dump_data = TestData(string='xxx',
                             integer=1,
                             float_=1.1,
                             bool_=True,
                             list_=['a', 'b'])

        # dump from object
        result = test_catalyst.dump(dump_data)
        self.assertDictEqual(
            result.valid_data, {
                'bool': True,
                'float': 1.1,
                'func': 6,
                'integer': 1,
                'list_': ['a', 'b'],
                'string': 'xxx'
            })

        # dump from dict
        dump_data_dict = {
            'float_': 1.1,
            'integer': 1,
            'string': 'xxx',
            'bool_': True,
            'func': dump_data.func,
            'list_': ['a', 'b']
        }
        self.assertEqual(
            test_catalyst.dump(dump_data_dict).valid_data, result.valid_data)

        # test load
        load_data = {
            'string': 'xxx',
            'integer': 1,
            'float': 1.1,
            'bool': True,
            'list_': ['a', 'b']
        }
        load_result = {
            'string': 'xxx',
            'integer': 1,
            'float_': 1.1,
            'bool_': True,
            'list_': ['a', 'b']
        }

        # test valid data
        result = test_catalyst.load(load_data)
        self.assertTrue(result.is_valid)
        self.assertFalse(result.errors)
        self.assertFalse(result.invalid_data)
        self.assertDictEqual(result.valid_data, load_result)

        # test invalid data: wrong type
        result = test_catalyst.load(1)
        self.assertFalse(result.is_valid)
        self.assertEqual(result.valid_data, {})
        self.assertEqual(result.invalid_data, 1)
        self.assertEqual(set(result.errors), {'load'})

        # test process_aliases
        test_catalyst.process_aliases['load'] = 'xxx'
        result = test_catalyst.load(1)
        self.assertFalse(result.is_valid)
        self.assertEqual(set(result.errors), {'xxx'})
        test_catalyst.process_aliases.clear()

        # test invalid data: validate errors
        invalid_data = {'string': 'xxx' * 20, 'integer': 100, 'float': 2}
        result = test_catalyst.load(invalid_data)
        self.assertFalse(result.is_valid)
        self.assertDictEqual(result.invalid_data, invalid_data)
        self.assertEqual(set(result.errors), {'string', 'integer', 'float'})
        self.assertDictEqual(result.valid_data, {})

        # test invalid_data: parse errors
        invalid_data = {'string': 'x', 'integer': 'str', 'float': []}
        result = test_catalyst.load(invalid_data)
        self.assertFalse(result.is_valid)
        self.assertDictEqual(result.invalid_data, invalid_data)
        self.assertEqual(set(result.errors), {'string', 'integer', 'float'})
        self.assertIsInstance(result.errors['string'], ValidationError)
        self.assertIsInstance(result.errors['integer'], ValueError)
        self.assertIsInstance(result.errors['float'], TypeError)

        # raise_error & all_errors
        result = test_catalyst.load(invalid_data, raise_error=False)
        self.assertFalse(result.is_valid)
        self.assertEqual(set(result.errors), {'string', 'integer', 'float'})

        with self.assertRaises(ValidationError) as ctx:
            test_catalyst.load(invalid_data, raise_error=True)
        self.assertEqual(set(ctx.exception.detail.errors),
                         {'string', 'integer', 'float'})

        catalyst_2 = TestDataCatalyst(all_errors=False)
        result = catalyst_2.load(invalid_data, raise_error=False)
        self.assertFalse(result.is_valid)
        self.assertEqual(len(result.errors), 1)

        with self.assertRaises(ValidationError) as ctx:
            catalyst_2.load(invalid_data, raise_error=True)
        self.assertEqual(len(ctx.exception.detail.errors), 1)

        # wrong process name
        with self.assertRaises(ValueError):
            test_catalyst._make_processor(1, False)

        # test return missing
        return_missing = lambda v: missing
        c = Catalyst(
            {
                'a':
                IntegerField(
                    formatter=return_missing, parser=return_missing, minimum=0)
            },
            raise_error=True)
        result = c.load({'a': 1})
        self.assertEqual(result.valid_data, {})

        with self.assertRaises(ValidationError) as cm:
            c.dump({'a': 1})
        result = cm.exception.detail
        self.assertIn('required', str(result.errors['a']))
Exemple #22
0
    def test_int_field(self):
        field = IntegerField(name='integer',
                             key='integer',
                             minimum=-10,
                             maximum=100,
                             error_messages={'not_between': '{self.maximum}'})

        # dump
        self.assertEqual(field.dump(1), 1)
        self.assertEqual(field.dump(1.6), 1)
        self.assertEqual(field.dump('10'), 10)

        # load
        self.assertEqual(field.load(0), 0)
        self.assertEqual(field.load(1), 1)
        self.assertEqual(field.load('1'), 1)
        self.assertEqual(field.load(None), None)

        with self.assertRaises(ValidationError) as cm:
            field.load(111)
        self.assertEqual(cm.exception.msg, '100')
        with self.assertRaises(ValueError):
            field.load('')
        with self.assertRaises(ValueError):
            field.load('asd')
        with self.assertRaises(TypeError):
            field.load([])