def enum_validator(swagger_spec, validator, enums, instance, schema):
    """Swagger 2.0 allows enums to be validated against objects of type
    arrays, like query parameter (collectionFormat: multi)

    :param swagger_spec: needed for access to deref()
    :type swagger_spec: :class:`bravado_core.spec.Spec`
    :param validator: Validator class used to validate the object
    :type validator: :class: `Swagger20Validator` or
        :class: `jsonschema.validators.Draft4Validator`
    :param enums: allowed enum values
    :type enums: list
    :param instance: enum instance value
    :param schema: swagger spec for the object
    :type schema: dict
    """
    if schema.get('type') == 'array':
        for element in instance:
            for error in _validators.enum(validator, enums, element, schema):
                yield error
        return

    # Handle optional enum params with no value
    if is_param_spec(swagger_spec, schema):
        if not is_required(swagger_spec, schema) and instance is None:
            return

    for error in _validators.enum(validator, enums, instance, schema):
        yield error
예제 #2
0
def marshal_primitive(swagger_spec, primitive_spec, value):
    """Marshal a python primitive type into a jsonschema primitive.

    :type swagger_spec: :class:`bravado_core.spec.Spec`
    :type primitive_spec: dict
    :type value: int, long, float, boolean, string, unicode, or an object
        based on 'format'

    :rtype: int, long, float, boolean, string, unicode, etc
    :raises: SwaggerMappingError
    """
    default_used = False

    if value is None and schema.has_default(swagger_spec, primitive_spec):
        default_used = True
        value = schema.get_default(swagger_spec, primitive_spec)

    if value is None and schema.is_required(swagger_spec, primitive_spec):
        raise SwaggerMappingError(
            'Spec {0} is a required value'.format(primitive_spec))

    if not default_used:
        value = formatter.to_wire(swagger_spec, primitive_spec, value)

    return value
def enum_validator(swagger_spec, validator, enums, instance, schema):
    """Swagger 2.0 allows enums to be validated against objects of type
    arrays, like query parameter (collectionFormat: multi)

    :param swagger_spec: needed for access to deref()
    :type swagger_spec: :class:`bravado_core.spec.Spec`
    :param validator: Validator class used to validate the object
    :type validator: :class: `Swagger20Validator` or
        :class: `jsonschema.validators.Draft4Validator`
    :param enums: allowed enum values
    :type enums: list
    :param instance: enum instance value
    :param schema: swagger spec for the object
    :type schema: dict
    """
    if schema.get('type') == 'array':
        for element in instance:
            for error in _validators.enum(validator, enums, element, schema):
                yield error
        return

    # Handle optional enum params with no value
    if is_param_spec(swagger_spec, schema):
        if not is_required(swagger_spec, schema) and instance is None:
            return

    for error in _validators.enum(validator, enums, instance, schema):
        yield error
예제 #4
0
def marshal_primitive(swagger_spec, primitive_spec, value):
    """Marshal a python primitive type into a jsonschema primitive.

    :type swagger_spec: :class:`bravado_core.spec.Spec`
    :type primitive_spec: dict
    :type value: int, long, float, boolean, string, unicode, or an object
        based on 'format'

    :rtype: int, long, float, boolean, string, unicode, etc
    :raises: SwaggerMappingError
    """
    default_used = False

    if value is None and schema.has_default(swagger_spec, primitive_spec):
        default_used = True
        value = schema.get_default(swagger_spec, primitive_spec)

    if value is None and schema.is_required(swagger_spec, primitive_spec):
        raise SwaggerMappingError(
            'Spec {0} is a required value'.format(primitive_spec))

    if not default_used:
        value = formatter.to_wire(swagger_spec, primitive_spec, value)

    return value
예제 #5
0
def unmarshal_collection_format(swagger_spec, param_spec, value):
    """For a non-body parameter of type array, unmarshal the value into an
    array of elements.

    Input:
        param_spec = {
            'name': 'status'
            'in': 'query',
            'collectionFormat': 'psv', # pipe separated value
            'type': 'array',
            'items': {
                'type': 'string',
            }
        }
        value="pending|completed|started"

    Output:
        ['pending', 'completed', 'started']

    :type swagger_spec: :class:`bravado_core.spec.Spec`
    :param param_spec: param_spec of the parameter with 'type': 'array'
    :type param_spec: dict
    :param value: parameter value
    :type value: string

    :rtype: list
    """
    deref = swagger_spec.deref
    param_spec = deref(param_spec)
    collection_format = param_spec.get('collectionFormat', 'csv')

    if value is None:
        if not schema.is_required(swagger_spec, param_spec):
            # Just pass through an optional array that has no value
            return None
        return schema.handle_null_value(swagger_spec, param_spec)

    if schema.is_list_like(value):
        value_array = value
    elif collection_format == 'multi':
        # http client lib should have already unmarshalled the value
        value_array = [value]
    else:
        sep = COLLECTION_FORMATS[collection_format]
        if value == '':
            value_array = []
        else:
            value_array = value.split(sep)

    items_spec = param_spec['items']
    items_type = deref(items_spec).get('type')
    param_name = param_spec['name']

    return [
        cast_request_param(items_type, param_name, item)
        for item in value_array
    ]
예제 #6
0
def unmarshal_collection_format(swagger_spec, param_spec, value):
    """For a non-body parameter of type array, unmarshal the value into an
    array of elements.

    Input:
        param_spec = {
            'name': 'status'
            'in': 'query',
            'collectionFormat': 'psv', # pipe separated value
            'type': 'array',
            'items': {
                'type': 'string',
            }
        }
        value="pending|completed|started"

    Output:
        ['pending', 'completed', 'started']

    :type swagger_spec: :class:`bravado_core.spec.Spec`
    :param param_spec: param_spec of the parameter with 'type': 'array'
    :type param_spec: dict
    :param value: parameter value
    :type value: string

    :rtype: list
    """
    deref = swagger_spec.deref
    param_spec = deref(param_spec)
    collection_format = param_spec.get('collectionFormat', 'csv')

    if value is None:
        if not schema.is_required(swagger_spec, param_spec):
            # Just pass through an optional array that has no value
            return None
        return schema.handle_null_value(swagger_spec, param_spec)

    if schema.is_list_like(value):
        value_array = value
    elif collection_format == 'multi':
        # http client lib should have already unmarshaled the value
        value_array = [value]
    else:
        sep = COLLECTION_FORMATS[collection_format]
        if value == '':
            value_array = []
        else:
            value_array = value.split(sep)

    items_spec = param_spec['items']
    items_type = deref(items_spec).get('type')
    param_name = param_spec['name']

    return [
        cast_request_param(items_type, param_name, item)
        for item in value_array
    ]
예제 #7
0
def marshal_param(param, value, request):
    """Given an operation's parameter and its value, marshal the value and
    place it in the proper request destination.

    Destination is one of:
        - path - can accept primitive and array of primitive types
        - query - can accept primitive and array of primitive types
        - header - can accept primitive and array of primitive types
        - body - can accept any type
        - formData - can accept primitive and array of primitive types

    :type param: :class:`bravado_core.param.Param`
    :param value: The value to assign to the parameter
    :type request: dict
    """
    swagger_spec = param.swagger_spec
    deref = swagger_spec.deref

    param_spec = deref(get_param_type_spec(param))
    location = param.location

    # Rely on unmarshalling behavior on the other side of the pipe to use
    # the default value if one is available.
    if value is None and not schema.is_required(swagger_spec, param_spec):
        return

    value = marshal_schema_object(swagger_spec, param_spec, value)

    if swagger_spec.config['validate_requests']:
        validate_schema_object(swagger_spec, param_spec, value)

    param_type = param_spec.get('type')
    if param_type == 'array' and location != 'body':
        value = marshal_collection_format(swagger_spec, param_spec, value)

    if location == 'path':
        token = u'{%s}' % param.name
        quoted_value = quote_plus(six.text_type(value).encode('utf8'),
                                  safe=',')
        request['url'] = request['url'].replace(token, quoted_value)
    elif location == 'query':
        request['params'][param.name] = value
    elif location == 'header':
        request['headers'][param.name] = str(value)
    elif location == 'formData':
        if param_type == 'file':
            add_file(param, value, request)
        else:
            request.setdefault('data', {})[param.name] = value
    elif location == 'body':
        request['headers']['Content-Type'] = APP_JSON
        request['data'] = json.dumps(value)
    else:
        raise SwaggerMappingError(
            "Don't know how to marshal_param with location {0}".format(
                location))
예제 #8
0
def marshal_param(param, value, request):
    """Given an operation's parameter and its value, marshal the value and
    place it in the proper request destination.

    Destination is one of:
        - path - can accept primitive and array of primitive types
        - query - can accept primitive and array of primitive types
        - header - can accept primitive and array of primitive types
        - body - can accept any type
        - formData - can accept primitive and array of primitive types

    :type param: :class:`bravado_core.param.Param`
    :param value: The value to assign to the parameter
    :type request: dict
    """
    swagger_spec = param.swagger_spec
    deref = swagger_spec.deref

    param_spec = deref(get_param_type_spec(param))
    location = param.location

    # Rely on unmarshalling behavior on the other side of the pipe to use
    # the default value if one is availabe.
    if value is None and not schema.is_required(swagger_spec, param_spec):
        return

    value = marshal_schema_object(swagger_spec, param_spec, value)

    if swagger_spec.config['validate_requests']:
        validate_schema_object(swagger_spec, param_spec, value)

    param_type = param_spec.get('type')
    if param_type == 'array' and location != 'body':
        value = marshal_collection_format(swagger_spec, param_spec, value)

    if location == 'path':
        token = u'{%s}' % param.name
        # Don't do any escaping/encoding - http_client will take care of it
        request['url'] = request['url'].replace(token, six.text_type(value))
    elif location == 'query':
        request['params'][param.name] = value
    elif location == 'header':
        request['headers'][param.name] = value
    elif location == 'formData':
        if param_type == 'file':
            add_file(param, value, request)
        else:
            request.setdefault('data', {})[param.name] = value
    elif location == 'body':
        request['headers']['Content-Type'] = APP_JSON
        request['data'] = json.dumps(value)
    else:
        raise SwaggerMappingError(
            "Don't know how to marshal_param with location {0}".
            format(location))
예제 #9
0
def unmarshal_param(param, request):
    """Unmarshal the given parameter from the passed in request like object.

    :type param: :class:`bravado_core.param.Param`
    :type request: :class:`bravado_core.request.IncomingRequest`
    :return: value of parameter
    """
    swagger_spec = param.swagger_spec
    deref = swagger_spec.deref
    param_spec = deref(get_param_type_spec(param))
    location = param.location
    param_type = deref(param_spec.get('type'))
    cast_param = partial(cast_request_param, param_type, param.name)

    default_value = schema.get_default(swagger_spec, param_spec)

    if location == 'path':
        raw_value = cast_param(request.path.get(param.name, None))
    elif location == 'query':
        raw_value = cast_param(request.query.get(param.name, default_value))
    elif location == 'header':
        raw_value = cast_param(request.headers.get(param.name, default_value))
    elif location == 'formData':
        if param_type == 'file':
            raw_value = request.files.get(param.name, None)
        else:
            raw_value = cast_param(request.form.get(param.name, default_value))
    elif location == 'body':
        # TODO: verify content-type header
        try:
            raw_value = request.json()
        except ValueError as json_error:
            raise SwaggerMappingError("Error reading request body JSON: {0}".
                                      format(str(json_error)))
    else:
        raise SwaggerMappingError(
            "Don't know how to unmarshal_param with location {0}".
            format(location))

    if raw_value is None and not schema.is_required(swagger_spec, param_spec):
        return None

    if param_type == 'array' and location != 'body':
        raw_value = unmarshal_collection_format(swagger_spec, param_spec,
                                                raw_value)

    if swagger_spec.config['validate_requests']:
        validate_schema_object(swagger_spec, param_spec, raw_value)

    value = unmarshal_schema_object(swagger_spec, param_spec, raw_value)
    return value
예제 #10
0
def unmarshal_param(param, request):
    """Unmarshal the given parameter from the passed in request like object.

    :type param: :class:`bravado_core.param.Param`
    :type request: :class:`bravado_core.request.IncomingRequest`
    :return: value of parameter
    """
    swagger_spec = param.swagger_spec
    deref = swagger_spec.deref
    param_spec = deref(get_param_type_spec(param))
    location = param.location
    param_type = deref(param_spec.get('type'))
    cast_param = partial(cast_request_param, param_type, param.name)

    default_value = schema.get_default(swagger_spec, param_spec)

    if location == 'path':
        raw_value = cast_param(request.path.get(param.name, None))
    elif location == 'query':
        raw_value = cast_param(request.query.get(param.name, default_value))
    elif location == 'header':
        raw_value = cast_param(request.headers.get(param.name, default_value))
    elif location == 'formData':
        if param_type == 'file':
            raw_value = request.files.get(param.name, None)
        else:
            raw_value = cast_param(request.form.get(param.name, default_value))
    elif location == 'body':
        # TODO: verify content-type header
        try:
            raw_value = request.json()
        except ValueError as json_error:
            raise SwaggerMappingError("Error reading request body JSON: {0}".
                                      format(str(json_error)))
    else:
        raise SwaggerMappingError(
            "Don't know how to unmarshal_param with location {0}".
            format(location))

    if raw_value is None and not schema.is_required(swagger_spec, param_spec):
        return None

    if param_type == 'array' and location != 'body':
        raw_value = unmarshal_collection_format(swagger_spec, param_spec,
                                                raw_value)

    if swagger_spec.config['validate_requests']:
        validate_schema_object(swagger_spec, param_spec, raw_value)

    value = unmarshal_schema_object(swagger_spec, param_spec, raw_value)
    return value
예제 #11
0
def unmarshal_primitive(swagger_spec, primitive_spec, value):
    """Unmarshal a jsonschema primitive type into a python primitive.

    :type swagger_spec: :class:`bravado_core.spec.Spec`
    :type primitive_spec: dict
    :type value: int, long, float, boolean, string, unicode, etc

    :rtype: int, long, float, boolean, string, unicode, or an object
        based on 'format'
    :raises: SwaggerMappingError
    """
    if value is None and schema.is_required(swagger_spec, primitive_spec):
        raise SwaggerMappingError(
            'Spec {0} says this is a required value'.format(primitive_spec))

    value = formatter.to_python(swagger_spec, primitive_spec, value)
    return value
예제 #12
0
def unmarshal_primitive(spec, value):
    """Unmarshal a jsonschema primitive type into a python primitive.

    :type spec: dict or jsonref.JsonRef
    :type value: int, long, float, boolean, string, unicode, etc
    :rtype: int, long, float, boolean, string, unicode, or an object
        based on 'format'
    :raises: TypeError
    """
    if value is None and schema.is_required(spec):
        # TODO: Error message needs more context. Consider adding a stack like
        #       `context` object to each `unmarshal_*` method that acts like
        #       breadcrumbs.
        raise TypeError('Spec {0} says this is a required value'.format(spec))

    value = formatter.to_python(spec, value)
    return value
예제 #13
0
def unmarshal_primitive(swagger_spec, primitive_spec, value):
    """Unmarshal a jsonschema primitive type into a python primitive.

    :type swagger_spec: :class:`bravado_core.spec.Spec`
    :type primitive_spec: dict
    :type value: int, long, float, boolean, string, unicode, etc

    :rtype: int, long, float, boolean, string, unicode, or an object
        based on 'format'
    :raises: SwaggerMappingError
    """
    if value is None and schema.is_required(swagger_spec, primitive_spec):
        raise SwaggerMappingError(
            'Spec {0} says this is a required value'.format(primitive_spec))

    value = formatter.to_python(swagger_spec, primitive_spec, value)
    return value
예제 #14
0
def unmarshal_primitive(swagger_spec, primitive_spec, value):
    """Unmarshal a jsonschema primitive type into a python primitive.

    :type swagger_spec: :class:`bravado_core.spec.Spec`
    :type primitive_spec: dict or jsonref.JsonRef
    :type value: int, long, float, boolean, string, unicode, etc
    :rtype: int, long, float, boolean, string, unicode, or an object
        based on 'format'
    :raises: SwaggerMappingError
    """
    if value is None and schema.is_required(primitive_spec):
        # TODO: Error message needs more context. Consider adding a stack like
        #       `context` object to each `unmarshal_*` method that acts like
        #       breadcrumbs.
        raise SwaggerMappingError(
            'Spec {0} says this is a required value'.format(primitive_spec))

    value = formatter.to_python(swagger_spec, primitive_spec, value)
    return value
예제 #15
0
def unmarshal_array(swagger_spec, array_spec, array_value):
    """Unmarshal a jsonschema type of 'array' into a python list.

    :type swagger_spec: :class:`bravado_core.spec.Spec`
    :type array_spec: dict
    :type array_value: list
    :rtype: list
    :raises: SwaggerMappingError
    """
    if not is_list_like(array_value):
        if array_value is None and not schema.is_required(swagger_spec,
                                                          array_spec):
            return None
        raise SwaggerMappingError('Expected list like type for {0}:{1}'.format(
            type(array_value), array_value))

    item_spec = swagger_spec.deref(array_spec).get('items')
    return [
        unmarshal_schema_object(swagger_spec, item_spec, item)
        for item in array_value
    ]
예제 #16
0
def unmarshal_array(swagger_spec, array_spec, array_value):
    """Unmarshal a jsonschema type of 'array' into a python list.

    :type swagger_spec: :class:`bravado_core.spec.Spec`
    :type array_spec: dict
    :type array_value: list
    :rtype: list
    :raises: SwaggerMappingError
    """
    if not is_list_like(array_value):
        if array_value is None and not schema.is_required(
                swagger_spec, array_spec):
            return None
        raise SwaggerMappingError('Expected list like type for {0}:{1}'.format(
            type(array_value), array_value))

    item_spec = swagger_spec.deref(array_spec).get('items')
    return [
        unmarshal_schema_object(swagger_spec, item_spec, item)
        for item in array_value
    ]
def enum_validator(
        swagger_spec,  # type: Spec
        validator,  # type: Draft4Validator
        enums,  # type: typing.Any
        instance,  # type: typing.Any
        schema,  # type: JSONDict
):
    # type: (...) -> typing.Generator[ValidationError, None, None]
    """Swagger 2.0 allows enums to be validated against objects of type
    arrays, like query parameter (collectionFormat: multi)

    :param swagger_spec: needed for access to deref()
    :type swagger_spec: :class:`bravado_core.spec.Spec`
    :param validator: Validator class used to validate the object
    :type validator: :class: `Swagger20Validator` or
        :class: `jsonschema.validators.Draft4Validator`
    :param enums: allowed enum values
    :type enums: list
    :param instance: enum instance value
    :param schema: swagger spec for the object
    :type schema: dict
    """

    if instance is None and is_prop_nullable(swagger_spec, schema):
        return

    if schema.get('type') == 'array':
        for element in instance:
            for error in _DRAFT4_ENUM_VALIDATOR(validator, enums, element,
                                                schema):
                yield error
        return

    # Handle optional enum params with no value
    if is_param_spec(swagger_spec, schema):
        if instance is None and not is_required(swagger_spec, schema):
            return

    for error in _DRAFT4_ENUM_VALIDATOR(validator, enums, instance, schema):
        yield error
예제 #18
0
def marshal_primitive(spec, value):
    """Marshal a python primitive type into a jsonschema primitive.

    :type spec: dict or jsonref.JsonRef
    :type value: int, long, float, boolean, string, unicode, or an object
        based on 'format'
    :rtype: int, long, float, boolean, string, unicode, etc
    :raises: TypeError
    """
    default_used = False

    if value is None and schema.has_default(spec):
        default_used = True
        value = schema.get_default(spec)

    if value is None and schema.is_required(spec):
        raise TypeError('Spec {0} is a required value'.format(spec))

    if not default_used:
        value = formatter.to_wire(spec, value)

    return value
예제 #19
0
def test_ref_default_to_false(minimal_swagger_dict):
    minimal_swagger_dict['definitions']['Foo'] = {'type': 'integer'}
    swagger_spec = Spec.from_dict(minimal_swagger_dict)
    assert not is_required(swagger_spec, {'$ref': '#/definitions/Foo'})
예제 #20
0
def test_ref_false(minimal_swagger_dict, required_false):
    minimal_swagger_dict["definitions"]["Foo"] = required_false
    swagger_spec = Spec(minimal_swagger_dict)
    assert not is_required(swagger_spec, {"$ref": "#/definitions/Foo"})
예제 #21
0
def test_ref_default_to_false(minimal_swagger_dict):
    minimal_swagger_dict["definitions"]["Foo"] = {"type": "integer"}
    swagger_spec = Spec.from_dict(minimal_swagger_dict)
    assert not is_required(swagger_spec, {"$ref": "#/definitions/Foo"})
예제 #22
0
def test_false(minimal_swagger_spec, object_spec):
    assert not is_required(minimal_swagger_spec, object_spec)
예제 #23
0
def test_true(minimal_swagger_spec, required_true):
    assert is_required(minimal_swagger_spec, required_true)
예제 #24
0
def test_false(minimal_swagger_spec, required_false):
    assert not is_required(minimal_swagger_spec, required_false)
예제 #25
0
def test_defaults_to_false(minimal_swagger_spec):
    assert not is_required(minimal_swagger_spec, {'type': 'integer'})
예제 #26
0
def test_ref_false(minimal_swagger_dict, required_false):
    minimal_swagger_dict['definitions']['Foo'] = required_false
    swagger_spec = Spec(minimal_swagger_dict)
    assert not is_required(swagger_spec, {'$ref': '#/definitions/Foo'})
예제 #27
0
def test_defaults_to_false(minimal_swagger_spec):
    assert not is_required(minimal_swagger_spec, {"type": "integer"})