From f0424abe81f1495797d9c45b924e8ea04f24efd5 Mon Sep 17 00:00:00 2001 From: Sufyan Abbasi Date: Wed, 11 Nov 2020 21:53:21 +0000 Subject: [PATCH] v0.1.242 --- demos/wmts/app.py | 2 +- javascript/build/ee_api_js.js | 22 +- javascript/build/ee_api_js_debug.js | 23 +- javascript/build/ee_api_js_npm.js | 55 +- javascript/package.json | 2 +- javascript/src/apiclient.js | 2 +- python/ee/__init__.py | 5 +- python/ee/apitestcase.py | 69 +- python/ee/batch.py | 277 +++--- python/ee/cli/commands.py | 260 ++--- python/ee/cli/eecli.py | 20 +- python/ee/cli/utils.py | 5 +- python/ee/data.py | 1081 ++++++++------------- python/ee/featurecollection.py | 5 +- python/ee/image.py | 20 +- python/ee/imagecollection.py | 6 +- python/ee/tests/_helpers_test.py | 17 +- python/ee/tests/batch_test.py | 510 ---------- python/ee/tests/data_test.py | 178 ---- python/ee/tests/ee_test.py | 388 ++++---- python/ee/tests/featurecollection_test.py | 30 +- python/ee/tests/image_test.py | 74 +- 22 files changed, 911 insertions(+), 2140 deletions(-) diff --git a/demos/wmts/app.py b/demos/wmts/app.py index fae27b982..8ac6f68e5 100644 --- a/demos/wmts/app.py +++ b/demos/wmts/app.py @@ -51,7 +51,7 @@ def setup_ee(): extracted_key_data = keyfile.read() credentials = ee.ServiceAccountCredentials(config.EE_SERVICE_ACCOUNT, key_data=extracted_key_data) - ee.Initialize(credentials, use_cloud_api=True) + ee.Initialize(credentials) @server.after_request diff --git a/javascript/build/ee_api_js.js b/javascript/build/ee_api_js.js index 150f55971..b278822ca 100644 --- a/javascript/build/ee_api_js.js +++ b/javascript/build/ee_api_js.js @@ -400,7 +400,7 @@ Jd(p,g[n]))});return b?b(h):h};return this.callback?(L(d,null,function(g,h){retu gj.prototype.send=function(a,b){var c=[a.u+" "+a.path+" HTTP/1.1"];c.push("Content-Type: application/json; charset=utf-8");var d=ij();null!=d&&c.push("Authorization: "+d);a=a.body?JSON.stringify(a.body):"";return[c.join("\r\n")+"\r\n\r\n"+a,b]}; var jj=function(a,b,c){a=m(b.split("--"+a.split("; boundary=")[1]));for(b=a.next();!b.done;b=a.next())if(b=b.value.split("\r\n\r\n"),!(3>b.length)){var d=b[0].match(/\r\nContent-ID: ]*)>/)[1],e=Number(b[1].match(/^HTTP\S*\s(\d+)\s/)[1]);c(d,e,b.slice(2).join("\r\n\r\n"))}},fj=function(){var a=kj.replace(/\/api$/,"");return"window"in r&&!a.match(/^https?:\/\/content-/)?a.replace(/^(https?:\/\/)(.*\.googleapis\.com)$/,"$1content-$2"):a},qj=function(a,b,c){lj&&mj&&lj({client_id:String(mj), immediate:!0,scope:nj.join(" ")},function(d){if("immediate_failed"==d.error&&c)c();else if(M&&"window"in r)try{oj(function(){try{r.gapi.auth.setToken(d),pj(a,b,d)}catch(e){b(e.toString())}})}catch(e){b(e.toString())}else pj(a,b,d)})},ij=function(){rj&&0<=Date.now()-rj&&sj();return tj},sj=function(){rj=tj=null},uj=function(a,b){mj=a;nj=b},cj=function(a,b,c){null!=a?kj=a:vj||(kj="https://earthengine.googleapis.com/api");null!=b?wj=b:vj||(wj="https://earthengine.googleapis.com");void 0!==c&&(xj=c);M&& -(aj=aj||"earthengine-legacy");vj=!0},L=function(a,b,c,d,e,f){cj();var g=yj,h="application/x-www-form-urlencoded";e&&(h="application/json",d&&d.startsWith("multipart")&&(h=d,d="POST"));d=d||"POST";h={"Content-Type":h};var n=bj.test(a);if(M&&!n){var p="0.1.241";"0.1.241"===p&&(p="latest");h["x-goog-api-client"]="ee-js/"+p}p=ij();if(null!=p)h.Authorization=p;else if(c&&lj&&mj)return qj(function(){zj(g,function(){L(a,b,c,d)})}),null;b=b?b.clone():new Zd;null!=Aj&&b.add("key",Aj);M?(g&&(h["X-Earth-Engine-Computation-Profile"]= +(aj=aj||"earthengine-legacy");vj=!0},L=function(a,b,c,d,e,f){cj();var g=yj,h="application/x-www-form-urlencoded";e&&(h="application/json",d&&d.startsWith("multipart")&&(h=d,d="POST"));d=d||"POST";h={"Content-Type":h};var n=bj.test(a);if(M&&!n){var p="0.1.242";"0.1.242"===p&&(p="latest");h["x-goog-api-client"]="ee-js/"+p}p=ij();if(null!=p)h.Authorization=p;else if(c&&lj&&mj)return qj(function(){zj(g,function(){L(a,b,c,d)})}),null;b=b?b.clone():new Zd;null!=Aj&&b.add("key",Aj);M?(g&&(h["X-Earth-Engine-Computation-Profile"]= "1"),aj&&"earthengine-legacy"!==aj&&!n&&(h["X-Goog-User-Project"]=aj)):g&&b.add("profiling","1");b=Bj(b,a);null!=xj&&(h["X-XSRF-Token"]=xj);null!=Cj&&(h["X-Earth-Engine-App-ID-Token"]=Cj);n=e||null;p=b?b.toString():"";"POST"===d&&void 0===e?n=p:/^[\s\xa0]*$/.test(p)||(a+=-1!=a.indexOf("?")?"&":"?",a+=p);e=a.startsWith("/")?kj+a:a;if(c)return Dj.push(Ej(e,c,d,n,h,f)),Fj.Hd(),null;p=function(D,ca){this.setRequestHeader&&this.setRequestHeader(ca,D)};var t=0;for(f=null!=f?f:5;;){var C=Ni(Ki);C.open(d, e,!1);Bb(h,p,C);C.send(n);if(429!=C.status||t>f)break;t++}return Gj(C.status,function(D){try{return C.getResponseHeader(D)}catch(ca){return null}},C.responseText,g,void 0,e,d)},Ej=function(a,b,c,d,e,f){var g=0,h={url:a,method:c,content:d,headers:e},n=yj,p=null!=f?f:10;h.callback=function(t){t=t.target;if(429==t.getStatus()&&ga.y||a.y>=1<= 300: - # Note if the response is JSON and contains an error value, we raise that - # error above rather than this generic one. - raise ee_exception.EEException( - 'Server returned HTTP code: %s. Reason: %s.' % - (response.status, response.reason)) - - # Now known not to be an error response... - if opt_raw: - return content - elif json_content is None: - raise ee_exception.EEException( - 'Response was unexpectedly not JSON, but %s' % response['content-type']) - else: - return json_content['data'] - - def create_assets(asset_ids, asset_type, mk_parents): """Creates the specified assets if they do not exist.""" for asset_id in asset_ids: @@ -1961,10 +1647,7 @@ def create_assets(asset_ids, asset_type, mk_parents): for part in parts[2:-1]: path += part if getInfo(path) is None: - if _use_cloud_api: - createAsset({'type': ASSET_TYPE_FOLDER_CLOUD}, path) - else: - createAsset({'type': ASSET_TYPE_FOLDER}, path) + createAsset({'type': ASSET_TYPE_FOLDER_CLOUD}, path) path += '/' createAsset({'type': asset_type}, asset_id) diff --git a/python/ee/featurecollection.py b/python/ee/featurecollection.py index b4fa861e0..0bd3f643a 100644 --- a/python/ee/featurecollection.py +++ b/python/ee/featurecollection.py @@ -130,10 +130,7 @@ def getDownloadURL(self, filetype=None, selectors=None, filename=None): A URL to download the specified feature collection. """ request = {} - if data._use_cloud_api: # pylint: disable=protected-access - request['table'] = self - else: - request['table'] = self.serialize() + request['table'] = self if filetype is not None: request['format'] = filetype.upper() if filename is not None: diff --git a/python/ee/image.py b/python/ee/image.py index 71a28310d..0c6650547 100644 --- a/python/ee/image.py +++ b/python/ee/image.py @@ -392,12 +392,8 @@ def prepare_for_export(self, params): - any remaining parameters. """ image = self - # If the Cloud API is enabled, we can do cleaner handling of the parameters. - # If it isn't enabled, we have to be bug-for-bug compatible with current - # behaviour, so we do nothing. - if data._use_cloud_api: # pylint: disable=protected-access - image, params = image._apply_crs_and_affine(params) # pylint: disable=protected-access - image, params = image._apply_selection_and_scale(params) # pylint: disable=protected-access + image, params = image._apply_crs_and_affine(params) # pylint: disable=protected-access + image, params = image._apply_selection_and_scale(params) # pylint: disable=protected-access return image, params def getDownloadURL(self, params=None): @@ -488,17 +484,7 @@ def getThumbURL(self, params=None): # If the Cloud API is enabled, we can do cleaner handling of the parameters. # If it isn't enabled, we have to be bug-for-bug compatible with current # behaviour. - if data._use_cloud_api: # pylint: disable=protected-access - return data.makeThumbUrl(self.getThumbId(params)) - image, params = self._apply_visualization(params) - params['image'] = image - if 'region' in params: - if isinstance(params['region'], (dict, list)): - params['region'] = json.dumps(params['region']) - elif not isinstance(params['region'], str): - raise ee_exception.EEException( - 'The region parameter must be an array or a GeoJSON object.') - return data.makeThumbUrl(data.getThumbId(params)) + return data.makeThumbUrl(self.getThumbId(params)) # Deprecated spellings to match the JS library. getDownloadUrl = deprecation.Deprecated('Use getDownloadURL().')( diff --git a/python/ee/imagecollection.py b/python/ee/imagecollection.py index 0b58a58e3..b9222b0f8 100644 --- a/python/ee/imagecollection.py +++ b/python/ee/imagecollection.py @@ -292,7 +292,5 @@ def prepare_for_export(self, params): # If the Cloud API is enabled, we can do cleaner handling of the parameters. # If it isn't enabled, we have to be bug-for-bug compatible with current # behaviour, so we do nothing. - if data._use_cloud_api: # pylint: disable=protected-access - return self._apply_preparation_function(image.Image.prepare_for_export, - params) - return self, params + return self._apply_preparation_function(image.Image.prepare_for_export, + params) diff --git a/python/ee/tests/_helpers_test.py b/python/ee/tests/_helpers_test.py index 395e39d93..699384939 100644 --- a/python/ee/tests/_helpers_test.py +++ b/python/ee/tests/_helpers_test.py @@ -6,25 +6,21 @@ import unittest import ee from ee import apitestcase -from ee import deserializer from ee.apifunction import ApiFunction from ee.computedobject import ComputedObject class ProfilingTest(apitestcase.ApiTestCase): - def MockSend(self, path, params, *args): + def MockValue(self, value): """Overridden to check for profiling-related data.""" - if path == '/value': - value = deserializer.fromJSON(params['json']) - hooked = ee.data._thread_locals.profile_hook is not None - is_get_profiles = (isinstance(value, ComputedObject) and value.func == - ApiFunction.lookup('Profile.getProfiles')) - return 'hooked=%s getProfiles=%s' % (hooked, is_get_profiles) - else: - return super(ProfilingTest, self).MockSend(path, params, *args) + hooked = ee.data._thread_locals.profile_hook is not None + is_get_profiles = (isinstance(value, ComputedObject) and value.func == + ApiFunction.lookup('Profile.getProfiles')) + return 'hooked=%s getProfiles=%s' % (hooked, is_get_profiles) def testProfilePrinting(self): + ee.data.computeValue = self.MockValue out = six.StringIO() with ee.profilePrinting(destination=out): self.assertEqual('hooked=True getProfiles=False', ee.Number(1).getInfo()) @@ -33,6 +29,7 @@ def testProfilePrinting(self): def testProfilePrintingDefaultSmoke(self): # This will print to sys.stderr, so we can't make any assertions about the # output. But we can check that it doesn't fail. + ee.data.computeValue = self.MockValue with ee.profilePrinting(): self.assertEqual('hooked=True getProfiles=False', ee.Number(1).getInfo()) diff --git a/python/ee/tests/batch_test.py b/python/ee/tests/batch_test.py index a5cb3dcc6..77cca22d0 100644 --- a/python/ee/tests/batch_test.py +++ b/python/ee/tests/batch_test.py @@ -1,7 +1,6 @@ #!/usr/bin/env python """Test for the ee.batch module.""" import copy -import json import mock @@ -41,82 +40,6 @@ def setUp(self): self.start_call_params = None self.update_call_params = None - def mock_send(path, params, unused_method=None, unused_raw=None): - if path == '/newtaskid': - return ['TESTTASKID'] - elif path == '/tasklist': - return {'tasks': [TASK_STATUS_1.copy(), TASK_STATUS_2.copy()]} - elif path == '/taskstatus': - if params['q'] == TASK_STATUS_1['id']: - return [TASK_STATUS_1.copy()] - elif params['q'] == TASK_STATUS_2['id']: - return [TASK_STATUS_2.copy()] - else: - return [{ - 'creation_timestamp_ms': 0, - 'id': params['q'], - 'state': 'UNKNOWN' - }] - elif path == '/processingrequest': - self.start_call_params = params - return {'started': 'OK'} - elif path == '/updatetask': - self.update_call_params = params - return {'updated': 'OK'} - else: - raise Exception('Unexpected API call to %s with %s' % (path, params)) - ee.data.send_ = mock_send - - def testTaskList(self): - """Verifies the return value of Task.list().""" - tasks = ee.batch.Task.list() - self.assertEqual(2, len(tasks)) - self.assertEqual(TASK_STATUS_1['id'], tasks[0].id) - self.assertEqual(TASK_STATUS_1['task_type'], tasks[0].task_type) - self.assertEqual(TASK_STATUS_2['id'], tasks[1].id) - - def testTaskStatus(self): - """Verifies the return value of Task.status().""" - tasks = ee.batch.Task.list() - self.assertEqual( - { - 'state': 'RUNNING', - 'creation_timestamp_ms': 7, - 'update_timestamp_ms': 42, - 'description': 'FirstTestTask', - 'id': 'TEST1', - 'source_url': 'http://example.org/', - 'start_timestamp_ms': 13, - 'task_type': 'EXPORT_IMAGE', - }, tasks[0].status()) - self.assertTrue(tasks[0].active()) - self.assertEqual( - { - 'state': 'FAILED', - 'creation_timestamp_ms': 17, - 'update_timestamp_ms': 142, - 'error_message': 'Explosions.', - 'description': 'SecondTestTask', - 'id': 'TEST2', - 'start_timestamp_ms': 113, - 'task_type': 'EXPORT_FEATURES', - }, tasks[1].status()) - self.assertFalse(tasks[1].active()) - new_task = ee.batch.Export.table(ee.FeatureCollection('foo')) - self.assertEqual({ - 'state': 'UNSUBMITTED', - 'creation_timestamp_ms': 0, - 'id': 'TESTTASKID', - }, new_task.status()) - self.assertFalse(new_task.active()) - - def testTaskStart(self): - """Verifies that Task.start() calls the server appropriately.""" - task = ee.batch.Export.table(ee.FeatureCollection('foo'), 'bar') - task.start() - self.assertEqual('TESTTASKID', self.start_call_params['id']) - self.assertEqual('bar', self.start_call_params['description']) - def testTaskStartCloudApi(self): """Verifies that Task.start() calls the server appropriately.""" mock_cloud_api_resource = mock.MagicMock() @@ -132,13 +55,6 @@ def testTaskStartCloudApi(self): self.assertTrue(export_args[1]['body']['requestId']) self.assertEqual(export_args[1]['body']['description'], 'bar') - def testTaskCancel(self): - """Verifies that Task.cancel() calls the server appropriately.""" - task = ee.batch.Task.list()[0] - task.cancel() - self.assertEqual('TEST1', self.update_call_params['id']) - self.assertEqual('CANCEL', self.update_call_params['action']) - def testTaskCancelCloudApi(self): mock_cloud_api_resource = mock.MagicMock() mock_cloud_api_resource.projects().operations().list( @@ -159,37 +75,6 @@ def testTaskCancelCloudApi(self): cancel_args[1]['name'], 'projects/earthengine-legacy/operations/TEST1') - def testStringRepresentation(self): - """Verifies the string representation of tasks.""" - tasks = ee.batch.Task.list() - self.assertEqual('', - str(tasks[0])) - self.assertEqual('', - str(tasks[1])) - new_task = ee.batch.Export.table(ee.FeatureCollection('foo'), 'bar') - self.assertEqual('', - str(new_task)) - self.assertEqual( - '', str(ee.batch.Task('foo', None, None, None))) - - def testExportImageTrivialRegion(self): - """Verifies the task created by Export.image() with a trivial region.""" - task = ee.batch.Export.image.toAsset( - ee.Image(42), - assetId='users/foo/bar', - region=[0, 0, 1, 0, 1, 1], - scale=1000) - self.assertEqual('TESTTASKID', task.id) - self.assertEqual('EXPORT_IMAGE', task.task_type) - self.assertEqual('UNSUBMITTED', task.state) - self.assertEqual({ - 'assetId': 'users/foo/bar', - 'description': 'myExportImageTask', - 'json': ee.Image(42).serialize(for_cloud_api=False), - 'region': '[0, 0, 1, 0, 1, 1]', - 'scale': 1000, - }, task.config) - def testExportImageTrivialRegionCloudApi(self): """Verifies the task created by Export.image() with a trivial region.""" with apitestcase.UsingCloudApi(): @@ -213,26 +98,6 @@ def testExportImageTrivialRegionCloudApi(self): 'description': 'myExportImageTask', }, task.config) - def testExportImage(self): - """Verifies the task created by Export.image().""" - region = ee.Geometry.Rectangle(1, 2, 3, 4) - config = dict(region=region['coordinates'], maxPixels=10**10, - crs='foo', crs_transform='[9,8,7,6,5,4]') - task = ee.batch.Export.image(ee.Image(1), 'TestDescription', config) - self.assertEqual('TESTTASKID', task.id) - self.assertEqual('EXPORT_IMAGE', task.task_type) - self.assertEqual('UNSUBMITTED', task.state) - self.assertEqual({ - 'fileFormat': 'GeoTIFF', - 'json': ee.Image(1).serialize(for_cloud_api=False), - 'description': 'TestDescription', - 'region': '[[[1, 4], [1, 2], [3, 2], [3, 4]]]', - 'driveFileNamePrefix': 'TestDescription', - 'maxPixels': 10**10, - 'crs': 'foo', - 'crs_transform': '[9,8,7,6,5,4]', - }, task.config) - def testExportImageCloudApi(self): """Verifies the task created by Export.image().""" with apitestcase.UsingCloudApi(): @@ -337,37 +202,6 @@ def testExportImageWithTfRecordCloudApi(self): }, }, task.config) - def testExportImageToAsset(self): - """Verifies the Asset export task created by Export.image.toAsset().""" - config = dict( - image=ee.Image(1), assetId='users/foo/bar', - pyramidingPolicy={'B1': 'min'}) - - # Test keyed parameters. - task_keyed = ee.batch.Export.image.toAsset( - image=config['image'], assetId=config['assetId'], - pyramidingPolicy=config['pyramidingPolicy']) - self.assertEqual('TESTTASKID', task_keyed.id) - self.assertEqual('EXPORT_IMAGE', task_keyed.task_type) - self.assertEqual('UNSUBMITTED', task_keyed.state) - self.assertEqual({ - 'json': config['image'].serialize(for_cloud_api=False), - 'description': 'myExportImageTask', - 'assetId': config['assetId'], - 'pyramidingPolicy': json.dumps(config['pyramidingPolicy']), - }, task_keyed.config) - - task_ordered = ee.batch.Export.image.toAsset( - config['image'], 'TestDescription', config['assetId'], maxPixels=1000) - self.assertEqual('EXPORT_IMAGE', task_ordered.task_type) - self.assertEqual('UNSUBMITTED', task_ordered.state) - self.assertEqual({ - 'json': config['image'].serialize(for_cloud_api=False), - 'description': 'TestDescription', - 'assetId': config['assetId'], - 'maxPixels': 1000 - }, task_ordered.config) - def testExportImageToAssetCloudApi(self): """Verifies the Asset export task created by Export.image.toAsset().""" with apitestcase.UsingCloudApi(): @@ -427,28 +261,6 @@ def testExportImageToAssetCloudApi(self): } }, task_ordered.config) - def testExportImageToCloudStorage(self): - """Verifies the Cloud Storage export task created by Export.image().""" - region = ee.Geometry.Rectangle(1, 2, 3, 4) - config = dict(region=region['coordinates'], maxPixels=10**10, - outputBucket='test-bucket') - task = ee.batch.Export.image.toCloudStorage( - ee.Image(1), 'TestDescription', - config['outputBucket'], None, None, - config['region'], None, None, None, config['maxPixels']) - self.assertEqual('TESTTASKID', task.id) - self.assertEqual('EXPORT_IMAGE', task.task_type) - self.assertEqual('UNSUBMITTED', task.state) - self.assertEqual({ - 'fileFormat': 'GeoTIFF', - 'json': ee.Image(1).serialize(for_cloud_api=False), - 'description': 'TestDescription', - 'region': '[[[1, 4], [1, 2], [3, 2], [3, 4]]]', - 'outputBucket': 'test-bucket', - 'outputPrefix': 'TestDescription', - 'maxPixels': 10**10, - }, task.config) - def testExportImageToCloudStorageCloudApi(self): """Verifies the Cloud Storage export task created by Export.image().""" with apitestcase.UsingCloudApi(): @@ -554,49 +366,6 @@ def testConvertFormatTfRecord(self): 'tfrecordCompressed': True }) - def testExportImageToGoogleDrive(self): - """Verifies the Drive destined task created by Export.image.toDrive().""" - region = ee.Geometry.Rectangle(1, 2, 3, 4) - drive_task_by_keys = ee.batch.Export.image.toDrive( - image=ee.Image(1), region=region['coordinates'], folder='foo', - maxPixels=10**10, crsTransform='[9,8,7,6,5,4]') - self.assertEqual('TESTTASKID', drive_task_by_keys.id) - self.assertEqual('EXPORT_IMAGE', drive_task_by_keys.task_type) - self.assertEqual('UNSUBMITTED', drive_task_by_keys.state) - self.assertEqual( - { - 'fileFormat': 'GeoTIFF', - 'json': ee.Image(1).serialize(for_cloud_api=False), - 'description': 'myExportImageTask', - 'region': '[[[1, 4], [1, 2], [3, 2], [3, 4]]]', - 'driveFileNamePrefix': 'myExportImageTask', - 'driveFolder': 'foo', - 'maxPixels': 10**10, - # Transformed by _ConvertToServerParams. - 'crs_transform': '[9,8,7,6,5,4]', - }, - drive_task_by_keys.config) - - drive_task_with_old_keys = ee.batch.Export.image.toDrive( - image=ee.Image(1), region=region['coordinates'], driveFolder='foo', - driveFileNamePrefix='fooExport', maxPixels=10**10, - crs_transform='[9,8,7,6,5,4]') - self.assertEqual('EXPORT_IMAGE', drive_task_with_old_keys.task_type) - self.assertEqual('UNSUBMITTED', drive_task_with_old_keys.state) - self.assertEqual( - { - 'fileFormat': 'GeoTIFF', - 'json': ee.Image(1).serialize(for_cloud_api=False), - 'description': 'myExportImageTask', - 'region': '[[[1, 4], [1, 2], [3, 2], [3, 4]]]', - 'driveFileNamePrefix': 'fooExport', - 'driveFolder': 'foo', - 'maxPixels': 10**10, - # Transformed by _ConvertToServerParams. - 'crs_transform': '[9,8,7,6,5,4]', - }, - drive_task_with_old_keys.config) - def testExportImageToGoogleDriveCloudApi(self): """Verifies the Drive destined task created by Export.image.toDrive().""" with apitestcase.UsingCloudApi(): @@ -652,54 +421,6 @@ def testExportImageToGoogleDriveCloudApi(self): 'Unknown configuration options.*'): ee.batch.Export.image.toDrive(image=ee.Image(1), framesPerSecond=30) - def testExportImageFileDimensions(self): - """Verifies proper handling of the fileDimensions parameter.""" - number_task = ee.batch.Export.image.toDrive( - image=ee.Image(1), fileDimensions=100) - self.assertEqual(100, number_task.config['fileDimensions']) - - tuple_task = ee.batch.Export.image.toDrive( - image=ee.Image(1), fileDimensions=(100, 200)) - self.assertEqual('100,200', tuple_task.config['fileDimensions']) - - def testExportMapToCloudStorage(self): - """Verifies the task created by Export.map.toCloudStorage().""" - config = dict( - image=ee.Image(1), bucket='test-bucket', maxZoom=7, path='foo/gcs/path') - - # Test keyed parameters. - task_keyed = ee.batch.Export.map.toCloudStorage( - image=config['image'], bucket=config['bucket'], - maxZoom=config['maxZoom'], path=config['path']) - self.assertEqual('TESTTASKID', task_keyed.id) - self.assertEqual('EXPORT_TILES', task_keyed.task_type) - self.assertEqual('UNSUBMITTED', task_keyed.state) - self.assertEqual({ - 'json': config['image'].serialize(for_cloud_api=False), - 'description': 'myExportMapTask', - 'outputBucket': config['bucket'], - 'maxZoom': config['maxZoom'], - 'outputPrefix': config['path'], - 'writePublicTiles': True, - 'fileFormat': 'auto' - }, task_keyed.config) - - # Test ordered parameters. - task_ordered = ee.batch.Export.map.toCloudStorage( - config['image'], 'TestDescription', config['bucket'], 'jpeg', None, - False, None, 30) - self.assertEqual('EXPORT_TILES', task_ordered.task_type) - self.assertEqual('UNSUBMITTED', task_ordered.state) - self.assertEqual({ - 'json': config['image'].serialize(for_cloud_api=False), - 'description': 'TestDescription', - 'outputBucket': config['bucket'], - 'outputPrefix': 'TestDescription', - 'scale': 30, - 'writePublicTiles': False, - 'fileFormat': 'jpeg' - }, task_ordered.config) - def testExportMapToCloudStorageCloudApi(self): """Verifies the task created by Export.map.toCloudStorage().""" with apitestcase.UsingCloudApi(): @@ -768,20 +489,6 @@ def testExportMapToCloudStorageCloudApi(self): 'maxWorkerCount': {'value': 100} }, task_ordered.config) - def testExportTable(self): - """Verifies the task created by Export.table().""" - task = ee.batch.Export.table(ee.FeatureCollection('drive test FC')) - self.assertEqual('TESTTASKID', task.id) - self.assertEqual('EXPORT_FEATURES', task.task_type) - self.assertEqual('UNSUBMITTED', task.state) - expected_fc = ee.FeatureCollection('drive test FC') - self.assertEqual({ - 'json': expected_fc.serialize(for_cloud_api=False), - 'description': 'myExportTableTask', - 'driveFileNamePrefix': 'myExportTableTask', - 'fileFormat': 'CSV', - }, task.config) - def testExportTableCloudApi(self): """Verifies the task created by Export.table().""" with apitestcase.UsingCloudApi(): @@ -811,22 +518,6 @@ def testExportTableCloudApiBogusParameter(self): ee.batch.Export.table.toDrive( ee.FeatureCollection('drive test FC'), framesPerSecond=30) - def testExportTableSelectors(self): - """Verifies that table export accepts a list or tuple of selectors.""" - task = ee.batch.Export.table.toCloudStorage( - collection=ee.FeatureCollection('foo'), - selectors=['ab', 'bb', 'c']) - self.assertEqual('ab,bb,c', task.config['selectors']) - task = ee.batch.Export.table.toCloudStorage( - collection=ee.FeatureCollection('foo'), - selectors=('x', 'y')) - self.assertEqual('x,y', task.config['selectors']) - # Single string should work too. - task = ee.batch.Export.table.toCloudStorage( - collection=ee.FeatureCollection('foo'), - selectors='ab,cd,ef') - self.assertEqual('ab,cd,ef', task.config['selectors']) - def testExportTableSelectorsCloudApi(self): """Verifies that table export accepts a list or tuple of selectors.""" with apitestcase.UsingCloudApi(): @@ -847,21 +538,6 @@ def testExportTableSelectorsCloudApi(self): outputBucket='foo') self.assertEqual(['ab', 'cd', 'ef'], task.config['selectors']) - def testExportTableToCloudStorage(self): - """Verifies the Cloud Storage task created by Export.table().""" - task = ee.batch.Export.table.toCloudStorage( - collection=ee.FeatureCollection('foo'), outputBucket='test-bucket') - self.assertEqual('TESTTASKID', task.id) - self.assertEqual('EXPORT_FEATURES', task.task_type) - self.assertEqual('UNSUBMITTED', task.state) - self.assertEqual({ - 'json': ee.FeatureCollection('foo').serialize(for_cloud_api=False), - 'description': 'myExportTableTask', - 'outputBucket': 'test-bucket', - 'outputPrefix': 'myExportTableTask', - 'fileFormat': 'CSV', - }, task.config) - def testExportTableToCloudStorageCloudApi(self): """Verifies the Cloud Storage task created by Export.table().""" with apitestcase.UsingCloudApi(): @@ -883,52 +559,6 @@ def testExportTableToCloudStorageCloudApi(self): } }, task.config) - def testExportTableToGoogleDrive(self): - """Verifies the Drive destined task created by Export.table.toDrive().""" - test_collection = ee.FeatureCollection('foo') - test_description = 'TestDescription' - test_file_name_prefix = 'fooDriveFileNamePrefix' - test_format = 'KML' - expected_config = { - 'json': test_collection.serialize(for_cloud_api=False), - 'description': test_description, - 'driveFileNamePrefix': test_file_name_prefix, - 'fileFormat': test_format, - } - - # Ordered parameters - task_ordered = ee.batch.Export.table.toDrive( - test_collection, test_description, - None, test_file_name_prefix, test_format) - self.assertEqual('TESTTASKID', task_ordered.id) - self.assertEqual('EXPORT_FEATURES', task_ordered.task_type) - self.assertEqual('UNSUBMITTED', task_ordered.state) - self.assertEqual(expected_config, task_ordered.config) - - # Updating expectations to test keyed parameters - expected_config.update({ - 'fileFormat': 'CSV', - 'description': 'myExportTableTask', - 'driveFolder': 'fooFolder' - }) - - # Test that deprecated parameters (driveFolder and driveFileNamePrefix) - # still work. - task_old_keys = ee.batch.Export.table.toDrive( - collection=test_collection, driveFolder='fooFolder', - driveFileNamePrefix='fooDriveFileNamePrefix') - self.assertEqual('EXPORT_FEATURES', task_old_keys.task_type) - self.assertEqual('UNSUBMITTED', task_old_keys.state) - self.assertEqual(expected_config, task_old_keys.config) - - # Test that new parameters work - task_new_keys = ee.batch.Export.table.toDrive( - collection=test_collection, folder='fooFolder', - fileNamePrefix='fooDriveFileNamePrefix') - self.assertEqual('EXPORT_FEATURES', task_new_keys.task_type) - self.assertEqual('UNSUBMITTED', task_new_keys.state) - self.assertEqual(expected_config, task_new_keys.config) - def testExportTableToGoogleDriveCloudApi(self): """Verifies the Drive destined task created by Export.table.toDrive().""" with apitestcase.UsingCloudApi(): @@ -980,21 +610,6 @@ def testExportTableToGoogleDriveCloudApi(self): self.assertEqual('UNSUBMITTED', task_new_keys.state) self.assertEqual(expected_config, task_new_keys.config) - def testExportTableToAsset(self): - """Verifies the export task created by Export.table.toAsset().""" - task = ee.batch.Export.table.toAsset( - collection=ee.FeatureCollection('foo'), - description='foo', - assetId='users/foo/bar') - self.assertEqual('TESTTASKID', task.id) - self.assertEqual('EXPORT_FEATURES', task.task_type) - self.assertEqual('UNSUBMITTED', task.state) - self.assertEqual({ - 'json': ee.FeatureCollection('foo').serialize(for_cloud_api=False), - 'description': 'foo', - 'assetId': 'users/foo/bar' - }, task.config) - def testExportTableToAssetCloudApi(self): """Verifies the export task created by Export.table.toAsset().""" with apitestcase.UsingCloudApi(): @@ -1016,24 +631,6 @@ def testExportTableToAssetCloudApi(self): } }, task.config) - def testExportTableWithFileFormat(self): - """Verifies the task created by Export.table() given a file format.""" - task = ee.batch.Export.table.toCloudStorage( - collection=ee.FeatureCollection('foo'), - outputBucket='test-bucket', - fileFormat='tfRecord') - self.assertEqual('TESTTASKID', task.id) - self.assertEqual('EXPORT_FEATURES', task.task_type) - self.assertEqual('UNSUBMITTED', task.state) - self.assertEqual( - { - 'json': ee.FeatureCollection('foo').serialize(for_cloud_api=False), - 'description': 'myExportTableTask', - 'outputBucket': 'test-bucket', - 'outputPrefix': 'myExportTableTask', - 'fileFormat': 'tfRecord', - }, task.config) - def testExportTableWithFileFormatCloudApi(self): """Verifies the task created by Export.table() given a file format.""" with apitestcase.UsingCloudApi(): @@ -1058,39 +655,6 @@ def testExportTableWithFileFormatCloudApi(self): } }, task.config) - def testExportVideo(self): - """Verifies the task created by Export.video().""" - region = ee.Geometry.Rectangle(1, 2, 3, 4) - config = dict(region=region['coordinates'], dimensions=16) - collection = ee.ImageCollection([ee.Image(1), ee.Image(2)]) - task = ee.batch.Export.video(collection, 'TestVideoName', config) - self.assertEqual('TESTTASKID', task.id) - self.assertEqual('EXPORT_VIDEO', task.task_type) - self.assertEqual('UNSUBMITTED', task.state) - # Defaults the destination to Drive. - self.assertEqual({ - 'json': collection.serialize(for_cloud_api=False), - 'description': 'TestVideoName', - 'crs': 'SR-ORG:6627', - 'driveFileNamePrefix': 'TestVideoName', - 'region': '[[[1, 4], [1, 2], [3, 2], [3, 4]]]', - 'dimensions': 16 - }, task.config) - - config['outputBucket'] = 'test-bucket' - gcs_task = ee.batch.Export.video(collection, 'TestVideoName', config) - self.assertEqual('EXPORT_VIDEO', gcs_task.task_type) - self.assertEqual('UNSUBMITTED', gcs_task.state) - self.assertEqual({ - 'json': collection.serialize(for_cloud_api=False), - 'description': 'TestVideoName', - 'crs': 'SR-ORG:6627', - 'outputBucket': 'test-bucket', - 'outputPrefix': 'TestVideoName', - 'region': '[[[1, 4], [1, 2], [3, 2], [3, 4]]]', - 'dimensions': 16 - }, gcs_task.config) - def testExportVideoCloudApi(self): """Verifies the task created by Export.video().""" with apitestcase.UsingCloudApi(): @@ -1173,44 +737,6 @@ def expected_preparation_function(img): ee.batch.Export.video(collection, 'TestVideoName', config_with_bogus_option) - def testExportVideoToCloudStorage(self): - """Verifies the task created by Export.video.toCloudStorage().""" - region = ee.Geometry.Rectangle(1, 2, 3, 4) - collection = ee.ImageCollection([ee.Image(1), ee.Image(2)]) - expected_config = { - 'json': collection.serialize(for_cloud_api=False), - 'description': 'TestVideoName', - 'outputBucket': 'test-bucket', - 'outputPrefix': 'TestVideoName', - 'region': '[[[1, 4], [1, 2], [3, 2], [3, 4]]]', - 'dimensions': 16, - # Transformed by _ConvertToServerParams. - 'crs_transform': '[9,8,7,6,5,4]', - 'crs': 'foo' - } - - # Test keyed parameters. - task_keyed = ee.batch.Export.video.toCloudStorage( - collection=collection, - description='TestVideoName', - bucket='test-bucket', - dimensions=16, - region=region['coordinates'], - crsTransform='[9,8,7,6,5,4]', - crs='foo') - self.assertEqual('TESTTASKID', task_keyed.id) - self.assertEqual('EXPORT_VIDEO', task_keyed.task_type) - self.assertEqual('UNSUBMITTED', task_keyed.state) - self.assertEqual(expected_config, task_keyed.config) - - # Test ordered parameters. - task_ordered = ee.batch.Export.video.toCloudStorage( - collection, 'TestVideoName', 'test-bucket', None, None, 16, - region['coordinates'], None, 'foo', '[9,8,7,6,5,4]') - self.assertEqual('EXPORT_VIDEO', task_ordered.task_type) - self.assertEqual('UNSUBMITTED', task_ordered.state) - self.assertEqual(expected_config, task_ordered.config) - def testExportVideoToCloudStorageCloudApi(self): """Verifies the task created by Export.video.toCloudStorage().""" with apitestcase.UsingCloudApi(): @@ -1263,42 +789,6 @@ def expected_preparation_function(img): task_ordered.config.pop('expression').serialize(for_cloud_api=True)) self.assertEqual(expected_config, task_ordered.config) - def testExportVideoToDrive(self): - """Verifies the task created by Export.video.toDrive().""" - region = ee.Geometry.Rectangle(1, 2, 3, 4) - collection = ee.ImageCollection([ee.Image(1), ee.Image(2)]) - expected_config = { - 'json': collection.serialize(for_cloud_api=False), - 'description': 'TestVideoName', - 'crs': 'SR-ORG:6627', - 'driveFolder': 'test-folder', - 'driveFileNamePrefix': 'TestVideoName', - 'region': '[[[1, 4], [1, 2], [3, 2], [3, 4]]]', - 'dimensions': 16, - 'crs_transform': '[9,8,7,6,5,4]' - } - - # Test keyed parameters. - task_keyed = ee.batch.Export.video.toDrive( - collection=collection, - description='TestVideoName', - folder='test-folder', - dimensions=16, - crsTransform='[9,8,7,6,5,4]', - region=region['coordinates']) - self.assertEqual('TESTTASKID', task_keyed.id) - self.assertEqual('EXPORT_VIDEO', task_keyed.task_type) - self.assertEqual('UNSUBMITTED', task_keyed.state) - self.assertEqual(expected_config, task_keyed.config) - - # Test ordered parameters. - task_ordered = ee.batch.Export.video.toDrive( - collection, 'TestVideoName', 'test-folder', None, None, 16, - region['coordinates'], None, 'SR-ORG:6627', '[9,8,7,6,5,4]') - self.assertEqual('EXPORT_VIDEO', task_ordered.task_type) - self.assertEqual('UNSUBMITTED', task_ordered.state) - self.assertEqual(expected_config, task_ordered.config) - def testExportVideoToDriveCloudApi(self): """Verifies the task created by Export.video.toDrive().""" with apitestcase.UsingCloudApi(): diff --git a/python/ee/tests/data_test.py b/python/ee/tests/data_test.py index 10de96fb1..ff94e5f16 100644 --- a/python/ee/tests/data_test.py +++ b/python/ee/tests/data_test.py @@ -5,7 +5,6 @@ import mock -from six.moves import urllib import unittest import ee from ee import apitestcase @@ -14,37 +13,6 @@ class DataTest(unittest.TestCase): - def setUp(self): - super(DataTest, self).setUp() - # Default this to false. Eventually this should default to true. - ee.data._use_cloud_api = False - - def testGetTaskList(self): - - def Request(unused_self, url, method, body, headers): - _ = method, body, headers # Unused kwargs. - - parse_result = urllib.parse.urlparse(url) - if parse_result.path != '/api/tasklist': - return httplib2.Response({'status': 404}), 'not found' - - resp_body = '{}' - query_args = urllib.parse.parse_qs(parse_result.query) - if query_args == {'pagesize': ['500']}: - resp_body = ('{"data": {"tasks": [{"id": "1"}],' - ' "next_page_token": "foo"}}') - elif query_args == {'pagesize': ['500'], 'pagetoken': ['foo']}: - resp_body = '{"data": {"tasks": [{"id": "2"}]}}' - - response = httplib2.Response({ - 'status': 200, - 'content-type': 'application/json', - }) - return response, resp_body - - with mock.patch('httplib2.Http.request', new=Request): - self.assertEqual([{'id': '1'}, {'id': '2'}], ee.data.getTaskList()) - def testListOperations(self): mock_http = mock.MagicMock(httplib2.Http) # Return in three groups. @@ -75,120 +43,6 @@ def testListOperationsEmptyList(self): with apitestcase.UsingCloudApi(mock_http=mock_http): self.assertEqual([], ee.data.listOperations()) - @mock.patch('time.sleep') - def testSuccess(self, mock_sleep): - with DoStubHttp(200, 'application/json', '{"data": "bar"}'): - self.assertEqual('bar', ee.data.send_('/foo', {})) - self.assertEqual(False, mock_sleep.called) - - @mock.patch('time.sleep') - def testRetry(self, mock_sleep): - with DoStubHttp(429, 'application/json', '{"data": "bar"}'): - with self.assertRaises(ee.ee_exception.EEException): - ee.data.send_('/foo', {}) - self.assertEqual(5, mock_sleep.call_count) - - def testNon200Success(self): - with DoStubHttp(202, 'application/json', '{"data": "bar"}'): - self.assertEqual('bar', ee.data.send_('/foo', {})) - - def testJsonSyntaxError(self): - with DoStubHttp(200, 'application/json', '{"data"}'): - with self.assertRaises(ee.ee_exception.EEException) as cm: - ee.data.send_('/foo', {}) - self.assertEqual('Invalid JSON: {"data"}', str(cm.exception)) - - def testJsonStructureError(self): - with DoStubHttp(200, 'application/json', '{}'): - with self.assertRaises(ee.ee_exception.EEException) as cm: - ee.data.send_('/foo', {}) - self.assertEqual('Malformed response: {}', str(cm.exception)) - - def testUnexpectedStatus(self): - with DoStubHttp(418, 'text/html', ''): - with self.assertRaises(ee.ee_exception.EEException) as cm: - ee.data.send_('/foo', {}) - self.assertEqual('Server returned HTTP code: 418. Reason: Ok.', - str(cm.exception)) - - def testJson200Error(self): - with DoStubHttp(200, 'application/json', - '{"error": {"code": 500, "message": "bar"}}'): - with self.assertRaises(ee.ee_exception.EEException) as cm: - ee.data.send_('/foo', {}) - self.assertEqual(u'bar', str(cm.exception)) - - def testJsonNon2xxError(self): - with DoStubHttp(400, 'application/json', - '{"error": {"code": 400, "message": "bar"}}'): - with self.assertRaises(ee.ee_exception.EEException) as cm: - ee.data.send_('/foo', {}) - self.assertEqual(u'bar', str(cm.exception)) - - def testWrongContentType(self): - with DoStubHttp(200, 'text/html', '{"data": "bar"}'): - with self.assertRaises(ee.ee_exception.EEException) as cm: - ee.data.send_('/foo', {}) - self.assertEqual(u'Response was unexpectedly not JSON, but text/html', - str(cm.exception)) - - def testNoContentType(self): - with DoStubHttp(200, None, '{"data": "bar"}'): - self.assertEqual('bar', ee.data.send_('/foo', {})) - - def testContentTypeParameterAllowed(self): - with DoStubHttp(200, 'application/json; charset=utf-8', '{"data": ""}'): - self.assertEqual('', ee.data.send_('/foo', {})) - - def testRawSuccess(self): - with DoStubHttp(200, 'image/png', 'FAKEDATA'): - self.assertEqual('FAKEDATA', ee.data.send_('/foo', {}, opt_raw=True)) - - def testRawError(self): - with DoStubHttp(400, 'application/json', - '{"error": {"code": 400, "message": "bar"}}'): - with self.assertRaises(ee.ee_exception.EEException) as cm: - ee.data.send_('/foo', {}, opt_raw=True) - self.assertEqual(u'Server returned HTTP code: 400. Reason: Ok.', - str(cm.exception)) - - def testRaw200Error(self): - """Raw shouldn't be parsed, so the error-in-200 shouldn't be noticed. - - (This is an edge case we do not expect to see.) - """ - with DoStubHttp(200, 'application/json', - '{"error": {"code": 400, "message": "bar"}}'): - self.assertEqual('{"error": {"code": 400, "message": "bar"}}', - ee.data.send_('/foo', {}, opt_raw=True)) - - def testNotProfiling(self): - # Test that we do not request profiling. - with DoProfileStubHttp(self, False): - ee.data.send_('/foo', {}) - - def testProfiling(self): - with DoProfileStubHttp(self, True): - seen = [] - def ProfileHook(profile_id): - seen.append(profile_id) - - with ee.data.profiling(ProfileHook): - ee.data.send_('/foo', {}) - self.assertEqual(['someProfileId'], seen) - - def testProfilingCleanup(self): - with DoProfileStubHttp(self, True): - try: - with ee.data.profiling(lambda _: None): - raise ExceptionForTest() - except ExceptionForTest: - pass - - # Should not have profiling enabled after exiting the context by raising. - with DoProfileStubHttp(self, False): - ee.data.send_('/foo', {}) - def testSetAssetProperties(self): mock_http = mock.MagicMock(httplib2.Http) with apitestcase.UsingCloudApi(mock_http=mock_http), mock.patch.object( @@ -408,34 +262,6 @@ def testCloudErrorTranslation(self): ee.data.listImages({'parent': 'projects/earthengine-public/assets/q'}) -def DoStubHttp(status, mime, resp_body): - """Context manager for temporarily overriding Http.""" - def Request(unused_self, unused_url, method, body, headers): - _ = method, body, headers # Unused kwargs. - response = httplib2.Response({ - 'status': status, - 'content-type': mime, - }) - return response, resp_body - return mock.patch('httplib2.Http.request', new=Request) - - -def DoProfileStubHttp(test, expect_profiling): - def Request(unused_self, unused_url, method, body, headers): - _ = method, headers # Unused kwargs. - test.assertEqual(expect_profiling, 'profiling=1' in body, msg=body) - response_dict = { - 'status': 200, - 'content-type': 'application/json' - } - if expect_profiling: - response_dict[ - ee.data._PROFILE_RESPONSE_HEADER_LOWERCASE] = 'someProfileId' - response = httplib2.Response(response_dict) - return response, '{"data": "dummy_data"}' - return mock.patch('httplib2.Http.request', new=Request) - - def DoCloudProfileStubHttp(test, expect_profiling): def Request(unused_self, unused_url, method, body, headers): @@ -454,9 +280,5 @@ def Request(unused_self, unused_url, method, body, headers): return mock.patch('httplib2.Http.request', new=Request) -class ExceptionForTest(Exception): - pass - - if __name__ == '__main__': unittest.main() diff --git a/python/ee/tests/ee_test.py b/python/ee/tests/ee_test.py index d50fc2b1f..c1db099e5 100644 --- a/python/ee/tests/ee_test.py +++ b/python/ee/tests/ee_test.py @@ -15,16 +15,14 @@ class EETestCase(apitestcase.ApiTestCase): def setUp(self): ee.Reset() + ee.data._install_cloud_api_resource = lambda: None def testInitialization(self): """Verifies library initialization.""" - def MockSend(path, params, unused_method=None, unused_raw=None): - if path == '/algorithms': - return {} - else: - raise Exception('Unexpected API call to %s with %s' % (path, params)) - ee.data.send_ = MockSend + def MockAlgorithms(): + return {} + ee.data.getAlgorithms = MockAlgorithms # Verify that the base state is uninitialized. self.assertFalse(ee.data._initialized) @@ -33,14 +31,14 @@ def MockSend(path, params, unused_method=None, unused_raw=None): self.assertFalse(ee.Image._initialized) # Verify that ee.Initialize() sets the URL and initializes classes. - ee.Initialize(None, 'foo', use_cloud_api=False) + ee.Initialize(None, 'foo') self.assertTrue(ee.data._initialized) self.assertEqual(ee.data._api_base_url, 'foo/api') self.assertEqual(ee.ApiFunction._api, {}) self.assertTrue(ee.Image._initialized) # Verify that ee.Initialize(None) does not override custom URLs. - ee.Initialize(None, use_cloud_api=False) + ee.Initialize(None) self.assertTrue(ee.data._initialized) self.assertEqual(ee.data._api_base_url, 'foo/api') @@ -55,24 +53,21 @@ def testCallAndApply(self): """Verifies library initialization.""" # Use a custom set of known functions. - def MockSend(path, params, unused_method=None, unused_raw=None): - if path == '/algorithms': - return { - 'fakeFunction': { - 'type': 'Algorithm', - 'args': [ - {'name': 'image1', 'type': 'Image'}, - {'name': 'image2', 'type': 'Image'} - ], - 'returns': 'Image' - }, - 'Image.constant': apitestcase.BUILTIN_FUNCTIONS['Image.constant'] - } - else: - raise Exception('Unexpected API call to %s with %s' % (path, params)) - ee.data.send_ = MockSend - - ee.Initialize(None, use_cloud_api=False) + def MockAlgorithms(): + return { + 'fakeFunction': { + 'type': 'Algorithm', + 'args': [ + {'name': 'image1', 'type': 'Image'}, + {'name': 'image2', 'type': 'Image'} + ], + 'returns': 'Image' + }, + 'Image.constant': apitestcase.BUILTIN_FUNCTIONS['Image.constant'] + } + ee.data.getAlgorithms = MockAlgorithms + + ee.Initialize(None) image1 = ee.Image(1) image2 = ee.Image(2) expected = ee.Image(ee.ComputedObject( @@ -105,77 +100,76 @@ def testDynamicClasses(self): """Verifies dynamic class initialization.""" # Use a custom set of known functions. - def MockSend(path, unused_params, unused_method=None, unused_raw=None): - if path == '/algorithms': - return { - 'Array': { - 'type': 'Algorithm', - 'args': [ - { - 'name': 'values', - 'type': 'Serializable', - 'description': '' - } - ], - 'description': '', - 'returns': 'Array' - }, - 'Array.cos': { - 'type': 'Algorithm', - 'args': [ - { - 'type': 'Array', - 'description': '', - 'name': 'input' - } - ], - 'description': '', - 'returns': 'Array' - }, - 'Kernel.circle': { - 'returns': 'Kernel', - 'args': [ - { - 'type': 'float', - 'description': '', - 'name': 'radius', - }, - { - 'default': 1.0, - 'type': 'float', - 'optional': True, - 'description': '', - 'name': 'scale' - }, - { - 'default': True, - 'type': 'boolean', - 'optional': True, - 'description': '', - 'name': 'normalize' - } - ], - 'type': 'Algorithm', - 'description': '' - }, - 'Reducer.mean': { - 'returns': 'Reducer', - 'args': [] - }, - 'fakeFunction': { - 'returns': 'Array', - 'args': [ - { - 'type': 'Reducer', - 'description': '', - 'name': 'kernel', - } - ] - } - } - ee.data.send_ = MockSend - - ee.Initialize(None, use_cloud_api=False) + def MockAlgorithms(): + return { + 'Array': { + 'type': 'Algorithm', + 'args': [ + { + 'name': 'values', + 'type': 'Serializable', + 'description': '' + } + ], + 'description': '', + 'returns': 'Array' + }, + 'Array.cos': { + 'type': 'Algorithm', + 'args': [ + { + 'type': 'Array', + 'description': '', + 'name': 'input' + } + ], + 'description': '', + 'returns': 'Array' + }, + 'Kernel.circle': { + 'returns': 'Kernel', + 'args': [ + { + 'type': 'float', + 'description': '', + 'name': 'radius', + }, + { + 'default': 1.0, + 'type': 'float', + 'optional': True, + 'description': '', + 'name': 'scale' + }, + { + 'default': True, + 'type': 'boolean', + 'optional': True, + 'description': '', + 'name': 'normalize' + } + ], + 'type': 'Algorithm', + 'description': '' + }, + 'Reducer.mean': { + 'returns': 'Reducer', + 'args': [] + }, + 'fakeFunction': { + 'returns': 'Array', + 'args': [ + { + 'type': 'Reducer', + 'description': '', + 'name': 'kernel', + } + ] + } + } + ee.data.getAlgorithms = MockAlgorithms + + ee.Initialize(None) # Verify that the expected classes got generated. self.assertTrue(hasattr(ee, 'Array')) @@ -220,35 +214,34 @@ def testDynamicConstructor(self): # Bar Foo.makeBar() # Bar Foo.takeBar(Bar bar) # Baz Foo.baz() - def MockSend(path, unused_params, unused_method=None, unused_raw=None): - if path == '/algorithms': - return { - 'Foo': { - 'returns': 'Foo', - 'args': [ - {'name': 'arg1', 'type': 'Object'}, - {'name': 'arg2', 'type': 'Object', 'optional': True} - ] - }, - 'Foo.makeBar': { - 'returns': 'Bar', - 'args': [{'name': 'foo', 'type': 'Foo'}] - }, - 'Foo.takeBar': { - 'returns': 'Bar', - 'args': [ - {'name': 'foo', 'type': 'Foo'}, - {'name': 'bar', 'type': 'Bar'} - ] - }, - 'Bar.baz': { - 'returns': 'Baz', - 'args': [{'name': 'bar', 'type': 'Bar'}] - } - } - - ee.data.send_ = MockSend - ee.Initialize(None, use_cloud_api=False) + def MockAlgorithms(): + return { + 'Foo': { + 'returns': 'Foo', + 'args': [ + {'name': 'arg1', 'type': 'Object'}, + {'name': 'arg2', 'type': 'Object', 'optional': True} + ] + }, + 'Foo.makeBar': { + 'returns': 'Bar', + 'args': [{'name': 'foo', 'type': 'Foo'}] + }, + 'Foo.takeBar': { + 'returns': 'Bar', + 'args': [ + {'name': 'foo', 'type': 'Foo'}, + {'name': 'bar', 'type': 'Bar'} + ] + }, + 'Bar.baz': { + 'returns': 'Baz', + 'args': [{'name': 'bar', 'type': 'Bar'}] + } + } + + ee.data.getAlgorithms = MockAlgorithms + ee.Initialize(None) # Try to cast something that's already of the right class. x = ee.Foo('argument') @@ -327,36 +320,34 @@ def testUnboundMethods(self): """Verifies unbound method attachment to ee.Algorithms.""" # Use a custom set of known functions. - def MockSend(path, unused_params, unused_method=None, unused_raw=None): - if path == '/algorithms': - return { - 'Foo': { - 'type': 'Algorithm', - 'args': [], - 'description': '', - 'returns': 'Object' - }, - 'Foo.bar': { - 'type': 'Algorithm', - 'args': [], - 'description': '', - 'returns': 'Object' - }, - 'Quux.baz': { - 'type': 'Algorithm', - 'args': [], - 'description': '', - 'returns': 'Object' - }, - 'last': { - 'type': 'Algorithm', - 'args': [], - 'description': '', - 'returns': 'Object' - } - } - ee.data.send_ = MockSend - ee.data._use_cloud_api = False + def MockAlgorithms(): + return { + 'Foo': { + 'type': 'Algorithm', + 'args': [], + 'description': '', + 'returns': 'Object' + }, + 'Foo.bar': { + 'type': 'Algorithm', + 'args': [], + 'description': '', + 'returns': 'Object' + }, + 'Quux.baz': { + 'type': 'Algorithm', + 'args': [], + 'description': '', + 'returns': 'Object' + }, + 'last': { + 'type': 'Algorithm', + 'args': [], + 'description': '', + 'returns': 'Object' + } + } + ee.data.getAlgorithms = MockAlgorithms ee.ApiFunction.importApi(lambda: None, 'Quux', 'Quux') ee._InitializeUnboundMethods() @@ -373,49 +364,48 @@ def testNonAsciiDocumentation(self): bar = u'b\u00E4r' baz = u'b\u00E2\u00DF' - def MockSend(path, unused_params, unused_method=None, unused_raw=None): - if path == '/algorithms': - return { - 'Foo': { - 'type': 'Algorithm', - 'args': [], - 'description': foo, - 'returns': 'Object' - }, - 'Image.bar': { - 'type': 'Algorithm', - 'args': [{ - 'name': 'bar', - 'type': 'Bar', - 'description': bar - }], - 'description': '', - 'returns': 'Object' - }, - 'Image.oldBar': { - 'type': 'Algorithm', - 'args': [], - 'description': foo, - 'returns': 'Object', - 'deprecated': 'Causes fire' - }, - 'Image.baz': { - 'type': 'Algorithm', - 'args': [], - 'description': baz, - 'returns': 'Object' - }, - 'Image.newBaz': { - 'type': 'Algorithm', - 'args': [], - 'description': baz, - 'returns': 'Object', - 'preview': True - } - } - ee.data.send_ = MockSend - - ee.Initialize(None, use_cloud_api=False) + def MockAlgorithms(): + return { + 'Foo': { + 'type': 'Algorithm', + 'args': [], + 'description': foo, + 'returns': 'Object' + }, + 'Image.bar': { + 'type': 'Algorithm', + 'args': [{ + 'name': 'bar', + 'type': 'Bar', + 'description': bar + }], + 'description': '', + 'returns': 'Object' + }, + 'Image.oldBar': { + 'type': 'Algorithm', + 'args': [], + 'description': foo, + 'returns': 'Object', + 'deprecated': 'Causes fire' + }, + 'Image.baz': { + 'type': 'Algorithm', + 'args': [], + 'description': baz, + 'returns': 'Object' + }, + 'Image.newBaz': { + 'type': 'Algorithm', + 'args': [], + 'description': baz, + 'returns': 'Object', + 'preview': True + } + } + ee.data.getAlgorithms = MockAlgorithms + + ee.Initialize(None) # The initialisation shouldn't blow up. self.assertTrue(callable(ee.Algorithms.Foo)) diff --git a/python/ee/tests/featurecollection_test.py b/python/ee/tests/featurecollection_test.py index c239b06a4..3358e0363 100644 --- a/python/ee/tests/featurecollection_test.py +++ b/python/ee/tests/featurecollection_test.py @@ -64,26 +64,20 @@ def testGetMapId(self): def testDownload(self): """Verifies that Download ID and URL generation.""" - csv_url = ee.FeatureCollection('test7').getDownloadURL('csv') + ee.FeatureCollection('test7').getDownloadURL('csv') self.assertEqual('/table', self.last_table_call['url']) - self.assertEqual({ - 'table': ee.FeatureCollection('test7').serialize(), - 'json_format': 'v2', - 'format': 'CSV' - }, self.last_table_call['data']) - self.assertEqual('/api/table?docid=5&token=6', csv_url) + self.assertEqual(ee.FeatureCollection('test7').serialize(), + self.last_table_call['data']['table'].serialize()) - everything_url = ee.FeatureCollection('test8').getDownloadURL( + ee.FeatureCollection('test8').getDownloadURL( 'json', 'bar, baz', 'qux') - self.assertEqual({ - 'table': ee.FeatureCollection('test8').serialize(), - 'json_format': 'v2', - 'format': 'JSON', - 'selectors': 'bar, baz', - 'filename': 'qux' - }, self.last_table_call['data']) - self.assertEqual('/api/table?docid=5&token=6', everything_url) + self.assertEqual( + ee.FeatureCollection('test8').serialize(), + self.last_table_call['data']['table'].serialize()) + self.assertEqual('JSON', self.last_table_call['data']['format']) + self.assertEqual('bar, baz', self.last_table_call['data']['selectors']) + self.assertEqual('qux', self.last_table_call['data']['filename']) self.assertEqual( ee.FeatureCollection('test7').getDownloadUrl('csv'), @@ -101,8 +95,8 @@ def testDownloadTableWithCloudApi(self): }) url = ee.data.makeTableDownloadUrl(result) - self.assertDictEqual(result, {'docid': 'table_name', 'token': ''}) - self.assertEqual(url, '/v1alpha/table_name:getFeatures') + self.assertDictEqual(result, {'docid': '5', 'token': '6'}) + self.assertEqual(url, '/v1alpha/5:getFeatures') def testSelect(self): def equals(c1, c2): diff --git a/python/ee/tests/image_test.py b/python/ee/tests/image_test.py index 9719c4810..10d749aad 100644 --- a/python/ee/tests/image_test.py +++ b/python/ee/tests/image_test.py @@ -85,8 +85,8 @@ def testGetMapIdVisualization(self): image.getMapId({'min': 0}) self.assertEqual( - ee.Image(1).visualize(min=0).serialize(for_cloud_api=False), - self.last_mapid_call['data']['image']) + ee.Image(1).visualize(min=0).serialize(), + self.last_mapid_call['data']['image'].serialize()) def testCombine(self): """Verifies the behavior of ee.Image.combine_().""" @@ -213,55 +213,18 @@ def testExpressionInCloudAPI(self): def testDownload(self): """Verifies Download ID and URL generation.""" - url = ee.Image(1).getDownloadURL() + ee.Image(1).getDownloadURL() self.assertEqual('/download', self.last_download_call['url']) - self.assertEqual({ - 'image': ee.Image(1).serialize(for_cloud_api=False), - 'json_format': 'v2' - }, self.last_download_call['data']) - self.assertEqual('/api/download?docid=1&token=2', url) - - def testThumb(self): - """Verifies Thumbnail ID and URL generation.""" - geo_json = { - 'type': 'Polygon', - 'coordinates': [[ - [-112.587890625, 44.94924926661151], - [-114.873046875, 39.48708498168749], - [-103.623046875, 41.82045509614031], - ]], - } - url = ee.Image(1).getThumbURL({ - 'size': [13, 42], - 'region': geo_json, - }) - - self.assertEqual('/thumb', self.last_thumb_call['url']) - self.assertEqual({ - 'image': ee.Image(1).serialize(for_cloud_api=False), - 'json_format': 'v2', - 'size': '13x42', - 'getid': '1', - 'region': json.dumps(geo_json), - }, self.last_thumb_call['data']) - self.assertEqual('/api/thumb?thumbid=3&token=4', url) - - # Again with visualization parameters - url = ee.Image(1).getThumbURL({ - 'size': [13, 42], - 'region': geo_json, - 'min': 0 - }) self.assertEqual( - ee.Image(1).visualize(min=0).serialize(for_cloud_api=False), - self.last_thumb_call['data']['image']) + ee.Image(1).serialize(), + self.last_download_call['data']['image'].serialize()) class CloudThumbnailAndExportImageTests(apitestcase.ApiTestCase): - def setUp(self): - super(CloudThumbnailAndExportImageTests, self).setUp() + def setUp(self): # pylint: disable=g-missing-super-call + self.InitializeApi(should_mock=False) self.cloud_api_resource = mock.MagicMock() self.cloud_api_resource.projects().thumbnails().create( ).execute.return_value = { @@ -283,8 +246,8 @@ def setUp(self): def assertImageEqual(self, expected, actual): self.assertDictEqual( - serializer.encode(expected, for_cloud_api=ee.data._use_cloud_api), - serializer.encode(actual, for_cloud_api=ee.data._use_cloud_api)) + serializer.encode(expected), + serializer.encode(actual)) def testThumb_withDimensionsRegionCrs(self): """Verifies Thumbnail ID and URL generation in the Cloud API.""" @@ -296,7 +259,7 @@ def testThumb_withDimensionsRegionCrs(self): 'crs': 'EPSG:4326', }) - self.assertEqual('/%s/thumbName:getPixels' % _cloud_api_utils.VERSION, + self.assertEqual('None/%s/thumbName:getPixels' % _cloud_api_utils.VERSION, url) _, kwargs = self.cloud_api_resource.projects().thumbnails( ).create.call_args @@ -308,8 +271,7 @@ def testThumb_withDimensionsRegionCrs(self): crsTransform=[1, 0, 0, 0, -1, 0]).clipToBoundsAndScale( geometry=ee.Geometry(self.geo_json, opt_geodesic=False), width=13, - height=42), - for_cloud_api=True)) + height=42))) self.assertEqual(kwargs['parent'], 'projects/earthengine-legacy') def testThumb_withDimensionsRegionJson(self): @@ -326,8 +288,7 @@ def testThumb_withDimensionsRegionJson(self): kwargs['body']['expression'], serializer.encode( self.base_image.clipToBoundsAndScale( - geometry=self.expected_geometry, width=13, height=42), - for_cloud_api=True)) + geometry=self.expected_geometry, width=13, height=42))) self.assertEqual(kwargs['parent'], 'projects/earthengine-legacy') def testThumb_withDimensionsListCoords(self): @@ -346,8 +307,7 @@ def testThumb_withDimensionsListCoords(self): kwargs['body']['expression'], serializer.encode( self.base_image.clipToBoundsAndScale( - geometry=expected_geometry, width=13, height=42), - for_cloud_api=True)) + geometry=expected_geometry, width=13, height=42))) self.assertEqual(kwargs['parent'], 'projects/earthengine-legacy') def testThumb_withDimensionsListMinMax(self): @@ -366,8 +326,7 @@ def testThumb_withDimensionsListMinMax(self): kwargs['body']['expression'], serializer.encode( self.base_image.clipToBoundsAndScale( - geometry=expected_geometry, width=13, height=42), - for_cloud_api=True)) + geometry=expected_geometry, width=13, height=42))) self.assertEqual(kwargs['parent'], 'projects/earthengine-legacy') def testThumb_withVisualizationParams(self): @@ -385,8 +344,7 @@ def testThumb_withVisualizationParams(self): serializer.encode( self.base_image.clipToBoundsAndScale( geometry=self.expected_geometry, width=13, - height=42).visualize(min=0), - for_cloud_api=True)) + height=42).visualize(min=0))) def testBuildDownloadIdImage_buildsImagePerBand(self): test_image = ee.Image('foo') @@ -582,7 +540,7 @@ def testDownloadURL(self): kwargs['body']['expression']) self.assertEqual('ZIPPED_GEO_TIFF_PER_BAND', kwargs['body']['fileFormat']) self.assertEqual('projects/earthengine-legacy', kwargs['parent']) - self.assertEqual('/%s/thumbName:getPixels' % _cloud_api_utils.VERSION, + self.assertEqual('None/%s/thumbName:getPixels' % _cloud_api_utils.VERSION, url) def testPrepareForExport_simple(self):