def test_provider_decorator(self):  # type: () -> None
        with pytest.raises(TypeError):
            # noinspection PyTypeChecker
            ClassConfigurationSchema.provider(Boolean())  # type: ignore

        schema = Dictionary({})

        decorator = ClassConfigurationSchema.provider(schema)

        class IsAClass(object):
            pass

        def is_not_a_class():
            pass

        with pytest.raises(TypeError):
            decorator(is_not_a_class)  # type: ignore

        cls = decorator(IsAClass)
        assert cls is IsAClass
        assert getattr(cls, '_conformity_initialization_schema') is schema

        another_schema = Dictionary({})

        @ClassConfigurationSchema.provider(another_schema)
        class Sample(object):
            pass

        assert getattr(Sample,
                       '_conformity_initialization_schema') is another_schema
    def test_validate_method(self):

        schema = Dictionary(
            {
                'name': UnicodeString(max_length=20),
                'greeting': UnicodeString(),
            },
            optional_keys=['greeting'])

        class Greeter(object):
            @classmethod
            @validate_method(schema, UnicodeString())
            def greeter(cls, name, greeting='Hello'):
                # Special case to check return value stuff
                if name == 'error':
                    return 5
                return '%s, %s!' % (greeting, name)

        self.assertEqual(Greeter.greeter(name='Andrew'), 'Hello, Andrew!')
        self.assertEqual(Greeter.greeter(name='Andrew', greeting='Ahoy'),
                         'Ahoy, Andrew!')

        with self.assertRaises(ValidationError):
            Greeter.greeter(name='Andrewverylongnameperson')

        with self.assertRaises(ValidationError):
            Greeter.greeter(name='Andrew', greeeeeeting='Boo')

        with self.assertRaises(ValidationError):
            Greeter.greeter(name='error')

        with self.assertRaises(PositionalError):
            Greeter.greeter('Andrew')
    def test_dictionary_subclass(self):
        """
        Tests that subclassing a Dictionary allows you to provide the
        same options as instantiating it.
        """
        class Coordinate(Dictionary):
            contents = {
                'x': Float(),
                'y': Float(),
                'z': Float(),
            }
            optional_keys = ['z']

        schema = Coordinate(description='Where the treasure is')

        # Test the options work right
        self.assertEqual(
            schema.errors({
                'x': 4.4,
                'y': 65.21
            }),
            [],
        )
        self.assertEqual(
            schema.errors({
                'x': 4.4,
                'y': 65.21,
                'z': 5542
            }),
            [],
        )
        self.assertEqual(
            len(schema.errors({
                'x': 'HERRING',
                'z': 5542
            })),
            2,
        )

        # Test you can't make a dict without contents
        with self.assertRaises(ValueError):
            Dictionary()

        # Test not overriding one field
        class TwoDeeCoordinate(Dictionary):
            contents = {
                'x': Float(),
                'y': Float(),
            }

        schema2d = TwoDeeCoordinate(description='Where the treasure is')
        self.assertEqual(
            len(schema2d.errors({
                'x': 3.14,
                'z': 5542
            })),
            2,
        )
    def test_validate(self):  # type: () -> None
        schema = Dictionary({
            'name': UnicodeString(max_length=20),
            'greeting': UnicodeString(),
        }, optional_keys=('greeting', ))

        validate(schema, {'name': 'Andrew'})
        validate(schema, {'name': 'Andrew', 'greeting': 'Ahoy-hoy'})

        with self.assertRaises(ValidationError):
            validate(schema, {'name': 'Andrewverylongnameperson'})

        with self.assertRaises(ValidationError):
            validate(schema, {'name': 'Andrew', 'greeeeeeting': 'Ahoy-hoy'})
Beispiel #5
0
    def test_dictionary_subclass(self):  # type: () -> None
        """
        Tests that subclassing a Dictionary allows you to provide the
        same options as instantiating it.
        """
        class Coordinate(Dictionary):
            contents = {
                'x': Float(),
                'y': Float(),
                'z': Float(),
            }
            optional_keys = ('z', )

        schema = Coordinate(description='Where the treasure is')  # type: Base

        # Test the options work right
        self.assertEqual(
            schema.errors({
                'x': 4.4,
                'y': 65.21
            }),
            [],
        )
        self.assertEqual(
            schema.errors({
                'x': 4.4,
                'y': 65.21,
                'z': 5542
            }),
            [],
        )
        self.assertEqual(
            len(schema.errors({
                'x': 'HERRING',
                'z': 5542
            })),
            2,
        )

        # Test you can't make a dict without contents
        with self.assertRaises(ValueError):
            Dictionary()

        # Test not overriding one field
        class TwoDeeCoordinate(Dictionary):
            contents = {
                'x': Float(),
                'y': Float(),
            }

        schema2d = TwoDeeCoordinate(description='Where the treasure is')
        self.assertEqual(
            len(schema2d.errors({
                'x': 3.14,
                'z': 5542
            })),
            2,
        )

        class Another(Dictionary):
            allow_extra_keys = True
            description = 'Yep'

        schema = Another({'foo': UnicodeString()})
        assert schema.introspect() == {
            'type': 'dictionary',
            'contents': {
                'foo': {
                    'type': 'unicode',
                }
            },
            'description': 'Yep',
            'allow_extra_keys': True,
            'optional_keys': [],
        }

        with pytest.raises(TypeError):
            # noinspection PyTypeChecker
            Another({'foo': UnicodeString()},
                    optional_keys=1234)  # type: ignore

        class BadDict1(Dictionary):
            allow_extra_keys = 'not a bool'  # type: ignore

        with pytest.raises(TypeError):
            BadDict1(contents={})

        class BadDict2(Dictionary):
            description = b'not a unicode'  # type: ignore

        with pytest.raises(TypeError):
            BadDict2(contents={})

        class BadDict3(Dictionary):
            contents = 'not a dict'  # type: ignore

        with pytest.raises(TypeError):
            BadDict3()

        class ExtraDict(Dictionary):
            contents = {}  # type: ignore
            optional_keys = ('one', 'two'
                             )  # type: TupleType[HashableType, ...]

        d = ExtraDict()
        assert d.optional_keys == frozenset({'one', 'two'})

        class ExtraExtraDict(ExtraDict):
            optional_keys = ()  # type: TupleType[HashableType, ...]

        d = ExtraExtraDict()
        assert d.optional_keys == frozenset({})
Beispiel #6
0
    def test_dictionary_ordering(self):  # type: () -> None
        schema1 = Dictionary(
            OrderedDict((
                ('foo', UnicodeString()),
                ('bar', Boolean()),
                ('baz', List(Integer())),
            )),
            optional_keys=('foo', ),
            description='Hello, world',
        )

        assert schema1.introspect()['contents'] == {
            'baz': List(Integer()).introspect(),
            'foo': UnicodeString().introspect(),
            'bar': Boolean().introspect(),
        }

        assert schema1.introspect()['display_order'] == ['foo', 'bar', 'baz']

        schema2 = schema1.extend(
            OrderedDict((
                ('bar', Integer()),
                ('qux', Set(UnicodeString())),
                ('moon', Tuple(Decimal(), UnicodeString())),
            )))

        assert schema2.introspect()['contents'] == {
            'baz': List(Integer()).introspect(),
            'foo': UnicodeString().introspect(),
            'moon': Tuple(Decimal(), UnicodeString()).introspect(),
            'bar': Integer().introspect(),
            'qux': Set(UnicodeString()).introspect(),
        }

        assert schema2.introspect()['display_order'] == [
            'foo', 'bar', 'baz', 'qux', 'moon'
        ]

        assert not schema1.errors({'bar': True, 'foo': 'Hello', 'baz': [15]})

        errors = schema1.errors({
            'baz': 'Nope',
            'foo': False,
            'bar': ['Heck nope']
        })

        assert errors == [
            Error(code='INVALID',
                  pointer='foo',
                  message='Not a unicode string'),
            Error(code='INVALID', pointer='bar', message='Not a boolean'),
            Error(code='INVALID', pointer='baz', message='Not a list'),
        ]

        assert not schema2.errors(
            {
                'bar': 91,
                'foo': 'Hello',
                'qux': {'Yes'},
                'baz': [15],
                'moon': (decimal.Decimal('15.25'), 'USD')
            }, )

        errors = schema2.errors({
            'baz': 'Nope',
            'foo': False,
            'bar': ['Heck nope'],
            'qux': 'Denied',
            'moon': 72
        })

        assert errors == [
            Error(code='INVALID',
                  pointer='foo',
                  message='Not a unicode string'),
            Error(code='INVALID', pointer='bar', message='Not an integer'),
            Error(code='INVALID', pointer='baz', message='Not a list'),
            Error(code='INVALID',
                  pointer='qux',
                  message='Not a set or frozenset'),
            Error(code='INVALID', pointer='moon', message='Not a tuple'),
        ]
Beispiel #7
0
    def test_dictionary_extension(self):  # type: () -> None
        schema1 = Dictionary(
            {
                'foo': UnicodeString(),
                'bar': Boolean(),
            },
            optional_keys=('foo', ),
            description='Hello, world',
        )

        schema2 = schema1.extend(
            {
                'bar': Integer(),
                'baz': List(Integer()),
            },
            optional_keys=('baz', ),
        )

        schema3 = schema1.extend(
            {
                'bar': Integer(),
                'baz': List(Integer()),
            },
            optional_keys=('baz', ),
            allow_extra_keys=True,
            description='Goodbye, universe',
            replace_optional_keys=True,
        )

        self.assertEqual(
            Dictionary(
                {
                    'foo': UnicodeString(),
                    'bar': Integer(),
                    'baz': List(Integer()),
                },
                optional_keys=(
                    'foo',
                    'baz',
                ),
                allow_extra_keys=False,
                description='Hello, world',
            ).introspect(),
            schema2.introspect(),
        )

        self.assertEqual(
            Dictionary(
                {
                    'foo': UnicodeString(),
                    'bar': Integer(),
                    'baz': List(Integer()),
                },
                optional_keys=('baz', ),
                allow_extra_keys=True,
                description='Goodbye, universe',
            ).introspect(),
            schema3.introspect(),
        )

        assert 'display_order' not in schema1.introspect()
        assert 'display_order' not in schema2.introspect()
        assert 'display_order' not in schema3.introspect()
Beispiel #8
0
    def test_complex(self):  # type: () -> None

        schema = Dictionary({
            'child_ids':
            List(Integer(gt=0)),
            'address':
            Dictionary(
                {
                    'line1': UnicodeString(),
                    'line2': UnicodeString(),
                    'city': UnicodeString(),
                    'postcode': UnicodeString(),
                    'state': UnicodeString(),
                    'country': UnicodeString(),
                },
                optional_keys=('line2', 'state'),
            ),
            'unique_things':
            Set(UnicodeString()),
        })

        self.assertEqual(
            schema.errors(None),
            [Error('Not a dict')],
        )

        self.assertEqual(
            sorted(
                schema.errors(
                    {
                        'child_ids': [1, 2, 'ten'],
                        'unsolicited_item': 'Should not be here',
                        'another_bad': 'Also extra',
                        'unique_things': ['hello', 'world'],
                    }, )),
            sorted([
                Error('Not an integer', pointer='child_ids.2'),
                Error('Missing key: address',
                      code=ERROR_CODE_MISSING,
                      pointer='address'),
                Error('Extra keys present: another_bad, unsolicited_item',
                      code=ERROR_CODE_UNKNOWN),
                Error('Not a set or frozenset', pointer='unique_things'),
            ]),
        )

        self.assertEqual(
            schema.errors({
                'child_ids': [1, 2, 3, 4],
                'address': {
                    'line1': '115 5th Street',
                    'city': 'San Francisco',
                    'state': 'CA',
                    'country': 'USA',
                    'postcode': '94103',
                },
                'unique_things': {'hello', b'world'},
            }),
            [
                Error('Not a unicode string',
                      pointer='unique_things.[{}]'.format(str(b'world')))
            ],
        )

        self.assertEqual(
            schema.errors({
                'child_ids': [1, 2, 3, 4],
                'address': {
                    'line1': '115 5th Street',
                    'city': 'San Francisco',
                    'state': 'CA',
                    'country': 'USA',
                    'postcode': '94103',
                },
                'unique_things': {'hello', 'world'},
            }),
            [],
        )

        introspection = schema.introspect()
        self.assertEqual('dictionary', introspection['type'])
        self.assertFalse(introspection['allow_extra_keys'])
        self.assertEqual([], introspection['optional_keys'])
        self.assertEqual(3, len(introspection['contents']))
        self.assertIn('child_ids', introspection['contents'])
        self.assertEqual(
            {
                'type': 'list',
                'contents': {
                    'gt': 0,
                    'type': 'integer'
                },
            },
            introspection['contents']['child_ids'],
        )
        self.assertIn('address', introspection['contents'])
        self.assertEqual('dictionary',
                         introspection['contents']['address']['type'])
        self.assertFalse(
            introspection['contents']['address']['allow_extra_keys'])
        self.assertEqual(
            {'line2', 'state'},
            set(introspection['contents']['address']['optional_keys']))
        self.assertEqual(
            {
                'city': {
                    'type': 'unicode'
                },
                'country': {
                    'type': 'unicode'
                },
                'line1': {
                    'type': 'unicode'
                },
                'line2': {
                    'type': 'unicode'
                },
                'postcode': {
                    'type': 'unicode'
                },
                'state': {
                    'type': 'unicode'
                },
            },
            introspection['contents']['address']['contents'],
        )
        self.assertEqual(
            {
                'type': 'set',
                'contents': {
                    'type': 'unicode'
                },
            },
            introspection['contents']['unique_things'],
        )
    def test_subclass_definition(self):  # type: () -> None
        class ImmutableDict(Mapping):
            def __init__(self, underlying):
                self.underlying = underlying

            def __contains__(self, item):
                return item in self.underlying

            def __getitem__(self, k):
                return self.underlying[k]

            def get(self, k, default=None):
                return self.underlying.get(k, default)

            def __iter__(self):
                return iter(self.underlying)

            def __len__(self):
                return len(self.underlying)

            def keys(self):
                return self.underlying.keys()

            def items(self):
                return self.underlying.items()

            def values(self):
                return self.underlying.values()

        class ExtendedSchema(ClassConfigurationSchema):
            base_class = BaseSomething
            default_path = 'tests.test_fields_meta.AnotherSomething'
            description = 'Neat-o schema thing'

        schema = ExtendedSchema()

        config = {}  # type: dict
        with pytest.raises(ValidationError) as error_context:
            schema.instantiate_from(config)
        assert error_context.value.args[0] == [
            Error('Missing key: baz', code='MISSING', pointer='kwargs.baz'),
        ]
        assert config['object'] == AnotherSomething

        config = {'kwargs': {'baz': None}}
        value = schema.instantiate_from(config)
        assert isinstance(value, AnotherSomething)
        assert value.baz is None
        assert value.qux == 'unset'
        assert config['object'] == AnotherSomething

        config2 = ImmutableDict({'kwargs': {'baz': None}})
        assert schema.errors(config2) == []
        assert 'object' not in config2

        assert schema.introspect() == {
            'type':
            'class_config_dictionary',
            'description':
            'Neat-o schema thing',
            'default_path':
            'tests.test_fields_meta.AnotherSomething',
            'base_class':
            'BaseSomething',
            'switch_field':
            'path',
            'switch_field_schema':
            TypePath(base_classes=BaseSomething).introspect(),
            'kwargs_field':
            'kwargs',
            'kwargs_contents_map': {
                'tests.test_fields_meta.AnotherSomething':
                Dictionary(
                    {
                        'baz': Nullable(UnicodeString()),
                        'qux': Boolean()
                    },
                    optional_keys=('qux', ),
                ).introspect(),
            },
        }
    def test_inline_definition_no_default_or_base_class(
            self):  # type: () -> None
        schema = ClassConfigurationSchema()

        assert schema.errors('Not a dict') == [
            Error('Not a mapping (dictionary)')
        ]
        assert schema.errors({
            'foo': 'bar',
            'baz': 'qux',
            'path': 'unprocessed',
            'kwargs': {},
            'object': Foo
        }) == [Error('Extra keys present: baz, foo', code='UNKNOWN')]
        assert schema.errors({}) == [
            Error('Missing key (and no default specified): path',
                  code='MISSING',
                  pointer='path'),
        ]
        assert schema.errors({'path': 'foo.bar:Hello'}) == [
            Error(
                'ImportError: No module named foo.bar'
                if six.PY2 else "ImportError: No module named 'foo'",
                pointer='path',
            )
        ]
        assert schema.errors({'path': 'tests.test_fields_meta.Foo'}) == [
            Error(
                "Neither class 'tests.test_fields_meta.Foo' nor one of its superclasses was decorated with "
                "@ClassConfigurationSchema.provider",
                pointer='path',
            )
        ]
        assert schema.errors({
            'path': 'tests.test_fields_meta:InvalidProvider'
        }) == [
            Error(
                "Class 'tests.test_fields_meta:InvalidProvider' attribute '_conformity_initialization_schema' should be a "
                "Dictionary or SchemalessDictionary Conformity field or one of their subclasses",
                pointer='path',
            )
        ]

        config = {
            'path': 'tests.test_fields_meta:BasicProvider'
        }  # type: Dict[HashableType, AnyType]
        assert sorted(schema.errors(config)) == [
            Error('Missing key: bar', code='MISSING', pointer='kwargs.bar'),
            Error('Missing key: foo', code='MISSING', pointer='kwargs.foo'),
        ]
        assert config['object'] == BasicProvider

        with pytest.raises(ValidationError) as error_context:
            # noinspection PyTypeChecker
            schema.instantiate_from('Not a dict')  # type: ignore
        assert error_context.value.args[0] == [
            Error('Not a mutable mapping (dictionary)')
        ]

        config = {'path': 'tests.test_fields_meta:BasicProvider'}
        with pytest.raises(ValidationError) as error_context:
            schema.instantiate_from(config)
        assert sorted(error_context.value.args[0]) == [
            Error('Missing key: bar', code='MISSING', pointer='kwargs.bar'),
            Error('Missing key: foo', code='MISSING', pointer='kwargs.foo'),
        ]
        assert config['object'] == BasicProvider

        config = {
            'path': 'tests.test_fields_meta:BasicProvider',
            'kwargs': {
                'foo': 'Fine',
                'bar': 'Bad'
            }
        }
        assert schema.errors(config) == [
            Error('Not a boolean', pointer='kwargs.bar')
        ]
        assert config['object'] == BasicProvider

        config = {
            'path': 'tests.test_fields_meta:BasicProvider',
            'kwargs': {
                'foo': 'Fine',
                'bar': 'Bad'
            }
        }
        with pytest.raises(ValidationError) as error_context:
            schema.instantiate_from(config)
        assert error_context.value.args[0] == [
            Error('Not a boolean', pointer='kwargs.bar')
        ]
        assert config['object'] == BasicProvider

        config = {
            'path': 'tests.test_fields_meta:BasicProvider',
            'kwargs': {
                'foo': 'Fine',
                'bar': True
            }
        }
        assert schema.errors(config) == []
        assert config['object'] == BasicProvider

        config = {
            'path': 'tests.test_fields_meta:BasicProvider',
            'kwargs': {
                'foo': 'Fine',
                'bar': True
            }
        }
        value = schema.instantiate_from(config)
        assert isinstance(value, BasicProvider)
        assert value.foo == 'Fine'
        assert value.bar is True
        assert config['object'] == BasicProvider

        schema = ClassConfigurationSchema()
        with pytest.raises(ValidationError):
            schema.initiate_cache_for('foo.bar:Hello')
        schema.initiate_cache_for('tests.test_fields_meta.BasicProvider')
        schema.initiate_cache_for('tests.test_fields_meta:BasicProvider')
        assert schema.introspect() == {
            'type': 'class_config_dictionary',
            'base_class': 'object',
            'switch_field': 'path',
            'switch_field_schema': TypePath(base_classes=object).introspect(),
            'kwargs_field': 'kwargs',
            'kwargs_contents_map': {
                'tests.test_fields_meta.BasicProvider':
                Dictionary({
                    'foo': UnicodeString(),
                    'bar': Boolean()
                }, ).introspect(),
                'tests.test_fields_meta:BasicProvider':
                Dictionary({
                    'foo': UnicodeString(),
                    'bar': Boolean()
                }, ).introspect(),
            },
        }

        schema = ClassConfigurationSchema(add_class_object_to_dict=False)
        config = {
            'path': 'tests.test_fields_meta:BasicProvider',
            'kwargs': {
                'foo': 'Fine',
                'bar': True
            }
        }
        value = schema.instantiate_from(config)
        assert isinstance(value, BasicProvider)
        assert value.foo == 'Fine'
        assert value.bar is True
        assert 'object' not in config
                  code='INVALID',
                  pointer='kwargs.Not unicode')
            if six.PY2 else Error('Not a unicode string',
                                  code='INVALID',
                                  pointer='kwargs.{!r}'.format(b'Not unicode'))
        ]
        assert config['object'] == SomethingWithJustKwargs


class InvalidProvider(object):
    _conformity_initialization_schema = Boolean()


@ClassConfigurationSchema.provider(
    Dictionary({
        'foo': UnicodeString(),
        'bar': Boolean()
    }))
class BasicProvider(object):
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar


class BaseSomething(object):
    pass


@ClassConfigurationSchema.provider(
    Dictionary({
        'foo': Boolean(),
        'bar': Constant('walk', 'run')
Beispiel #12
0
    UnicodeString,
)

__all__ = (
    'ActionRequestSchema',
    'ContextHeaderSchema',
    'ControlHeaderSchema',
    'JobRequestSchema',
)

ActionRequestSchema = Dictionary(
    {
        'action':
        UnicodeString(
            description='The name of the service action to execute.'),
        'body':
        SchemalessDictionary(
            key_type=UnicodeString(),
            description='The request parameters for this action.'),
    },
    optional_keys=('body', ),
)
"""The Conformity schema with which action requests are validated."""

ControlHeaderSchema = Dictionary(
    {
        'continue_on_error':
        Boolean(
            description=
            'Whether to continue executing more actions in a multi-action job request if an action '
            'results in an error.', ),
        'suppress_response':
    def test_dictionary(self):
        with pytest.raises(TypeError):
            # noinspection PyTypeChecker
            Dictionary({'foo': UnicodeString()},
                       additional_validator='Not a validator')  # type: ignore

        field = Dictionary({
            'foo': UnicodeString(),
            'bar': Integer(),
            'baz': UnicodeString(),
        })

        assert field.errors(['foo', 'bar',
                             'baz']) == [Error(message='Not a dict')]
        assert field.errors(
            ('foo', 'bar', 'baz')) == [Error(message='Not a dict')]
        assert field.errors({'foo', 'bar',
                             'baz'}) == [Error(message='Not a dict')]
        assert field.errors({
            'foo': 'Hello',
            'bar': 12,
            'baz': True
        }) == [
            Error(message='Not a unicode string', pointer='baz'),
        ]
        assert field.errors({
            'foo': 'Hello',
            'bar': 12,
            'baz': 'Goodbye'
        }) == []

        class V(AdditionalCollectionValidator[Mapping[HashableType, AnyType]]):
            def errors(self, value):
                if value['foo'] != value['baz']:
                    return [
                        Error('Value foo does not match value baz',
                              pointer='foo')
                    ]
                return []

        field = field.extend(additional_validator=V())

        assert field.errors({
            'foo': 'Hello',
            'bar': 12,
            'baz': 'Goodbye'
        }) == [
            Error(message='Value foo does not match value baz', pointer='foo'),
        ]
        assert field.errors({'foo': 'Hello', 'bar': 12, 'baz': 'Hello'}) == []
    def test_validate_call(self):  # type: () -> None
        schema = Dictionary({
            'name': UnicodeString(max_length=20),
            'greeting': UnicodeString(),
        }, optional_keys=('greeting', ))

        @validate_call(schema, UnicodeString())
        def greeter(name, greeting='Hello'):
            # Special case to check return value stuff
            if name == 'error':
                return 5
            return '{}, {}!'.format(greeting, name)

        assert getattr(greeter, '__validated__') is True
        assert getattr(greeter, '__validated_schema_args__') is None
        assert getattr(greeter, '__validated_schema_kwargs__') is schema
        assert getattr(greeter, '__validated_schema_returns__') == UnicodeString()

        self.assertEqual(greeter(name='Andrew'), 'Hello, Andrew!')
        self.assertEqual(greeter(name='Andrew', greeting='Ahoy'), 'Ahoy, Andrew!')

        with self.assertRaises(ValidationError):
            greeter(name='Andrewverylongnameperson')

        with self.assertRaises(ValidationError):
            greeter(name='Andrew', greeeeeeting='Boo')

        with self.assertRaises(ValidationError):
            greeter(name='error')

        with self.assertRaises(PositionalError):
            greeter('Andrew')

        @validate_call(
            args=Tuple(Integer(), UnicodeString()),
            kwargs=None,
            returns=Null(),
        )
        def args_function(foo, bar):
            if foo:
                return bar.format(bar)

        assert getattr(args_function, '__validated__') is True
        assert getattr(args_function, '__validated_schema_args__') == Tuple(Integer(), UnicodeString())
        assert getattr(args_function, '__validated_schema_kwargs__') is None
        assert getattr(args_function, '__validated_schema_returns__') == Null()

        assert args_function(0, 'John {}') is None
        with pytest.raises(ValidationError):
            args_function(1, 'Jeff {}')
        with pytest.raises(ValidationError):
            args_function(0, b'Nope {}')
        with pytest.raises(ValidationError):
            args_function(0, bar='John {}')
        with pytest.raises(KeywordError):
            args_function(0, 'John {}', extra='Unsupported')

        @validate_call(
            args=Tuple(Integer(), UnicodeString()),
            kwargs=Dictionary({'extra': UnicodeString()}, optional_keys=('extra', )),
            returns=UnicodeString(),
        )
        def args_and_kwargs_function(foo, bar, extra='baz'):
            return bar.format(foo, extra)

        assert getattr(args_and_kwargs_function, '__validated__') is True
        assert getattr(args_and_kwargs_function, '__validated_schema_args__') == Tuple(Integer(), UnicodeString())
        assert (
            getattr(args_and_kwargs_function, '__validated_schema_kwargs__') ==
            Dictionary({'extra': UnicodeString()}, optional_keys=('extra', ))
        )
        assert getattr(args_and_kwargs_function, '__validated_schema_returns__') == UnicodeString()

        assert args_and_kwargs_function(0, 'John {}: {}') == 'John 0: baz'
        assert args_and_kwargs_function(1, 'Jeff {}: {}', extra='cool') == 'Jeff 1: cool'
        with pytest.raises(ValidationError):
            args_and_kwargs_function(1, 'Jeff {}: {}', 'cool')
        with pytest.raises(ValidationError):
            args_and_kwargs_function('nope', 'Jeff {}: {}')
        with pytest.raises(ValidationError):
            args_and_kwargs_function(1, b'nope')
        with pytest.raises(ValidationError):
            args_and_kwargs_function(0, bar='John {}: {}')
    def test_validate_method(self):  # type: () -> None
        schema = Dictionary({
            'name': UnicodeString(max_length=20),
            'greeting': UnicodeString(),
        }, optional_keys=('greeting', ))

        class Helper(object):
            @classmethod
            @validate_method(schema, UnicodeString())
            def greeter(cls, name, greeting='Hello'):
                # Special case to check return value stuff
                if name == 'error':
                    return 5
                return '{}, {}!'.format(greeting, name)

            @staticmethod
            @validate_call(args=Tuple(Integer(), Integer()), kwargs=None, returns=Integer())
            def args_method(one, two):
                return one + two

            # noinspection PyMethodMayBeStatic
            @validate_method(
                args=List(UnicodeString()),
                kwargs=SchemalessDictionary(value_type=UnicodeString()),
                returns=List(UnicodeString()),
            )
            def args_and_kwargs_method(self, *args, **kwargs):
                return [s.format(**kwargs) for s in args]

        assert getattr(Helper.greeter, '__validated__') is True
        assert getattr(Helper.greeter, '__validated_schema_args__') is None
        assert getattr(Helper.greeter, '__validated_schema_kwargs__') is schema
        assert getattr(Helper.greeter, '__validated_schema_returns__') == UnicodeString()

        assert getattr(Helper.args_method, '__validated__') is True
        assert getattr(Helper.args_method, '__validated_schema_args__') == Tuple(Integer(), Integer())
        assert getattr(Helper.args_method, '__validated_schema_kwargs__') is None
        assert getattr(Helper.args_method, '__validated_schema_returns__') == Integer()

        assert getattr(Helper.args_and_kwargs_method, '__validated__') is True
        assert getattr(Helper.args_and_kwargs_method, '__validated_schema_args__') == List(UnicodeString())
        assert (
            getattr(Helper.args_and_kwargs_method, '__validated_schema_kwargs__') ==
            SchemalessDictionary(value_type=UnicodeString())
        )
        assert getattr(Helper.args_and_kwargs_method, '__validated_schema_returns__') == List(UnicodeString())

        self.assertEqual(Helper.greeter(name='Andrew'), 'Hello, Andrew!')
        self.assertEqual(Helper.greeter(name='Andrew', greeting='Ahoy'), 'Ahoy, Andrew!')

        with self.assertRaises(ValidationError):
            Helper.greeter(name='Andrewverylongnameperson')

        with self.assertRaises(ValidationError):
            Helper.greeter(name='Andrew', greeeeeeting='Boo')

        with self.assertRaises(ValidationError):
            Helper.greeter(name='error')

        with self.assertRaises(PositionalError):
            Helper.greeter('Andrew')

        assert Helper.args_method(1, 2) == 3
        assert Helper.args_method(75, 23) == 98
        with pytest.raises(ValidationError):
            Helper.args_method(1.0, 2)
        with pytest.raises(ValidationError):
            Helper.args_method(1, 2.0)
        with pytest.raises(KeywordError):
            Helper.args_method(1, 2, extra='Forbidden')

        assert Helper().args_and_kwargs_method('hello', 'cool {planet}', 'hot {star}', planet='Earth', star='Sun') == [
            'hello',
            'cool Earth',
            'hot Sun',
        ]
        with pytest.raises(ValidationError):
            Helper().args_and_kwargs_method(1, 'sweet', planet='Earth', star='Sun')
        with pytest.raises(ValidationError):
            Helper().args_and_kwargs_method('hello', 'cool {planet}', 'hot {star}', planet=1, star=2)
Beispiel #16
0
    def test_polymorph(self):

        card = Dictionary({
            'payment_type':
            Constant('card'),
            'number':
            UnicodeString(),
            'cvc':
            UnicodeString(description='Card Verification Code'),
        })

        bankacc = Dictionary({
            'payment_type':
            Constant('bankacc'),
            'routing':
            UnicodeString(description='US RTN or foreign equivalent'),
            'account':
            UnicodeString(),
        })

        schema = Polymorph(
            'payment_type',
            {
                'card': card,
                'bankacc': bankacc,
            },
        )

        self.assertEqual(
            schema.errors({
                'payment_type': 'card',
                'number': '1234567890123456',
                'cvc': '000',
            }),
            [],
        )

        self.assertEqual(
            schema.errors({
                'payment_type': 'bankacc',
                'routing': '13456790',
                'account': '13910399',
            }),
            [],
        )

        self.assertEqual(
            schema.introspect(),
            {
                'type': 'polymorph',
                'contents_map': {
                    'bankacc': {
                        'type': 'dictionary',
                        'allow_extra_keys': False,
                        'contents': {
                            'account': {
                                'type': 'unicode'
                            },
                            'payment_type': {
                                'type': 'constant',
                                'values': ['bankacc'],
                            },
                            'routing': {
                                'type': 'unicode',
                                'description': 'US RTN or foreign equivalent',
                            },
                        },
                        'optional_keys': [],
                    },
                    'card': {
                        'type': 'dictionary',
                        'allow_extra_keys': False,
                        'contents': {
                            'cvc': {
                                'type': 'unicode',
                                'description': 'Card Verification Code',
                            },
                            'number': {
                                'type': 'unicode'
                            },
                            'payment_type': {
                                'type': 'constant',
                                'values': ['card'],
                            },
                        },
                        'optional_keys': [],
                    },
                },
                'switch_field': 'payment_type',
            },
        )
Beispiel #17
0
from conformity.fields import (
    Boolean,
    Dictionary,
    Integer,
    List,
    SchemalessDictionary,
    UnicodeString,
)

ActionRequestSchema = Dictionary(
    {
        'action': UnicodeString(),
        'body': SchemalessDictionary(key_type=UnicodeString()),
    },
    optional_keys=['body'],
)

ControlHeaderSchema = Dictionary(
    {
        'continue_on_error': Boolean(),
    },
    allow_extra_keys=True,
)

ContextHeaderSchema = Dictionary(
    {
        'switches': List(Integer()),
        'correlation_id': UnicodeString(),
    },
    allow_extra_keys=True,
)
Beispiel #18
0
from conformity.fields import Dictionary, UnicodeString, List
import json

instance = Dictionary(
    {
        "title": UnicodeString(),
        "url": UnicodeString(),
        "about_url": UnicodeString(),
        "description": UnicodeString(),
        "tags": List(UnicodeString()),
    },
    optional_keys=["description", "tags", "about_url"])
instances = List(instance)


def test_registry():
    data = json.load(open('registry.json'))
    assert [] == instances.errors(data)