Exemplo n.º 1
0
 def test_children_have_their_errors_dicts_built(self):
     e1, e2 = (
         exceptions.ValidationError("1", validator="foo", path=["bar", 0]),
         exceptions.ValidationError("2", validator="quux", path=["bar", 0]),
     )
     tree = exceptions.ErrorTree([e1, e2])
     self.assertEqual(tree["bar"][0].errors, {"foo": e1, "quux": e2})
Exemplo n.º 2
0
    def test_short_paths_are_better_matches(self):
        shallow = exceptions.ValidationError("Oh no!", path=["baz"])
        deep = exceptions.ValidationError("Oh yes!", path=["foo", "bar"])
        match = max([shallow, deep], key=exceptions.relevance)
        self.assertIs(match, shallow)

        match = max([deep, shallow], key=exceptions.relevance)
        self.assertIs(match, shallow)
Exemplo n.º 3
0
 def test_it_creates_a_child_tree_for_each_nested_path(self):
     errors = [
         exceptions.ValidationError("a bar message", path=["bar"]),
         exceptions.ValidationError("a bar -> 0 message", path=["bar", 0]),
     ]
     tree = exceptions.ErrorTree(errors)
     self.assertIn(0, tree["bar"])
     self.assertNotIn(1, tree["bar"])
Exemplo n.º 4
0
    def test_weak_validators_are_lower_priority(self):
        weak = exceptions.ValidationError("Oh no!", path=[], validator="a")
        normal = exceptions.ValidationError("Oh yes!", path=[], validator="b")

        best_match = exceptions.by_relevance(weak="a")

        match = max([weak, normal], key=best_match)
        self.assertIs(match, normal)

        match = max([normal, weak], key=best_match)
        self.assertIs(match, normal)
Exemplo n.º 5
0
 def test_multiple_errors_with_instance(self):
     e1, e2 = (
         exceptions.ValidationError("1",
                                    validator="foo",
                                    path=["bar", "bar2"],
                                    instance="i1"),
         exceptions.ValidationError("2",
                                    validator="quux",
                                    path=["foobar", 2],
                                    instance="i2"),
     )
     exceptions.ErrorTree([e1, e2])
Exemplo n.º 6
0
    def test_strong_validators_are_higher_priority(self):
        weak = exceptions.ValidationError("Oh no!", path=[], validator="a")
        normal = exceptions.ValidationError("Oh yes!", path=[], validator="b")
        strong = exceptions.ValidationError("Oh fine!", path=[], validator="c")

        best_match = exceptions.by_relevance(weak="a", strong="c")

        match = max([weak, normal, strong], key=best_match)
        self.assertIs(match, strong)

        match = max([strong, normal, weak], key=best_match)
        self.assertIs(match, strong)
Exemplo n.º 7
0
 def test_regression_multiple_errors_with_instance(self):
     e1, e2 = (
         exceptions.ValidationError("1",
                                    validator="foo",
                                    path=["bar", "bar2"],
                                    instance="i1"),
         exceptions.ValidationError("2",
                                    validator="quux",
                                    path=["foobar", 2],
                                    instance="i2"),
     )
     # Will raise an exception if the bug is still there.
     exceptions.ErrorTree([e1, e2])
Exemplo n.º 8
0
 def test_repr(self):
     e1, e2 = (
         exceptions.ValidationError(
             "1",
             validator="foo",
             path=["bar", "bar2"],
             instance="i1"),
         exceptions.ValidationError(
             "2",
             validator="quux",
             path=["foobar", 2],
             instance="i2"),
     )
     tree = exceptions.ErrorTree([e1, e2])
     self.assertEqual(repr(tree), "<ErrorTree (2 total errors)>")
Exemplo n.º 9
0
    def test_global_errors_are_even_better_matches(self):
        shallow = exceptions.ValidationError("Oh no!", path=[])
        deep = exceptions.ValidationError("Oh yes!", path=["foo"])

        errors = sorted([shallow, deep], key=exceptions.relevance)
        self.assertEqual(
            [list(error.path) for error in errors],
            [["foo"], []],
        )

        errors = sorted([deep, shallow], key=exceptions.relevance)
        self.assertEqual(
            [list(error.path) for error in errors],
            [["foo"], []],
        )
Exemplo n.º 10
0
    def properties(validator, properties, instance, schema):
        if not validator.is_type(instance, "object"):
            return

        # for managing defaults in the schema
        for property, subschema in properties.items():
            if "default" in subschema:
                instance.setdefault(property, subschema["default"])

        # for handling additional properties found in user spec
        for property, value in instance.items():

            if property in properties:
                for error in validator.descend(
                        value,
                        properties[property],
                        path=properties[property],
                        schema_path=properties[property],
                ):
                    yield error

            else:
                error = "Additional properties are not allowed : %r" % (
                    property)
                yield exceptions.ValidationError(error)
Exemplo n.º 11
0
    def test_validate(self):
        # set up
        expected = "No exception"
        side_effect = [
            expected,
            exceptions.SchemaError("SchemaError"),
            exceptions.ValidationError("ValidationError")
        ]
        returned_defaults = Mock()
        validator_with_defaults = Mock(return_value=returned_defaults)
        validate = Mock(side_effect=side_effect)
        returned_defaults.validate = validate
        self.validator.schema = "schema"
        self.validator._extend_with_default = \
            Mock(return_value=validator_with_defaults)
        cfg = "cfg"

        # test positive case
        result = self.validator.validate(cfg)
        self.validator._extend_with_default.assert_called_once_with(
            Draft4Validator)
        assert result == expected, expected
        validate.assert_called_once_with(cfg)
        validator_with_defaults.assert_called_once_with(self.validator.schema)

        # test negative cases
        expected_exceptions = [F5CcclError, F5CcclError]
        while expected_exceptions:
            expected = expected_exceptions.pop(0)
            with pytest.raises(expected):
                self.validator.validate(cfg)
Exemplo n.º 12
0
    def test_unset_error(self):
        error = exceptions.ValidationError("message")
        self.assertEqual(str(error), "message")

        kwargs = {
            "validator": "type",
            "validator_value": "string",
            "instance": 5,
            "schema": {"type": "string"},
        }
        # Just the message should show if any of the attributes are unset
        for attr in kwargs:
            k = dict(kwargs)
            del k[attr]
            error = exceptions.ValidationError("message", **k)
            self.assertEqual(str(error), "message")
Exemplo n.º 13
0
def _soft_validate_additional_properties(validator, aP, instance, schema):
    """This validator function is used for legacy v2 compatible mode in v2.1.
    This will skip all the addtional properties checking but keep check the
    'patternProperties'. 'patternProperties' is used for metadata API.

    """
    if not validator.is_type(instance, "object"):
        return

    properties = schema.get("properties", {})
    patterns = "|".join(schema.get("patternProperties", {}))
    extra_properties = set()
    for prop in instance:
        if prop not in properties:
            if patterns:
                if not re.search(patterns, prop):
                    extra_properties.add(prop)
            else:
                extra_properties.add(prop)

    if not extra_properties:
        return

    if patterns:
        error = "Additional properties are not allowed (%s %s unexpected)"
        if len(extra_properties) == 1:
            verb = "was"
        else:
            verb = "were"
        yield jsonschema_exc.ValidationError(
            error % (", ".join(repr(extra)
                               for extra in extra_properties), verb))
    else:
        for prop in extra_properties:
            del instance[prop]
Exemplo n.º 14
0
 def __call__(self, **op_kwargs):
     try:
         return super(OSLCallableOperation, self).__call__(
             **op_kwargs).response().result
     except (SwaggerMappingError,
             jsonschema.exceptions.ValidationError) as e:
         exc_type, exc_value, exc_traceback = sys.exc_info()
         LOG.exception(
             'Exception happens during request or response parsing. '
             'Please check schema is valid and server version corresponds '
             'to the declared')
         raise six.reraise(
             exceptions.ValidationError,
             exceptions.ValidationError(e),
             exc_traceback)
     except Exception as e:
         exc_type, exc_value, exc_traceback = sys.exc_info()
         LOG.exception(
             'Exception happens while getting response from server. '
             'This could be part of the normal flow '
             'like 404 for non existing objects')
         new_exception = exceptions.UnexpectedResponse(e, e)
         raise six.reraise(
             exceptions.UnexpectedResponse,
             new_exception,
             exc_traceback)
Exemplo n.º 15
0
 def test_it_knows_how_many_total_errors_it_contains(self):
     # FIXME: https://github.com/Julian/jsonschema/issues/442
     errors = [
         exceptions.ValidationError("Something", validator=i)
         for i in range(8)
     ]
     tree = exceptions.ErrorTree(errors)
     self.assertEqual(tree.total_errors, 8)
Exemplo n.º 16
0
    def to_internal_value(self, data):
        """Verbatim copy of the original drf `to_internal_value()` method.

        This method replicates the implementation found on
        `restframework.serializers.Serializer.to_internal_value` method because the
        dynamic-rest package (which we are using, and which overrides the base
        implementation) adds some custom stuff on top of it which depends on the input
        data containing the instance's `id` property, which we are not requiring.

        A HarvestableResource's `id` is an implementation detail that is not exposed
        publicly. We rely on the instance's `unique_identifier` instead.

        """

        if not isinstance(data, typing.Mapping):
            message = self.error_messages['invalid'].format(
                datatype=type(data).__name__
            )
            raise exceptions.ValidationError({
                api_settings.NON_FIELD_ERRORS_KEY: [message]
            }, code='invalid')

        ret = collections.OrderedDict()
        errors = collections.OrderedDict()
        fields = self._writable_fields

        for field in fields:
            validate_method = getattr(self, f"validate_{field.field_name}", None)
            primitive_value = field.get_value(data)
            try:
                validated_value = field.run_validation(primitive_value)
                if validate_method is not None:
                    validated_value = validate_method(validated_value)
            except exceptions.ValidationError as exc:
                errors[field.field_name] = exc.detail
            except DjangoValidationError as exc:
                errors[field.field_name] = get_error_detail(exc)
            except SkipField:
                pass
            else:
                set_value(ret, field.source_attrs, validated_value)

        if errors:
            raise exceptions.ValidationError(errors)

        return ret
Exemplo n.º 17
0
 def test_it_knows_how_many_total_errors_it_contains(self):
     # FIXME: #442
     errors = [
         exceptions.ValidationError("Something", validator=i)
         for i in range(8)
     ]
     tree = exceptions.ErrorTree(errors)
     self.assertEqual(tree.total_errors, 8)
Exemplo n.º 18
0
        def iter_errors(self, instance, _schema=None):
            if _schema is None:
                _schema = self.schema

            if _schema is True:
                return
            elif _schema is False:
                yield exceptions.ValidationError(
                    "False schema does not allow %r" % (instance, ),
                    validator=None,
                    validator_value=None,
                    instance=instance,
                    schema=_schema,
                )
                return

            scope = id_of(_schema)
            if scope:
                self.resolver.push_scope(scope)
            try:
                ref = _schema.get(u"$ref")
                if ref is not None:
                    validators = [(u"$ref", ref)]
                else:
                    validators = iteritems(_schema)

                for k, v in validators:
                    validator = self.VALIDATORS.get(k)
                    if validator is None:
                        continue
                    if PY36 and inspect.isasyncgenfunction(validator):
                        bp = AsyncValidationBreakpoint(
                            coroutine=validator,
                            value=v,
                            validator=k,
                            validator_value=v,
                            instance=instance,
                            schema=_schema,
                        )
                        yield bp
                        errors = bp.errors
                    else:
                        errors = validator(self, v, instance, _schema) or ()

                    for error in errors:
                        # set details if not already set by the called fn
                        error._set(
                            validator=k,
                            validator_value=v,
                            instance=instance,
                            schema=_schema,
                        )
                        if k != u"$ref":
                            error.schema_path.appendleft(k)
                        yield error
            finally:
                if scope:
                    self.resolver.pop_scope()
Exemplo n.º 19
0
    def test_main_with_mock_invalid_source(self, mock_parse_arguments,
                                           mock_setup_logger, mock_Source):
        mock_parse_arguments.return_value = \
            argparse.Namespace(debug=False, source=sentinel.source)
        mock_Source.return_value.compile.side_effect = \
            jsonschema_exceptions.ValidationError(sentinel.message)

        with self.assertRaises(SystemExit):
            cli.main()
Exemplo n.º 20
0
 def make_error(self, **kwargs):
     defaults = dict(
         message=u"hello",
         validator=u"type",
         validator_value=u"string",
         instance=5,
         schema={u"type": u"string"},
     )
     defaults.update(kwargs)
     return exceptions.ValidationError(**defaults)
Exemplo n.º 21
0
def _soft_validate_additional_properties(validator,
                                         additional_properties_value,
                                         instance,
                                         schema):
    """This validator function is used for legacy v2 compatible mode in v2.1.
    This will skip all the additional properties checking but keep check the
    'patternProperties'. 'patternProperties' is used for metadata API.

    If there are not any properties on the instance that are not specified in
    the schema, this will return without any effect. If there are any such
    extra properties, they will be handled as follows:

    - if the validator passed to the method is not of type "object", this
      method will return without any effect.
    - if the 'additional_properties_value' parameter is True, this method will
      return without any effect.
    - if the schema has an additionalProperties value of True, the extra
      properties on the instance will not be touched.
    - if the schema has an additionalProperties value of False and there
      aren't patternProperties specified, the extra properties will be stripped
      from the instance.
    - if the schema has an additionalProperties value of False and there
      are patternProperties specified, the extra properties will not be
      touched and raise validation error if pattern doesn't match.
    """
    if (not validator.is_type(instance, "object") or
            additional_properties_value):
        return

    properties = schema.get("properties", {})
    patterns = "|".join(schema.get("patternProperties", {}))
    extra_properties = set()
    for prop in instance:
        if prop not in properties:
            if patterns:
                if not re.search(patterns, prop):
                    extra_properties.add(prop)
            else:
                extra_properties.add(prop)

    if not extra_properties:
        return

    if patterns:
        error = "Additional properties are not allowed (%s %s unexpected)"
        if len(extra_properties) == 1:
            verb = "was"
        else:
            verb = "were"
        yield jsonschema_exc.ValidationError(
            error % (", ".join(repr(extra) for extra in extra_properties),
                     verb))
    else:
        for prop in extra_properties:
            del instance[prop]
Exemplo n.º 22
0
    def test_if_its_in_the_tree_anyhow_it_does_not_raise_an_error(self):
        """
        If a validator is dumb (like :validator:`required` in draft 3) and
        refers to a path that isn't in the instance, the tree still properly
        returns a subtree for that path.
        """

        error = exceptions.ValidationError(
            "a message", validator="foo", instance={}, path=["foo"],
        )
        tree = exceptions.ErrorTree([error])
        self.assertIsInstance(tree["foo"], exceptions.ErrorTree)
Exemplo n.º 23
0
        def iter_errors(self, instance, _schema=None):
            if _schema is not None:
                warnings.warn(
                    ("Passing a schema to Validator.iter_errors "
                     "is deprecated and will be removed in a future "
                     "release. Call validator.evolve(schema=new_schema)."
                     "iter_errors(...) instead."),
                    DeprecationWarning,
                    stacklevel=2,
                )
            else:
                _schema = self.schema

            if _schema is True:
                return
            elif _schema is False:
                yield exceptions.ValidationError(
                    f"False schema does not allow {instance!r}",
                    validator=None,
                    validator_value=None,
                    instance=instance,
                    schema=_schema,
                )
                return

            scope = id_of(_schema)
            if scope:
                self.resolver.push_scope(scope)
            try:
                for k, v in applicable_validators(_schema):
                    validator = self.VALIDATORS.get(k)
                    if validator is None:
                        continue

                    errors = validator(self, v, instance, _schema) or ()
                    for error in errors:
                        # set details if not already set by the called fn
                        error._set(
                            validator=k,
                            validator_value=v,
                            instance=instance,
                            schema=_schema,
                        )
                        if k not in {"if", "$ref"}:
                            error.schema_path.appendleft(k)
                        yield error
            finally:
                if scope:
                    self.resolver.pop_scope()
Exemplo n.º 24
0
        def iter_errors(self, instance, _schema=None):
            if _schema is None:
                _schema = self.schema

            if _schema is True:
                return
            elif _schema is False:
                yield exceptions.ValidationError(
                    "False schema does not allow %r" % (instance, ),
                    validator=None,
                    validator_value=None,
                    instance=instance,
                    schema=_schema,
                )
                return

            scope = id_of(_schema)
            if scope:
                self.resolver.push_scope(scope)
            try:
                ref = _schema.get(u"$ref")
                if ref is not None:
                    validators = [(u"$ref", ref)]
                else:
                    validators = iteritems(_schema)

                for k, v in validators:
                    validator = self.VALIDATORS.get(k)
                    if validator is None:
                        continue

                    errors = validator(self, v, instance, _schema) or ()
                    for error in errors:
                        # set details if not already set by the called fn
                        error._set(
                            validator=k,
                            validator_value=v,
                            instance=instance,
                            schema=_schema,
                        )
                        if k not in {u"if", u"$ref"}:
                            error.schema_path.appendleft(k)
                        yield error
            finally:
                if scope:
                    self.resolver.pop_scope()
Exemplo n.º 25
0
    def test_str_works_with_instances_having_overriden_eq_operator(self):
        """
        Check for https://github.com/Julian/jsonschema/issues/164 which
        rendered exceptions unusable when a `ValidationError` involved
        instances with an `__eq__` method that returned truthy values.

        """

        instance = mock.MagicMock()
        error = exceptions.ValidationError(
            "a message",
            validator="foo",
            instance=instance,
            validator_value="some",
            schema="schema",
        )
        str(error)
        self.assertFalse(instance.__eq__.called)
Exemplo n.º 26
0
    def validate(self, loaded_user_configuration: Any) -> str:
        """Perform validation on the configuration against supported schemas.

    :param loaded_user_configuration: A Python object containing user config.
    :returns: The first configuration schema version that passes validation.
    :raises: :class:`jsonschema.exceptions.ValidationError`
    """

        validation_exception = exceptions.ValidationError("No schema found!")

        for version, schema in self.schemas.items():
            try:
                resolver = RefResolver("file://" + str(self._schema_folder),
                                       None)
                validate(loaded_user_configuration, schema, resolver=resolver)
                return version
            except exceptions.ValidationError as last_exception:
                validation_exception = last_exception

        raise validation_exception
    def test_str_works_with_instances_having_overriden_eq_operator(self):
        """
        Check for https://github.com/Julian/jsonschema/issues/164 which
        rendered exceptions unusable when a `ValidationError` involved
        instances with an `__eq__` method that returned truthy values.
        """
        class DontEQMeBro(object):
            def __eq__(this, other):  # pragma: no cover
                self.fail("Don't!")

            def __ne__(this, other):  # pragma: no cover
                self.fail("Don't!")

        instance = DontEQMeBro()
        error = exceptions.ValidationError(
            "a message",
            validator="foo",
            instance=instance,
            validator_value="some",
            schema="schema",
        )
        self.assertIn(repr(instance), str(error))
Exemplo n.º 28
0
 def test_repr(self):
     self.assertEqual(
         repr(exceptions.ValidationError(message="Hello!")),
         "<ValidationError: %r>" % "Hello!",
     )
Exemplo n.º 29
0
    def test_it_does_not_contain_subtrees_that_are_not_in_the_instance(self):
        error = exceptions.ValidationError("123", validator="foo", instance=[])
        tree = exceptions.ErrorTree([error])

        with self.assertRaises(IndexError):
            tree[0]
Exemplo n.º 30
0
 def test_validators_that_failed_appear_in_errors_dict(self):
     error = exceptions.ValidationError("a message", validator="foo")
     tree = exceptions.ErrorTree([error])
     self.assertEqual(tree.errors, {"foo": error})