예제 #1
0
def add_photo_to_observation(
    observation_id: int,
    file_object: BinaryIO,
    access_token: str,
    user_agent: str = None,
):
    """Upload a picture and assign it to an existing observation.

    Args:
        observation_id: the ID of the observation
        file_object: a file-like object for the picture. Example: open('/Users/nicolasnoe/vespa.jpg', 'rb')
        access_token: the access token, as returned by :func:`get_access_token()`
        user_agent: a user-agent string that will be passed to iNaturalist.
    """
    data = {"observation_photo[observation_id]": observation_id}
    file_data = {"file": file_object}

    response = post(
        url="{base_url}/observation_photos".format(base_url=INAT_BASE_URL),
        access_token=access_token,
        user_agent=user_agent,
        data=data,
        files=file_data,
    )

    return response.json()
예제 #2
0
def create_observations(params: Dict[str, Dict[str, Any]],
                        access_token: str,
                        user_agent: str = None) -> List[Dict[str, Any]]:
    """Create a single or several (if passed an array) observations).
    For API reference, see: https://www.inaturalist.org/pages/api+reference#post-observations

    Example:
        >>> params = {'observation': {'species_guess': 'Pieris rapae'}}
        >>> token = get_access_token('...')
        >>> create_observations(params=params, access_token=token)

    Args:
        params:
        access_token: the access token, as returned by :func:`get_access_token()`
        user_agent: a user-agent string that will be passed to iNaturalist.

    Returns:
         The newly created observation(s) in JSON format

    Raises:
        :py:exc:`requests.HTTPError`, if the call is not successful. iNaturalist returns an error 422 (unprocessable entity)
        if it rejects the observation data (for example an observation date in the future or a latitude > 90. In
        that case the exception's `response` attribute give details about the errors.

    TODO investigate: according to the doc, we should be able to pass multiple observations (in an array, and in
    renaming observation to observations, but as far as I saw they are not created (while a status of 200 is returned)
    """
    response = post(
        url="{base_url}/observations.json".format(base_url=INAT_BASE_URL),
        json=params,
        access_token=access_token,
        user_agent=user_agent,
    )
    response.raise_for_status()
    return response.json()
예제 #3
0
def create_observation(
    params: RequestParams = None, access_token: str = None, user_agent: str = None, **kwargs
) -> ListResponse:
    """Create a new observation.

    **API reference:** https://www.inaturalist.org/pages/api+reference#post-observations

    Example:
        >>> token = get_access_token('...')
        >>> create_observation(
        >>>     access_token=token,
        >>>     species_guess='Pieris rapae',
        >>>     local_photos='~/observation_photos/2020_09_01_14003156.jpg',
        >>>     observation_fields={297: 1},  # 297 is the obs. field ID for 'Number of individuals'
        >>> )

        .. admonition:: Example Response
            :class: toggle

            .. literalinclude:: ../sample_data/create_observation_result.json
                :language: javascript

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

            .. literalinclude:: ../sample_data/create_observation_fail.json
                :language: javascript

    Returns:
        JSON response containing the newly created observation(s)

    Raises:
        :py:exc:`requests.HTTPError`, if the call is not successful. iNaturalist returns an
        error 422 (unprocessable entity) if it rejects the observation data (for example an
        observation date in the future or a latitude > 90. In that case the exception's
        ``response`` attribute gives more details about the errors.
    """
    # Accept either top-level params (like most other endpoints)
    # or nested {"observation": params} (like the iNat API accepts directly)
    if "observation" in kwargs:
        kwargs.update(kwargs.pop("observation"))
    kwargs = check_deprecated_params(params, **kwargs)
    kwargs = convert_observation_fields(kwargs)
    if "local_photos" in kwargs:
        kwargs["local_photos"] = ensure_file_objs(kwargs["local_photos"])

    response = post(
        url="{base_url}/observations.json".format(base_url=INAT_BASE_URL),
        json={"observation": kwargs},
        access_token=access_token,
        user_agent=user_agent,
    )
    response.raise_for_status()
    return response.json()
예제 #4
0
def add_photo_to_observation(
    observation_id: int,
    photo: FileOrPath,
    access_token: str,
    user_agent: str = None,
):
    """Upload a local photo and assign it to an existing observation.

    **API reference:** https://www.inaturalist.org/pages/api+reference#post-observation_photos

    Example:

        >>> token = get_access_token('...')
        >>> add_photo_to_observation(
        >>>     1234,
        >>>     '~/observation_photos/2020_09_01_14003156.jpg',
        >>>     access_token=token,
        >>> )

        .. admonition:: Example Response
            :class: toggle

            .. literalinclude:: ../sample_data/add_photo_to_observation.json
                :language: javascript

    Args:
        observation_id: the ID of the observation
        photo: An image file, file-like object, or path
        access_token: the access token, as returned by :func:`get_access_token()`
        user_agent: a user-agent string that will be passed to iNaturalist.

    Returns:
        Information about the newly created photo
    """
    response = post(
        url="{base_url}/observation_photos".format(base_url=INAT_BASE_URL),
        access_token=access_token,
        data={"observation_photo[observation_id]": observation_id},
        files={"file": ensure_file_obj(photo)},
        user_agent=user_agent,
    )

    return response.json()
예제 #5
0
def get_access_token(username: str,
                     password: str,
                     app_id: str,
                     app_secret: str,
                     user_agent: str = None) -> str:
    """ Get an access token using the user's iNaturalist username and password.
    You still need an iNaturalist app to do this.

    Example:
        >>> access_token = get_access_token('...')
        >>> headers = {"Authorization": f"Bearer {access_token}"}

    Args:
        username: iNaturalist username
        password: iNaturalist password
        app_id: iNaturalist application ID
        app_secret: iNaturalist application secret
        user_agent: a user-agent string that will be passed to iNaturalist.
    """
    payload = {
        "client_id": app_id,
        "client_secret": app_secret,
        "grant_type": "password",
        "username": username,
        "password": password,
    }

    response = post(
        "{base_url}/oauth/token".format(base_url=INAT_BASE_URL),
        json=payload,
        user_agent=user_agent,
    )
    try:
        return response.json()["access_token"]
    except KeyError:
        raise AuthenticationError(
            "Authentication error, please check credentials.")