Validate and clean up a query to be sent to Search.
    Cleans the query string, removes unneeded parameters, and validates for correctness.
    Does not modify the original argument.
    Raises an Exception on invalid input.

    Arguments:
        query (dict): The query to validate.

    Returns:
        dict: The validated query.

def _validate_query(query):
    """Validate and clean up a query to be sent to Search.
    Cleans the query string, removes unneeded parameters, and validates for correctness.
    Does not modify the original argument.
    Raises an Exception on invalid input.

    Arguments:
        query (dict): The query to validate.

    Returns:
        dict: The validated query.
    """
    query = deepcopy(query)
    # q is always required
    if query["q"] == BLANK_QUERY["q"]:
        raise ValueError("No query specified.")

    query["q"] = _clean_query_string(query["q"])

    # limit should be set to appropriate default if not specified
    if query["limit"] is None:
        query["limit"] = SEARCH_LIMIT if query["advanced"] else NONADVANCED_LIMIT
    # If specified, the limit should not be greater than the Search maximum
    elif query["limit"] > SEARCH_LIMIT:
        warnings.warn('Reduced result limit from {} to the Search maximum: {}'
                      .format(query["limit"], SEARCH_LIMIT), RuntimeWarning)
        query["limit"] = SEARCH_LIMIT

    # Remove all blank/default values
    for key, val in BLANK_QUERY.items():
        # Default for get is NaN so comparison is always False
        if query.get(key, float('nan')) == val:
            query.pop(key)

    # Remove unsupported fields
    to_remove = [field for field in query.keys() if field not in BLANK_QUERY.keys()]
    [query.pop(field) for field in to_remove]

    return query