Ejemplo n.º 1
0
 def test_throws_when_scene_is_missing_status(self):
     mangled_scene = json.loads(RESPONSE_SCENE_ACTIVE)
     del mangled_scene['properties']['status']
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            json=mangled_scene)
     with self.assertRaises(scenes.ValidationError):
         scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
Ejemplo n.º 2
0
 def test_throws_when_scene_has_invalid_resolution(self):
     mangled_scene = json.loads(RESPONSE_SCENE_ACTIVE)
     mangled_scene['properties']['resolution'] = None
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            json=mangled_scene)
     with self.assertRaises(scenes.ValidationError):
         scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
Ejemplo n.º 3
0
 def test_throws_when_scene_has_invalid_tide_max(self):
     mangled_scene = json.loads(RESPONSE_SCENE_ACTIVE)
     mangled_scene['properties']['MaximumTide24Hours'] = 'whee'
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            json=mangled_scene)
     with self.assertRaises(scenes.ValidationError):
         scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
Ejemplo n.º 4
0
 def test_throws_when_scene_id_is_malformed(self):
     malformed_ids = (
         'lolwut',
         'planetnope:foobar',
     )
     for malformed_id in malformed_ids:
         with self.assertRaises(scenes.MalformedSceneID):
             scenes.get(malformed_id, 'test-planet-api-key')
Ejemplo n.º 5
0
 def test_calls_correct_url_for_rapideye_scene(self):
     self.mock_requests.get('/planet/rapideye/test-scene-id',
                            text=RESPONSE_SCENE_INACTIVE)
     scenes.get('rapideye:test-scene-id', 'test-planet-api-key')
     uri, params = self.mock_requests.request_history[0].url.split('?', 1)
     self.assertEqual(
         'https://test-catalog-host.localdomain/planet/rapideye/test-scene-id',
         uri)
     self.assertEqual({'PL_API_KEY=test-planet-api-key', 'tides=True'},
                      set(params.split('&')))
Ejemplo n.º 6
0
 def test_returns_correct_geotiff_single_band_urls(self):
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            text=RESPONSE_SCENE_INACTIVE)
     scene = scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
     # FIXME -- if Planet's API ever offers Landsat retrieval...
     self.assertIsNone(scene.geotiff_coastal)
     self.assertIsNone(scene.geotiff_swir1)
Ejemplo n.º 7
0
 def test_returns_correct_uri(self):
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            text=RESPONSE_SCENE_INACTIVE)
     scene = scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
     self.assertEqual(
         'https://test-catalog-host.localdomain/planet/planetscope/test-scene-id',
         scene.uri)
Ejemplo n.º 8
0
 def test_returns_correct_geometry(self):
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            text=RESPONSE_SCENE_INACTIVE)
     scene = scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
     self.assertIsInstance(scene.geometry, dict)
     self.assertIsInstance(scene.geometry.get('coordinates'), list)
     self.assertEqual([[[115.78907135188213, 26.67939763560932],
                        [115.78653934657243, 26.905071315070465],
                        [116.01004245933433, 26.90679345550323],
                        [115.95815780815747, 26.680701401397425],
                        [115.78907135188213, 26.67939763560932]]],
                      scene.geometry.get('coordinates'))
Ejemplo n.º 9
0
def forward_to_geotiff(scene_id: str):
    planet_api_key = flask.request.args.get('planet_api_key')
    if not planet_api_key:
        return 'Missing `planet_api_key` parameter', 400

    user = getattr(flask.request, 'user', None)
    user_id = user.user_id if user else None
    try:
        scene = _scenes.get(scene_id, planet_api_key)
        geotiff_url = _scenes.activate(scene, planet_api_key, user_id)
    except _scenes.NotFound:
        return 'Cannot download: Scene `{}` not found'.format(scene_id), 404
    except (_scenes.CatalogError,
            _scenes.MalformedSceneID) as err:
        return 'Cannot download: {}'.format(err), 500

    if geotiff_url:
        return flask.redirect(geotiff_url)

    return flask.render_template('download_scene.jinja2', scene_id=scene_id), 202
Ejemplo n.º 10
0
 def test_saves_scene_to_database(self):
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            text=RESPONSE_SCENE_INACTIVE)
     scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
     self.assertTrue(self._mockdb.executed)
Ejemplo n.º 11
0
 def test_gracefully_handles_database_errors(self):
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            text=RESPONSE_SCENE_INACTIVE)
     self._mockdb.raise_on_execute()
     with self.assertRaises(DatabaseError):
         scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
Ejemplo n.º 12
0
 def test_returns_correct_capture_date(self):
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            text=RESPONSE_SCENE_INACTIVE)
     scene = scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
     self.assertEqual('2017-01-20T00:00:00+00:00',
                      scene.capture_date.isoformat())
Ejemplo n.º 13
0
 def test_fetches_scenes(self):
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            text=RESPONSE_SCENE_INACTIVE)
     scene = scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
     self.assertIsInstance(scene, scenes.Scene)
Ejemplo n.º 14
0
 def test_returns_correct_geotiff_multispectral_url_for_inactive_scene(
         self):
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            text=RESPONSE_SCENE_INACTIVE)
     scene = scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
     self.assertIsNone(scene.geotiff_multispectral)
Ejemplo n.º 15
0
 def test_returns_correct_cloud_cover(self):
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            text=RESPONSE_SCENE_INACTIVE)
     scene = scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
     self.assertEqual(1.47, scene.cloud_cover)
Ejemplo n.º 16
0
 def test_throws_when_scene_does_not_exist(self):
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            status_code=404,
                            text='wat')
     with self.assertRaises(scenes.NotFound):
         scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
Ejemplo n.º 17
0
 def test_throws_when_not_permitted(self):
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            status_code=401,
                            text='oopsie')
     with self.assertRaises(scenes.NotPermitted):
         scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
Ejemplo n.º 18
0
 def test_throws_when_catalog_throws(self):
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            status_code=500,
                            text='oh noes')
     with self.assertRaises(scenes.CatalogError):
         scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
Ejemplo n.º 19
0
 def test_throws_when_catalog_is_unreachable(self):
     with unittest.mock.patch('requests.get') as stub:
         stub.side_effect = ConnectionError()
         with self.assertRaises(scenes.CatalogError):
             scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
Ejemplo n.º 20
0
def create(user_id: str, scene_id: str, service_id: str, job_name: str,
           planet_api_key: str) -> Job:
    log = logging.getLogger(__name__)
    log.info('Job service create', action='service job create', actor=user_id)

    # Fetch prerequisites
    try:
        algorithm = algorithms.get(service_id)
        scene = scenes.get(scene_id, planet_api_key)
        scenes.activate(scene, planet_api_key, user_id)
    except (algorithms.NotFound, algorithms.ValidationError,
            scenes.MalformedSceneID, scenes.CatalogError, scenes.NotFound,
            scenes.NotPermitted, scenes.ValidationError) as err:
        log.error('Preprocessing error: %s', err)
        raise PreprocessingError(err)

    # Determine GeoTIFF URLs.
    if scene.platform in ('rapideye', 'planetscope'):
        geotiff_filenames = ['multispectral.TIF']
        geotiff_urls = [scenes.create_download_url(scene.id, planet_api_key)]
    elif scene.platform == 'landsat':
        geotiff_filenames = ['coastal.TIF', 'swir1.TIF']
        geotiff_urls = [scene.geotiff_coastal, scene.geotiff_swir1]
    else:
        raise PreprocessingError(message='Unexpected platform')

    # Dispatch to Piazza
    try:
        log.info('Dispatching <scene:%s> to <algo:%s>', scene_id,
                 algorithm.name)
        cli_cmd = _create_algorithm_cli_cmd(algorithm.interface,
                                            geotiff_filenames, scene.platform)
        job_id = piazza.execute(
            algorithm.service_id, {
                'body': {
                    'content':
                    json.dumps({
                        'cmd': cli_cmd,
                        'inExtFiles': geotiff_urls,
                        'inExtNames': geotiff_filenames,
                        'outGeoJson': ['shoreline.geojson'],
                        'userID': user_id,
                    }),
                    'type':
                    'body',
                    'mimeType':
                    'application/json',
                },
            })
    except piazza.Error as err:
        log.error('Could not execute via Piazza: %s', err)
        raise

    # Record the data
    log.debug('Saving job record <%s>', job_id)
    conn = db.get_connection()
    transaction = conn.begin()
    try:
        db.jobs.insert_job(
            conn,
            algorithm_id=algorithm.service_id,
            algorithm_name=algorithm.name,
            algorithm_version=algorithm.version,
            job_id=job_id,
            name=job_name,
            scene_id=scene_id,
            status=piazza.STATUS_PENDING,
            user_id=user_id,
            tide=scene.tide,
            tide_min_24h=scene.tide_min,
            tide_max_24h=scene.tide_max,
        )
        db.jobs.insert_job_user(
            conn,
            job_id=job_id,
            user_id=user_id,
        )
        transaction.commit()
    except db.DatabaseError as err:
        transaction.rollback()
        log.error('Could not save job to database')
        db.print_diagnostics(err)
        raise
    finally:
        conn.close()

    return Job(
        algorithm_name=algorithm.name,
        algorithm_version=algorithm.version,
        created_by=user_id,
        created_on=datetime.utcnow(),
        geometry=scene.geometry,
        job_id=job_id,
        name=job_name,
        scene_time_of_collect=scene.capture_date,
        scene_sensor_name=scene.sensor_name,
        scene_id=scene_id,
        status=piazza.STATUS_PENDING,
        tide=scene.tide,
        tide_min_24h=scene.tide_min,
        tide_max_24h=scene.tide_max,
    )
Ejemplo n.º 21
0
 def test_returns_correct_sensor_name(self):
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            text=RESPONSE_SCENE_INACTIVE)
     scene = scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
     self.assertEqual('test-sensor-name', scene.sensor_name)
Ejemplo n.º 22
0
 def test_returns_correct_resolution(self):
     self.mock_requests.get('/planet/planetscope/test-scene-id',
                            text=RESPONSE_SCENE_INACTIVE)
     scene = scenes.get('planetscope:test-scene-id', 'test-planet-api-key')
     self.assertEqual(4, scene.resolution)