Source code for aiohttp_json_api.fields.trafarets
"""
Additional trafaret's fields
============================
"""
import decimal
import numbers
import trafaret as t
[docs]class DecimalTrafaret(t.Float):
convertable = t.str_types + (numbers.Real, int)
value_type = decimal.Decimal
def __init__(self, places=None, rounding=None, allow_nan=False, **kwargs):
self.allow_nan = allow_nan
self.places = decimal.Decimal((0, (1,), -places)) \
if places is not None else None
self.rounding = rounding
super(DecimalTrafaret, self).__init__(**kwargs)
def _converter(self, value):
if not isinstance(value, self.convertable):
self._failure(f'value is not {self.value_type.__name__}',
value=value)
try:
return self.value_type(value)
except (ValueError, decimal.InvalidOperation):
self._failure(
f"value can't be converted to {self.value_type.__name__}",
value=value
)
[docs] def check_and_return(self, data):
data = super(DecimalTrafaret, self).check_and_return(data)
if self.allow_nan:
if data.is_nan():
return decimal.Decimal('NaN') # avoid sNaN, -sNaN and -NaN
else:
if data.is_nan() or data.is_infinite():
self._failure('Special numeric values are not permitted.',
value=data)
if self.places is not None and data.is_finite():
try:
data = data.quantize(self.places, rounding=self.rounding)
except decimal.InvalidOperation:
self._failure('Decimal can not be properly quantized.',
value=data)
return data