Source code for paramtools.contrib.validate

import datetime

import numpy as np
from marshmallow import (
    validate as marshmallow_validate,
    ValidationError,
    fields as marshmallow_fields,
)

from paramtools import utils


[docs]class Range(marshmallow_validate.Range): """ Implements "range" :ref:`spec:Validator object`. """ error = "" def __init__( self, min=None, max=None, error_min=None, error_max=None, step=None ): self.min = min self.max = max self.error_min = error_min self.error_max = error_max self.step = step or 1 # default to 1 def _format_error(self, value, message): return message.format(input=value, min=self.min, max=self.max) def __call__(self, value): if value is None: return value if not isinstance(value, list): value_list = [value] else: value_list = utils.ravel(value) for val in value_list: if self.min is not None and val < self.min: message = self.error_min or self.message_min raise ValidationError(self._format_error(value, message)) if self.max is not None and val > self.max: message = self.error_max or self.message_max raise ValidationError(self._format_error(value, message)) return value def mesh(self): # make np.arange inclusive. max_ = self.max + self.step arr = np.arange(self.min, max_, self.step) return arr[arr <= self.max].tolist()
[docs]class DateRange(Range): """ Implements "date_range" :ref:`spec:Validator object`. Behaves like ``Range``, except values are ensured to be ``datetime.date`` type and ``mesh`` has special logic for dates. """ def __init__( self, min=None, max=None, error_min=None, error_max=None, step=None ): if min is not None and not isinstance(min, datetime.date): min = marshmallow_fields.Date()._deserialize(min, None, None) if max is not None and not isinstance(max, datetime.date): max = marshmallow_fields.Date()._deserialize(max, None, None) super().__init__(min, max, error_min, error_max) if step is None: # set to to default step. step = {"days": 1} # check against allowed args: # https://docs.python.org/3/library/datetime.html#datetime.timedelta timedelta_args = { "days", "seconds", "microseconds", "milliseconds", "minutes", "hours", "weeks", } assert len(set(step.keys()) - timedelta_args) == 0 self.step = datetime.timedelta(**step) def mesh(self): # make np.arange inclusive. max_ = self.max + self.step arr = np.arange(self.min, max_, self.step, dtype=datetime.date) return arr[arr <= self.max].tolist()
[docs]class OneOf(marshmallow_validate.OneOf): """ Implements "choice" :ref:`spec:Validator object`. """ def __call__(self, value): if value is None: return value if not isinstance(value, list): values = [value] else: values = utils.ravel(value) for val in values: try: if val not in self.choices: raise ValidationError(self._format_error(val)) except TypeError: raise ValidationError(self._format_error(val)) return value def mesh(self): return self.choices