def generate_response_header_validator(headers, context, **kwargs): validators = ValidationDict() for key, header_definition in headers.items(): # generate a function that will attempt to cast the header to the # appropriate type. header_processor = generate_value_processor( context=context, **header_definition ) # generate a function that will validate the header. header_validator = functools.partial( validate_object, field_validators=construct_header_validators(header_definition, context=context), ) # Chain the type casting function, the individual header validation # function with a methodcaller that will fetch the header with # `response.headers.get(header_name, EMPTY)` and then feed that into # the type casting function and then into the validation function. validators.add_validator(key, chain_reduce_partial( operator.methodcaller('get', key, EMPTY), header_processor, header_validator, )) return chain_reduce_partial( operator.attrgetter('headers'), functools.partial(validate_object, field_validators=validators), )
def generate_path_validator(api_path, path_definition, parameters, context, **kwargs): """ Generates a callable for validating the parameters in a response object. """ path_level_parameters = dereference_parameter_list( path_definition.get('parameters', []), context, ) operation_level_parameters = dereference_parameter_list( parameters, context, ) all_parameters = merge_parameter_lists( path_level_parameters, operation_level_parameters, ) # PATH in_path_parameters = filter_parameters(all_parameters, in_=PATH) return chain_reduce_partial( operator.attrgetter('path'), generate_path_parameters_validator(api_path, in_path_parameters, context), )
def generate_header_validator(headers, context, **kwargs): validators = {} for header_definition in headers: header_validator = functools.partial( validate_object, validators=construct_header_validators(header_definition, context=context), inner=True, ) validators[header_definition['name']] = chain_reduce_partial( operator.methodcaller('get', header_definition['name'], EMPTY), header_validator, ) return chain_reduce_partial( operator.attrgetter('headers'), functools.partial(validate_object, validators=validators, inner=True), )
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_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_request_content_type_validator(consumes, **kwargs): validator = functools.partial( validate_request_content_type, content_types=consumes, ) return chain_reduce_partial( operator.attrgetter('request'), validator, )
def generate_response_body_validator(schema, context, **kwargs): return chain_reduce_partial( attrgetter('data'), functools.partial( validate_object, schema=schema, context=context, ), )
def generate_response_body_validator(schema, context, **kwargs): return chain_reduce_partial( operator.attrgetter('data'), functools.partial( validate_object, schema=schema, context=context, ), )
def generate_response_body_validator(schema, context, inner=False): validators = construct_schema_validators(schema, context=context) return chain_reduce_partial( operator.attrgetter('data'), functools.partial( validate_object, validators=validators, inner=True, ), )
def generate_query_parameters_validator(query_parameters, context): query_parameter_validator = functools.partial( validate_query_parameters, query_parameters=query_parameters, context=context, inner=True, ) return chain_reduce_partial( operator.attrgetter('query_data'), query_parameter_validator, )
def generate_response_header_validator(headers, context, **kwargs): validators = {} for key, header_definition in headers.items(): header_validator = functools.partial( validate_object, validators=construct_header_validators(header_definition, context=context), inner=True, ) # Chain the individual header validation function with a methodcaller # that will fetch the header with # `response.headers.get(header_name, EMPTY)` # and then feed that into the validation function. validators[key] = chain_reduce_partial( operator.methodcaller('get', key, EMPTY), header_validator, ) return chain_reduce_partial( operator.attrgetter('headers'), functools.partial(validate_object, validators=validators, inner=True), )
def generate_response_validator(schema, **kwargs): response_validator = functools.partial( validate_response, paths=schema['paths'], base_path=schema.get('basePath', ''), context=schema, **kwargs ) return chain_reduce_partial( normalize_response, response_validator, )
def test_chain_reduce_partial(): def fn_a(v): return v * 3 def fn_b(v): return v * 5 fn_c = chain_reduce_partial(fn_a, fn_b) for _ in range(100): v = random.randint(-1000000, 1000000) assert fn_c(v) == fn_b(fn_a(v))
def generate_path_parameters_validator(api_path, path_parameters, context): path_parameter_validator = functools.partial( validate_path_parameters, api_path=api_path, path_parameters=path_parameters, context=context, inner=True, ) return chain_reduce_partial( operator.attrgetter('path'), path_parameter_validator, )
def generate_header_validator(headers, context, **kwargs): """ Generates a validation function that will validate a dictionary of headers. """ validators = ValidationDict() for header_definition in headers: header_processor = generate_value_processor(context=context, **header_definition) header_validator = generate_object_validator( field_validators=construct_header_validators(header_definition, context=context) ) validators.add_property_validator( header_definition["name"], chain_reduce_partial(header_processor, header_validator) ) return generate_object_validator(field_validators=validators)
def generate_header_validator(headers, context, **kwargs): """ Generates a validation function that will validate a dictionary of headers. """ validators = ValidationDict() for header_definition in headers: header_processor = generate_value_processor(context=context, **header_definition) header_validator = generate_object_validator( field_validators=construct_header_validators(header_definition, context=context), ) validators.add_property_validator( header_definition['name'], chain_reduce_partial( header_processor, header_validator, ), ) return generate_object_validator(field_validators=validators)
def generate_parameters_validator(api_path, path_definition, parameters, context, **kwargs): """ Generates a validator function to validate. - request.path against the path parameters. - request.query against the query parameters. - TODO: request.headers against the header parameters. - TODO: request.body against the body parameters. - TODO: request.formData against any form data. """ validators = {} path_level_parameters = path_definition.get('parameters', []) operation_level_parameters = parameters all_parameters = merge_parameter_lists( path_level_parameters, operation_level_parameters, ) # PATH in_path_parameters = filter_parameters(all_parameters, in_=PATH) validators['path'] = generate_path_parameters_validator( api_path, in_path_parameters, context, ) # QUERY in_query_parameters = filter_parameters(all_parameters, in_=QUERY) validators['query'] = generate_query_parameters_validator(in_query_parameters, context) # HEADERS in_header_parameters = filter_parameters(all_parameters, in_=HEADER) validators['headers'] = generate_header_validator(in_header_parameters, context) return chain_reduce_partial( operator.attrgetter('request'), functools.partial(validate_request_parameters, validators=validators), )
def processor(value, **kwargs): try: return chain_reduce_partial(*processors)(value) except (ValueError, TypeError): return value
def generate_parameters_validator(api_path, path_definition, parameters, context, **kwargs): """ Generates a validator function to validate. - request.path against the path parameters. - request.query against the query parameters. - request.headers against the header parameters. - TODO: request.body against the body parameters. - TODO: request.formData against any form data. """ # TODO: figure out how to merge this with the same code in response # validation. validators = ValidationDict() path_level_parameters = dereference_parameter_list( path_definition.get('parameters', []), context, ) operation_level_parameters = dereference_parameter_list( parameters, context, ) all_parameters = merge_parameter_lists( path_level_parameters, operation_level_parameters, ) # PATH in_path_parameters = filter_parameters(all_parameters, in_=PATH) validators.add_validator( 'path', chain_reduce_partial( operator.attrgetter('path'), generate_path_parameters_validator(api_path, in_path_parameters, context), ), ) # QUERY in_query_parameters = filter_parameters(all_parameters, in_=QUERY) validators.add_validator( 'query', chain_reduce_partial( operator.attrgetter('query_data'), functools.partial( validate_query_parameters, query_parameters=in_query_parameters, context=context, ), ), ) # HEADERS in_header_parameters = filter_parameters(all_parameters, in_=HEADER) validators.add_validator( 'headers', chain_reduce_partial( operator.attrgetter('headers'), generate_header_validator(in_header_parameters, context), ), ) # FORM_DATA # in_form_data_parameters = filter_parameters(all_parameters, in_=FORM_DATA) # validators.add_validator( # 'form_data', # chain_reduce_partial( # operator.attrgetter('data'), # generate_form_data_validator(in_form_data_parameters, context), # ) # ) # REQUEST_BODY in_request_body_parameters = filter_parameters(all_parameters, in_=BODY) validators.add_validator( 'request_body', chain_reduce_partial( operator.attrgetter('data'), generate_request_body_validator(in_request_body_parameters, context), )) return generate_object_validator(field_validators=validators)
def generate_parameters_validator(api_path, path_definition, parameters, context, **kwargs): """ Generates a validator function to validate. - request.path against the path parameters. - request.query against the query parameters. - request.headers against the header parameters. - TODO: request.body against the body parameters. - TODO: request.formData against any form data. """ # TODO: figure out how to merge this with the same code in response # validation. validators = ValidationDict() path_level_parameters = dereference_parameter_list(path_definition.get("parameters", []), context) operation_level_parameters = dereference_parameter_list(parameters, context) all_parameters = merge_parameter_lists(path_level_parameters, operation_level_parameters) # PATH in_path_parameters = filter_parameters(all_parameters, in_=PATH) validators.add_validator( "path", chain_reduce_partial( operator.attrgetter("path"), generate_path_parameters_validator(api_path, in_path_parameters, context) ), ) # QUERY in_query_parameters = filter_parameters(all_parameters, in_=QUERY) validators.add_validator( "query", chain_reduce_partial( operator.attrgetter("query_data"), functools.partial(validate_query_parameters, query_parameters=in_query_parameters, context=context), ), ) # HEADERS in_header_parameters = filter_parameters(all_parameters, in_=HEADER) validators.add_validator( "headers", chain_reduce_partial(operator.attrgetter("headers"), generate_header_validator(in_header_parameters, context)), ) # FORM_DATA # in_form_data_parameters = filter_parameters(all_parameters, in_=FORM_DATA) # validators.add_validator( # 'form_data', # chain_reduce_partial( # operator.attrgetter('data'), # generate_form_data_validator(in_form_data_parameters, context), # ) # ) # REQUEST_BODY in_request_body_parameters = filter_parameters(all_parameters, in_=BODY) validators.add_validator( "request_body", chain_reduce_partial( operator.attrgetter("data"), generate_request_body_validator(in_request_body_parameters, context) ), ) return generate_object_validator(field_validators=validators)