You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
3.7 KiB

"""
Copyright (C) 2019 Splunk Inc. All Rights Reserved.
"""
from six import string_types
class FieldValidationError(Exception):
"""Raised when a field fails to validate its value"""
def __init__(self, value):
"""
:param str value: the exception's error message value
"""
super(FieldValidationError, self).__init__()
self.value = value
def __str__(self):
"""
:return: the error message value
:rtype: str
"""
return repr(self.value)
class BaseField(object):
"""A base implementation class for a model's field definition"""
def __init__(self, required=False, default=None):
self.required = True if required else False
self.default = default
def validate(self, value):
"""
Validates the given value based on the current field type
:param value: the value to validate
"""
if self.required and value is None:
raise FieldValidationError('is required')
class StringField(BaseField):
"""A field that validates string values"""
def validate(self, value):
"""
Validates that the given value is a string
:param value: the value to validate
"""
super(StringField, self).validate(value)
if value is not None and not isinstance(value, string_types):
raise FieldValidationError('should be string')
class NumberField(BaseField):
"""A field that validates number values"""
def validate(self, value):
"""
Validates that the given value is a number
:param value: the value to validate
"""
super(NumberField, self).validate(value)
if value is not None and not isinstance(value, (int, float)):
raise FieldValidationError('should be number')
class CompoundField(BaseField):
def __init__(self, subtype=None, *args, **kwargs):
super(CompoundField, self).__init__(*args, **kwargs)
self.subtype = subtype
class DictField(CompoundField):
"""A field that validates dict values"""
def validate(self, value):
"""
Validates that the given value is a dict
:param value: the value to validate
"""
super(DictField, self).validate(value)
if value is not None and not isinstance(value, dict):
raise FieldValidationError('should be dict')
self._validate_values_type(value)
def _validate_values_type(self, value):
"""
Validates that the inner values have the correct type
:param value: the iterable value to validate
"""
if not value or self.subtype is None:
return
for val in list(value.values()):
if val is not None and not isinstance(val, self.subtype):
raise FieldValidationError('should have all {} values'.format(self.subtype))
class ListField(CompoundField):
"""A field that validates list values"""
def validate(self, value):
"""
Validates that the given value is a list
:param value: the value to validate
"""
super(ListField, self).validate(value)
if value is not None and not isinstance(value, list):
raise FieldValidationError('should be list')
self._validate_values_type(value)
def _validate_values_type(self, value):
"""
Validates that the inner values have the correct type
:param value: the iterable value to validate
"""
if not value or self.subtype is None:
return
for val in value:
if val is not None and not isinstance(val, self.subtype):
raise FieldValidationError('should have all {} values'.format(self.subtype))