Source code for typedpy.fields.numbers

from decimal import Decimal

from typedpy.structures import ImmutableField, Field
from typedpy.commons import wrap_val


[docs]class Number(Field): """ Base class for numerical fields. Based on Json schema draft4. Accepts and int or float. Arguments: multipleOf(int): optional The number must be a multiple of this number minimum(int or float): optional value cannot be lower than this number maximum(int or float): optional value cannot be higher than this number exclusiveMaximum(bool): optional marks the maximum threshold above as exclusive """ def __init__( self, *args, multiplesOf=None, minimum=None, maximum=None, exclusiveMaximum=None, **kwargs, ): self.multiplesOf = multiplesOf self.minimum = minimum self.maximum = maximum self.exclusiveMaximum = exclusiveMaximum super().__init__(*args, **kwargs) def _validate_static(self, value): def is_number(val): return isinstance(val, (float, int, Decimal)) def err_prefix(): return f"{self._name}: Got {wrap_val(value)}; " if self._name else "" if not is_number(value): raise TypeError(f"{err_prefix()}Expected a number") if ( isinstance(self.multiplesOf, float) and int(value / self.multiplesOf) != value / self.multiplesOf or isinstance(self.multiplesOf, int) and value % self.multiplesOf ): raise ValueError( f"{err_prefix()}Expected a a multiple of {self.multiplesOf}" ) if (is_number(self.minimum)) and self.minimum > value: raise ValueError(f"{err_prefix()}Expected a minimum of {self.minimum}") if is_number(self.maximum): if self.exclusiveMaximum and self.maximum == value: raise ValueError( f"{err_prefix()}Expected a maximum of less than {self.maximum}" ) if self.maximum < value: raise ValueError(f"{err_prefix()}Expected a maximum of {self.maximum}") def _validate(self, value): Number._validate_static(self, value) def __set__(self, instance, value): if not getattr(instance, "_skip_validation", False) and not getattr( instance, "_trust_supplied_values", False ): self._validate(value) super().__set__(instance, value)
[docs]class Positive(Number): """ An extension of :class:`Number`. Requires the number to be positive """ def __set__(self, instance, value): if value <= 0: raise ValueError(f"{self._name}: Got {value}; Expected a positive number") super().__set__(instance, value)
[docs]class NonPositive(Number): """ An extension of :class:`Number`. Requires the number to be negative or 0 """ def __set__(self, instance, value): if value > 0: raise ValueError( f"{self._name}: Got {value}; Expected a negative number or 0" ) super().__set__(instance, value)
[docs]class Negative(Number): """ An extension of :class:`Number`. Requires the number to be negative """ def __set__(self, instance, value): if value >= 0: raise ValueError(f"{self._name}: Got {value}; Expected a negative number") super().__set__(instance, value)
[docs]class NonNegative(Number): """ An extension of :class:`Number`. Requires the number to be positive or 0 """ def __set__(self, instance, value): if value < 0: raise ValueError( f"{self._name}: Got {value}; Expected a positive number or 0" ) super().__set__(instance, value)
[docs]class ImmutableNumber(ImmutableField, Number): """ An immutable version of :class:`Number` """ pass