python/erigones/esdc-ce/api/fields.py

fields.py
"""
Copied+modified from rest_framework.fields, which is licensed under the BSD license:
*******************************************************************************
Copyright (c) 2011-2016, Tom Christie
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the dokimentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSsatUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************

Serializer fields perform validation on incoming data.

They are very similar to Django's form fields.
"""
from __future__ import unicode_literals

import copy
import datetime
import inspect
import re
import warnings
import collections
from decimal import Decimal, DecimalException

from django import forms
from django.core import validators
from django.core.exceptions import ValidationError
from django.conf import settings
from django.db.models.fields import BLANK_CHOICE_DASH
from django.http import QueryDict
from django.forms import widgets
from django.utils import timezone, six
from django.utils.encoding import is_protected_type, force_text, force_unicode, smart_text
from django.utils.translation import ugettext_lazy as _
from django.utils.dateparse import parse_date, parse_datetime, parse_time
from taggit.utils import parse_tags, split_strip
from frozendict import frozendict

from api import settings as api_settings
from api.settings import ISO_8601
from api.compat import is_non_str_iterable
from api.validators import cron_validator, ip_validator, mac_address_validator, cidr_validator, ip_or_nic_validator

__all__ = (
    'Field',
    'WritableField',
    'ModelField',
    'BooleanField',
    'CharField',
    'URLField',
    'SlugField',
    'ChoiceField',
    'EmailField',
    'RegexField',
    'DateField',
    'DateTimeField',
    'TimeField',
    'IntegerField',
    'FloatField',
    'DecimalField',
    'FileField',
    'ImageField',
    'SerializerMethodField',
    'DisplayChoiceField',
    'IntegerChoiceField',
    'IPAddressField',
    'MACAddressField',
    'TimeStampField',
    'DictField',
    'TagField',
    'BaseArrayField',
    'ArrayField',
    'DictArrayField',
    'IntegerArrayField',
    'IPAddressArrayField',
    'CronField',
    'CIDRField',
    'IPNICField',
    'BaseDictField',
    'RoutesField',
    'MetadataField',
    'URLDictField',
    'SafeCharField',
)


SAFE_CHARS = re.compile(r'^[^%$&;\'"]*$')
TRUE_VALUES = frozenset(['t', 'T', 'true', 'True', 'TRUE', '1', 1, True])
FALSE_VALUES = frozenset(['f', 'F', 'false', 'False', 'FALSE', '0', 0, 0.0, False])


def get_boolean_value(value):
    """BooleanField.to_native()"""
    if value in TRUE_VALUES:
        return True
    if value in FALSE_VALUES:
        return False
    return bool(value)


def is_simple_callable(obj):
    """
    True if the object is a callable that takes no arguments.
    """
    function_ = inspect.isfunction(obj)
    method = inspect.ismethod(obj)

    if not (function_ or method):
        return False

    args, _, _, defaults = inspect.getargspec(obj)
    len_args = len(args) if function_ else len(args) - 1
    len_defaults = len(defaults) if defaults else 0

    return len_args