Source code for kim.pipelines.numeric

# kim/pipelines/numeric.py
# Copyright (C) 2014-2015 the Kim authors and contributors
# <see AUTHORS file>
#
# This module is part of Kim and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php

from decimal import Decimal, InvalidOperation

from .base import pipe, is_valid_choice
from .marshaling import MarshalPipeline
from .serialization import SerializePipeline


@pipe()
[docs]def is_valid_integer(session): """Pipe used to determine if a value can be coerced to an int :param session: Kim pipeline session instance """ try: session.data = int(session.data) except TypeError: raise session.field.invalid(error_type='type_error') except ValueError: raise session.field.invalid(error_type='type_error') return session.data
@pipe()
[docs]def bounds_check(session): """Pipe used to determine if a value is within the min and max bounds on the field :param session: Kim pipeline session instance """ max_ = session.field.opts.max min_ = session.field.opts.min if max_ is not None and session.data > max_: raise session.field.invalid(error_type='out_of_bounds') if min_ is not None and session.data < min_: raise session.field.invalid(error_type='out_of_bounds') return session.data
[docs]class IntegerMarshalPipeline(MarshalPipeline): """IntegerMarshalPipeline .. seealso:: :func:`kim.pipelines.numeric.is_valid_integer` :func:`kim.pipelines.base.is_valid_choice` :func:`kim.pipelines.numeric.bounds_check` :class:`kim.pipelines.marshaling.MarshalPipeline` """ validation_pipes = \ [is_valid_integer, is_valid_choice, bounds_check] + MarshalPipeline.validation_pipes
[docs]class IntegerSerializePipeline(SerializePipeline): """IntegerSerializePipeline .. seealso:: :class:`kim.pipelines.serialization.SerializePipeline` """ pass
@pipe()
[docs]def is_valid_decimal(session): """Pipe used to determine if a value can be coerced to a Decimal :param session: Kim pipeline session instance """ try: return Decimal(session.data) except InvalidOperation: raise session.field.invalid(error_type='type_error')
@pipe()
[docs]def coerce_to_decimal(session): """Coerce str representation of a decimal into a valid Decimal object. """ decimals = session.field.opts.precision precision = Decimal('0.' + '0' * (decimals - 1) + '1') session.data = Decimal(session.data).quantize(precision) return session.data
[docs]class DecimalMarshalPipeline(MarshalPipeline): """DecimalMarshalPipeline .. seealso:: :func:`kim.pipelines.numeric.is_valid_decimal` :func:`kim.pipelines.numeric.coerce_to_decimal` :class:`kim.pipelines.marshaling.MarshalPipeline` """ validation_pipes = [is_valid_decimal, bounds_check] + MarshalPipeline.validation_pipes process_pipes = [coerce_to_decimal] + MarshalPipeline.process_pipes # TODO(mike) This should probably move to base
@pipe()
[docs]def to_string(session): """coerce decimal value into str so it's valid for json """ if session.data is not None: session.data = str(session.data) return session.data
[docs]class DecimalSerializePipeline(SerializePipeline): """DecimalSerializePipeline .. seealso:: :func:`kim.pipelines.numeric.coerce_to_decimal` :func:`kim.pipelines.numeric.to_string` :class:`kim.pipelines.serialization.SerializePipeline` """ process_pipes = [coerce_to_decimal, to_string] + SerializePipeline.process_pipes
@pipe() def is_valid_float(session): """Pipe used to determine if a value can be coerced to a Float :param session: Kim pipeline session instance """ try: return float(session.data) except (InvalidOperation, ValueError): raise session.field.invalid(error_type='type_error') @pipe() def coerce_to_float(session): """Coerce str representation of a decimal into a valid Float object. """ decimals = session.field.opts.precision session.data = round(float(session.data), decimals) return session.data class FloatMarshalPipeline(MarshalPipeline): """FloatMarshalPipeline .. seealso:: :func:`kim.pipelines.numeric.is_valid_decimal` :func:`kim.pipelines.numeric.coerce_to_decimal` :class:`kim.pipelines.marshaling.MarshalPipeline` """ validation_pipes = [is_valid_float, bounds_check] + MarshalPipeline.validation_pipes process_pipes = [coerce_to_float] + MarshalPipeline.process_pipes class FloatSerializePipeline(SerializePipeline): """FloatSerializePipeline .. seealso:: :func:`kim.pipelines.numeric.coerce_to_float` :func:`kim.pipelines.numeric.to_string` :class:`kim.pipelines.serialization.SerializePipeline` """ process_pipes = [coerce_to_float, to_string] + SerializePipeline.process_pipes