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_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'), ]
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'], )