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
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
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
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
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
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
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
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
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)}
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
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
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