コード例 #1
0
ファイル: models.py プロジェクト: pieterprovoost/vespa-watch
    def create_at_inaturalist(self, access_token, user_agent):
        """Creates a new observation at iNaturalist for this observation

        It will update the current object so self.inaturalist_id is properly set.
        On the other side, it will also set the vespawatch_id observation field so the observation can be found from
        the iNaturalist record.

        :param access_token: as returned by pyinaturalist.rest_api.get_access_token(
        """

        params_only_for_create = {
            'taxon_id': self.taxon.inaturalist_push_taxon_id
        }  # TODO: with the new sync, does it still makes sense to separate the create/update parameters?

        params = {
            'observation': {
                **params_only_for_create,
                **self._params_for_inat()
            }
        }

        r = create_observations(params=params,
                                access_token=access_token,
                                user_agent=user_agent)
        self.inaturalist_id = r[0]['id']
        self.save()
        self.push_attached_pictures_at_inaturalist(access_token=access_token,
                                                   user_agent=user_agent)
コード例 #2
0
    def create_at_inaturalist(self, access_token):
        """Creates a new observation at iNaturalist for this observation

        It will update the current object so self.inaturalist_id is properly set.
        On the other side, it will also set the vespawatch_id observation field so the observation can be found from
        the iNaturalist record.

        :param access_token: as returned by pyinaturalist.rest_api.get_access_token(
        """

        # TODO: push more fields
        # TODO: check the push works when optional fields are missing
        params_only_for_create = {
            'taxon_id': self.taxon.inaturalist_push_taxon_id
        }

        params = {
            'observation': {
                **params_only_for_create,
                **self._params_for_inat()
            }
        }

        r = create_observations(params=params, access_token=access_token)
        self.inaturalist_id = r[0]['id']
        self.save()
        self.push_attached_pictures_at_inaturalist(access_token=access_token)
コード例 #3
0
def upload_obs(obs: Observation, token: str):

    logger.debug('upload_obs()')
    #TODO: Give the observation class a method to generate this JSON
    params = {
        'observation': {
            'taxon_id':
            obs.taxon_id,
            'species_guess':
            obs.taxon_name,
            'observed_on_string':
            str(obs.observed_on),
            'time_zone':
            obs.tzone,
            'description':
            obs.comment,
            'tag_list':
            obs.tags,
            'latitude':
            obs.coordinates[0],
            'longitude':
            obs.coordinates[1],
            'positional_accuracy':
            obs.geotag_accuracy,  # meters,
            'geoprivacy':
            obs.geotag_privacy,
            'observation_field_values_attributes': [{
                'observation_field_id': '',
                'value': ''
            }],
        },
    }

    try:
        logger.info('Uploading observation for taxon {0}'.format(obs.taxon_id))
        r = create_observations(params=params, access_token=token)

        obs.inat_id = r[0]['id']

        for file in obs.photos:

            r = add_photo_to_observation(observation_id=obs.inat_id,
                                         file_object=open(file, 'rb'),
                                         access_token=token)

    except HTTPError as ex:
        obs.inat_result = 'Error creating observation: {0}'.format(ex)
        logger.error('Bad result from iNaturalist API, skipping this one')
        logger.exception(ex)

    except Exception as ex:
        raise
    else:
        logger.info('Success')
        obs.inat_result = 'ok'
コード例 #4
0
def test_create_observation_fail(requests_mock):
    params = {
        "observation": {
            "species_guess": "Pieris rapae",
            # Some invalid data so the observation is rejected...
            "observed_on_string": (datetime.now() + timedelta(days=1)).isoformat(),
            "latitude": 200,
        }
    }

    requests_mock.post(
        "https://www.inaturalist.org/observations.json",
        json=load_sample_data("create_observation_fail.json"),
        status_code=422,
    )

    with pytest.raises(HTTPError) as excinfo:
        create_observations(params=params, access_token="valid token")
    assert excinfo.value.response.status_code == 422
    assert "errors" in excinfo.value.response.json()  # iNat also give details about the errors
コード例 #5
0
def test_create_observation(requests_mock):
    requests_mock.post(
        "https://www.inaturalist.org/observations.json",
        json=load_sample_data("create_observation_result.json"),
        status_code=200,
    )

    params = {
        "observation": {"species_guess": "Pieris rapae"},
    }

    r = create_observations(params=params, access_token="valid token")
    assert len(r) == 1  # We added a single one
    assert (
        r[0]["latitude"] is None
    )  # We have the field, but it's none since we didn't submitted anything
    assert r[0]["taxon_id"] == 55626  # Pieris Rapae @ iNaturalist
コード例 #6
0
                time_zone,
                'description':
                'This is a test upload',
                'tag_list':
                '',
                'latitude':
                coordinates[0],
                'longitude':
                coordinates[1],
                'positional_accuracy':
                50,  # meters,
                'observation_field_values_attributes': [{
                    'observation_field_id':
                    '',
                    'value':
                    ''
                }],
            },
        }
        r = create_observations(params=params, access_token=token)

        new_observation_id = r[0]['id']

        from pyinaturalist.rest_api import add_photo_to_observation

        r = add_photo_to_observation(observation_id=new_observation_id,
                                     file_object=open(file, 'rb'),
                                     access_token=token)

print("Program complete")
コード例 #7
0
def upload_folder_multiple(species_folder, folder, uploaded_folder, time_zone,
                           accuracy, user, passw, app, secret):
    # Makes a list of all files in the folder inside element 2 of a tuple
    for file in os.walk(folder):
        if file[0] == folder:
            files = file

    # Creates list of all the file paths for every file in the folder.
    file_paths = []
    for file in files[2]:  # All files are in files[2]
        file_path = files[0] + file  # files[0] has the path to the folder
        file_paths.append(file_path)  # Makes a big list of paths

    # This is getting a token to allow photos to be uploaded.
    token = get_access_token(username=user,
                             password=passw,
                             app_id=app,
                             app_secret=secret)

    # This goes to every file, checks if it is a jpg, gets the gps coordinates,
    # get the time, and uploads it to iNaturalist.
    jpgs = []
    for file in file_paths:
        if file[-3:].lower() == 'jpg':
            jpgs.append(file)

    try:
        img = PIL.Image.open(jpgs[0])
        coordinates = get_lat_long(img)
        img.close()
    except:
        coordinates = 'No Coordinates'
    try:
        date_time = get_date(file)
        img.close()
    except:
        date_time = 'No Date or Time'

    [species, taxon] = get_taxon(species_folder)
    print(species)
    #    print(coordinates)
    #    print(date_time)
    #    print(' the taxon is ' + str(taxon))

    params = {
        'observation': {
            'taxon_id':
            taxon,
            'species_guess':
            species,
            'observed_on_string':
            date_time,
            'time_zone':
            time_zone,
            'description':
            '',
            'tag_list':
            '',
            'latitude':
            coordinates[0],
            'longitude':
            coordinates[1],
            'positional_accuracy':
            int(accuracy),  # meters,
            'observation_field_values_attributes': [{
                'observation_field_id': '',
                'value': ''
            }],
        },
    }
    r = create_observations(params=params, access_token=token)

    new_observation_id = r[0]['id']

    print('Uploaded as observation #' + str(new_observation_id))
    print('Uploading photos')
    for file in jpgs:
        print('uploading ' + str(file) + ' TO ' + str(new_observation_id))
        r = add_photo_to_observation(observation_id=new_observation_id,
                                     file_object=open(file, 'rb'),
                                     access_token=token)

    folder_name = os.path.split(folder)
    folder1_name = os.path.split(folder_name[0])
    folder2_name = os.path.split(folder1_name[0])

    new_species_folder = uploaded_folder + folder2_name[1] + '/'
    destination = new_species_folder + folder1_name[1]

    if new_observation_id:

        try:
            os.mkdir(new_species_folder)
        except:
            pass
        try:
            shutil.move(folder, destination)
        except:
            print('failed file move')
            pass