Source code for ripozo.viewsets.fields.base

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from ripozo.exceptions import ValidationException
from ripozo.viewsets.constants import input_categories
from ripozo.exceptions import RestException

import six


[docs]class BaseField(object): """ The BaseField class is simply an abstract base class that defines the necessary methods for casting and validating a field. """ field_type = object def __init__(self, name, required=False, maximum=None, minimum=None, arg_type=input_categories.BODY_ARGS, error_message=None): self.name = name self.required = required self.maximum = maximum self.minimum = minimum self.arg_type = arg_type self.error_message = error_message
[docs] def translate(self, obj, skip_required=False, validate=False): """ A shortcut method to _translate and _validate the object that is being passed in. It returns this object or raises a ValueError. :param object obj: :return: The translated and validated object :rtype: object :raises: ripozo.exceptions.ValidationsException :raises: ripozo.exceptions.TranslationException """ obj = self._translate(obj, skip_required=skip_required) if validate: obj = self._validate(obj, skip_required=skip_required) return obj
def _translate(self, obj, skip_required=False): """ This method is responsible for translating an input string or object. :param object obj: The input from the request that is being translated :param bool skip_required: This is being ignored for now :return: The object in the appropriate form :rtype: object :raises: ripozo.exceptions.TranslationException """ if isinstance(obj, (list, set)): if len(obj) > 0: return obj[0] else: return None return obj def _validate(self, obj, skip_required=False): """ An object to be validated :param object obj: :param bool skip_required: If this is set to True then the required statement will be skipped regardless of whether the field is actually required or not. This is useful for circumstances where you want validations to run and the field is normally required but not in this case. See the restmixins.Update for an example. :return: The same exact object simple validated. :rtype: object :raises: ripozo.exceptions.ValidationException """ if self.required and obj is None and skip_required is False: raise ValidationException(self.error_message or 'The field "{0}" is required ' 'and cannot be None'.format(self.name)) obj = self._validate_type(obj) return obj def _skip_validation(self, obj): """ Deteremines whether validation should be skipped because the input is None and the field is not required. :param object obj: :return: A boolean indicating whether validation should be skipped :rtype: bool """ if obj is None and not self.required: return True return False def _validate_size(self, obj, obj_size, msg=None): """ Validates the size of the object. :param Sized obj_size: The size of the object. This must be an object that is comparable, i.e. it must be comparable via ">" and "<" operators :param msg: The message to display if the object fails validation :type msg: unicode :returns: The validated object :rtype: object :raises: ValidationException """ if self.minimum and obj_size < self.minimum: if not msg: msg = ('The input was too small for the field {2}: ' '{0} < {1}'.format(obj_size, self.minimum, self.name)) raise ValidationException(self.error_message or msg) if self.maximum and obj_size > self.maximum: if not msg: msg = ('The input was too large for the field {2}: ' '{0} > {1}'.format(obj_size, self.maximum, self.name)) raise ValidationException(self.error_message or msg) return obj def _validate_type(self, obj, msg=None): """ Validates that is object matches the classes field_type :param object obj: :return: The validated object :rtype: object """ if obj is None and not self.required: return obj if obj is not None and isinstance(obj, self.field_type): return obj if msg is None: msg = "obj is not a valid type for field {0}. A type of {1} is required.".format(self.name, self.field_type) raise ValidationException(self.error_message or msg)
[docs]def translate_fields(url_params, query_args, body_args, fields=None, skip_required=False, validate=False): """ Performs the specified action on the field. The action can be a string of either _translate, _validate, or translate. :param dict url_params: The url parameters. Typically this is going to be things like primary keys and such :param dict query_args: The query args. Typically these are going to be filters on lists and such :param dict body_args: The arguments in the body. This may be for updates and creations :param list fields: The list of BaseField instances that are supposed to be validated. Only items in this list will be translated and validated :param bool skip_required: A flag that indicates the required fields are not required. This is helpful for updates where fields are not usually required. :param bool validate: A flag that indicates whether the field validations should be run. If not, it will just translate the fields. :return: Returns the translated url_params, query_args and body_args :rtype: tuple :raises: RestException :raises: ValidationException :raises: TranslationException """ updated_url_params = url_params.copy() updated_query_args = query_args.copy() updated_body_args = body_args.copy() fields = fields or [] for field in fields: if field.arg_type == input_categories.URL_PARAMS: args = updated_url_params elif field.arg_type == input_categories.QUERY_ARGS: args = updated_query_args elif field.arg_type == input_categories.BODY_ARGS: args = updated_body_args else: raise RestException('Invalid arg_type, {0}, on Field {1}'.format(field.arg_type, field.name)) if field.name not in args and skip_required: continue field_value = field.translate(args.get(field.name, None), skip_required=skip_required, validate=validate) if field.name in args: args[field.name] = field_value return updated_url_params, updated_query_args, updated_body_args