import decimal from math import isfinite from apistar import validators class Decimal(validators.NumericType): numeric_type = decimal.Decimal def validate(self, value, definitions=None, allow_coerce=False): if value is None and self.allow_null: return None elif value is None: self.error('null') elif isinstance(value, bool): self.error('type') elif self.numeric_type is int and isinstance(value, float) and not value.is_integer(): self.error('integer') elif not isinstance(value, (int, float, decimal.Decimal)) and not allow_coerce: self.error('type') elif isinstance(value, float) and not isfinite(value): self.error('finite') try: value = self.numeric_type(value) except (TypeError, ValueError): self.error('type') if self.enum is not None: if value not in self.enum: if len(self.enum) == 1: self.error('exact') self.error('enum') if self.minimum is not None: if self.exclusive_minimum: if value <= self.minimum: self.error('exclusive_minimum') else: if value < self.minimum: self.error('minimum') if self.maximum is not None: if self.exclusive_maximum: if value >= self.maximum: self.error('exclusive_maximum') else: if value > self.maximum: self.error('maximum') if self.multiple_of is not None: if isinstance(self.multiple_of, float): if not (value * (1 / self.multiple_of)).is_integer(): self.error('multiple_of') else: if value % self.multiple_of: self.error('multiple_of') return value