def validate_string(typedef, value): """ Validate a string, check length. """ # Check to see if the typedef has any pattern restrictions. If it does, # then match against all of the patterns. If it matches any # of the patterns (i.e. not all of the patterns), then the argument # value is considered to be valid. patterns = typedef.get('pattern') if patterns: # If it's a single pattern convert it to a tuple, so we can handle # it in a common way below. Note that we don't use collection.Sequence # in the isinstance call because strings are sequences if command._is_string(patterns): patterns = (patterns,) for pattern in patterns: if re.match(pattern, str(value)): break else: command._raise_argument_validation_exception(typedef, value, 'invalid string pattern') # Check for any length restrictions. This can be a single scalar length or # a single length range or a sequence of either of those. For scalar lengths # the length must match it exactly. For length ranges the length of the argument # must be between the two values (inclusive). For a list of length specs, the # length must match any of the lengths (either scalar or range) in the list. lengths = typedef.get('length') if lengths: if command._is_single_range(lengths): lengths = (lengths,) for length in lengths: command._check_one_range(length) if isinstance(length, numbers.Integral): if len(value) == length: break if len(value) >= length[0] and len(value) <= length[1]: break else: command._raise_argument_validation_exception(typedef, value, 'invalid string length') return value
def validate_enum(typedef, value): # FIXME: Sort of a hack. The base enum class doesn't have a values # field, so there's nothing to check against. We really just use it # as a base type to indicate the validation function (i.e. this function) # to use. name = typedef.get('name') if name == 'enum': return enum_values = typedef.get('values') if not enum_values: raise error.CommandDescriptionError('Unspecified enum values') if not isinstance(enum_values, collections.Mapping): # If it's not a dictionary then it should be an array # or tuple where the (string) elements are both the key # and the value for the enum items. So here we convert # to a dictionary so we can use the same logic for both # cases below. if command._is_string(enum_values): enum_values = (enum_values,) if isinstance(enum_values, collections.Sequence): enum_values = dict((v,v) for v in enum_values) else: raise error.CommandDescriptionError( 'Enum values must be either a string, dict, tuple, or list') prefix_matches = [] lower_value = value.lower() for enum_value, return_value in enum_values.items(): lower_enum_value = enum_value.lower() if lower_enum_value == lower_value: return (return_value, enum_value) if lower_enum_value.startswith(lower_value): prefix_matches.append((return_value, enum_value)) if len(prefix_matches) == 0: command._raise_argument_validation_exception(typedef, value, 'unexpected value for enum', enum_values.keys()) return prefix_matches