Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def validate(self, value: typing.Any, *, strict: bool = False) -> typing.Any:
if value is None and self.allow_null:
return None
elif value is None:
raise self.validation_error("null")
elif value not in Uniqueness([key for key, value in self.choices]):
if value == "":
if self.allow_null and not strict:
return None
raise self.validation_error("required")
raise self.validation_error("choice")
return value
class Object(Field):
errors = {
"type": "Must be an object.",
"null": "May not be null.",
"invalid_key": "All object keys must be strings.",
"required": "This field is required.",
"invalid_property": "Invalid property name.",
"empty": "Must not be empty.",
"max_properties": "Must have no more than {max_properties} properties.",
"min_properties": "Must have at least {min_properties} properties.",
}
def __init__(
self,
*,
properties: typing.Dict[str, Field] = None,
pattern_properties: typing.Dict[str, Field] = None,
if isinstance(value, str):
value = value.lower()
if self.allow_null and value in self.coerce_null_values:
return None
try:
value = self.coerce_values[value]
except (KeyError, TypeError):
raise self.validation_error("type")
return value
class Choice(Field):
errors = {
"null": "May not be null.",
"required": "This field is required.",
"choice": "Not a valid choice.",
}
def __init__(
self,
*,
choices: typing.Sequence[typing.Union[str, typing.Tuple[str, str]]] = None,
**kwargs: typing.Any,
) -> None:
super().__init__(**kwargs)
self.choices = [
(choice if isinstance(choice, (tuple, list)) else (choice, choice))
for choice in choices or []
def __or__(self, other: "Field") -> "Union":
if isinstance(self, Union):
any_of = self.any_of
else:
any_of = [self]
if isinstance(other, Union):
any_of += other.any_of
else:
any_of += [other]
return Union(any_of=any_of)
class String(Field):
errors = {
"type": "Must be a string.",
"null": "May not be null.",
"blank": "Must not be blank.",
"max_length": "Must have no more than {max_length} characters.",
"min_length": "Must have at least {min_length} characters.",
"pattern": "Must match the pattern /{pattern}/.",
"format": "Must be a valid {format}.",
}
def __init__(
self,
*,
allow_blank: bool = False,
trim_whitespace: bool = True,
max_length: int = None,
self.choice_items = [(choice, choice) for choice in choices]
else:
self.choice_items = list(choices)
self.choice_dict = dict(self.choice_items)
def validate_value(self, value, strict=False):
if value is None and self.allow_null:
return None
elif value is None:
return self.error("null")
elif value not in self.choice_dict:
return self.error("choice")
return value
class Object(Field):
errors = {
"type": "Must be an object.",
"null": "May not be null.",
"invalid_key": "All object keys must be strings.",
"required": "This field is required.",
"invalid_property": "Invalid property name.",
"empty": "Must not be empty.",
"max_properties": "Must have no more than {max_properties} properties.",
"min_properties": "Must have at least {min_properties} properties.",
}
def __init__(
self,
properties=None,
pattern_properties=None,
additional_properties=True,
class Date(String):
def __init__(self, **kwargs: typing.Any) -> None:
super().__init__(format="date", **kwargs)
class Time(String):
def __init__(self, **kwargs: typing.Any) -> None:
super().__init__(format="time", **kwargs)
class DateTime(String):
def __init__(self, **kwargs: typing.Any) -> None:
super().__init__(format="datetime", **kwargs)
class Union(Field):
errors = {"null": "May not be null.", "union": "Did not match any valid type."}
def __init__(self, any_of: typing.List[Field], **kwargs: typing.Any):
super().__init__(**kwargs)
self.any_of = any_of
if any([child.allow_null for child in any_of]):
self.allow_null = True
def validate(self, value: typing.Any, strict: bool = False) -> typing.Any:
if value is None and self.allow_null:
return None
elif value is None:
raise self.validation_error("null")
candidate_errors = []
class Integer(Number):
numeric_type = int
class Float(Number):
numeric_type = float
class Decimal(Number):
numeric_type = decimal.Decimal
def serialize(self, obj: typing.Any) -> typing.Any:
return None if obj is None else float(obj)
class Boolean(Field):
errors = {"type": "Must be a boolean.", "null": "May not be null."}
coerce_values = {
"true": True,
"false": False,
"on": True,
"off": False,
"1": True,
"0": False,
"": False,
1: True,
0: False,
}
coerce_null_values = {"", "null", "none"}
def validate(self, value: typing.Any, *, strict: bool = False) -> typing.Any:
if value is None and self.allow_null:
messages = error.messages()
if (
len(messages) != 1
or messages[0].code != "type"
or messages[0].index
):
candidate_errors.append(error)
if len(candidate_errors) == 1:
# If exactly one child was of the correct type, then we can use
# the error from the child.
raise candidate_errors[0]
raise self.validation_error("union")
class Any(Field):
"""
Always matches.
"""
def validate(self, value: typing.Any, strict: bool = False) -> typing.Any:
return value
class Const(Field):
"""
Only ever matches the given given value.
"""
errors = {"only_null": "Must be null.", "const": "Must be the value '{const}'."}
def __init__(self, const: typing.Any, **kwargs: typing.Any):
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),
}
# The following fields are required for complete JSON schema support,
# but are undocumented as we don't recommend using them directly.
import typing
from typesystem.fields import Any, Field
class NeverMatch(Field):
"""
Doesn't ever match.
"""
errors = {"never": "This never validates."}
def __init__(self, **kwargs: typing.Any) -> None:
assert "allow_null" not in kwargs
super().__init__(**kwargs)
def validate(self, value: typing.Any, strict: bool = False) -> typing.Any:
raise self.validation_error("never")
class OneOf(Field):
"""
"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
)