Given a type and any value, return a runtime value coerced to match the type.

def coerce_value(type, value):
    # type: (Any, Any) -> Union[List, Dict, int, float, bool, str, None]
    """Given a type and any value, return a runtime value coerced to match the type."""
    if isinstance(type, GraphQLNonNull):
        # Note: we're not checking that the result of coerceValue is
        # non-null.
        # We only call this function after calling isValidValue.
        return coerce_value(type.of_type, value)

    if value is None:
        return None

    if isinstance(type, GraphQLList):
        item_type = type.of_type
        if not isinstance(value, string_types) and isinstance(value, Iterable):
            return [coerce_value(item_type, item) for item in value]
        else:
            return [coerce_value(item_type, value)]

    if isinstance(type, GraphQLInputObjectType):
        fields = type.fields
        obj = {}
        for field_name, field in fields.items():
            if field_name not in value:
                if field.default_value is not None:
                    field_value = field.default_value
                    obj[field.out_name or field_name] = field_value
            else:
                field_value = coerce_value(field.type, value.get(field_name))
                obj[field.out_name or field_name] = field_value

        return type.create_container(obj)

    assert isinstance(type, (GraphQLScalarType, GraphQLEnumType)), "Must be input type"

    return type.parse_value(value)