def __init__(self, error): if not isinstance(error, collections.Mapping) and \ is_non_string_iterable(error) and \ len(error) == 1: error = error[0] self._error = error if isinstance(self._error, collections.Mapping): self.error_dict = self._error elif is_non_string_iterable(self._error): self.error_list = self._error
def inner(value): if is_non_string_iterable(value): # TODO: this should collect all errors that are raised and re-raise # them as a list. return list(map(func, value)) else: return func(value)
def add_validator(self, validator): if is_non_string_iterable(validator)\ and not isinstance(validator, collections.Mapping): for value in validator: self.add_validator(value) else: self.append(validator)
def validator(value): if is_non_string_iterable(value): if not all([v.startswith('bar') for v in value]): raise ValidationError('error') else: if not value.startswith('bar'): raise ValidationError('error')
def generate_value_processor(type_, collectionFormat=None, items=None, **kwargs): """ Create a callable that will take the string value of a header and cast it to the appropriate type. This can involve: - splitting a header of type 'array' by its delimeters. - type casting the internal elements of the array. """ processors = [] if is_non_string_iterable(type_): assert False, "This should not be possible" else: if type_ == ARRAY and collectionFormat: delimeter = DELIMETERS[collectionFormat] # split the string based on the delimeter specified by the # `collectionFormat` processors.append(operator.methodcaller('split', delimeter)) # remove any Falsy values like empty strings. processors.append(functools.partial(filter, bool)) # strip off any whitespace processors.append( functools.partial(map, operator.methodcaller('strip'))) if items is not None: if isinstance(items, collections.Mapping): items_processors = itertools.repeat( generate_value_processor(**items)) elif isinstance(items, collections.Sequence): items_processors = itertools.chain( (generate_value_processor(**item) for item in items), itertools.repeat(lambda v: v), ) elif isinstance(items, six.string_types): raise NotImplementedError("Not implemented") else: assert False, "Should not be possible" # 1. zip the processor and the array items together # 2. apply the processor to each array item. # 3. cast the starmap generator to a list. processors.append( chain_reduce_partial( functools.partial(zip, items_processors), functools.partial(itertools.starmap, lambda fn, v: fn(v)), list, )) else: processors.append( functools.partial(cast_value_to_type, type_=type_)) def processor(value, **kwargs): try: return chain_reduce_partial(*processors)(value) except (ValueError, TypeError): return value return processor
def validate_query_parameters(raw_query_data, query_parameters, context): query_data = {} for key, value in raw_query_data.items(): if is_non_string_iterable(value) and len(value) == 1: query_data[key] = value[0] else: query_data[key] = value validate_parameters(query_data, query_parameters, context)
def validate_query_parameters(raw_query_data, query_parameters, context, inner=False): query_data = {} for key, value in raw_query_data.items(): if is_non_string_iterable(value) and len(value) == 1: query_data[key] = value[0] else: query_data[key] = value validate_parameters(query_data, query_parameters, context, inner=inner)
def validate_query_parameters(raw_query_data, query_parameters, context): query_data = {} for key, value in raw_query_data.items(): if is_non_string_iterable(value) and len(value) == 1: query_data[key] = value[0] else: query_data[key] = value query_data = type_cast_parameters(query_data, query_parameters, context) validate_parameters(query_data, query_parameters, context)
def generate_value_processor(type_, collectionFormat=None, items=None, **kwargs): """ Create a callable that will take the string value of a header and cast it to the appropriate type. This can involve: - splitting a header of type 'array' by its delimeters. - type casting the internal elements of the array. """ processors = [] if is_non_string_iterable(type_): assert False, "This should not be possible" else: if type_ == ARRAY and collectionFormat: delimeter = DELIMETERS[collectionFormat] # split the string based on the delimeter specified by the # `collectionFormat` processors.append(operator.methodcaller('split', delimeter)) # remove any Falsy values like empty strings. processors.append(functools.partial(filter, bool)) # strip off any whitespace processors.append(functools.partial(map, operator.methodcaller('strip'))) if items is not None: if isinstance(items, collections.Mapping): items_processors = itertools.repeat( generate_value_processor(**items) ) elif isinstance(items, collections.Sequence): items_processors = itertools.chain( (generate_value_processor(**item) for item in items), itertools.repeat(lambda v: v), ) elif isinstance(items, six.string_types): raise NotImplementedError("Not implemented") else: assert False, "Should not be possible" # 1. zip the processor and the array items together # 2. apply the processor to each array item. # 3. cast the starmap generator to a list. processors.append( chain_reduce_partial( functools.partial(zip, items_processors), functools.partial(itertools.starmap, lambda fn, v: fn(v)), list, ) ) else: processors.append( functools.partial(cast_value_to_type, type_=type_) ) def processor(value, **kwargs): try: return chain_reduce_partial(*processors)(value) except (ValueError, TypeError): return value return processor
def generate_type_validator(type_, **kwargs): """ Generates a callable validator for the given type or iterable of types. """ if is_non_string_iterable(type_): types = type_ else: types = (type_, ) return functools.partial(validate_type, types=types)
def generate_type_validator(type_, **kwargs): """ Generates a callable validator for the given type or iterable of types. """ if is_non_string_iterable(type_): types = type_ else: types = (type_,) return functools.partial(validate_type, types=types)
def add_error(self, error): """ In the case where a list/tuple is passed in this just extends the list rather than having nested lists. Otherwise, the value is appended. """ if is_non_string_iterable(error) and not isinstance(error, collections.Mapping): for value in error: self.add_error(value) else: self.append(error)
def add_error(self, error): """ In the case where a list/tuple is passed in this just extends the list rather than having nested lists. Otherwise, the value is appended. """ if is_non_string_iterable(error) and not isinstance(error, Mapping): for value in error: self.add_error(value) else: self.append(error)
def generate_type_validator(type_, **kwargs): """ Generates a callable validator for the given type or iterable of types. """ if is_non_string_iterable(type_): types = type_ else: types = (type_,) # support x-nullable since Swagger 2.0 doesn't support null type # (see https://github.com/OAI/OpenAPI-Specification/issues/229) if kwargs.get('x-nullable', False) and NULL not in types: types = types + (NULL,) return functools.partial(validate_type, types=types)
def generate_type_validator(type_, **kwargs): """ Generates a callable validator for the given type or iterable of types. """ if is_non_string_iterable(type_): types = type_ else: types = (type_, ) # support x-nullable since Swagger 2.0 doesn't support null type # (see https://github.com/OAI/OpenAPI-Specification/issues/229) if kwargs.get('x-nullable', False) and NULL not in types: types = types + (NULL, ) return functools.partial(validate_type, types=types)
def test_tuple(): assert is_non_string_iterable(tuple())
def inner(value): if is_non_string_iterable(value): return map(func, value) else: return func(value)
def from_native(self, value): if is_non_string_iterable(value): return value return super(MaybeListCharField, self).from_native(value)
def test_not_bytes(): if six.PY2: assert not is_non_string_iterable(six.binary_type('is-a-string')) else: assert not is_non_string_iterable(six.binary_type('is-a-string', encoding='utf-8'))
def test_not_string(): assert not is_non_string_iterable('is-a-string')
def test_dict(): assert is_non_string_iterable({})
def test_list(): assert is_non_string_iterable([])
def test_not_bytes(): if six.PY2: assert not is_non_string_iterable(six.binary_type('is-a-string')) else: assert not is_non_string_iterable( six.binary_type('is-a-string', encoding='utf-8'))