Ejemplo n.º 1
0
def convert_pagination_params(params: RequestParams) -> RequestParams:
    """Allow ``count_only=True`` as a slightly more intuitive shortcut to only get a count of
    results"""
    if params.pop('count_only', False) is True:
        params['per_page'] = 0
    if params.pop('reverse', False) is True:
        params['order'] = 'descending'
    return params
Ejemplo n.º 2
0
def convert_observation_fields(params: RequestParams) -> RequestParams:
    """Translate simplified format of observation field values into API-compatible format"""
    if "observation_fields" in params:
        params["observation_field_values_attributes"] = params.pop("observation_fields")
    obs_fields = params.get("observation_field_values_attributes")
    if isinstance(obs_fields, dict):
        params["observation_field_values_attributes"] = [
            {"observation_field_id": k, "value": v} for k, v in obs_fields.items()
        ]
    return params
Ejemplo n.º 3
0
def convert_observation_field_params(params: RequestParams) -> RequestParams:
    """Translate simplified format of observation field values into API-compatible format"""
    if 'observation_fields' in params:
        params['observation_field_values_attributes'] = params.pop(
            'observation_fields')
    obs_fields = params.get('observation_field_values_attributes')
    if isinstance(obs_fields, dict):
        params['observation_field_values_attributes'] = [{
            'observation_field_id':
            k,
            'value':
            v
        } for k, v in obs_fields.items()]
    return params
Ejemplo n.º 4
0
def translate_rank_range(params: RequestParams) -> RequestParams:
    """If min and/or max rank is specified in params, translate into a list of ranks"""

    def _get_rank_index(rank: str) -> int:
        if rank not in RANKS:
            raise ValueError("Invalid rank")
        return RANKS.index(rank)

    min_rank, max_rank = params.pop("min_rank", None), params.pop("max_rank", None)
    if min_rank or max_rank:
        # Use indices in RANKS list to determine range of ranks to include
        min_rank_index = _get_rank_index(min_rank) if min_rank else 0
        max_rank_index = _get_rank_index(max_rank) + 1 if max_rank else len(RANKS)
        params["rank"] = RANKS[min_rank_index:max_rank_index]
    return params
Ejemplo n.º 5
0
def _validate_multiple_choice_param(
        params: RequestParams, key: str,
        choices: Iterable) -> Tuple[RequestParams, Optional[str]]:
    """Verify that a multiple-choice request parameter contains valid value(s);
    if not, return an error message.

    Returns:
        Parameters with modifications (if any), and a validation error message (if any)
    """
    def is_valid(value, choices):
        if not value:
            return True
        if not isinstance(value, list):
            value = [value]
        return all([v in choices for v in value])

    def normalize(value):
        if not value:
            return value
        if isinstance(value, list):
            return [v.replace(' ', '_') for v in value]
        return value.replace(' ', '_')

    error_msg = None
    if key in params:
        params[key] = normalize(params[key])
    if not is_valid(params.get(key), choices):
        error_msg = MULTIPLE_CHOICE_ERROR_MSG.format(key, choices, params[key])
    return params, error_msg
Ejemplo n.º 6
0
def convert_datetime_params(params: RequestParams) -> RequestParams:
    """Convert any dates, datetimes, or timestamps in other formats into ISO 8601 strings.

    API behavior note: params that take date but not time info will accept a full timestamp and
    just ignore the time, so it's safe to parse both date and datetime strings into timestamps

    Raises:
        :py:exc:`dateutil.parser._parser.ParserError` if a date/datetime format is invalid
    """
    for k, v in params.items():
        if isinstance(v, (date, datetime)) or (isinstance(v, str)
                                               and k in DATETIME_PARAMS):
            params[k] = convert_isoformat(v)
    return params
Ejemplo n.º 7
0
def strip_empty_params(params: RequestParams) -> RequestParams:
    """Remove any request parameters with empty or ``None`` values."""
    return {k: v for k, v in params.items() if v or v is False}
Ejemplo n.º 8
0
def convert_list_params(params: RequestParams) -> RequestParams:
    """Convert any list parameters into an API-compatible (comma-delimited) string.
    Will be url-encoded by requests. For example: `['k1', 'k2', 'k3'] -> k1%2Ck2%2Ck3`
    """
    return {k: convert_list(v) for k, v in params.items()}
Ejemplo n.º 9
0
def convert_bool_params(params: RequestParams) -> RequestParams:
    """ Convert any boolean request parameters to javascript-style boolean strings """
    for k, v in params.items():
        if isinstance(v, bool):
            params[k] = str(v).lower()
    return params
Ejemplo n.º 10
0
def split_common_params(
        params: RequestParams) -> Tuple[RequestParams, RequestParams]:
    """Split out common keyword args (for pyinaturalist functions) from request params (for API)"""
    kwargs = {k: params.pop(k, None) for k in COMMON_PARAMS}
    return params, kwargs