Source code for statham.schema.validation.array
from typing import Any, cast, Optional
from statham.schema.exceptions import ValidationError
from statham.schema.helpers import remove_duplicates
from statham.schema.validation.base import Validator, replace_bool
[docs]class MinItems(Validator):
"""Validate that arrays have a minimum number of items."""
types = (list,)
keywords = ("minItems",)
message = "Must contain at least {minItems} items."
def _validate(self, value: Any):
if len(value) < self.params["minItems"]:
raise ValidationError
[docs]class MaxItems(Validator):
"""Validate that arrays have a maximum number of items."""
types = (list,)
keywords = ("maxItems",)
message = "Must contain fewer than {maxItems} items."
def _validate(self, value: Any):
if len(value) > self.params["maxItems"]:
raise ValidationError
[docs]class AdditionalItems(Validator):
"""Validate array items not covered by the ``"items"`` keyword.
Only relevant when using "tuple" style ``"items"``.
"""
types = (list,)
keywords = ("items", "additionalItems")
message = "Must not contain additional items. Accepts: {items}"
def _validate(self, value: Any):
if not isinstance(self.params["items"], list):
return
if len(value) <= len(self.params["items"]):
return
if self.params["additionalItems"]:
return
raise ValidationError
[docs]class UniqueItems(Validator):
"""Validate that array items are unique."""
types = (list,)
keywords = ("uniqueItems",)
message = "Must not contain duplicates."
@classmethod
def from_element(cls, element) -> Optional["UniqueItems"]:
validator: Optional[UniqueItems] = cast(
Optional[UniqueItems], super().from_element(element)
)
if validator and validator.params["uniqueItems"] is False:
return None
return validator
def _validate(self, value: Any):
# Once again, Cpython's 1 in [True] nightmare.
aliased_value = list(map(replace_bool, value))
length = len(aliased_value)
try:
# Try the hashable approach
if len(set(aliased_value)) == length:
return
except TypeError:
# Long version
if len(remove_duplicates(aliased_value)) == length:
return
raise ValidationError
[docs]class Contains(Validator):
"""Validate that at least one array item matches a schema."""
types = (list,)
keywords = ("contains",)
message = "Must contain one element matching {contains}."
def _validate(self, value: Any):
for sub_value in value:
try:
_ = self.params["contains"](sub_value)
return
except (TypeError, ValidationError):
continue
raise ValidationError