Example #1
0
        def wrapped(*args, **kwargs):
            request.validation_error = None

            if request.method in ('POST', 'PUT'):
                try:
                    body = request.body.decode()
                    if not body:
                        raise ValueError('No JSON object could be decoded')
                    data = json.loads(body)
                    notario.validate(data, schema)
                except (Invalid, ValueError) as error:
                    # TODO: It would be nice if we could have a sane default
                    # here where we set the response body instead of requiring
                    # a handler
                    request.validation_error = error
                    if handler:
                        redirect_to_handler(error, handler)
                    # a controller can say `handler=False` to signal they don't
                    # want to delegate, not even to the fallback
                    if handler is None:
                        headers = {'Content-Type': 'application/json'}
                        raise JSONValidationException(detail=error,
                                                      headers=headers)

            return f(*args, **kwargs)
Example #2
0
 def test_all_objects_fail_non_callable(self):
     data = {'a': {'a': 1, 'b': 1, 'c': 1}}
     schema = ('a', recursive.AllObjects((types.string, 2)))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert '-> a -> a -> 1  did not match 2' in error
Example #3
0
 def test_all_items_fail(self):
     def fail(value): raise AssertionError
     data = {'a': 'some string'}
     schema = ('a', chainable.AnyIn(types.boolean, fail))
     with raises(Invalid) as exc:
         validate(data, schema)
     assert exc.value.args[0] == '-> a  did not pass validation against callable: AnyIn'
Example #4
0
 def test_one_item_fails(self):
     data = {'a': 'some string'}
     schema = ('a', chainable.AllIn(types.string, types.boolean))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert '-> a -> some string  did not pass validation against callable: AllIn -> boolean' in error
Example #5
0
        def wrapped(*args, **kwargs):
            request.validation_error = None

            if request.method in ('POST', 'PUT'):
                try:
                    body = request.body.decode()
                    if not body:
                        raise ValueError('No JSON object could be decoded')
                    data = json.loads(body)
                    notario.validate(data, schema)
                except (Invalid, ValueError) as error:
                    # TODO: It would be nice if we could have a sane default
                    # here where we set the response body instead of requiring
                    # a handler
                    request.validation_error = error
                    if handler:
                        redirect_to_handler(error, handler)
                    # a controller can say `handler=False` to signal they don't
                    # want to delegate, not even to the fallback
                    if handler is None:
                        headers = {'Content-Type': 'application/json'}
                        raise JSONValidationException(
                            detail=error,
                            headers=headers
                        )

            return f(*args, **kwargs)
Example #6
0
 def test_all_items_fail_length(self):
     data = {'a': [{'a': 2}, {'b': {'a': 'b'}}]}
     schema = ('a', iterables.AllItems((types.string, 2)))
     with raises(SchemaError) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert  '-> a -> b  has less items in schema than in data' in error
Example #7
0
 def test_all_items_fail_length(self):
     data = {"a": [{"a": 2}, {"b": {"a": "b"}}]}
     schema = ("a", iterables.AllItems((types.string, 2)))
     with raises(SchemaError) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert "-> a -> b  has less items in schema than in data" in error
Example #8
0
 def test_one_item_fails(self):
     data = {'a': 'some string'}
     schema = ('a', chainable.AllIn(types.string, types.boolean))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert '-> a -> some string did not pass validation against callable: AllIn -> boolean' in error
Example #9
0
 def test_all_objects_fail_non_callable(self):
     data = {"a": {"a": 1, "b": 1, "c": 1}}
     schema = ("a", recursive.AllObjects((types.string, 2)))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert "-> a -> a -> 1 did not match 2" in error
Example #10
0
 def test_nested_raises_nested_invalid(self):
     data = {'a': [{'a': ['a']}, {'b': 'c'}]}
     nested_schema = iterables.MultiIterable(('a', ['b']), ('b', 'c'))
     schema = ('a', iterables.AllItems(nested_schema))
     with raises(Invalid) as exc:
         validate(data, schema)
     assert exc.value.reason == 'expected a list but got dict'
Example #11
0
 def test_nested_raises_nested_invalid(self):
     data = {"a": [{"a": ["a"]}, {"b": "c"}]}
     nested_schema = iterables.MultiIterable(("a", ["b"]), ("b", "c"))
     schema = ("a", iterables.AllItems(nested_schema))
     with raises(Invalid) as exc:
         validate(data, schema)
     assert exc.value.reason == "expected a list but got dict"
Example #12
0
 def test_nested_raises_nested_invalid(self):
     data = {'a': [{'a': ['a']}, {'b': 'c'}]}
     nested_schema = iterables.MultiIterable(('a', ['b']), ('b', 'c'))
     schema = ('a', iterables.AllItems(nested_schema))
     with raises(Invalid) as exc:
         validate(data, schema)
     assert exc.value.reason == 'expected a list but got dict'
Example #13
0
 def test_all_items_fail_length(self):
     data = {'a': [{'a': 2}, {'b': {'a': 'b'}}]}
     schema = ('a', iterables.AllItems((types.string, 2)))
     with raises(SchemaError) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert '-> a -> b  has less items in schema than in data' in error
Example #14
0
 def test_all_objects_fail_non_callable(self):
     data = {'a': {'a': 1, 'b': 1, 'c': 1}}
     schema = ('a', recursive.AllObjects((types.string, 2)))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert  '-> a -> a -> 1 did not match 2' in error
Example #15
0
 def test_no_pollution_from_previous_traversing_all_items(self):
     data = {"a": {"a": 1, "b": 2}, "b": {"c": 1, "d": 2}, "c": ["e", 1, "f", 2]}
     schema = (("a", (("a", 1), ("b", 2))), ("b", (("c", 1), ("d", 2))), ("c", iterables.AllItems(types.string)))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert "not of type string" in error
     assert "-> c -> list[1] item did not pass validation against callable: string" in error
Example #16
0
    def test_any_objects_fail_non_callable(self):
        data = {"a": {"a": 1, "b": 4, "c": 3}}
        schema = ("a", recursive.AnyObject(("a", "a")))
        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert "-> a did not contain any valid objects against callable: AnyObject" in error
Example #17
0
    def test_all_objects_fail_length(self):
        data = {"a": {"a": 2, "b": {"a": "b"}}}
        schema = ("a", recursive.AllObjects((types.string, 2)))
        with raises(SchemaError) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert "-> a -> b  has less items in schema than in data" in error
Example #18
0
 def test_all_objects_fail(self):
     data = {"a": {"a": 1, "b": "a string", "c": 3}}
     schema = ("a", recursive.AllObjects((types.string, types.integer)))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert "-> a -> b -> a string did not pass validation against callable: integer" in error
     assert "not of type int" in error
Example #19
0
    def test_most_simple_validation(self):
        data = {'a': 'a'}
        schema = (('a', 'b'))

        with raises(Invalid) as exc:
            validate(data, schema)

        assert exc.value.args[0] == "-> a -> a  did not match 'b'"
Example #20
0
    def test_multi_pair_non_nested_third_key(self):
        data = {'a': 'a', 'b':'b', 'c':'c', 'd':'d'}
        schema = (('a', 'a'), ('b', 'b'), ('f', 'c'), ('d', 'a'))

        with raises(Invalid) as exc:
            validate(data, schema)

        assert exc.value.args[0] == "-> c key did not match 'f'"
Example #21
0
 def test_nested_raises_nested_invalid(self):
     data = {"a": {"a": ["a"], "b": {}}}
     nested_schema = iterables.AllItems(types.string)
     schema = ("a", recursive.AllObjects((types.string, nested_schema)))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert "did not pass validation against callable: AllItems" in error
Example #22
0
    def test_any_item_with_dictionaries(self):
        data = {'a': [{'a': 1}, {'b': 2}]}
        schema = ('a', iterables.AnyItem(('c', 4)))
        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert  "-> a -> list[] did not contain any valid items matching ('c', 4)" in error
Example #23
0
    def test_multi_pair_non_nested_second(self):
        data = {'a': 'a', 'b':'b', 'c':'c', 'd':'d'}
        schema = (('a', 'a'), ('b', 'a'), ('c', 'c'), ('d', 'd'))

        with raises(Invalid) as exc:
            validate(data, schema)

        assert exc.value.args[0] == "-> b -> b  did not match 'a'"
Example #24
0
    def test_top_level_cherry_pick_with_optionals_complains(self):
        data = {'b': 'b', 'optional': 1, 'garbage': 'yes'}
        schema = (('b', types.string), (optional('optional'), types.string))

        with raises(Invalid) as exc:
            validate(data, schema, defined_keys=True)
        error = exc.value.args[0]
        assert '1 did not pass validation against callable: string' in error
Example #25
0
    def test_any_item_with_dictionaries(self):
        data = {'a': [{'a': 1}, {'b': 2}]}
        schema = ('a', iterables.AnyItem(('c', 4)))
        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert "-> a -> list[]  did not contain any valid items matching ('c', 4)" in error
Example #26
0
 def test_all_objects_fail(self):
     data = {'a': {'a': 1, 'b': 'a string', 'c': 3}}
     schema = ('a', recursive.AllObjects((types.string, types.integer)))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert '-> a -> b -> a string  did not pass validation against callable: integer' in error
     assert 'not of type int' in error
Example #27
0
    def test_any_items_fail_non_callable(self):
        data = {'a': [1, 2, 3, 4, 5]}
        schema = ('a', iterables.AnyItem('foo'))
        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert  "-> a -> list[] did not contain any valid items matching 'foo'" in error
Example #28
0
    def test_any_items_fail(self):
        data = {'a': [1, 2, 3, 4, 5]}
        schema = ('a', iterables.AnyItem(types.string))
        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert  '-> a -> list[] did not contain any valid items against callable: string' in error
Example #29
0
 def test_nested_raises_nested_invalid(self):
     data = {'a': {'a': ['a'], 'b': {}}}
     nested_schema = iterables.AllItems(types.string)
     schema = ('a', recursive.AllObjects((types.string, nested_schema)))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert 'did not pass validation against callable: AllItems' in error
Example #30
0
    def test_any_items_fail(self):
        data = {'a': [1, 2, 3, 4, 5]}
        schema = ('a', iterables.AnyItem(types.string))
        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert '-> a -> list[]  did not contain any valid items against callable: string' in error
Example #31
0
 def test_all_objects_fail(self):
     data = {'a': {'a': 1, 'b': 'a string', 'c': 3}}
     schema = ('a', recursive.AllObjects((types.string, types.integer)))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert '-> a -> b -> a string did not pass validation against callable: integer' in error
     assert 'not of type int' in error
Example #32
0
    def test_all_items_fail_non_callable(self):
        data = {'a': [1, 2, '3', 4, 5]}
        schema = ('a', iterables.AllItems('foo'))
        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert  "-> a -> list[0] item did not match 'foo'" in error
Example #33
0
    def test_all_objects_fail_length(self):
        data = {'a': {'a': 2, 'b': {'a': 'b'}}}
        schema = ('a', recursive.AllObjects((types.string, 2)))
        with raises(SchemaError) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert '-> a -> b  has less items in schema than in data' in error
Example #34
0
 def test_all_items_fail(self):
     data = {'a': [1, 2, '3', 4, 5]}
     schema = ('a', iterables.AllItems(types.integer))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert 'not of type int' in error
     assert '-> a -> list[2] item did not pass validation against callable: integer' in error
Example #35
0
 def test_all_items_fail(self):
     data = {'a': [1, 2, '3', 4, 5]}
     schema = ('a', iterables.AllItems(types.integer))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert 'not of type int' in error
     assert '-> a -> list[2] item did not pass validation against callable: integer' in error
Example #36
0
    def test_all_items_fail_non_callable(self):
        data = {'a': [1, 2, '3', 4, 5]}
        schema = ('a', iterables.AllItems('foo'))
        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert "-> a -> list[0] item did not match 'foo'" in error
Example #37
0
 def test_nested_raises_nested_invalid(self):
     data = {'a': {'a': ['a'], 'b': {}}}
     nested_schema = iterables.AllItems(types.string)
     schema = ('a', recursive.AllObjects((types.string, nested_schema)))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert 'did not pass validation against callable: AllItems' in error
Example #38
0
    def test_any_items_fail_non_callable(self):
        data = {'a': [1, 2, 3, 4, 5]}
        schema = ('a', iterables.AnyItem('foo'))
        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert "-> a -> list[]  did not contain any valid items matching 'foo'" in error
Example #39
0
    def test_any_objects_fail_non_callable(self):
        data = {'a': {'a': 1, 'b': 4, 'c': 3}}
        schema = ('a', recursive.AnyObject(('a', 'a')))
        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert '-> a  did not contain any valid objects against callable: AnyObject' in error
Example #40
0
    def test_any_objects_fail_non_callable(self):
        data = {'a': {'a': 1, 'b': 4, 'c': 3}}
        schema = ('a', recursive.AnyObject(('a', 'a')))
        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert  '-> a did not contain any valid objects against callable: AnyObject' in error
Example #41
0
    def test_all_objects_fail_length(self):
        data = {'a': {'a': 2, 'b': {'a': 'b'}}}
        schema = ('a', recursive.AllObjects((types.string, 2)))
        with raises(SchemaError) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert  '-> a -> b  has less items in schema than in data' in error
Example #42
0
 def test_fail_object(self):
     sschema = (1, 1)
     schema = ('a', Hybrid(validator, sschema))
     data = {'a': {1: 2}}
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert '1 -> 2 did not match 1' in error
     assert error.startswith('-> a -> 1')
Example #43
0
 def test_extra_unexpected_items(self):
     optional_schema = (optional(1), 1)
     schema = ('a', Hybrid(validator, optional_schema))
     data = {'a': {'foo': 'bar'}}
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert '-> a did not match {}' in error
     assert exc.value.reason == 'unexpected extra items'
Example #44
0
    def test_key_is_empty_string(self):
        data = {'a': ''}
        schema = (('a', 'b'))

        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert "-> a -> ''  did not match 'b'" in error
Example #45
0
 def test_hybrid_delegates_when_dict_or_list(self):
     # send off to Recursive when isinstance(value, (dict, list))
     data = {'a': ['a']}
     hybrid = Hybrid(types.string, iterables.AllItems('b'))
     schema = ('a', hybrid)
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert "list[0] item did not match 'b'" in error
Example #46
0
    def test_validate_only_one_item(self):
        data = {'a': {'b': 'b', 'c': 'c', 'd': 'd'}}
        schema = ('a', cherry_pick(('b', 'a')))

        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert "-> a -> b -> b  did not match 'a'" in error
Example #47
0
    def test_simple_validation_against_empty_data(self):
        data = {}
        schema = (('a', 'b'))

        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert 'top level has no data to validate against schema' in error
Example #48
0
    def test_key_fails_before_value(self):
        data = {'a': {'a': {'b': 'b'}}}
        schema = ('a', ('b', ('b', 'b')))

        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert "-> a -> a key did not match 'b'" in error
Example #49
0
    def test_validate_only_one_item(self):
        data = {'b': 'b', 'c': 'c', 'd': 'd'}
        schema = ('d', 'a')

        with raises(Invalid) as exc:
            validate(data, schema, defined_keys=True)

        error = exc.value.args[0]
        assert "-> d -> d did not match 'a'" in error
Example #50
0
    def test_key_is_empty_string(self):
        data = {'a': ''}
        schema = (('a', 'b'))

        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert  "-> a -> '' did not match 'b'" in error
Example #51
0
    def test_complain_about_non_alpha_optional_schema(self):
        data = {'a': 'a', 'b': 'b', 'c': 'c'}
        schema = ((optional('b') ,'b'), ('a', 'a'), ('c', 'c'))

        with raises(SchemaError) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert  "b  schema item is not alphabetically ordered" in error
Example #52
0
    def test_multi_pair_non_nested_first(self):
        data = {'a': 'a', 'b':'b', 'c':'c', 'd':'d'}
        schema = (('a', 'b'), ('b', 'b'), ('c', 'c'), ('d', 'd'))

        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert  "-> a -> a did not match 'b'" in error
Example #53
0
    def test_multi_pair_non_nested_third_key(self):
        data = {'a': 'a', 'b': 'b', 'c': 'c', 'd': 'd'}
        schema = (('a', 'a'), ('b', 'b'), ('f', 'c'), ('d', 'a'))

        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert "-> c key did not match 'f'" in error
Example #54
0
 def test_hybrid_delegates_when_dict_or_list(self):
     # send off to Recursive when isinstance(value, (dict, list))
     data = {'a':  ['a']}
     hybrid = Hybrid(types.string, iterables.AllItems('b'))
     schema = ('a', hybrid)
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert "list[0] item did not match 'b'" in error
Example #55
0
    def test_most_simple_validation(self):
        data = {'a': 'a'}
        schema = (('a', 'b'))

        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert "-> a -> a  did not match 'b'" in error
Example #56
0
    def test_complain_about_non_alpha_optional_schema(self):
        data = {'a': 'a', 'b': 'b', 'c': 'c'}
        schema = ((optional('b'), 'b'), ('a', 'a'), ('c', 'c'))

        with raises(SchemaError) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert "b  schema item is not alphabetically ordered" in error
Example #57
0
 def test_nested_can_raise_nested_invalid(self):
     data = {'a': {'a': 'b'}}
     data = {'a': [{'a': [1, 2]}, {'a': {}}]}
     nested_schema = ('a', iterables.AllItems(types.integer))
     schema = ('a', iterables.AllItems(nested_schema))
     with raises(Invalid) as exc:
         validate(data, schema)
     error = exc.value.args[0]
     assert 'did not pass validation against callable: integer'
     assert exc.value.reason == 'expected a list but got dict'
Example #58
0
    def test_all_items_fail(self):
        def fail(value):
            raise AssertionError

        data = {'a': 'some string'}
        schema = ('a', chainable.AnyIn(types.boolean, fail))
        with raises(Invalid) as exc:
            validate(data, schema)
        error = exc.value.args[0]
        assert '-> a -> some string  did not pass validation against callable: AnyIn' in error
Example #59
0
    def test_required_key_is_missing(self):
        data = {'a': 'a', 'c': 'c'}
        schema = (('a', 'a'), ('b', 'b'), ('c', 'c'))

        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert "key did not match schema" in error
        assert "required key in data is missing: b" in error
Example #60
0
    def test_required_key_is_missing(self):
        data = {'k1': 'v1', 'k3': 'v3'}
        schema = (('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3'))

        with raises(Invalid) as exc:
            validate(data, schema)

        error = exc.value.args[0]
        assert "key did not match schema" in error
        assert "required key in data is missing: k2" in error