Пример #1
0
def get_identifications(**params) -> JsonResponse:
    """Search identifications

    .. rubric:: Notes

    * API reference: :v1:`GET /identifications <Identifications/get_identifications>`

    Example:
        Get all of your own species-level identifications:

        >>> response = get_identifications(user_login='******', rank='species')
        >>> print([f"{i['user']['login']}: {i['taxon_id']} ({i['category']})" for i in response['results']])
        [155043569] Species: 76465 (leading) added on 2021-02-15 10:46:27-06:00 by jkcook
        [153668189] Species: 76465 (supporting) added on 2021-02-06 17:43:37+00:00 by jkcook
        [147500725] Species: 1163860 (improving) added on 2020-12-24 23:52:30+00:00 by jkcook
        ...

        .. admonition:: Example Response
            :class: toggle

            .. literalinclude:: ../sample_data/get_identifications.py

    Returns:
        Response dict containing identification records
    """
    params = convert_rank_range(params)
    if params.get('page') == 'all':
        identifications = paginate_all(get_v1, 'identifications', **params)
    else:
        identifications = get_v1('identifications', **params).json()

    identifications['results'] = convert_all_timestamps(
        identifications['results'])
    return identifications
Пример #2
0
def get_identifications_by_id(identification_id: MultiInt,
                              **params) -> JsonResponse:
    """Get one or more identification records by ID

    .. rubric:: Notes

    * API reference: :v1:`GET /identifications/{id} <Identifications/get_identifications_id>`

    Example:
        >>> get_identifications_by_id(155554373)

        .. admonition:: Example Response
            :class: toggle

            .. literalinclude:: ../sample_data/get_identifications.py

    Args:
        identification_id: Get taxa with this ID. Multiple values are allowed.

    Returns:
        Response dict containing identification records
    """
    response = get_v1('identifications', ids=identification_id, **params)
    identifications = response.json()
    identifications['results'] = convert_all_timestamps(
        identifications['results'])
    return identifications
Пример #3
0
def get_users_autocomplete(q: str, **params) -> JsonResponse:
    """Given a query string, return users with names or logins starting with the search term

    .. rubric:: Notes

    * API reference: :v1:`GET /users/autocomplete <Users/get_users_autocomplete>`
    * Pagination is supported; default page size is 6, and max is 100.

    Example:
        >>> response = get_taxa_autocomplete(q='my_userna')
        >>> pprint(response)
        [1234] my_username
        [12345] my_username_2

        .. admonition:: Example Response
            :class: toggle

            .. literalinclude:: ../sample_data/get_users_autocomplete.py

    Returns:
        Response dict containing user records
    """
    response = get_v1('users/autocomplete', q=q, **params)
    users = response.json()
    users['results'] = convert_all_timestamps(users['results'])
    return users
Пример #4
0
def get_messages(**params) -> JsonResponse:
    """Get messages from the user's inbox

    .. rubric:: Notes

    * :fa:`lock` :ref:`Requires authentication <auth>`
    * API reference: :v1:`GET /messages <Messages/get_messages>`

    Example:
        >>> response = get_messages()
        >>> pprint(response)

        .. admonition:: Example Response
            :class: toggle

            .. literalinclude:: ../sample_data/get_messages.json

    Returns:
        Response dict containing user record
    """
    # `threads` is not compatible with `q` param, and includes totals from both inbox and sent
    if params.get('threads') is True:
        params['box'] = 'any'
        params['q'] = None

    response = get_v1('messages', **params)
    messages = response.json()
    messages['results'] = convert_all_timestamps(messages['results'])
    return messages
Пример #5
0
def search(q: str, **params) -> JsonResponse:
    """A unified search endpoint for places, projects, taxa, and/or users

    .. rubric:: Notes

    * API reference: :v1:`GET /search <Search/get_search>`

    Example:
        >>> response = search(q='odonat')
        >>> pprint(response)
        [Taxon  ] [47792   ] Order: Odonata (Dragonflies and Damselflies)
        [Place  ] [113562  ] Odonates of Peninsular India and Sri Lanka
        [Project] [9978    ] Ohio Dragonfly Survey  (Ohio Odonata Survey)
        [User   ] [113886  ] odonatanb (Gilles Belliveau)

        .. admonition:: Example Response
            :class: toggle

            .. literalinclude:: ../sample_data/get_search.py

    Returns:
        Response dict containing search results
    """
    response = get_v1('search', q=q, **params)
    search_results = response.json()
    search_results['results'] = convert_all_timestamps(
        search_results['results'])
    search_results['results'] = convert_all_coordinates(
        search_results['results'])
    return search_results
Пример #6
0
def get_taxa_by_id(taxon_id: MultiInt, **params) -> JsonResponse:
    """Get one or more taxa by ID

    .. rubric:: Notes

    * API reference: :v1:`GET /taxa/{id} <Taxa/get_taxa_id>`

    Example:
        >>> response = get_taxa_by_id(343248)
        >>> basic_fields = ['preferred_common_name', 'observations_count', 'wikipedia_url', 'wikipedia_summary']
        >>> print({f: response['results'][0][f] for f in basic_fields})
        {
            'preferred_common_name': 'Paper Wasps',
            'observations_count': 69728,
            'wikipedia_url': 'http://en.wikipedia.org/wiki/Polistinae',
            'wikipedia_summary': 'The Polistinae are eusocial wasps closely related to yellow jackets...',
        }

        .. admonition:: Example Response
            :class: toggle

            .. literalinclude:: ../sample_data/get_taxa_by_id.py

    Args:
        taxon_id: Get taxa with this ID. Multiple values are allowed.

    Returns:
        Response dict containing taxon records
    """
    response = get_v1('taxa', ids=taxon_id, **params)
    taxa = response.json()
    taxa['results'] = convert_all_timestamps(taxa['results'])
    return taxa
Пример #7
0
def get_taxa(**params) -> JsonResponse:
    """Search taxa

    .. rubric:: Notes

    * API reference: :v1:`GET /taxa <Taxa/get_taxa>`

    Example:
        >>> response = get_taxa(q='vespi', rank=['genus', 'family'])
        >>> pprint(response)
        [52747] Family: Vespidae (Hornets, Paper Wasps, Potter Wasps, and Allies)
        [92786] Genus: Vespicula
        [646195] Genus: Vespiodes
        ...

        .. admonition:: Example Response
            :class: toggle

            .. literalinclude:: ../sample_data/get_taxa.json
                :language: JSON

    Returns:
        Response dict containing taxon records
    """
    params = convert_rank_range(params)
    if params.get('page') == 'all':
        taxa = paginate_all(get_v1, 'taxa', **params)
    else:
        taxa = get_v1('taxa', **params).json()

    taxa['results'] = convert_all_timestamps(taxa['results'])
    return taxa
Пример #8
0
def get_observations(**params) -> JsonResponse:
    """Search observations

    .. rubric:: Notes

    * API reference: :v1:`GET /observations <Observations/get_observations>`

    Examples:

        Get observations of Monarch butterflies with photos + public location info,
        on a specific date in the provice of Saskatchewan, CA (place ID 7953):

        >>> response = get_observations(
        >>>     taxon_name='Danaus plexippus',
        >>>     created_on='2020-08-27',
        >>>     photos=True,
        >>>     geo=True,
        >>>     geoprivacy='open',
        >>>     place_id=7953,
        >>> )

        Get basic info for observations in response:

        >>> pprint(response)
        '[57754375] Species: Danaus plexippus (Monarch) observed by samroom on 2020-08-27 at Railway Ave, Wilcox, SK'
        '[57707611] Species: Danaus plexippus (Monarch) observed by ingridt3 on 2020-08-26 at Michener Dr, Regina, SK'

        .. admonition:: Example Response
            :class: toggle

            .. literalinclude:: ../sample_data/get_observations_node.py

    Returns:
        Response dict containing observation records
    """
    validate_multiple_choice_param(params, 'order_by',
                                   V1_OBS_ORDER_BY_PROPERTIES)

    if params.get('page') == 'all':
        observations = paginate_all(get_v1,
                                    'observations',
                                    method='id',
                                    **params)
    else:
        observations = get_v1('observations', **params).json()

    observations['results'] = convert_all_coordinates(observations['results'])
    observations['results'] = convert_all_timestamps(observations['results'])
    return observations
Пример #9
0
def get_observation_fields(**params) -> JsonResponse:
    """Search observation fields. Observation fields are basically typed data fields that
    users can attach to observation.

    .. rubric:: Notes

    * API reference: :v0:`GET /observation_fields <get-observation_fields>`
    * This endpoint does not support the ``per_page`` parameter

    Example:

        >>> get_observation_fields(q='number of individuals')
        >>> # Show just observation field IDs and names
        >>> from pprint import pprint
        >>> pprint({r['id']: r['name'] for r in response})

        .. admonition:: Example Response
            :class: toggle

            .. literalinclude:: ../sample_data/get_observation_fields.py

    Returns:
        Observation fields
    """
    all_pages = params.pop('page', None)
    params['page'] = 1
    params[
        'per_page'] = 30  # This seems to return 30 results regardless of the per_page param
    obs_fields = get(f'{API_V0_BASE_URL}/observation_fields.json',
                     **params).json()

    # This endpoint returns a list with no pagination metadata, so iterate until there are no more pages
    if all_pages:
        page_results = obs_fields
        while len(page_results) == 30:
            params['page'] += 1
            page_results = get(f'{API_V0_BASE_URL}/observation_fields.json',
                               **params).json()
            obs_fields.extend(page_results)

    obs_fields = convert_all_timestamps(obs_fields)
    return {'results': obs_fields, 'total_results': len(obs_fields)}
Пример #10
0
def get_posts(**params) -> ListResponse:
    """Search posts

    .. rubric:: Notes

    * API reference: :v1:`GET /posts <Posts/get_posts>`

    Example:
        Get journal posts from user 'username'

        >>> response = get_posts(login='******')

    Returns:
        List containing journal posts from the iNaturalist site
    """
    response = get_v1('posts', **params)

    posts = response.json()
    posts = convert_all_coordinates(posts)
    posts = convert_all_timestamps(posts)

    return posts
Пример #11
0
def get_message_by_id(message_id: MultiInt, **params) -> JsonResponse:
    """Get a message by ID

    .. rubric:: Notes

    * :fa:`lock` :ref:`Requires authentication <auth>`
    * API reference: :v1:`GET /messages/{id} <Messages/get_messages_id>`

    Example:
        >>> response = get_messages(123456)
        >>> pprint(response)

        .. admonition:: Example Response
            :class: toggle

            .. literalinclude:: ../sample_data/get_messages.json

    Returns:
        Response dict containing user record
    """
    response = get_v1('messages', ids=message_id, **params)
    messages = response.json()
    messages['results'] = convert_all_timestamps(messages['results'])
    return messages
Пример #12
0
def get_observations(**params) -> Union[List, str]:
    """Get observation data, optionally in an alternative format

    .. rubric:: Notes

    * API reference: :v0:`GET /observations <get-observations>`

    Example:

        >>> get_observations(id=45414404, converters='atom')

        .. admonition:: Example Response (atom)
            :class: toggle

            .. literalinclude:: ../sample_data/get_observations.atom
                :language: xml

        .. admonition:: Example Response (csv)
            :class: toggle

            .. literalinclude:: ../sample_data/get_observations.csv

        .. admonition:: Example Response (dwc)
            :class: toggle

            .. literalinclude:: ../sample_data/get_observations.dwc
                :language: xml

        .. admonition:: Example Response (json)
            :class: toggle

            .. literalinclude:: ../sample_data/get_observations.json
                :language: json

        .. admonition:: Example Response (kml)
            :class: toggle

            .. literalinclude:: ../sample_data/get_observations.kml
                :language: xml

        .. admonition:: Example Response (widget)
            :class: toggle

            .. literalinclude:: ../sample_data/get_observations.js
                :language: javascript

    Returns:
        Return type will be ``dict`` for the ``json`` response format, and ``str`` for all others.
    """
    response_format = params.pop('response_format', 'json')
    if response_format not in OBSERVATION_FORMATS:
        raise ValueError('Invalid response format')
    validate_multiple_choice_param(params, 'order_by',
                                   V0_OBS_ORDER_BY_PROPERTIES)

    response = get(f'{API_V0_BASE_URL}/observations.{response_format}',
                   **params)
    if response_format == 'json':
        observations = response.json()
        observations = convert_all_coordinates(observations)
        observations = convert_all_timestamps(observations)
        return observations
    else:
        return response.text