Exemple #1
0
def test_error_messages_interface():
    """
    `errors.messages()` should return a list of Message instances.
    """
    validator = Integer()
    value, error = validator.validate_or_error("abc")
    assert error.messages() == [Message(text="Must be a number.", code="type")]
Exemple #2
0
def test_not():
    validator = Not(Integer())
    value, error = validator.validate_or_error("abc")
    assert value == "abc"
    assert error is None

    validator = Not(Integer())
    value, error = validator.validate_or_error(5)
    assert value is None
    assert error == ValidationError(text="Must not match.", code="negated")
Exemple #3
0
def test_union():
    validator = Union(any_of=[Integer(), String()])
    value, error = validator.validate_or_error("abc")
    assert value == "abc"
    assert error is None

    validator = Union(any_of=[Integer(), String()])
    value, error = validator.validate_or_error(123)
    assert value == 123
    assert error is None

    validator = Union(any_of=[Integer(), String()])
    value, error = validator.validate_or_error(None)
    assert value is None
    assert error == ValidationError(text="May not be null.", code="null")

    validator = Union(any_of=[Integer(), String()])
    value, error = validator.validate_or_error(True)
    assert value is None
    assert error == ValidationError(text="Did not match any valid type.",
                                    code="union")

    validator = Union(any_of=[Integer(allow_null=True), String()])
    value, error = validator.validate_or_error(None)
    assert error is None
    assert value is None

    validator = Union(any_of=[Integer(), String()], allow_null=True)
    value, error = validator.validate_or_error(None)
    assert error is None
    assert value is None

    validator = Union(any_of=[Integer(maximum=1000), String()])
    value, error = validator.validate_or_error(9999)
    assert value is None
    assert error == ValidationError(text="Must be less than or equal to 1000.",
                                    code="maximum")

    validator = Integer() | String() | Boolean()
    value, error = validator.validate_or_error(123)
    assert value == 123

    validator = Integer() | (String() | Boolean())
    value, error = validator.validate_or_error(123)
    assert value == 123
Exemple #4
0
def test_errors_dict_interface():
    """
    `validated.errors` should present a dict-like interface.
    """
    validator = Object(properties={"example": Integer()})
    value, error = validator.validate_or_error({"example": "abc"})
    assert dict(error) == {"example": "Must be a number."}

    validator = Object(properties={"example": Integer()})
    value, error = validator.validate_or_error({"example": "abc"})
    assert error["example"] == "Must be a number."

    validator = Object(additional_properties=Object(
        additional_properties=Integer()))
    value, error = validator.validate_or_error({"example": {"nested": "abc"}})
    assert dict(error) == {"example": {"nested": "Must be a number."}}

    validator = Integer()
    value, error = validator.validate_or_error("abc")
    assert error[""] == "Must be a number."

    validator = Integer()
    value, error = validator.validate_or_error("abc")
    assert dict(error) == {"": "Must be a number."}
Exemple #5
0
def test_one_of():
    validator = OneOf([String(), Integer()])
    value, error = validator.validate_or_error(123)
    assert value is 123
    assert error is None

    validator = OneOf([String(allow_null=True), Integer()])
    value, error = validator.validate_or_error(None)
    assert value is None
    assert error is None

    validator = OneOf([String(allow_null=True), Integer(allow_null=True)])
    value, error = validator.validate_or_error(None)
    assert value is None
    assert error == ValidationError(
        text="Matched more than one type.", code="multiple_matches"
    )

    validator = OneOf([String(), Integer()])
    value, error = validator.validate_or_error(None)
    assert value is None
    assert error == ValidationError(
        text="Did not match any valid type.", code="no_match"
    )
Exemple #6
0
def test_all_of():
    validator = AllOf([Integer(multiple_of=5), Integer(multiple_of=3)])
    value, error = validator.validate_or_error(3)
    assert value is None
    assert error == ValidationError(text="Must be a multiple of 5.", code="multiple_of")

    validator = AllOf([Integer(multiple_of=5), Integer(multiple_of=3)])
    value, error = validator.validate_or_error(5)
    assert value is None
    assert error == ValidationError(text="Must be a multiple of 3.", code="multiple_of")

    validator = AllOf([Integer(multiple_of=5), Integer(multiple_of=3)])
    value, error = validator.validate_or_error(15)
    assert value == 15
    assert error is None
def from_json_schema_type(data: dict, type_string: str, allow_null: bool,
                          definitions: SchemaDefinitions) -> Field:
    """
    Build a typed field from a JSON schema object.
    """

    if type_string == "number":
        kwargs = {
            "allow_null": allow_null,
            "minimum": data.get("minimum", None),
            "maximum": data.get("maximum", None),
            "exclusive_minimum": data.get("exclusiveMinimum", None),
            "exclusive_maximum": data.get("exclusiveMaximum", None),
            "multiple_of": data.get("multipleOf", None),
            "default": data.get("default", NO_DEFAULT),
        }
        return Float(**kwargs)

    elif type_string == "integer":
        kwargs = {
            "allow_null": allow_null,
            "minimum": data.get("minimum", None),
            "maximum": data.get("maximum", None),
            "exclusive_minimum": data.get("exclusiveMinimum", None),
            "exclusive_maximum": data.get("exclusiveMaximum", None),
            "multiple_of": data.get("multipleOf", None),
            "default": data.get("default", NO_DEFAULT),
        }
        return Integer(**kwargs)

    elif type_string == "string":
        min_length = data.get("minLength", 0)
        kwargs = {
            "allow_null": allow_null,
            "allow_blank": min_length == 0,
            "min_length": min_length if min_length > 1 else None,
            "max_length": data.get("maxLength", None),
            "format": data.get("format"),
            "pattern": data.get("pattern", None),
            "default": data.get("default", NO_DEFAULT),
        }
        return String(**kwargs)

    elif type_string == "boolean":
        kwargs = {
            "allow_null": allow_null,
            "default": data.get("default", NO_DEFAULT)
        }
        return Boolean(**kwargs)

    elif type_string == "array":
        items = data.get("items", None)
        if items is None:
            items_argument: typing.Union[None, Field,
                                         typing.List[Field]] = None
        elif isinstance(items, list):
            items_argument = [
                from_json_schema(item, definitions=definitions)
                for item in items
            ]
        else:
            items_argument = from_json_schema(items, definitions=definitions)

        additional_items = data.get("additionalItems", None)
        if additional_items is None:
            additional_items_argument: typing.Union[bool, Field] = True
        elif isinstance(additional_items, bool):
            additional_items_argument = additional_items
        else:
            additional_items_argument = from_json_schema(
                additional_items, definitions=definitions)

        kwargs = {
            "allow_null": allow_null,
            "min_items": data.get("minItems", 0),
            "max_items": data.get("maxItems", None),
            "additional_items": additional_items_argument,
            "items": items_argument,
            "unique_items": data.get("uniqueItems", False),
            "default": data.get("default", NO_DEFAULT),
        }
        return Array(**kwargs)

    elif type_string == "object":
        properties = data.get("properties", None)
        if properties is None:
            properties_argument: typing.Optional[typing.Dict[str,
                                                             Field]] = None
        else:
            properties_argument = {
                key: from_json_schema(value, definitions=definitions)
                for key, value in properties.items()
            }

        pattern_properties = data.get("patternProperties", None)
        if pattern_properties is None:
            pattern_properties_argument: typing.Optional[typing.Dict[
                str, Field]] = (None)
        else:
            pattern_properties_argument = {
                key: from_json_schema(value, definitions=definitions)
                for key, value in pattern_properties.items()
            }

        additional_properties = data.get("additionalProperties", None)
        if additional_properties is None:
            additional_properties_argument: typing.Union[None, bool,
                                                         Field] = (None)
        elif isinstance(additional_properties, bool):
            additional_properties_argument = additional_properties
        else:
            additional_properties_argument = from_json_schema(
                additional_properties, definitions=definitions)

        property_names = data.get("propertyNames", None)
        if property_names is None:
            property_names_argument: typing.Optional[Field] = None
        else:
            property_names_argument = from_json_schema(property_names,
                                                       definitions=definitions)

        kwargs = {
            "allow_null": allow_null,
            "properties": properties_argument,
            "pattern_properties": pattern_properties_argument,
            "additional_properties": additional_properties_argument,
            "property_names": property_names_argument,
            "min_properties": data.get("minProperties", None),
            "max_properties": data.get("maxProperties", None),
            "required": data.get("required", None),
            "default": data.get("default", NO_DEFAULT),
        }
        return Object(**kwargs)

    assert False, f"Invalid argument type_string={type_string!r}"  # pragma: no cover
JSONSchema = (
    Object(
        properties={
            "$ref":
            String(),
            "type":
            String() | Array(items=String()),
            "enum":
            Array(unique_items=True, min_items=1),
            "definitions":
            Object(additional_properties=Reference("JSONSchema",
                                                   definitions=definitions)),
            # String
            "minLength":
            Integer(minimum=0),
            "maxLength":
            Integer(minimum=0),
            "pattern":
            String(format="regex"),
            "format":
            String(),
            # Numeric
            "minimum":
            Number(),
            "maximum":
            Number(),
            "exclusiveMinimum":
            Number(),
            "exclusiveMaximum":
            Number(),
Exemple #9
0
def test_array():
    validator = Array()
    value, error = validator.validate_or_error([])
    assert value == []

    validator = Array()
    value, error = validator.validate_or_error(None)
    assert error == ValidationError(text="May not be null.", code="null")

    validator = Array()
    value, error = validator.validate_or_error(123)
    assert error == ValidationError(text="Must be an array.", code="type")

    validator = Array(allow_null=True)
    value, error = validator.validate_or_error(None)
    assert value is None
    assert error is None

    validator = Array(min_items=1)
    value, error = validator.validate_or_error([])
    assert error == ValidationError(text="Must not be empty.", code="empty")

    validator = Array(min_items=1)
    value, error = validator.validate_or_error([1])
    assert value == [1]

    validator = Array(min_items=2)
    value, error = validator.validate_or_error([])
    assert error == ValidationError(text="Must have at least 2 items.",
                                    code="min_items")

    validator = Array(min_items=2)
    value, error = validator.validate_or_error([1, 2])
    assert value == [1, 2]

    validator = Array(max_items=2)
    value, error = validator.validate_or_error([])
    assert value == []

    validator = Array(max_items=2)
    value, error = validator.validate_or_error([1, 2, 3])
    assert error == ValidationError(text="Must have no more than 2 items.",
                                    code="max_items")

    validator = Array(exact_items=2)
    value, error = validator.validate_or_error([1, 2])
    assert value == [1, 2]

    validator = Array(exact_items=2)
    value, error = validator.validate_or_error([1, 2, 3])
    assert error == ValidationError(text="Must have 2 items.",
                                    code="exact_items")

    validator = Array(items=Integer())
    value, error = validator.validate_or_error(["1", 2, "3"])
    assert value == [1, 2, 3]

    validator = Array(items=Integer())
    value, error = validator.validate_or_error(["a", 2, "c"])
    assert dict(error) == {0: "Must be a number.", 2: "Must be a number."}

    validator = Array(items=[String(), Integer()])
    value, error = validator.validate_or_error(["a", "b", "c"])
    assert error == ValidationError(text="Must have 2 items.",
                                    code="exact_items")

    validator = Array(items=[String(), Integer()])
    value, error = validator.validate_or_error(["a", "123"])
    assert value == ["a", 123]

    validator = Array(items=[String(), Integer()], additional_items=Integer())
    value, error = validator.validate_or_error(["a", "123", "456"])
    assert value == ["a", 123, 456]

    validator = Array(items=String(), unique_items=True)
    value, error = validator.validate_or_error(["a", "b"])
    assert value == ["a", "b"]

    validator = Array(items=String(), unique_items=True)
    value, error = validator.validate_or_error(["a", "a"])
    assert dict(error) == {1: "Items must be unique."}

    validator = Array(items=[String(), Integer(), Boolean()], min_items=1)
    value, error = validator.validate_or_error(["a"])
    assert value == ["a"]

    validator = Array(items=[String(), Integer(), Boolean()], min_items=1)
    value, error = validator.validate_or_error(["a", "123"])
    assert value == ["a", 123]

    validator = Array(items=[String(), Integer(), Boolean()], min_items=1)
    value, error = validator.validate_or_error([])
    assert error == ValidationError(text="Must not be empty.", code="empty")

    validator = Array(items=[String(), Integer(), Boolean()], min_items=2)
    value, error = validator.validate_or_error([])
    assert error == ValidationError(text="Must have at least 2 items.",
                                    code="min_items")
Exemple #10
0
def test_object():
    validator = Object()
    value, error = validator.validate_or_error({})
    assert value == {}

    validator = Object()
    value, error = validator.validate_or_error(None)
    assert dict(error) == {"": "May not be null."}

    validator = Object()
    value, error = validator.validate_or_error(123)
    assert dict(error) == {"": "Must be an object."}

    validator = Object()
    value, error = validator.validate_or_error({1: 123})
    assert dict(error) == {"": "All object keys must be strings."}

    validator = Object(allow_null=True)
    value, error = validator.validate_or_error(None)
    assert value is None
    assert error is None

    validator = Object(min_properties=1)
    value, error = validator.validate_or_error({})
    assert dict(error) == {"": "Must not be empty."}

    validator = Object(min_properties=1)
    value, error = validator.validate_or_error({"a": 1})
    assert value == {"a": 1}

    validator = Object(min_properties=2)
    value, error = validator.validate_or_error({})
    assert dict(error) == {"": "Must have at least 2 properties."}

    validator = Object(min_properties=2)
    value, error = validator.validate_or_error({"a": 1, "b": 2})
    assert value == {"a": 1, "b": 2}

    validator = Object(max_properties=2)
    value, error = validator.validate_or_error({})
    assert value == {}

    validator = Object(max_properties=2)
    value, error = validator.validate_or_error({"a": 1, "b": 2, "c": 3})
    assert dict(error) == {"": "Must have no more than 2 properties."}

    validator = Object(required=["example"])
    value, error = validator.validate_or_error({"example": 123})
    assert value == {"example": 123}

    validator = Object(required=["example"])
    value, error = validator.validate_or_error({})
    assert dict(error) == {"example": "This field is required."}

    validator = Object(properties={"example": Integer()})
    value, error = validator.validate_or_error({"example": "123"})
    assert value == {"example": 123}

    validator = Object(properties={"example": Integer()})
    value, error = validator.validate_or_error({"example": "abc"})
    assert dict(error) == {"example": "Must be a number."}

    validator = Object(pattern_properties={"^x-.*$": Integer()})
    value, error = validator.validate_or_error({"x-example": "123"})
    assert value == {"x-example": 123}

    validator = Object(pattern_properties={"^x-.*$": Integer()})
    value, error = validator.validate_or_error({"x-example": "abc"})
    assert dict(error) == {"x-example": "Must be a number."}

    validator = Object(properties={"example": Integer(default=0)})
    value, error = validator.validate_or_error({"example": "123"})
    assert value == {"example": 123}

    validator = Object(properties={"example": Integer(default=0)})
    value, error = validator.validate_or_error({})
    assert value == {"example": 0}

    validator = Object(additional_properties=False)
    value, error = validator.validate_or_error({"example": "123"})
    assert dict(error) == {"example": "Invalid property name."}

    validator = Object(additional_properties=True)
    value, error = validator.validate_or_error({"example": "abc"})
    assert value == {"example": "abc"}

    validator = Object(additional_properties=None)
    value, error = validator.validate_or_error({"example": "abc"})
    assert value == {}

    validator = Object(properties=Integer())
    value, error = validator.validate_or_error({"example": "123"})
    assert value == {"example": 123}

    validator = Object(properties=Integer())
    value, error = validator.validate_or_error({"example": "abc"})
    assert dict(error) == {"example": "Must be a number."}

    validator = Object(properties={"example": Integer()})
    value, error = validator.validate_or_error({"example": "123"})
    assert value == {"example": 123}

    validator = Object(properties={"example": Integer()})
    value, error = validator.validate_or_error({"example": "abc"})
    assert dict(error) == {"example": "Must be a number."}

    validator = Object(additional_properties=Object(
        additional_properties=Integer()))
    value, error = validator.validate_or_error({"example": {"nested": "123"}})
    assert value == {"example": {"nested": 123}}

    validator = Object(additional_properties=Object(
        additional_properties=Integer()))
    value, error = validator.validate_or_error({"example": {"nested": "abc"}})
    assert dict(error) == {"example": {"nested": "Must be a number."}}
Exemple #11
0
def test_integer():
    validator = Integer()
    value, error = validator.validate_or_error(123)
    assert value == 123

    validator = Integer()
    value, error = validator.validate_or_error("123")
    assert value == 123

    validator = Integer()
    value, error = validator.validate_or_error(123.0)
    assert value == 123

    validator = Integer()
    value, error = validator.validate_or_error("123.0")
    assert value == 123

    validator = Integer()
    value, error = validator.validate_or_error(None)
    assert error == ValidationError(text="May not be null.", code="null")

    validator = Integer()
    value, error = validator.validate_or_error("abc")
    assert error == ValidationError(text="Must be a number.", code="type")

    validator = Integer()
    value, error = validator.validate_or_error(True)
    assert error == ValidationError(text="Must be a number.", code="type")

    validator = Integer()
    value, error = validator.validate_or_error(123.1)
    assert error == ValidationError(text="Must be an integer.", code="integer")

    validator = Integer()
    value, error = validator.validate_or_error(float("inf"))
    assert error == ValidationError(text="Must be an integer.", code="integer")

    validator = Integer()
    value, error = validator.validate_or_error(float("nan"))
    assert error == ValidationError(text="Must be an integer.", code="integer")

    validator = Integer()
    value, error = validator.validate_or_error("123", strict=True)
    assert error == ValidationError(text="Must be a number.", code="type")

    validator = Integer(allow_null=True)
    value, error = validator.validate_or_error(None)
    assert value is None
    assert error is None

    validator = Integer(allow_null=True)
    value, error = validator.validate_or_error("")
    assert value is None
    assert error is None

    validator = Integer(allow_null=True)
    value, error = validator.validate_or_error("", strict=True)
    assert error == ValidationError(text="Must be a number.", code="type")

    validator = Integer(maximum=10)
    value, error = validator.validate_or_error(100)
    assert error == ValidationError(text="Must be less than or equal to 10.",
                                    code="maximum")

    validator = Integer(maximum=10)
    value, error = validator.validate_or_error(10)
    assert value == 10

    validator = Integer(minimum=3)
    value, error = validator.validate_or_error(1)
    assert error == ValidationError(text="Must be greater than or equal to 3.",
                                    code="minimum")

    validator = Integer(minimum=3)
    value, error = validator.validate_or_error(3)
    assert value == 3

    validator = Integer(exclusive_maximum=10)
    value, error = validator.validate_or_error(10)
    assert error == ValidationError(text="Must be less than 10.",
                                    code="exclusive_maximum")

    validator = Integer(exclusive_minimum=3)
    value, error = validator.validate_or_error(3)
    assert error == ValidationError(text="Must be greater than 3.",
                                    code="exclusive_minimum")

    validator = Integer(multiple_of=10)
    value, error = validator.validate_or_error(5)
    assert error == ValidationError(text="Must be a multiple of 10.",
                                    code="multiple_of")
Exemple #12
0
def test_validation_error_is_hashable():
    validator = Integer()
    _, error = validator.validate_or_error("abc")
    hash(error)