コード例 #1
0
 def test_latitude(self):
     schema = Latitude()
     self.assertEqual(
         schema.errors(89) or [],
         [],
     )
     self.assertEqual(
         schema.errors(-1.3412) or [],
         [],
     )
     self.assertEqual(
         schema.errors(180),
         [Error('Value not <= 90')],
     )
     self.assertEqual(
         schema.errors(-91),
         [Error('Value not >= -90')],
     )
コード例 #2
0
ファイル: test_fields.py プロジェクト: beamerblvd/conformity
    def test_hashable(self):  # type: () -> None
        assert Hashable('Another description 2').introspect() == {
            'type': 'hashable',
            'description': 'Another description 2',
        }

        assert Hashable().errors('this is hashable') == []
        assert Hashable().errors({'this', 'is', 'not', 'hashable'
                                  }) == [Error('Value is not hashable')]
コード例 #3
0
 def test_ipv4address(self):
     schema = IPv4Address()
     self.assertEqual(
         schema.errors('127.0.0.1'),
         [],
     )
     self.assertEqual(
         schema.errors('127.300.0.1'),
         [Error('Not a valid IPv4 address')],
     )
     self.assertEqual(
         schema.errors('127.0.0'),
         [Error('Not a valid IPv4 address')],
     )
     self.assertEqual(
         schema.errors('a2.12.55.3'),
         [Error('Not a valid IPv4 address')],
     )
コード例 #4
0
 def test_limited_longitude(self):
     schema = Longitude(lte=-50)
     self.assertEqual(
         schema.errors(-51.2) or [],
         [],
     )
     self.assertEqual(
         schema.errors(-49.32) or [],
         [Error('Value not <= -50')],
     )
コード例 #5
0
 def test_non_whitelisted_address(self):  # type: () -> None
     whitelisted_domains = ['a-whitelisted-domain']
     schema = EmailAddress(whitelist=whitelisted_domains)
     self.assertEqual(
         schema.errors('a-name@non-whitelisted-domain'),
         [
             Error('Not a valid email address (invalid domain field)',
                   pointer='non-whitelisted-domain')
         ],
     )
コード例 #6
0
ファイル: net.py プロジェクト: beamerblvd/conformity
 def errors(self, value):  # type: (AnyType) -> ListType[Error]
     # Get any basic type errors
     result = super(IPv4Address, self).errors(value)
     if result:
         return result
     # Check for IPv4-ness
     if ipv4_regex.match(value):
         return []
     else:
         return [Error('Not a valid IPv4 address')]
コード例 #7
0
ファイル: basic.py プロジェクト: beamerblvd/conformity
    def errors(self, value):  # type: (AnyType) -> ListType[Error]
        try:
            is_valid = value in self.values
        except TypeError:
            # Unhashable values can't be used for membership checks.
            is_valid = False

        if not is_valid:
            return [Error(self._error_message, code=ERROR_CODE_UNKNOWN)]
        return []
コード例 #8
0
ファイル: meta.py プロジェクト: pombredanne/conformity
    def errors(self, value):
        if not isinstance(value, Mapping):
            return [Error('Not a mapping (dictionary)')]

        # check for extra keys (object is allowed in case this gets validated twice)
        extra_keys = [
            k for k in six.iterkeys(value)
            if k not in ('path', 'kwargs', 'object')
        ]
        if extra_keys:
            return [
                Error(
                    'Extra keys present: {}'.format(', '.join(
                        six.text_type(k) for k in sorted(extra_keys))),
                    code=ERROR_CODE_UNKNOWN,
                )
            ]

        sentinel = object()
        path = value.get('path', sentinel)
        if path is sentinel and not self.default_path:
            return [
                Error('Missing key (and no default specified): path',
                      code=ERROR_CODE_MISSING,
                      pointer='path')
            ]

        if not path or path is sentinel:
            path = self.default_path

        errors = self._populate_schema_cache_if_necessary(path)
        if errors:
            return [update_error_pointer(e, 'path') for e in errors]

        if isinstance(value, MutableMapping):
            value['path'] = path  # in case it was defaulted
            if self.add_class_object_to_dict:
                value['object'] = PythonPath.resolve_python_path(path)

        return [
            update_error_pointer(e, 'kwargs')
            for e in self._schema_cache[path].errors(value.get('kwargs', {}))
        ]
コード例 #9
0
    def errors(self, value):
        if not isinstance(value, tuple):
            return [
                Error('Not a tuple'),
            ]

        result = []
        if len(value) != len(self.contents):
            result.append(
                Error('Number of elements %d does not match expected %d' % (len(value), len(self.contents)))
            )

        for i, (c_elem, v_elem) in enumerate(zip(self.contents, value)):
            result.extend(
                _update_error_pointer(error, i)
                for error in (c_elem.errors(v_elem) or [])
            )

        return result
コード例 #10
0
    def errors(self, value):
        if not isinstance(value, self.valid_types):
            return [Error(self.type_error)]

        result = []
        if self.max_length is not None and len(value) > self.max_length:
            result.append(
                Error('List longer than %s' % self.max_length),
            )
        elif self.min_length is not None and len(value) < self.min_length:
            result.append(
                Error('List is shorter than %s' % self.min_length),
            )
        for lazy_pointer, element in self._enumerate(value):
            result.extend(
                _update_error_pointer(error, lazy_pointer.get())
                for error in (self.contents.errors(element) or [])
            )
        return result
コード例 #11
0
ファイル: basic.py プロジェクト: manuelcorrales/conformity
 def errors(self, value):
     if not isinstance(value, self.valid_type):
         return [
             Error('Not a %s' % self.valid_noun),
         ]
     elif self.min_length is not None and len(value) < self.min_length:
         return [
             Error('String must have a length of at least %s' %
                   self.min_length),
         ]
     elif self.max_length is not None and len(value) > self.max_length:
         return [
             Error('String must have a length no more than %s' %
                   self.max_length),
         ]
     elif not (self.allow_blank or value.strip()):
         return [
             Error('String cannot be blank'),
         ]
コード例 #12
0
ファイル: meta.py プロジェクト: pombredanne/conformity
    def errors(self, value):  # type: (AnyType) -> ListType[Error]
        if not isinstance(value, six.text_type):
            return [Error('Not a unicode string')]

        try:
            thing = self.resolve_python_path(value)
        except ValueError:
            return [
                Error('Value "{}" is not a valid Python import path'.format(
                    value))
            ]
        except ImportError as e:
            return [Error(six.text_type(e.args[0]))]
        except AttributeError as e:
            return [Error(six.text_type(e.args[0]))]

        if self.value_schema:
            return self.value_schema.errors(thing)

        return []
コード例 #13
0
ファイル: structures.py プロジェクト: beamerblvd/conformity
    def errors(self, value):  # type: (AnyType) -> ListType[Error]
        if not isinstance(value, tuple):
            return [Error('Not a tuple')]

        result = []
        if len(value) != len(self.contents):
            result.append(
                Error(
                    'Number of elements {} does not match expected {}'.format(
                        len(value), len(self.contents))))

        for i, (c_elem, v_elem) in enumerate(zip(self.contents, value)):
            result.extend(
                update_error_pointer(error, i)
                for error in (c_elem.errors(v_elem) or []))

        if not result and self.additional_validator:
            return self.additional_validator.errors(value)

        return result
コード例 #14
0
ファイル: structures.py プロジェクト: beamerblvd/conformity
    def errors(self, value):  # type: (AnyType) -> ListType[Error]
        if not isinstance(value, self.valid_types):
            return [Error(self.type_error)]

        result = []
        if self.max_length is not None and len(value) > self.max_length:
            result.append(
                Error('List is longer than {}'.format(self.max_length)), )
        elif self.min_length is not None and len(value) < self.min_length:
            result.append(
                Error('List is shorter than {}'.format(self.min_length)), )
        for lazy_pointer, element in self._enumerate(value):
            result.extend(
                update_error_pointer(error, lazy_pointer.get())
                for error in (self.contents.errors(element) or []))

        if not result and self.additional_validator:
            return self.additional_validator.errors(value)

        return result
コード例 #15
0
    def test_schemaless(self):  # type: () -> None
        schema = ClassConfigurationSchema(base_class=BaseSomething)

        config = {
            'path': 'tests.test_fields_meta:SomethingWithJustKwargs'
        }  # type: dict
        value = schema.instantiate_from(config)
        assert config['object'] == SomethingWithJustKwargs
        assert isinstance(value, SomethingWithJustKwargs)
        assert value.kwargs == {}

        config = {
            'path': 'tests.test_fields_meta:SomethingWithJustKwargs',
            'kwargs': {
                'dog': 'Bree',
                'cute': True,
                'cat': b'Pumpkin'
            },
        }
        value = schema.instantiate_from(config)
        assert config['object'] == SomethingWithJustKwargs
        assert isinstance(value, SomethingWithJustKwargs)
        assert value.kwargs == {'dog': 'Bree', 'cute': True, 'cat': b'Pumpkin'}

        config = {
            'path': 'tests.test_fields_meta:SomethingWithJustKwargs',
            'kwargs': {
                b'Not unicode': False
            }
        }
        with pytest.raises(ValidationError) as error_context:
            schema.instantiate_from(config)
        assert error_context.value.args[0] == [
            Error('Not a unicode string',
                  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
コード例 #16
0
ファイル: email.py プロジェクト: pombredanne/conformity
    def errors(self, value):
        # Get any basic type errors
        result = super(EmailAddress, self).errors(value)
        if result:
            return result
        if not value or '@' not in value:
            return [Error('Not a valid email address (missing @ sign)')]

        user_part, domain_part = value.rsplit('@', 1)
        if not self.user_regex.match(user_part):
            return [Error('Not a valid email address (invalid local user field)', pointer=user_part)]
        if domain_part in self.domain_whitelist or self.is_domain_valid(domain_part):
            return []
        else:
            try:
                domain_part = domain_part.encode('idna').decode('ascii')
                if self.is_domain_valid(domain_part):
                    return []
            except UnicodeError:
                pass
            return [Error('Not a valid email address (invalid domain field)', pointer=domain_part)]
コード例 #17
0
ファイル: basic.py プロジェクト: manuelcorrales/conformity
 def errors(self, value):
     if not isinstance(value, self.valid_type) or isinstance(value, bool):
         return [
             Error('Not %s' % self.valid_noun),
         ]
     elif self.gt is not None and value <= self.gt:
         return [
             Error('Value not > %s' % self.gt),
         ]
     elif self.lt is not None and value >= self.lt:
         return [
             Error('Value not < %s' % self.lt),
         ]
     elif self.gte is not None and value < self.gte:
         return [
             Error('Value not >= %s' % self.gte),
         ]
     elif self.lte is not None and value > self.lte:
         return [
             Error('Value not <= %s' % self.lte),
         ]
コード例 #18
0
ファイル: test_fields.py プロジェクト: pombredanne/conformity
    def test_schemaless_dict_empty(self):  # type: () -> None
        """
        Tests the schemaless dict without any schema at all
        (so the default Hashable: Anything)
        """
        schema = SchemalessDictionary()

        self.assertEqual(schema.errors({'key': 'value'}), [])

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

        self.assertEqual(schema.introspect(), {
            'type': 'schemaless_dictionary',
        })
コード例 #19
0
ファイル: test_fields.py プロジェクト: beamerblvd/conformity
    def test_set(self):  # type: () -> None
        with pytest.raises(TypeError):
            # noinspection PyTypeChecker
            Set(UnicodeString(),
                additional_validator='Not a validator')  # type: ignore

        field = Set(UnicodeString())

        assert field.errors(
            ('hello', 'goodbye')) == [Error(message='Not a set or frozenset')]
        assert field.errors({'hello': 'goodbye'
                             }) == [Error(message='Not a set or frozenset')]
        assert field.errors(['hello', 'goodbye'
                             ]) == [Error(message='Not a set or frozenset')]
        assert field.errors(
            {'hello',
             2}) == [Error(message='Not a unicode string', pointer='[2]')]
        assert field.errors(frozenset(
            ('hello',
             2))) == [Error(message='Not a unicode string', pointer='[2]')]
        assert field.errors({'hello', 'goodbye'}) == []
        assert field.errors(frozenset(('hello', 'goodbye'))) == []

        class V(AdditionalCollectionValidator[AbstractSet]):
            def errors(self, value):
                errors = []
                for v in value:
                    if v > 500:
                        errors.append(
                            Error('Whoop custom error',
                                  pointer='{}'.format(v)))
                return errors

        field = Set(Integer(), additional_validator=V())

        assert field.errors({501, 'Not a number'}) == [
            Error(message='Not an integer', pointer='[Not a number]')
        ]
        assert field.errors(
            {501,
             499}) == [Error(message='Whoop custom error', pointer='501')]
        assert field.errors(frozenset(
            (501,
             499))) == [Error(message='Whoop custom error', pointer='501')]
        assert field.errors({500, 499}) == []
        assert field.errors(frozenset((500, 499))) == []
コード例 #20
0
ファイル: test_fields.py プロジェクト: beamerblvd/conformity
    def test_multi_constant(self):  # type: () -> None
        """
        Tests constants with multiple options
        """
        schema = Constant(42, 36, 81, 9231)
        self.assertEqual(
            schema.errors(9231),
            [],
        )
        self.assertEqual(
            schema.errors(81),
            [],
        )
        self.assertEqual(
            schema.errors(360000),
            [
                Error('Value is not one of: 36, 42, 81, 9231',
                      code=ERROR_CODE_UNKNOWN)
            ],
        )
        self.assertEqual(
            schema.errors([42]),
            [
                Error('Value is not one of: 36, 42, 81, 9231',
                      code=ERROR_CODE_UNKNOWN)
            ],
        )

        with pytest.raises(TypeError):
            Constant(42, 36, 81, 9231, description='foo', unsupported='bar')

        with pytest.raises(ValueError):
            Constant()

        with pytest.raises(TypeError):
            Constant(42, 36, 81, 9231, description=b'not unicode')
コード例 #21
0
    def errors(self, value):
        if not isinstance(value, dict):
            return [Error('Not a dict')]

        result = []

        if self.max_length is not None and len(value) > self.max_length:
            result.append(
                Error('Dict contains more than {} value(s)'.format(
                    self.max_length)))
        elif self.min_length is not None and len(value) < self.min_length:
            result.append(
                Error('Dict contains fewer than {} value(s)'.format(
                    self.min_length)))

        for key, field in value.items():
            result.extend(
                update_error_pointer(error, key)
                for error in (self.key_type.errors(key) or []))
            result.extend(
                update_error_pointer(error, key)
                for error in (self.value_type.errors(field) or []))

        return result
コード例 #22
0
ファイル: temporal.py プロジェクト: manuelcorrales/conformity
 def errors(self, value):
     if type(value) not in self.valid_types and (
             not self.valid_isinstance
             or not isinstance(value, self.valid_isinstance)):
         # using stricter type checking, because date is subclass of datetime, but they're not comparable
         return [
             Error('Not a %s instance' % self.valid_noun),
         ]
     elif self.gt is not None and value <= self.gt:
         return [
             Error('Value not > %s' % self.gt),
         ]
     elif self.lt is not None and value >= self.lt:
         return [
             Error('Value not < %s' % self.lt),
         ]
     elif self.gte is not None and value < self.gte:
         return [
             Error('Value not >= %s' % self.gte),
         ]
     elif self.lte is not None and value > self.lte:
         return [
             Error('Value not <= %s' % self.lte),
         ]
コード例 #23
0
    def test_type_path(self):  # type: () -> None
        schema = TypePath(description='This is another test')
        assert schema.errors(b'Nope nope nope') == [
            Error('Not a unicode string')
        ]
        assert schema.errors('Nope nope nope') == [
            Error('Value "Nope nope nope" is not a valid Python import path')
        ]
        assert schema.errors('foo.bar:Hello') == [
            Error('ImportError: No module named foo.bar' if six.
                  PY2 else "ImportError: No module named 'foo'")
        ]
        assert schema.errors('conformity.fields:NotARealField') == [
            Error(
                "AttributeError: 'module' object has no attribute 'NotARealField'"
                if six.PY2 else
                "AttributeError: module 'conformity.fields' has no attribute 'NotARealField'"
            )
        ]
        assert schema.errors('conformity.fields:UnicodeString') == []
        assert schema.errors('conformity.fields.UnicodeString') == []
        assert schema.errors('conformity.fields.ByteString') == []
        assert schema.errors('conformity.fields:ByteString') == []
        assert schema.errors('tests.test_fields_meta.Foo') == []
        assert schema.errors('tests.test_fields_meta.Bar') == []
        assert schema.errors('tests.test_fields_meta.Baz') == []
        assert schema.errors('tests.test_fields_meta.Qux') == []
        assert schema.errors('tests.test_fields_meta:Qux.InnerQux') == []

        schema = TypePath(base_classes=Foo)
        assert schema.errors('tests.test_fields_meta.Foo') == []
        assert schema.errors('tests.test_fields_meta.Bar') == []
        assert schema.errors('tests.test_fields_meta.Baz') == [
            Error('Type {} is not one of or a subclass of one of: {}'.format(
                Baz, Foo)),
        ]
        assert schema.errors('conformity.fields.UnicodeString') == [
            Error('Type {} is not one of or a subclass of one of: {}'.format(
                TypePath.resolve_python_path(
                    'conformity.fields.UnicodeString'),
                Foo,
            )),
        ]
        assert schema.introspect() == {
            'type': 'python_path',
            'value_schema': {
                'type': 'type_reference',
                'base_classes': [six.text_type(Foo)],
            }
        }

        assert TypePath.resolve_python_path(
            'tests.test_fields_meta.Qux') == Qux
        assert TypePath.resolve_python_path(
            'tests.test_fields_meta:Qux.InnerQux') == Qux.InnerQux
コード例 #24
0
ファイル: meta.py プロジェクト: pombredanne/conformity
    def instantiate_from(
        self, configuration
    ):  # type: (MutableMapping[HashableType, AnyType]) -> AnyType
        if not isinstance(configuration, MutableMapping):
            raise ValidationError(
                [Error('Not a mutable mapping (dictionary)')])

        errors = self.errors(configuration)
        if errors:
            raise ValidationError(errors)

        clazz = configuration.get('object')
        if not clazz:
            clazz = PythonPath.resolve_python_path(configuration['path'])

        return clazz(**configuration.get('kwargs', {}))
コード例 #25
0
 def errors(self, value):
     if not isinstance(value, dict):
         return [
             Error('Not a dict'),
         ]
     result = []
     for key, field in value.items():
         result.extend(
             _update_error_pointer(error, key)
             for error in (self.key_type.errors(key) or [])
         )
         result.extend(
             _update_error_pointer(error, key)
             for error in (self.value_type.errors(field) or [])
         )
     return result
コード例 #26
0
ファイル: test_fields.py プロジェクト: pombredanne/conformity
    def test_integers(self):  # type: () -> None
        schema = Integer(gt=0, lt=10)
        self.assertEqual([], schema.errors(1))
        self.assertEqual([Error('Not an integer')], schema.errors('one'))
        self.assertEqual([Error('Not an integer')], schema.errors(True))
        self.assertEqual([Error('Value not > 0')], schema.errors(0))
        self.assertEqual([Error('Value not < 10')], schema.errors(10))

        schema = Integer(gte=0, lte=10)
        self.assertEqual([Error('Value not >= 0')], schema.errors(-1))
        self.assertEqual([Error('Value not <= 10')], schema.errors(11))
コード例 #27
0
 def errors(self, value):
     # Get switch field value
     bits = self.switch_field.split('.')
     switch_value = value
     for bit in bits:
         switch_value = switch_value[bit]
     # Get field
     if switch_value not in self.contents_map:
         if '__default__' in self.contents_map:
             switch_value = '__default__'
         else:
             return [
                 Error('Invalid switch value {}'.format(switch_value), code=ERROR_CODE_UNKNOWN),
             ]
     field = self.contents_map[switch_value]
     # Run field errors
     return field.errors(value)
コード例 #28
0
ファイル: currency.py プロジェクト: beamerblvd/conformity
    def errors(self, value):  # type: (AnyType) -> ListType[Error]
        if not isinstance(value, currint.Amount):
            return [
                Error(
                    'Not a currint.Amount instance',
                    code=ERROR_CODE_INVALID,
                )
            ]

        return _get_errors_for_currency_amount(
            value.currency.code,
            value.value,
            self.valid_currencies,
            self.gt,
            self.gte,
            self.lt,
            self.lte,
        )
コード例 #29
0
    def test_objectinstance(self):
        class Thing(object):
            pass

        class Thingy(Thing):
            pass

        class SomethingElse(object):
            pass

        schema = ObjectInstance(Thing)

        self.assertEqual(schema.errors(Thing()), [])

        # subclasses are valid
        self.assertEqual(schema.errors(Thingy()), [])

        self.assertEqual(schema.errors(SomethingElse()),
                         [Error('Not an instance of Thing')])
コード例 #30
0
 def test_multi_constant(self):
     """
     Tests constants with multiple options
     """
     schema = Constant(42, 36, 81, 9231)
     self.assertEqual(
         schema.errors(9231),
         [],
     )
     self.assertEqual(
         schema.errors(81),
         [],
     )
     self.assertEqual(
         schema.errors(360000),
         [
             Error('Value is not one of: 36, 42, 81, 9231',
                   code=ERROR_CODE_UNKNOWN)
         ],
     )