earthengine-api 1.7.1rc0__tar.gz → 1.7.2rc0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {earthengine_api-1.7.1rc0/earthengine_api.egg-info → earthengine_api-1.7.2rc0}/PKG-INFO +1 -1
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0/earthengine_api.egg-info}/PKG-INFO +1 -1
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/__init__.py +1 -1
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/data.py +1 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/oauth.py +2 -2
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/data_test.py +295 -1
- earthengine_api-1.7.2rc0/ee/tests/oauth_test.py +263 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/table_converter_test.py +47 -3
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/pyproject.toml +1 -1
- earthengine_api-1.7.1rc0/ee/tests/oauth_test.py +0 -100
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/LICENSE +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/MANIFEST.in +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/README.md +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/earthengine_api.egg-info/SOURCES.txt +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/earthengine_api.egg-info/dependency_links.txt +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/earthengine_api.egg-info/entry_points.txt +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/earthengine_api.egg-info/requires.txt +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/earthengine_api.egg-info/top_level.txt +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/_arg_types.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/_cloud_api_utils.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/_helpers.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/_state.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/_utils.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/apifunction.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/apitestcase.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/batch.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/blob.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/classifier.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/cli/__init__.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/cli/commands.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/cli/eecli.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/cli/eecli_wrapper.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/cli/utils.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/clusterer.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/collection.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/computedobject.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/confusionmatrix.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/customfunction.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/daterange.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/deprecation.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/deserializer.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/dictionary.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/ee_array.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/ee_date.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/ee_exception.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/ee_list.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/ee_number.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/ee_string.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/ee_types.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/element.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/encodable.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/errormargin.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/feature.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/featurecollection.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/filter.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/function.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/geometry.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/image.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/image_converter.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/imagecollection.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/join.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/kernel.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/mapclient.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/model.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/pixeltype.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/projection.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/py.typed +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/reducer.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/serializer.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/table_converter.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/terrain.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/_cloud_api_utils_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/_helpers_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/_state_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/_utils_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/algorithms.json +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/apifunction_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/batch_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/blob_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/classifier_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/cloud_api_discovery_document.json +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/clusterer_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/collection_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/computedobject_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/confusionmatrix_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/daterange_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/deprecation_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/deserializer_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/dictionary_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/ee_array_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/ee_date_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/ee_list_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/ee_number_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/ee_string_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/ee_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/ee_types_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/element_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/errormargin_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/feature_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/featurecollection_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/filter_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/function_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/geometry_point_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/geometry_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/image_converter_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/image_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/imagecollection_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/join_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/kernel_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/model_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/pixeltype_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/projection_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/reducer_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/serializer_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/ee/tests/terrain_test.py +0 -0
- {earthengine_api-1.7.1rc0 → earthengine_api-1.7.2rc0}/setup.cfg +0 -0
|
@@ -2161,6 +2161,7 @@ def setIamPolicy(asset_id: str, policy: Any) -> None:
|
|
|
2161
2161
|
.setIamPolicy(resource=name, body={'policy': policy}, prettyPrint=False)
|
|
2162
2162
|
)
|
|
2163
2163
|
|
|
2164
|
+
|
|
2164
2165
|
@deprecation.Deprecated('Use ee.data.updateAsset().')
|
|
2165
2166
|
def setAssetProperties(assetId: str, properties: dict[str, Any]) -> None:
|
|
2166
2167
|
"""Sets metadata properties of the asset with the given ID.
|
|
@@ -226,7 +226,7 @@ def _in_jupyter_shell() -> bool:
|
|
|
226
226
|
"""Tests if the code is being executed within Jupyter."""
|
|
227
227
|
try:
|
|
228
228
|
import ipykernel.zmqshell
|
|
229
|
-
return isinstance(IPython.get_ipython(),
|
|
229
|
+
return isinstance(IPython.get_ipython(), # pylint: disable=undefined-variable
|
|
230
230
|
ipykernel.zmqshell.ZMQInteractiveShell)
|
|
231
231
|
except ImportError:
|
|
232
232
|
return False
|
|
@@ -329,7 +329,7 @@ def _display_auth_instructions_with_html(
|
|
|
329
329
|
) -> None:
|
|
330
330
|
"""Displays instructions for authenticating using HTML code."""
|
|
331
331
|
try:
|
|
332
|
-
IPython.display.display(IPython.display.HTML(
|
|
332
|
+
IPython.display.display(IPython.display.HTML( # pylint: disable=undefined-variable
|
|
333
333
|
"""<p>To authorize access needed by Earth Engine, open the following
|
|
334
334
|
URL in a web browser and follow the instructions:</p>
|
|
335
335
|
<p><a href={0}>{0}</a></p>
|
|
@@ -87,6 +87,26 @@ class DataTest(unittest.TestCase):
|
|
|
87
87
|
_state.get_state().cloud_api_user_project, 'earthengine-legacy'
|
|
88
88
|
)
|
|
89
89
|
|
|
90
|
+
@mock.patch.object(ee.data, '_install_cloud_api_resource', return_value=None)
|
|
91
|
+
def test_initialize_with_credentials(
|
|
92
|
+
self, unused_mock_install_cloud_api_resource
|
|
93
|
+
):
|
|
94
|
+
creds = mock.MagicMock()
|
|
95
|
+
ee.data.initialize(credentials=creds)
|
|
96
|
+
|
|
97
|
+
self.assertTrue(ee.data.is_initialized())
|
|
98
|
+
self.assertEqual(creds, _state.get_state().credentials)
|
|
99
|
+
|
|
100
|
+
@mock.patch.object(ee.data, '_install_cloud_api_resource', return_value=None)
|
|
101
|
+
def test_initialize_with_cloud_api_key(
|
|
102
|
+
self, unused_mock_install_cloud_api_resource
|
|
103
|
+
):
|
|
104
|
+
cloud_api_key = 'a cloud api key'
|
|
105
|
+
ee.data.initialize(cloud_api_key=cloud_api_key)
|
|
106
|
+
|
|
107
|
+
self.assertTrue(ee.data.is_initialized())
|
|
108
|
+
self.assertEqual(cloud_api_key, _state.get_state().cloud_api_key)
|
|
109
|
+
|
|
90
110
|
def test_set_max_retries_bad_values(self):
|
|
91
111
|
with self.assertRaises(ValueError):
|
|
92
112
|
ee.data.setMaxRetries(-1)
|
|
@@ -110,6 +130,46 @@ class DataTest(unittest.TestCase):
|
|
|
110
130
|
.execute.call_args.kwargs['num_retries'],
|
|
111
131
|
)
|
|
112
132
|
|
|
133
|
+
def test_set_cloud_api_key(self):
|
|
134
|
+
cloud_api_key = 'a cloud api key'
|
|
135
|
+
with mock.patch.object(
|
|
136
|
+
ee.data, '_install_cloud_api_resource', return_value=None
|
|
137
|
+
) as mock_install_cloud_api_resource:
|
|
138
|
+
ee.data.setCloudApiKey(cloud_api_key)
|
|
139
|
+
self.assertEqual(cloud_api_key, _state.get_state().cloud_api_key)
|
|
140
|
+
mock_install_cloud_api_resource.assert_called_once()
|
|
141
|
+
|
|
142
|
+
def test_set_deadline(self):
|
|
143
|
+
deadline_ms = 12345
|
|
144
|
+
with mock.patch.object(
|
|
145
|
+
ee.data, '_install_cloud_api_resource', return_value=None
|
|
146
|
+
) as mock_install_cloud_api_resource:
|
|
147
|
+
ee.data.setDeadline(deadline_ms)
|
|
148
|
+
self.assertEqual(deadline_ms, _state.get_state().deadline_ms)
|
|
149
|
+
mock_install_cloud_api_resource.assert_called_once()
|
|
150
|
+
|
|
151
|
+
def test_get_set_user_agent(self):
|
|
152
|
+
self.assertIsNone(ee.data.getUserAgent())
|
|
153
|
+
user_agent = 'user-agent'
|
|
154
|
+
ee.data.setUserAgent(user_agent)
|
|
155
|
+
self.assertEqual(user_agent, ee.data.getUserAgent())
|
|
156
|
+
|
|
157
|
+
def test_authorize_http_no_credentials(self):
|
|
158
|
+
self.assertIsNone(ee.data._get_state().credentials)
|
|
159
|
+
http = mock.MagicMock()
|
|
160
|
+
self.assertEqual(http, ee.data.authorizeHttp(http))
|
|
161
|
+
|
|
162
|
+
def test_authorize_http_with_credentials(self):
|
|
163
|
+
creds = mock.MagicMock()
|
|
164
|
+
ee.data._get_state().credentials = creds
|
|
165
|
+
http = mock.MagicMock()
|
|
166
|
+
with mock.patch.object(
|
|
167
|
+
ee.data.google_auth_httplib2, 'AuthorizedHttp'
|
|
168
|
+
) as mock_authorized_http:
|
|
169
|
+
result = ee.data.authorizeHttp(http)
|
|
170
|
+
self.assertEqual(mock_authorized_http.return_value, result)
|
|
171
|
+
mock_authorized_http.assert_called_once_with(creds)
|
|
172
|
+
|
|
113
173
|
def test_list_operations(self):
|
|
114
174
|
mock_http = mock.MagicMock(httplib2.Http)
|
|
115
175
|
# Return in three groups.
|
|
@@ -342,6 +402,14 @@ class DataTest(unittest.TestCase):
|
|
|
342
402
|
asset = mock_create_asset.call_args.kwargs['body']
|
|
343
403
|
self.assertEqual(asset, {'type': 'FOLDER'})
|
|
344
404
|
|
|
405
|
+
@mock.patch.object(ee.data, 'createAsset')
|
|
406
|
+
def test_create_asset_home(self, mock_create_asset):
|
|
407
|
+
ee.data.createAssetHome('users/test')
|
|
408
|
+
mock_create_asset.assert_called_once_with({
|
|
409
|
+
'name': 'projects/earthengine-legacy/assets/users/test',
|
|
410
|
+
'type': 'FOLDER',
|
|
411
|
+
})
|
|
412
|
+
|
|
345
413
|
def test_create_assets(self):
|
|
346
414
|
cloud_api_resource = mock.MagicMock()
|
|
347
415
|
with apitestcase.UsingCloudApi(cloud_api_resource=cloud_api_resource):
|
|
@@ -432,6 +500,68 @@ class DataTest(unittest.TestCase):
|
|
|
432
500
|
)
|
|
433
501
|
self.assertTrue(import_args['overwrite'])
|
|
434
502
|
|
|
503
|
+
def test_start_table_ingestion(self):
|
|
504
|
+
cloud_api_resource = mock.MagicMock()
|
|
505
|
+
with apitestcase.UsingCloudApi(cloud_api_resource=cloud_api_resource):
|
|
506
|
+
mock_result = {'name': 'operations/ingestion', 'done': False}
|
|
507
|
+
cloud_api_resource.projects().table().import_.return_value.execute.return_value = (
|
|
508
|
+
mock_result
|
|
509
|
+
)
|
|
510
|
+
params = {
|
|
511
|
+
'id': 'users/test/table',
|
|
512
|
+
'sources': [{'uris': ['gs://bucket/file.shp'], 'charset': 'UTF-8'}],
|
|
513
|
+
}
|
|
514
|
+
result = ee.data.startTableIngestion('request_id', params, True)
|
|
515
|
+
self.assertEqual(result['id'], 'ingestion')
|
|
516
|
+
self.assertEqual(result['name'], 'operations/ingestion')
|
|
517
|
+
|
|
518
|
+
mock_import = cloud_api_resource.projects().table().import_
|
|
519
|
+
mock_import.assert_called_once()
|
|
520
|
+
call_kwargs = mock_import.call_args.kwargs
|
|
521
|
+
self.assertEqual(call_kwargs['project'], 'projects/earthengine-legacy')
|
|
522
|
+
body = call_kwargs['body']
|
|
523
|
+
self.assertEqual(
|
|
524
|
+
body['tableManifest'],
|
|
525
|
+
{
|
|
526
|
+
'name': 'projects/earthengine-legacy/assets/users/test/table',
|
|
527
|
+
'sources': [
|
|
528
|
+
{'uris': ['gs://bucket/file.shp'], 'charset': 'UTF-8'}
|
|
529
|
+
],
|
|
530
|
+
},
|
|
531
|
+
)
|
|
532
|
+
self.assertEqual(body['requestId'], 'request_id')
|
|
533
|
+
self.assertTrue(body['overwrite'])
|
|
534
|
+
|
|
535
|
+
def test_start_external_image_ingestion(self):
|
|
536
|
+
cloud_api_resource = mock.MagicMock()
|
|
537
|
+
with apitestcase.UsingCloudApi(cloud_api_resource=cloud_api_resource):
|
|
538
|
+
cloud_api_resource.projects().image().importExternal.return_value.execute.return_value = (
|
|
539
|
+
{}
|
|
540
|
+
)
|
|
541
|
+
manifest = {
|
|
542
|
+
'id': 'users/test/image',
|
|
543
|
+
'tilesets': [{'sources': [{'uris': ['gs://bucket/file.tif']}]}],
|
|
544
|
+
}
|
|
545
|
+
result = ee.data.startExternalImageIngestion(manifest, True)
|
|
546
|
+
expected_name = 'projects/earthengine-legacy/assets/users/test/image'
|
|
547
|
+
self.assertEqual(result['name'], expected_name)
|
|
548
|
+
|
|
549
|
+
mock_import_external = (
|
|
550
|
+
cloud_api_resource.projects().image().importExternal
|
|
551
|
+
)
|
|
552
|
+
mock_import_external.assert_called_once()
|
|
553
|
+
call_kwargs = mock_import_external.call_args.kwargs
|
|
554
|
+
self.assertEqual(call_kwargs['project'], 'projects/earthengine-legacy')
|
|
555
|
+
body = call_kwargs['body']
|
|
556
|
+
self.assertEqual(
|
|
557
|
+
body['imageManifest'],
|
|
558
|
+
{
|
|
559
|
+
'name': expected_name,
|
|
560
|
+
'tilesets': [{'sources': [{'uris': ['gs://bucket/file.tif']}]}],
|
|
561
|
+
},
|
|
562
|
+
)
|
|
563
|
+
self.assertTrue(body['overwrite'])
|
|
564
|
+
|
|
435
565
|
def test_set_asset_properties(self):
|
|
436
566
|
mock_http = mock.MagicMock(httplib2.Http)
|
|
437
567
|
with apitestcase.UsingCloudApi(mock_http=mock_http), mock.patch.object(
|
|
@@ -453,6 +583,18 @@ class DataTest(unittest.TestCase):
|
|
|
453
583
|
{'properties.\"mYPropErTy\"',
|
|
454
584
|
'properties.\"system:time_start\"'})
|
|
455
585
|
|
|
586
|
+
def test_update_asset(self):
|
|
587
|
+
cloud_api_resource = mock.MagicMock()
|
|
588
|
+
with apitestcase.UsingCloudApi(cloud_api_resource=cloud_api_resource):
|
|
589
|
+
asset_id = 'users/test/asset'
|
|
590
|
+
asset = {'properties': {'foo': 'bar'}}
|
|
591
|
+
update_mask = ['properties.foo']
|
|
592
|
+
ee.data.updateAsset(asset_id, asset, update_mask)
|
|
593
|
+
cloud_api_resource.projects().assets().patch.assert_called_once_with(
|
|
594
|
+
name='projects/earthengine-legacy/assets/users/test/asset',
|
|
595
|
+
body={'updateMask': {'paths': update_mask}, 'asset': asset},
|
|
596
|
+
)
|
|
597
|
+
|
|
456
598
|
def test_list_assets(self):
|
|
457
599
|
cloud_api_resource = mock.MagicMock()
|
|
458
600
|
with apitestcase.UsingCloudApi(cloud_api_resource=cloud_api_resource):
|
|
@@ -576,6 +718,16 @@ class DataTest(unittest.TestCase):
|
|
|
576
718
|
cloud_api_resource.projects().listAssets().execute.assert_called_once()
|
|
577
719
|
self.assertEqual(mock_result, actual_result)
|
|
578
720
|
|
|
721
|
+
def test_get_asset_roots(self):
|
|
722
|
+
with mock.patch.object(
|
|
723
|
+
ee.data,
|
|
724
|
+
'listBuckets',
|
|
725
|
+
return_value={'assets': [{'name': 'id1', 'type': 'FOLDER'}]},
|
|
726
|
+
) as mock_list_buckets:
|
|
727
|
+
result = ee.data.getAssetRoots()
|
|
728
|
+
mock_list_buckets.assert_called_once()
|
|
729
|
+
self.assertEqual([{'id': 'id1', 'type': 'Folder'}], result)
|
|
730
|
+
|
|
579
731
|
def test_simple_get_list_via_cloud_api(self):
|
|
580
732
|
cloud_api_resource = mock.MagicMock()
|
|
581
733
|
with apitestcase.UsingCloudApi(cloud_api_resource=cloud_api_resource):
|
|
@@ -881,6 +1033,50 @@ class DataTest(unittest.TestCase):
|
|
|
881
1033
|
).execute.assert_called_once()
|
|
882
1034
|
self.assertEqual(mock_result, actual_result)
|
|
883
1035
|
|
|
1036
|
+
def test_get_pixels(self):
|
|
1037
|
+
cloud_api_resource_raw = mock.MagicMock()
|
|
1038
|
+
with apitestcase.UsingCloudApi(
|
|
1039
|
+
cloud_api_resource_raw=cloud_api_resource_raw
|
|
1040
|
+
):
|
|
1041
|
+
assets = cloud_api_resource_raw.projects().assets()
|
|
1042
|
+
mock_result = b'pixel data'
|
|
1043
|
+
assets.getPixels.return_value.execute.return_value = mock_result
|
|
1044
|
+
asset_id = 'users/foo/bar'
|
|
1045
|
+
params = {'assetId': asset_id}
|
|
1046
|
+
result = ee.data.getPixels(params)
|
|
1047
|
+
self.assertEqual(mock_result, result)
|
|
1048
|
+
assets.getPixels.assert_called_once_with(
|
|
1049
|
+
name='projects/earthengine-legacy/assets/users/foo/bar',
|
|
1050
|
+
body={'fileFormat': 'AUTO_JPEG_PNG'},
|
|
1051
|
+
)
|
|
1052
|
+
|
|
1053
|
+
def test_compute_pixels(self):
|
|
1054
|
+
cloud_api_resource_raw = mock.MagicMock()
|
|
1055
|
+
with apitestcase.UsingCloudApi(
|
|
1056
|
+
cloud_api_resource_raw=cloud_api_resource_raw
|
|
1057
|
+
):
|
|
1058
|
+
mock_result = b'pixel data'
|
|
1059
|
+
(
|
|
1060
|
+
cloud_api_resource_raw.projects()
|
|
1061
|
+
.image()
|
|
1062
|
+
.computePixels.return_value.execute.return_value
|
|
1063
|
+
) = mock_result
|
|
1064
|
+
expression = ee.Image(1)
|
|
1065
|
+
params = {'expression': expression}
|
|
1066
|
+
result = ee.data.computePixels(params)
|
|
1067
|
+
self.assertEqual(mock_result, result)
|
|
1068
|
+
(
|
|
1069
|
+
cloud_api_resource_raw.projects()
|
|
1070
|
+
.image()
|
|
1071
|
+
.computePixels.assert_called_once_with(
|
|
1072
|
+
project='projects/earthengine-legacy',
|
|
1073
|
+
body={
|
|
1074
|
+
'expression': ee.serializer.encode(expression),
|
|
1075
|
+
'fileFormat': 'AUTO_JPEG_PNG',
|
|
1076
|
+
},
|
|
1077
|
+
)
|
|
1078
|
+
)
|
|
1079
|
+
|
|
884
1080
|
def test_get_feature_view_tiles_key(self):
|
|
885
1081
|
cloud_api_resource = mock.MagicMock()
|
|
886
1082
|
_state.get_state().tile_base_url = 'base_url'
|
|
@@ -922,8 +1118,31 @@ class DataTest(unittest.TestCase):
|
|
|
922
1118
|
cloud_api_resource.projects().updateConfig().execute.return_value = (
|
|
923
1119
|
mock_result
|
|
924
1120
|
)
|
|
1121
|
+
project_config = {'maxConcurrentExports': 2}
|
|
925
1122
|
actual_result = ee.data.updateProjectConfig(
|
|
926
|
-
|
|
1123
|
+
project_config, ['max_concurrent_exports']
|
|
1124
|
+
)
|
|
1125
|
+
cloud_api_resource.projects().updateConfig.assert_called_with(
|
|
1126
|
+
name='projects/earthengine-legacy/config',
|
|
1127
|
+
body=project_config,
|
|
1128
|
+
updateMask='max_concurrent_exports',
|
|
1129
|
+
)
|
|
1130
|
+
cloud_api_resource.projects().updateConfig().execute.assert_called_once()
|
|
1131
|
+
self.assertEqual(mock_result, actual_result)
|
|
1132
|
+
|
|
1133
|
+
def test_update_project_config_no_mask(self) -> None:
|
|
1134
|
+
cloud_api_resource = mock.MagicMock()
|
|
1135
|
+
with apitestcase.UsingCloudApi(cloud_api_resource=cloud_api_resource):
|
|
1136
|
+
mock_result = {'fake-project-config-value': 1}
|
|
1137
|
+
cloud_api_resource.projects().updateConfig().execute.return_value = (
|
|
1138
|
+
mock_result
|
|
1139
|
+
)
|
|
1140
|
+
project_config = {'maxConcurrentExports': 2}
|
|
1141
|
+
actual_result = ee.data.updateProjectConfig(project_config)
|
|
1142
|
+
cloud_api_resource.projects().updateConfig.assert_called_with(
|
|
1143
|
+
name='projects/earthengine-legacy/config',
|
|
1144
|
+
body=project_config,
|
|
1145
|
+
updateMask='max_concurrent_exports',
|
|
927
1146
|
)
|
|
928
1147
|
cloud_api_resource.projects().updateConfig().execute.assert_called_once()
|
|
929
1148
|
self.assertEqual(mock_result, actual_result)
|
|
@@ -1040,6 +1259,81 @@ class DataTest(unittest.TestCase):
|
|
|
1040
1259
|
}
|
|
1041
1260
|
self.assertEqual(expected, quota)
|
|
1042
1261
|
|
|
1262
|
+
def test_get_asset_root_quota_not_root(self):
|
|
1263
|
+
cloud_api_resource = mock.MagicMock()
|
|
1264
|
+
with apitestcase.UsingCloudApi(cloud_api_resource=cloud_api_resource):
|
|
1265
|
+
asset_id = 'users/test/asset'
|
|
1266
|
+
fake_asset = {
|
|
1267
|
+
'type': 'IMAGE',
|
|
1268
|
+
'name': 'projects/earthengine-legacy/assets/users/test/asset',
|
|
1269
|
+
}
|
|
1270
|
+
cloud_api_resource.projects().assets().get().execute.return_value = (
|
|
1271
|
+
fake_asset
|
|
1272
|
+
)
|
|
1273
|
+
with self.assertRaisesRegex(
|
|
1274
|
+
ee.ee_exception.EEException, f'{asset_id} is not a root folder.'
|
|
1275
|
+
):
|
|
1276
|
+
ee.data.getAssetRootQuota(asset_id)
|
|
1277
|
+
|
|
1278
|
+
def test_get_iam_policy(self):
|
|
1279
|
+
cloud_api_resource = mock.MagicMock()
|
|
1280
|
+
with apitestcase.UsingCloudApi(cloud_api_resource=cloud_api_resource):
|
|
1281
|
+
asset_id = 'users/test/asset'
|
|
1282
|
+
ee.data.getIamPolicy(asset_id)
|
|
1283
|
+
cloud_api_resource.projects().assets().getIamPolicy.assert_called_once_with(
|
|
1284
|
+
resource='projects/earthengine-legacy/assets/users/test/asset',
|
|
1285
|
+
body={},
|
|
1286
|
+
prettyPrint=False,
|
|
1287
|
+
)
|
|
1288
|
+
|
|
1289
|
+
def test_get_asset_acl(self):
|
|
1290
|
+
asset_id = 'users/test/asset'
|
|
1291
|
+
policy = {'bindings': [{'role': 'roles/viewer', 'members': ['allUsers']}]}
|
|
1292
|
+
acl = {'readers': ['allUsers']}
|
|
1293
|
+
with mock.patch.object(
|
|
1294
|
+
ee.data, 'getIamPolicy', return_value=policy
|
|
1295
|
+
) as mock_get_iam_policy, mock.patch.object(
|
|
1296
|
+
ee.data._cloud_api_utils, 'convert_iam_policy_to_acl', return_value=acl
|
|
1297
|
+
) as mock_convert:
|
|
1298
|
+
result = ee.data.getAssetAcl(asset_id)
|
|
1299
|
+
mock_get_iam_policy.assert_called_once_with(asset_id)
|
|
1300
|
+
mock_convert.assert_called_once_with(policy)
|
|
1301
|
+
self.assertEqual(acl, result)
|
|
1302
|
+
|
|
1303
|
+
def test_set_asset_acl(self):
|
|
1304
|
+
asset_id = 'users/test/asset'
|
|
1305
|
+
acl_update_dict = {'readers': ['allUsers']}
|
|
1306
|
+
acl_update_str = '{"readers": ["allUsers"]}'
|
|
1307
|
+
policy = {'bindings': [{'role': 'roles/viewer', 'members': ['allUsers']}]}
|
|
1308
|
+
with mock.patch.object(
|
|
1309
|
+
ee.data._cloud_api_utils,
|
|
1310
|
+
'convert_acl_to_iam_policy',
|
|
1311
|
+
return_value=policy,
|
|
1312
|
+
) as mock_convert, mock.patch.object(
|
|
1313
|
+
ee.data, 'setIamPolicy'
|
|
1314
|
+
) as mock_set_iam_policy:
|
|
1315
|
+
ee.data.setAssetAcl(asset_id, acl_update_dict)
|
|
1316
|
+
mock_convert.assert_called_once_with(acl_update_dict)
|
|
1317
|
+
mock_set_iam_policy.assert_called_once_with(asset_id, policy)
|
|
1318
|
+
|
|
1319
|
+
mock_convert.reset_mock()
|
|
1320
|
+
mock_set_iam_policy.reset_mock()
|
|
1321
|
+
ee.data.setAssetAcl(asset_id, acl_update_str)
|
|
1322
|
+
mock_convert.assert_called_once_with(acl_update_dict)
|
|
1323
|
+
mock_set_iam_policy.assert_called_once_with(asset_id, policy)
|
|
1324
|
+
|
|
1325
|
+
def test_set_iam_policy(self):
|
|
1326
|
+
cloud_api_resource = mock.MagicMock()
|
|
1327
|
+
with apitestcase.UsingCloudApi(cloud_api_resource=cloud_api_resource):
|
|
1328
|
+
asset_id = 'users/test/asset'
|
|
1329
|
+
policy = {'bindings': [{'role': 'roles/viewer', 'members': ['allUsers']}]}
|
|
1330
|
+
ee.data.setIamPolicy(asset_id, policy)
|
|
1331
|
+
cloud_api_resource.projects().assets().setIamPolicy.assert_called_once_with(
|
|
1332
|
+
resource='projects/earthengine-legacy/assets/users/test/asset',
|
|
1333
|
+
body={'policy': policy},
|
|
1334
|
+
prettyPrint=False,
|
|
1335
|
+
)
|
|
1336
|
+
|
|
1043
1337
|
|
|
1044
1338
|
def DoCloudProfileStubHttp(test, expect_profiling):
|
|
1045
1339
|
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Test for the oauth module."""
|
|
3
|
+
|
|
4
|
+
import http.client
|
|
5
|
+
import io
|
|
6
|
+
import json
|
|
7
|
+
import sys
|
|
8
|
+
import tempfile
|
|
9
|
+
from unittest import mock
|
|
10
|
+
import urllib.parse
|
|
11
|
+
|
|
12
|
+
import unittest
|
|
13
|
+
from ee import ee_exception
|
|
14
|
+
from ee import oauth
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class OAuthTest(unittest.TestCase):
|
|
18
|
+
|
|
19
|
+
def setUp(self):
|
|
20
|
+
super().setUp()
|
|
21
|
+
self.test_tmpdir = tempfile.mkdtemp()
|
|
22
|
+
|
|
23
|
+
def test_request_token(self):
|
|
24
|
+
|
|
25
|
+
class MockResponse:
|
|
26
|
+
|
|
27
|
+
def __init__(self, code):
|
|
28
|
+
self.code = code.decode()
|
|
29
|
+
|
|
30
|
+
def read(self):
|
|
31
|
+
return ('{"refresh_token": "' + self.code + '456"}').encode()
|
|
32
|
+
|
|
33
|
+
def mock_urlopen(url, param):
|
|
34
|
+
del url # Unused.
|
|
35
|
+
parsed = urllib.parse.parse_qs(param)
|
|
36
|
+
self.assertEqual('xyz', parsed[b'code_verifier'][0].decode())
|
|
37
|
+
return MockResponse(parsed[b'code'][0])
|
|
38
|
+
|
|
39
|
+
with mock.patch.object(urllib.request, 'urlopen', new=mock_urlopen):
|
|
40
|
+
auth_code = '123'
|
|
41
|
+
verifier = 'xyz'
|
|
42
|
+
refresh_token = oauth.request_token(auth_code, verifier)
|
|
43
|
+
self.assertEqual('123456', refresh_token)
|
|
44
|
+
|
|
45
|
+
def test_request_token_http_error(self):
|
|
46
|
+
mock_fp = io.BytesIO(b'error details')
|
|
47
|
+
http_error = urllib.error.HTTPError(
|
|
48
|
+
'url', 400, 'message', hdrs=http.client.HTTPMessage(), fp=mock_fp
|
|
49
|
+
)
|
|
50
|
+
with mock.patch.object(urllib.request, 'urlopen', side_effect=http_error):
|
|
51
|
+
with self.assertRaisesRegex(
|
|
52
|
+
Exception,
|
|
53
|
+
r"Problem requesting tokens.*HTTP Error 400: message.*b'error"
|
|
54
|
+
r" details'",
|
|
55
|
+
):
|
|
56
|
+
oauth.request_token('auth_code', 'code_verifier')
|
|
57
|
+
|
|
58
|
+
def test_write_token(self):
|
|
59
|
+
|
|
60
|
+
def mock_credentials_path():
|
|
61
|
+
return f'{self.test_tmpdir}/tempfile'
|
|
62
|
+
|
|
63
|
+
with mock.patch.object(
|
|
64
|
+
oauth, 'get_credentials_path', new=mock_credentials_path
|
|
65
|
+
):
|
|
66
|
+
client_info = dict(refresh_token='123')
|
|
67
|
+
oauth.write_private_json(oauth.get_credentials_path(), client_info)
|
|
68
|
+
|
|
69
|
+
with open(mock_credentials_path()) as f:
|
|
70
|
+
token = json.load(f)
|
|
71
|
+
self.assertEqual({'refresh_token': '123'}, token)
|
|
72
|
+
|
|
73
|
+
def test_get_credentials_arguments(self):
|
|
74
|
+
credentials_path = f'{self.test_tmpdir}/temp_creds'
|
|
75
|
+
|
|
76
|
+
creds = {
|
|
77
|
+
'refresh_token': 'REFRESH_TOKEN',
|
|
78
|
+
'client_id': 'CLIENT_ID',
|
|
79
|
+
'project': 'PROJECT',
|
|
80
|
+
}
|
|
81
|
+
with open(credentials_path, 'w') as f:
|
|
82
|
+
json.dump(creds, f)
|
|
83
|
+
|
|
84
|
+
with mock.patch.object(
|
|
85
|
+
oauth, 'get_credentials_path', return_value=credentials_path
|
|
86
|
+
):
|
|
87
|
+
args = oauth.get_credentials_arguments()
|
|
88
|
+
|
|
89
|
+
expected_args = {
|
|
90
|
+
'token_uri': oauth.TOKEN_URI,
|
|
91
|
+
'refresh_token': 'REFRESH_TOKEN',
|
|
92
|
+
'client_id': 'CLIENT_ID',
|
|
93
|
+
'client_secret': oauth.CLIENT_SECRET,
|
|
94
|
+
'scopes': oauth.SCOPES,
|
|
95
|
+
'quota_project_id': 'PROJECT',
|
|
96
|
+
}
|
|
97
|
+
self.assertEqual(expected_args, args)
|
|
98
|
+
|
|
99
|
+
def test_is_valid_credentials(self):
|
|
100
|
+
self.assertFalse(oauth.is_valid_credentials(None))
|
|
101
|
+
|
|
102
|
+
mock_credentials_valid = mock.MagicMock()
|
|
103
|
+
self.assertTrue(oauth.is_valid_credentials(mock_credentials_valid))
|
|
104
|
+
mock_credentials_valid.refresh.assert_called_once()
|
|
105
|
+
|
|
106
|
+
mock_credentials_invalid = mock.MagicMock()
|
|
107
|
+
mock_credentials_invalid.refresh.side_effect = (
|
|
108
|
+
oauth.google.auth.exceptions.RefreshError()
|
|
109
|
+
)
|
|
110
|
+
self.assertFalse(oauth.is_valid_credentials(mock_credentials_invalid))
|
|
111
|
+
mock_credentials_invalid.refresh.assert_called_once()
|
|
112
|
+
|
|
113
|
+
def test_in_colab_shell(self):
|
|
114
|
+
with mock.patch.dict(sys.modules, {'google.colab': None}):
|
|
115
|
+
self.assertFalse(oauth.in_colab_shell())
|
|
116
|
+
|
|
117
|
+
with mock.patch.dict(sys.modules, {'google.colab': mock.MagicMock()}):
|
|
118
|
+
self.assertTrue(oauth.in_colab_shell())
|
|
119
|
+
|
|
120
|
+
def test_is_sdk_credentials(self):
|
|
121
|
+
sdk_project = oauth.SDK_PROJECTS[0]
|
|
122
|
+
self.assertFalse(oauth.is_sdk_credentials(None))
|
|
123
|
+
self.assertFalse(oauth.is_sdk_credentials(mock.MagicMock()))
|
|
124
|
+
self.assertFalse(
|
|
125
|
+
oauth.is_sdk_credentials(mock.MagicMock(client_id='123'))
|
|
126
|
+
)
|
|
127
|
+
self.assertTrue(
|
|
128
|
+
oauth.is_sdk_credentials(mock.MagicMock(client_id=sdk_project))
|
|
129
|
+
)
|
|
130
|
+
self.assertTrue(
|
|
131
|
+
oauth.is_sdk_credentials(
|
|
132
|
+
mock.MagicMock(client_id=f'{sdk_project}-somethingelse')
|
|
133
|
+
)
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
def test_colab_mode_with_nonstandard_scopes_raises_exception(self):
|
|
137
|
+
with self.assertRaisesRegex(
|
|
138
|
+
ee_exception.EEException,
|
|
139
|
+
'Scopes cannot be customized when auth_mode is "colab".'
|
|
140
|
+
):
|
|
141
|
+
oauth.authenticate(
|
|
142
|
+
auth_mode='colab',
|
|
143
|
+
scopes=['https://www.googleapis.com/auth/earthengine.readonly']
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
def test_colab_auth_mode_with_standard_scopes_succeeds(self):
|
|
147
|
+
# Should not raise an exception if the scopes are not narrowed.
|
|
148
|
+
with mock.patch.dict(sys.modules, {'google.colab': mock.MagicMock()}):
|
|
149
|
+
try:
|
|
150
|
+
oauth.authenticate(auth_mode='colab', scopes=oauth.SCOPES)
|
|
151
|
+
except ee_exception.EEException:
|
|
152
|
+
self.fail('authenticate raised an exception unexpectedly.')
|
|
153
|
+
|
|
154
|
+
def test_authenticate_appdefault(self):
|
|
155
|
+
with mock.patch.object(
|
|
156
|
+
oauth,
|
|
157
|
+
'_valid_credentials_exist',
|
|
158
|
+
return_value=False,
|
|
159
|
+
), mock.patch.object(
|
|
160
|
+
sys, 'stderr', new_callable=io.StringIO
|
|
161
|
+
) as mock_stderr:
|
|
162
|
+
oauth.authenticate(auth_mode='appdefault')
|
|
163
|
+
self.assertIn('appdefault no longer necessary', mock_stderr.getvalue())
|
|
164
|
+
|
|
165
|
+
@mock.patch.object(oauth, '_load_gcloud_credentials')
|
|
166
|
+
@mock.patch.object(oauth, '_valid_credentials_exist', return_value=False)
|
|
167
|
+
@mock.patch.object(oauth, 'in_colab_shell', return_value=False)
|
|
168
|
+
@mock.patch.object(oauth, '_in_jupyter_shell', return_value=False)
|
|
169
|
+
@mock.patch.object(oauth, '_localhost_is_viable', return_value=False)
|
|
170
|
+
def test_authenticate_default_gcloud(
|
|
171
|
+
self,
|
|
172
|
+
mock_localhost_viable,
|
|
173
|
+
mock_jupyter,
|
|
174
|
+
mock_colab,
|
|
175
|
+
mock_valid_creds,
|
|
176
|
+
mock_load_gcloud,
|
|
177
|
+
):
|
|
178
|
+
del (
|
|
179
|
+
mock_localhost_viable,
|
|
180
|
+
mock_jupyter,
|
|
181
|
+
mock_colab,
|
|
182
|
+
mock_valid_creds,
|
|
183
|
+
) # Unused
|
|
184
|
+
oauth.authenticate()
|
|
185
|
+
mock_load_gcloud.assert_called_once_with(None, None, False)
|
|
186
|
+
|
|
187
|
+
def test_localhost_fetch_code(self):
|
|
188
|
+
mock_server = mock.MagicMock()
|
|
189
|
+
mock_server.url = 'http://localhost:8085'
|
|
190
|
+
mock_server.fetch_code.return_value = 'FETCHED_CODE'
|
|
191
|
+
with mock.patch.object(
|
|
192
|
+
oauth, '_start_server', return_value=mock_server
|
|
193
|
+
), mock.patch.object(oauth, '_obtain_and_write_token') as mock_obtain:
|
|
194
|
+
flow = oauth.Flow(auth_mode='localhost')
|
|
195
|
+
flow.save_code()
|
|
196
|
+
mock_server.fetch_code.assert_called_once()
|
|
197
|
+
mock_obtain.assert_called_once_with(
|
|
198
|
+
'FETCHED_CODE',
|
|
199
|
+
flow.code_verifier,
|
|
200
|
+
flow.scopes,
|
|
201
|
+
'http://localhost:8085',
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
@mock.patch.object(oauth, '_display_auth_instructions_for_noninteractive')
|
|
205
|
+
def test_display_instructions_quiet(self, mock_display):
|
|
206
|
+
flow = oauth.Flow(auth_mode='notebook')
|
|
207
|
+
self.assertTrue(flow.display_instructions(quiet=True))
|
|
208
|
+
mock_display.assert_called_once_with(flow.auth_url, flow.code_verifier)
|
|
209
|
+
|
|
210
|
+
@mock.patch.object(oauth, '_display_auth_instructions_with_print')
|
|
211
|
+
@mock.patch.object(oauth, 'in_colab_shell', return_value=True)
|
|
212
|
+
def test_display_instructions_colab(self, mock_in_colab, mock_display_print):
|
|
213
|
+
del mock_in_colab # Unused
|
|
214
|
+
flow = oauth.Flow(auth_mode='notebook')
|
|
215
|
+
self.assertTrue(flow.display_instructions())
|
|
216
|
+
mock_display_print.assert_called_once_with(flow.auth_url, None)
|
|
217
|
+
|
|
218
|
+
@mock.patch.object(oauth, '_display_auth_instructions_with_html')
|
|
219
|
+
@mock.patch.object(oauth, '_in_jupyter_shell', return_value=True)
|
|
220
|
+
def test_display_instructions_jupyter(
|
|
221
|
+
self, mock_in_jupyter, mock_display_html
|
|
222
|
+
):
|
|
223
|
+
del mock_in_jupyter # Unused
|
|
224
|
+
flow = oauth.Flow(auth_mode='notebook')
|
|
225
|
+
self.assertTrue(flow.display_instructions())
|
|
226
|
+
mock_display_html.assert_called_once_with(flow.auth_url, None)
|
|
227
|
+
|
|
228
|
+
@mock.patch.object(oauth, '_display_auth_instructions_with_print')
|
|
229
|
+
@mock.patch.object(oauth, 'in_colab_shell', return_value=False)
|
|
230
|
+
@mock.patch.object(oauth, '_in_jupyter_shell', return_value=False)
|
|
231
|
+
def test_display_instructions_print(
|
|
232
|
+
self, mock_in_jupyter, mock_in_colab, mock_display_print
|
|
233
|
+
):
|
|
234
|
+
del mock_in_jupyter, mock_in_colab # Unused
|
|
235
|
+
flow = oauth.Flow(auth_mode='notebook')
|
|
236
|
+
self.assertTrue(flow.display_instructions())
|
|
237
|
+
mock_display_print.assert_called_once_with(flow.auth_url, None)
|
|
238
|
+
|
|
239
|
+
@mock.patch.object(oauth, '_display_auth_instructions_with_print')
|
|
240
|
+
@mock.patch.object(oauth, 'in_colab_shell', return_value=True)
|
|
241
|
+
@mock.patch.object(oauth.http.server, 'HTTPServer')
|
|
242
|
+
def test_display_instructions_localhost_colab(
|
|
243
|
+
self, mock_http_server, mock_in_colab, mock_display_print
|
|
244
|
+
):
|
|
245
|
+
del mock_http_server, mock_in_colab # Unused
|
|
246
|
+
flow = oauth.Flow(auth_mode='localhost')
|
|
247
|
+
self.assertTrue(flow.display_instructions())
|
|
248
|
+
mock_display_print.assert_called_once_with(
|
|
249
|
+
flow.auth_url, oauth.WAITING_CODA
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
def test_flow_unknown_auth_mode(self):
|
|
253
|
+
with self.assertRaisesRegex(ee_exception.EEException, 'Unknown auth_mode'):
|
|
254
|
+
oauth.Flow(auth_mode='unknown')
|
|
255
|
+
|
|
256
|
+
def test_flow_localhost_with_port(self):
|
|
257
|
+
with mock.patch.object(oauth, '_start_server') as mock_start_server:
|
|
258
|
+
oauth.Flow(auth_mode='localhost:1234')
|
|
259
|
+
mock_start_server.assert_called_once_with(1234)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
if __name__ == '__main__':
|
|
263
|
+
unittest.main()
|