a validator designed for hstore to requirerestrict keys messages missingkeys some keys were missing keyss extrakeys some unknown keys were provided keyss strict false def initself keys strictfalse messagesnone self keys setkeys self strict strict if messages is not none self messages self messages messages def callself value keys setvalue missingkeys self keys keys if missingkeys raise validationerror self messagesmissingkeys codemissingkeys paramskeys joinmissingkeys if self strict extrakeys keys self keys if extrakeys raise validationerror self messagesextrakeys codeextrakeys paramskeys joinextrakeys def eqself other return isinstanceother self class and self keys other keys and self messages other messages and self strict other strict class rangemaxvaluevalidatormaxvaluevalidator def compareself a b return a upper is none or a upper b message ensure that the upper bound of the range is not greater than limitvalues class rangeminvaluevalidatorminvaluevalidator def compareself a b return a lower is none or a lower b message ensure that the lower bound of the range is not less than limitvalues a validator designed for hstore to require restrict keys
from django.core.exceptions import ValidationError
from django.core.validators import (
    MaxLengthValidator,
    MaxValueValidator,
    MinLengthValidator,
    MinValueValidator,
)
from django.utils.deconstruct import deconstructible
from django.utils.translation import gettext_lazy as _
from django.utils.translation import ngettext_lazy


class ArrayMaxLengthValidator(MaxLengthValidator):
    message = ngettext_lazy(
        "List contains %(show_value)d item, it should contain no more than "
        "%(limit_value)d.",
        "List contains %(show_value)d items, it should contain no more than "
        "%(limit_value)d.",
        "show_value",
    )


class ArrayMinLengthValidator(MinLengthValidator):
    message = ngettext_lazy(
        "List contains %(show_value)d item, it should contain no fewer than "
        "%(limit_value)d.",
        "List contains %(show_value)d items, it should contain no fewer than "
        "%(limit_value)d.",
        "show_value",
    )


@deconstructible
class KeysValidator:
    

    messages = {
        "missing_keys": _("Some keys were missing: %(keys)s"),
        "extra_keys": _("Some unknown keys were provided: %(keys)s"),
    }
    strict = False

    def __init__(self, keys, strict=False, messages=None):
        self.keys = set(keys)
        self.strict = strict
        if messages is not None:
            self.messages = {**self.messages, **messages}

    def __call__(self, value):
        keys = set(value)
        missing_keys = self.keys - keys
        if missing_keys:
            raise ValidationError(
                self.messages["missing_keys"],
                code="missing_keys",
                params={"keys": ", ".join(missing_keys)},
            )
        if self.strict:
            extra_keys = keys - self.keys
            if extra_keys:
                raise ValidationError(
                    self.messages["extra_keys"],
                    code="extra_keys",
                    params={"keys": ", ".join(extra_keys)},
                )

    def __eq__(self, other):
        return (
            isinstance(other, self.__class__)
            and self.keys == other.keys
            and self.messages == other.messages
            and self.strict == other.strict
        )


class RangeMaxValueValidator(MaxValueValidator):
    def compare(self, a, b):
        return a.upper is None or a.upper > b

    message = _(
        "Ensure that the upper bound of the range is not greater than %(limit_value)s."
    )


class RangeMinValueValidator(MinValueValidator):
    def compare(self, a, b):
        return a.lower is None or a.lower < b

    message = _(
        "Ensure that the lower bound of the range is not less than %(limit_value)s."
    )