earthengine-api 1.7.1rc0__py3-none-any.whl → 1.7.2rc0__py3-none-any.whl
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.
Potentially problematic release.
This version of earthengine-api might be problematic. Click here for more details.
- {earthengine_api-1.7.1rc0.dist-info → earthengine_api-1.7.2rc0.dist-info}/METADATA +1 -1
- {earthengine_api-1.7.1rc0.dist-info → earthengine_api-1.7.2rc0.dist-info}/RECORD +12 -12
- ee/__init__.py +1 -1
- ee/data.py +1 -0
- ee/oauth.py +2 -2
- ee/tests/data_test.py +295 -1
- ee/tests/oauth_test.py +170 -7
- ee/tests/table_converter_test.py +47 -3
- {earthengine_api-1.7.1rc0.dist-info → earthengine_api-1.7.2rc0.dist-info}/WHEEL +0 -0
- {earthengine_api-1.7.1rc0.dist-info → earthengine_api-1.7.2rc0.dist-info}/entry_points.txt +0 -0
- {earthengine_api-1.7.1rc0.dist-info → earthengine_api-1.7.2rc0.dist-info}/licenses/LICENSE +0 -0
- {earthengine_api-1.7.1rc0.dist-info → earthengine_api-1.7.2rc0.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
earthengine_api-1.7.
|
|
2
|
-
ee/__init__.py,sha256=
|
|
1
|
+
earthengine_api-1.7.2rc0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
2
|
+
ee/__init__.py,sha256=qXFqyr1frW_X1pYT3uUOMUT6rvGLGcCNejHvZ_g-VQI,16761
|
|
3
3
|
ee/_arg_types.py,sha256=nrJrnPFnAS8fzMxAGmG3TbUOi_yFVrnSGW5IP8ATzDQ,2662
|
|
4
4
|
ee/_cloud_api_utils.py,sha256=5WPzP5bcBIbjA7yYN-Cwmht_HU-XobbTrZvRiOEn0e0,32890
|
|
5
5
|
ee/_helpers.py,sha256=afDDqoz1WESKE-lzqLtrCbvoQ1yVpfvJIgFcmUjO4L8,4821
|
|
@@ -15,7 +15,7 @@ ee/collection.py,sha256=c8OFIX9OVLxTbu8HGYiHOS3Yg6QjnxaO_FAhDhDQpic,32588
|
|
|
15
15
|
ee/computedobject.py,sha256=Cdlccd4vw2neeRQlo5Jn3Q5R-VpQcQufNuxOHfpd1FU,9186
|
|
16
16
|
ee/confusionmatrix.py,sha256=e6vz-FcT6acWxk5pDEK0vLIN1pUjYMh5Gyn1QSGJT3I,4233
|
|
17
17
|
ee/customfunction.py,sha256=Me_iHDnjkYR33JMttGA7pKJlPCjUk8rO_kgaIhDm27M,7408
|
|
18
|
-
ee/data.py,sha256=
|
|
18
|
+
ee/data.py,sha256=TmtDZZXVJxKOVPNSabQ9DxtYALn1BXUHiZJKXzVL6w4,85371
|
|
19
19
|
ee/daterange.py,sha256=nrRYkR2M2aVU0ZJyG7yiZStFt-W2TvYVuazoZK_WZqM,4948
|
|
20
20
|
ee/deprecation.py,sha256=mAFdO7fBjOu9TJd8CJB_M_NsZ6VNSxtSe820QKJx8fE,6243
|
|
21
21
|
ee/deserializer.py,sha256=TjhQjcBnFpz8Kodoj74eSbvkJ2zLjpTTfUpcNEoQR2o,8357
|
|
@@ -42,7 +42,7 @@ ee/join.py,sha256=idnuzRNFvKHRLHV5m9unp_xTsZb-E2kfgUCEYSg64ts,7578
|
|
|
42
42
|
ee/kernel.py,sha256=eTzJFvW4nbyiFl2dDZ0_cA_o3KqCbBewY-BDp7tCB_M,15002
|
|
43
43
|
ee/mapclient.py,sha256=feCFwL76juFFZPI4uycVxUoFMeEFbPFfIVETkmpvmcY,17491
|
|
44
44
|
ee/model.py,sha256=ZLBT0bdo16V_fSR3eqVxvEmkpGGqMdqYBVZTwOAXvcU,12069
|
|
45
|
-
ee/oauth.py,sha256=
|
|
45
|
+
ee/oauth.py,sha256=i2R56YDJwC9A1Wpf9MOz-01L4PYoHvuIs0TnCpjlLxU,22194
|
|
46
46
|
ee/pixeltype.py,sha256=ucUwJ5SvcOT849Ap4mlJL9z11IAbcT1w9ii8-zOoqdI,5196
|
|
47
47
|
ee/projection.py,sha256=n7WvMeYEG9zksGN1tIX7RGweC4IyCrXAKsvPY0e2b8k,5868
|
|
48
48
|
ee/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -69,7 +69,7 @@ ee/tests/clusterer_test.py,sha256=B4m06wAtBeqvnIhRD2lnNy1UHDB_caleK_CqcrAU8dk,11
|
|
|
69
69
|
ee/tests/collection_test.py,sha256=zsBerYrFr390awe-wD8uN9VME_qEsuaEN197hom4Xps,8815
|
|
70
70
|
ee/tests/computedobject_test.py,sha256=B27rDq9Urpvy0WqpdbKRYbt6AcT1i93HX-es7hrhWVY,4840
|
|
71
71
|
ee/tests/confusionmatrix_test.py,sha256=46JJh1-91AiYISXWZ6-2lvY5_Njvc8ompO9kmwqlFdg,7437
|
|
72
|
-
ee/tests/data_test.py,sha256=
|
|
72
|
+
ee/tests/data_test.py,sha256=8oiSnzGoOtWx3YIld8owWYw1zC517uLkq1Uf2Xn4iCI,52063
|
|
73
73
|
ee/tests/daterange_test.py,sha256=a5fpg2lko3kCJzxQPCoAc_vjXkKy2zYcXbeSZKAFovI,8583
|
|
74
74
|
ee/tests/deprecation_test.py,sha256=CoVug7J9YdB2utZ-BikyJcjitYPQLz49JL_z89xuQSQ,8484
|
|
75
75
|
ee/tests/deserializer_test.py,sha256=i_tlyzKgCo1-VpWPAQnTWNcr2klourcMcBbFZJN6Ivw,5050
|
|
@@ -95,15 +95,15 @@ ee/tests/imagecollection_test.py,sha256=qosRZXCbhwFuy8qR7DbA-FMl4ktW7Y2cUJHeXLcs
|
|
|
95
95
|
ee/tests/join_test.py,sha256=pFILq3qM27rO64WYbBC1A_Gs8_pabRv68X7MU_EM_cw,7630
|
|
96
96
|
ee/tests/kernel_test.py,sha256=-0nZVNSxE1IGs4y60oijISh2Hi1V7NCjrmUnEMDd0nQ,19378
|
|
97
97
|
ee/tests/model_test.py,sha256=dgnWfqR4R4MIUljMBL1TOcztzA-lWEl7cT5f2Y0k2ck,12483
|
|
98
|
-
ee/tests/oauth_test.py,sha256=
|
|
98
|
+
ee/tests/oauth_test.py,sha256=8hldNiR3AYtQkWA4vwwSAO6jDIsh_fww7b_cOI9MJjo,9202
|
|
99
99
|
ee/tests/pixeltype_test.py,sha256=00IWKnZ7xxkVwSSCuWOlCwlTsHAb3XPyKp1Arc4S12U,10024
|
|
100
100
|
ee/tests/projection_test.py,sha256=fKXXxQPBvWdlMNtNsJze2pbsT0yHHlL7ON8Pdjm1Z7E,6871
|
|
101
101
|
ee/tests/reducer_test.py,sha256=vqXpgLZ7fPyfZ12srpREgMpfrKYLcFQod3Qn1Niv7VM,31979
|
|
102
102
|
ee/tests/serializer_test.py,sha256=d6IEW_dt-G900IRfQnZftrwjpc1wJ-ouaQQwaLO0FxI,9834
|
|
103
|
-
ee/tests/table_converter_test.py,sha256=
|
|
103
|
+
ee/tests/table_converter_test.py,sha256=t4yIfy40R3U17I_2nVtKm_Q2Tae-UifwZLz8qOmoC9A,5091
|
|
104
104
|
ee/tests/terrain_test.py,sha256=inZ2sy807nDG_HMutzGHaqcTUaLnZQOMdWyf0NrQzV0,4561
|
|
105
|
-
earthengine_api-1.7.
|
|
106
|
-
earthengine_api-1.7.
|
|
107
|
-
earthengine_api-1.7.
|
|
108
|
-
earthengine_api-1.7.
|
|
109
|
-
earthengine_api-1.7.
|
|
105
|
+
earthengine_api-1.7.2rc0.dist-info/METADATA,sha256=-fSFJkm8cxCurqIIWXyR5FNsmKOb8LaI72q9K7fqf2k,2147
|
|
106
|
+
earthengine_api-1.7.2rc0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
107
|
+
earthengine_api-1.7.2rc0.dist-info/entry_points.txt,sha256=-Ax4SCU-S474r8OD2LIxata6PRmkZoDrppQ4fP_exNc,50
|
|
108
|
+
earthengine_api-1.7.2rc0.dist-info/top_level.txt,sha256=go5zOwCgm5lIS3yTR-Vsxp1gNI4qdS-MP5eY-7zMxVY,3
|
|
109
|
+
earthengine_api-1.7.2rc0.dist-info/RECORD,,
|
ee/__init__.py
CHANGED
ee/data.py
CHANGED
|
@@ -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.
|
ee/oauth.py
CHANGED
|
@@ -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>
|
ee/tests/data_test.py
CHANGED
|
@@ -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
|
|
ee/tests/oauth_test.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""Test for the oauth module."""
|
|
3
3
|
|
|
4
|
+
import http.client
|
|
5
|
+
import io
|
|
4
6
|
import json
|
|
5
7
|
import sys
|
|
6
8
|
import tempfile
|
|
@@ -34,20 +36,33 @@ class OAuthTest(unittest.TestCase):
|
|
|
34
36
|
self.assertEqual('xyz', parsed[b'code_verifier'][0].decode())
|
|
35
37
|
return MockResponse(parsed[b'code'][0])
|
|
36
38
|
|
|
37
|
-
with mock.patch(
|
|
39
|
+
with mock.patch.object(urllib.request, 'urlopen', new=mock_urlopen):
|
|
38
40
|
auth_code = '123'
|
|
39
41
|
verifier = 'xyz'
|
|
40
42
|
refresh_token = oauth.request_token(auth_code, verifier)
|
|
41
43
|
self.assertEqual('123456', refresh_token)
|
|
42
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
|
+
|
|
43
58
|
def test_write_token(self):
|
|
44
59
|
|
|
45
60
|
def mock_credentials_path():
|
|
46
|
-
return self.test_tmpdir
|
|
61
|
+
return f'{self.test_tmpdir}/tempfile'
|
|
47
62
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
63
|
+
with mock.patch.object(
|
|
64
|
+
oauth, 'get_credentials_path', new=mock_credentials_path
|
|
65
|
+
):
|
|
51
66
|
client_info = dict(refresh_token='123')
|
|
52
67
|
oauth.write_private_json(oauth.get_credentials_path(), client_info)
|
|
53
68
|
|
|
@@ -55,6 +70,46 @@ class OAuthTest(unittest.TestCase):
|
|
|
55
70
|
token = json.load(f)
|
|
56
71
|
self.assertEqual({'refresh_token': '123'}, token)
|
|
57
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
|
+
|
|
58
113
|
def test_in_colab_shell(self):
|
|
59
114
|
with mock.patch.dict(sys.modules, {'google.colab': None}):
|
|
60
115
|
self.assertFalse(oauth.in_colab_shell())
|
|
@@ -78,7 +133,7 @@ class OAuthTest(unittest.TestCase):
|
|
|
78
133
|
)
|
|
79
134
|
)
|
|
80
135
|
|
|
81
|
-
def
|
|
136
|
+
def test_colab_mode_with_nonstandard_scopes_raises_exception(self):
|
|
82
137
|
with self.assertRaisesRegex(
|
|
83
138
|
ee_exception.EEException,
|
|
84
139
|
'Scopes cannot be customized when auth_mode is "colab".'
|
|
@@ -88,7 +143,7 @@ class OAuthTest(unittest.TestCase):
|
|
|
88
143
|
scopes=['https://www.googleapis.com/auth/earthengine.readonly']
|
|
89
144
|
)
|
|
90
145
|
|
|
91
|
-
def
|
|
146
|
+
def test_colab_auth_mode_with_standard_scopes_succeeds(self):
|
|
92
147
|
# Should not raise an exception if the scopes are not narrowed.
|
|
93
148
|
with mock.patch.dict(sys.modules, {'google.colab': mock.MagicMock()}):
|
|
94
149
|
try:
|
|
@@ -96,5 +151,113 @@ class OAuthTest(unittest.TestCase):
|
|
|
96
151
|
except ee_exception.EEException:
|
|
97
152
|
self.fail('authenticate raised an exception unexpectedly.')
|
|
98
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
|
+
|
|
99
262
|
if __name__ == '__main__':
|
|
100
263
|
unittest.main()
|
ee/tests/table_converter_test.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""Tests for the table_converter module."""
|
|
3
3
|
|
|
4
|
+
import builtins
|
|
4
5
|
from typing import Any
|
|
6
|
+
from unittest import mock
|
|
5
7
|
|
|
6
8
|
from absl.testing import parameterized
|
|
7
9
|
import geopandas
|
|
@@ -29,7 +31,7 @@ class TableConverterTest(parameterized.TestCase):
|
|
|
29
31
|
self,
|
|
30
32
|
data_format: str,
|
|
31
33
|
expected: type[table_converter.TableConverter] | None,
|
|
32
|
-
)
|
|
34
|
+
):
|
|
33
35
|
"""Verifies `from_file_format` returns the correct converter class."""
|
|
34
36
|
if expected is None:
|
|
35
37
|
self.assertIsNone(table_converter.from_file_format(data_format))
|
|
@@ -38,7 +40,17 @@ class TableConverterTest(parameterized.TestCase):
|
|
|
38
40
|
table_converter.from_file_format(data_format), expected
|
|
39
41
|
)
|
|
40
42
|
|
|
41
|
-
def
|
|
43
|
+
def test_from_file_format_instance(self):
|
|
44
|
+
"""Verifies `from_file_format` returns the same instance."""
|
|
45
|
+
converter = table_converter.PandasConverter()
|
|
46
|
+
self.assertIs(table_converter.from_file_format(converter), converter)
|
|
47
|
+
|
|
48
|
+
def test_table_converter_fails(self):
|
|
49
|
+
"""Verifies `TableConverter` cannot be used for conversion."""
|
|
50
|
+
with self.assertRaises(NotImplementedError):
|
|
51
|
+
table_converter.TableConverter().do_conversion(iter([]))
|
|
52
|
+
|
|
53
|
+
def test_pandas_converter(self):
|
|
42
54
|
"""Verifies `PandasConverter` does the correct conversion."""
|
|
43
55
|
converter = table_converter.PandasConverter()
|
|
44
56
|
|
|
@@ -69,7 +81,23 @@ class TableConverterTest(parameterized.TestCase):
|
|
|
69
81
|
]),
|
|
70
82
|
)
|
|
71
83
|
|
|
72
|
-
def
|
|
84
|
+
def test_pandas_converter_importerror(self):
|
|
85
|
+
"""Ensures ImportError is raised when pandas is not available."""
|
|
86
|
+
real_import = builtins.__import__
|
|
87
|
+
|
|
88
|
+
def mock_import(name, globals=None, locals=None, fromlist=(), level=0):
|
|
89
|
+
if name == 'pandas':
|
|
90
|
+
raise ImportError
|
|
91
|
+
return real_import(name, globals, locals, fromlist, level)
|
|
92
|
+
|
|
93
|
+
with mock.patch('builtins.__import__', mock_import):
|
|
94
|
+
converter = table_converter.PandasConverter()
|
|
95
|
+
with self.assertRaisesRegex(
|
|
96
|
+
ImportError, 'Using format PANDAS_DATAFRAME requires pandas.'
|
|
97
|
+
):
|
|
98
|
+
converter.do_conversion(iter([]))
|
|
99
|
+
|
|
100
|
+
def test_geopandas_converter(self):
|
|
73
101
|
"""Verifies `GeoPandasConverter` does the correct conversion."""
|
|
74
102
|
converter = table_converter.GeoPandasConverter()
|
|
75
103
|
|
|
@@ -105,6 +133,22 @@ class TableConverterTest(parameterized.TestCase):
|
|
|
105
133
|
geopandas.GeoDataFrame.from_features(feature_coll),
|
|
106
134
|
)
|
|
107
135
|
|
|
136
|
+
def test_geopandas_converter_importerror(self):
|
|
137
|
+
"""Ensures ImportError is raised when geopandas is not available."""
|
|
138
|
+
real_import = builtins.__import__
|
|
139
|
+
|
|
140
|
+
def mock_import(name, globals=None, locals=None, fromlist=(), level=0):
|
|
141
|
+
if name == 'geopandas':
|
|
142
|
+
raise ImportError
|
|
143
|
+
return real_import(name, globals, locals, fromlist, level)
|
|
144
|
+
|
|
145
|
+
with mock.patch('builtins.__import__', mock_import):
|
|
146
|
+
converter = table_converter.GeoPandasConverter()
|
|
147
|
+
with self.assertRaisesRegex(
|
|
148
|
+
ImportError, 'Using format GEOPANDAS_GEODATAFRAME requires geopandas.'
|
|
149
|
+
):
|
|
150
|
+
converter.do_conversion(iter([]))
|
|
151
|
+
|
|
108
152
|
|
|
109
153
|
if __name__ == '__main__':
|
|
110
154
|
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|