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
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))
|