earthengine-api 1.6.13__py3-none-any.whl → 1.7.4__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.6.13.dist-info → earthengine_api-1.7.4.dist-info}/METADATA +2 -3
- {earthengine_api-1.6.13.dist-info → earthengine_api-1.7.4.dist-info}/RECORD +44 -44
- ee/__init__.py +13 -13
- ee/_cloud_api_utils.py +29 -28
- ee/_helpers.py +6 -6
- ee/_utils.py +2 -1
- ee/apitestcase.py +10 -10
- ee/batch.py +7 -0
- ee/cli/commands.py +6 -10
- ee/cli/utils.py +28 -23
- ee/collection.py +3 -2
- ee/computedobject.py +4 -1
- ee/customfunction.py +2 -1
- ee/data.py +32 -31
- ee/deprecation.py +8 -2
- ee/deserializer.py +10 -10
- ee/ee_number.py +6 -16
- ee/encodable.py +2 -1
- ee/image_converter.py +3 -3
- ee/imagecollection.py +2 -2
- ee/model.py +29 -31
- ee/oauth.py +37 -37
- ee/reducer.py +2 -0
- ee/serializer.py +6 -6
- ee/table_converter.py +3 -3
- ee/terrain.py +1 -1
- ee/tests/batch_test.py +67 -3
- ee/tests/collection_test.py +35 -0
- ee/tests/data_test.py +300 -4
- ee/tests/deprecation_test.py +4 -2
- ee/tests/deserializer_test.py +47 -0
- ee/tests/ee_number_test.py +40 -1
- ee/tests/image_converter_test.py +1 -3
- ee/tests/kernel_test.py +4 -0
- ee/tests/model_test.py +12 -0
- ee/tests/oauth_test.py +170 -7
- ee/tests/reducer_test.py +13 -0
- ee/tests/serializer_test.py +29 -2
- ee/tests/table_converter_test.py +49 -5
- ee/tests/terrain_test.py +8 -0
- {earthengine_api-1.6.13.dist-info → earthengine_api-1.7.4.dist-info}/WHEEL +0 -0
- {earthengine_api-1.6.13.dist-info → earthengine_api-1.7.4.dist-info}/entry_points.txt +0 -0
- {earthengine_api-1.6.13.dist-info → earthengine_api-1.7.4.dist-info}/licenses/LICENSE +0 -0
- {earthengine_api-1.6.13.dist-info → earthengine_api-1.7.4.dist-info}/top_level.txt +0 -0
ee/model.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"""A wrapper for Models."""
|
|
2
2
|
|
|
3
|
-
from typing import Optional
|
|
4
|
-
|
|
5
3
|
from ee import _arg_types
|
|
6
4
|
from ee import apifunction
|
|
7
5
|
from ee import computedobject
|
|
@@ -66,26 +64,26 @@ class Model(computedobject.ComputedObject):
|
|
|
66
64
|
@deprecation.Deprecated('Migrate to Vertex AI')
|
|
67
65
|
def fromAiPlatformPredictor(
|
|
68
66
|
# pylint: disable=invalid-name
|
|
69
|
-
projectName:
|
|
70
|
-
projectId:
|
|
71
|
-
modelName:
|
|
67
|
+
projectName: _arg_types.Any | None = None,
|
|
68
|
+
projectId: _arg_types.String | None = None,
|
|
69
|
+
modelName: _arg_types.String | None = None,
|
|
72
70
|
# pylint: enable=invalid-name
|
|
73
|
-
version:
|
|
74
|
-
region:
|
|
71
|
+
version: _arg_types.String | None = None,
|
|
72
|
+
region: _arg_types.String | None = None,
|
|
75
73
|
# pylint: disable=invalid-name
|
|
76
|
-
inputProperties:
|
|
77
|
-
inputTypeOverride:
|
|
78
|
-
inputShapes:
|
|
74
|
+
inputProperties: _arg_types.List | None = None,
|
|
75
|
+
inputTypeOverride: _arg_types.Dictionary | None = None,
|
|
76
|
+
inputShapes: _arg_types.Dictionary | None = None,
|
|
79
77
|
# pylint: enable=invalid-name
|
|
80
|
-
proj:
|
|
78
|
+
proj: _arg_types.Projection | None = None,
|
|
81
79
|
# pylint: disable=invalid-name
|
|
82
|
-
fixInputProj:
|
|
83
|
-
inputTileSize:
|
|
84
|
-
inputOverlapSize:
|
|
85
|
-
outputTileSize:
|
|
86
|
-
outputBands:
|
|
87
|
-
outputProperties:
|
|
88
|
-
outputMultiplier:
|
|
80
|
+
fixInputProj: _arg_types.Bool | None = None,
|
|
81
|
+
inputTileSize: _arg_types.List | None = None,
|
|
82
|
+
inputOverlapSize: _arg_types.List | None = None,
|
|
83
|
+
outputTileSize: _arg_types.List | None = None,
|
|
84
|
+
outputBands: _arg_types.Dictionary | None = None,
|
|
85
|
+
outputProperties: _arg_types.Dictionary | None = None,
|
|
86
|
+
outputMultiplier: _arg_types.Number | None = None,
|
|
89
87
|
# pylint: enable=invalid-name
|
|
90
88
|
) -> 'Model':
|
|
91
89
|
"""Returns an ee.Model from a description of an AI Platform prediction model.
|
|
@@ -168,21 +166,21 @@ class Model(computedobject.ComputedObject):
|
|
|
168
166
|
def fromVertexAi(
|
|
169
167
|
endpoint: _arg_types.String,
|
|
170
168
|
# pylint: disable=invalid-name
|
|
171
|
-
inputProperties:
|
|
172
|
-
inputTypeOverride:
|
|
173
|
-
inputShapes:
|
|
169
|
+
inputProperties: _arg_types.List | None = None,
|
|
170
|
+
inputTypeOverride: _arg_types.Dictionary | None = None,
|
|
171
|
+
inputShapes: _arg_types.Dictionary | None = None,
|
|
174
172
|
# pylint: enable=invalid-name
|
|
175
|
-
proj:
|
|
173
|
+
proj: _arg_types.Projection | None = None,
|
|
176
174
|
# pylint: disable=invalid-name
|
|
177
|
-
fixInputProj:
|
|
178
|
-
inputTileSize:
|
|
179
|
-
inputOverlapSize:
|
|
180
|
-
outputTileSize:
|
|
181
|
-
outputBands:
|
|
182
|
-
outputProperties:
|
|
183
|
-
outputMultiplier:
|
|
184
|
-
maxPayloadBytes:
|
|
185
|
-
payloadFormat:
|
|
175
|
+
fixInputProj: _arg_types.Bool | None = None,
|
|
176
|
+
inputTileSize: _arg_types.List | None = None,
|
|
177
|
+
inputOverlapSize: _arg_types.List | None = None,
|
|
178
|
+
outputTileSize: _arg_types.List | None = None,
|
|
179
|
+
outputBands: _arg_types.Dictionary | None = None,
|
|
180
|
+
outputProperties: _arg_types.Dictionary | None = None,
|
|
181
|
+
outputMultiplier: _arg_types.Number | None = None,
|
|
182
|
+
maxPayloadBytes: _arg_types.Integer | None = None,
|
|
183
|
+
payloadFormat: _arg_types.String | None = None,
|
|
186
184
|
# pylint: enable=invalid-name
|
|
187
185
|
) -> 'Model':
|
|
188
186
|
"""Returns an ee.Model from a description of a Vertex AI model endpoint.
|
ee/oauth.py
CHANGED
|
@@ -9,6 +9,7 @@ Typical use-case consists of:
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
import base64
|
|
12
|
+
from collections.abc import Sequence
|
|
12
13
|
import errno
|
|
13
14
|
import hashlib
|
|
14
15
|
import http.server
|
|
@@ -17,8 +18,7 @@ import os
|
|
|
17
18
|
import shutil
|
|
18
19
|
import subprocess
|
|
19
20
|
import sys
|
|
20
|
-
from typing import Any
|
|
21
|
-
from collections.abc import Sequence
|
|
21
|
+
from typing import Any
|
|
22
22
|
import urllib.error
|
|
23
23
|
import urllib.parse
|
|
24
24
|
import urllib.request
|
|
@@ -101,13 +101,13 @@ def get_credentials_arguments() -> dict[str, Any]:
|
|
|
101
101
|
return args
|
|
102
102
|
|
|
103
103
|
|
|
104
|
-
def is_sdk_credentials(credentials:
|
|
104
|
+
def is_sdk_credentials(credentials: Any | None) -> bool:
|
|
105
105
|
return is_sdk_project(project_number_from_credentials(credentials))
|
|
106
106
|
|
|
107
107
|
|
|
108
108
|
def project_number_from_credentials(
|
|
109
|
-
credentials:
|
|
110
|
-
) ->
|
|
109
|
+
credentials: Any | None,
|
|
110
|
+
) -> str | None:
|
|
111
111
|
client_id = credentials and getattr(credentials, 'client_id', None)
|
|
112
112
|
return _project_number_from_client_id(client_id)
|
|
113
113
|
|
|
@@ -116,7 +116,7 @@ def is_sdk_project(project: str) -> bool:
|
|
|
116
116
|
return project in SDK_PROJECTS
|
|
117
117
|
|
|
118
118
|
|
|
119
|
-
def get_appdefault_project() ->
|
|
119
|
+
def get_appdefault_project() -> str | None:
|
|
120
120
|
try:
|
|
121
121
|
adc_path = _cloud_sdk.get_application_default_credentials_path()
|
|
122
122
|
with open(adc_path) as adc_json:
|
|
@@ -134,7 +134,7 @@ def _valid_credentials_exist() -> bool:
|
|
|
134
134
|
return False
|
|
135
135
|
|
|
136
136
|
|
|
137
|
-
def is_valid_credentials(credentials:
|
|
137
|
+
def is_valid_credentials(credentials: Any | None) -> bool:
|
|
138
138
|
if credentials is None:
|
|
139
139
|
return False
|
|
140
140
|
try:
|
|
@@ -146,8 +146,8 @@ def is_valid_credentials(credentials: Optional[Any]) -> bool:
|
|
|
146
146
|
|
|
147
147
|
def get_authorization_url(
|
|
148
148
|
code_challenge: str,
|
|
149
|
-
scopes:
|
|
150
|
-
redirect_uri:
|
|
149
|
+
scopes: Sequence[str] | None = None,
|
|
150
|
+
redirect_uri: str | None = None,
|
|
151
151
|
) -> str:
|
|
152
152
|
"""Returns a URL to generate an auth code."""
|
|
153
153
|
|
|
@@ -164,9 +164,9 @@ def get_authorization_url(
|
|
|
164
164
|
def request_token(
|
|
165
165
|
auth_code: str,
|
|
166
166
|
code_verifier: str,
|
|
167
|
-
client_id:
|
|
168
|
-
client_secret:
|
|
169
|
-
redirect_uri:
|
|
167
|
+
client_id: str | None = None,
|
|
168
|
+
client_secret: str | None = None,
|
|
169
|
+
redirect_uri: str | None = None,
|
|
170
170
|
) -> str:
|
|
171
171
|
"""Uses authorization code to request tokens."""
|
|
172
172
|
|
|
@@ -201,7 +201,7 @@ def write_private_json(json_path: str, info_dict: dict[str, Any]) -> None:
|
|
|
201
201
|
except OSError as e:
|
|
202
202
|
if e.errno != errno.EEXIST:
|
|
203
203
|
# pylint:disable=broad-exception-raised,raise-missing-from
|
|
204
|
-
raise Exception('Error creating directory {}: {}'
|
|
204
|
+
raise Exception(f'Error creating directory {dirname}: {e}')
|
|
205
205
|
# pylint:enable=broad-exception-raised,raise-missing-from
|
|
206
206
|
|
|
207
207
|
file_content = json.dumps(info_dict)
|
|
@@ -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
|
|
@@ -234,7 +234,7 @@ def _in_jupyter_shell() -> bool:
|
|
|
234
234
|
return False
|
|
235
235
|
|
|
236
236
|
|
|
237
|
-
def _project_number_from_client_id(client_id:
|
|
237
|
+
def _project_number_from_client_id(client_id: str | None) -> str | None:
|
|
238
238
|
"""Returns the project number associated with the given OAuth client ID."""
|
|
239
239
|
# Client IDs are of the form:
|
|
240
240
|
# PROJECTNUMBER-BASE32STUFF.apps.googleusercontent.com.
|
|
@@ -243,10 +243,10 @@ def _project_number_from_client_id(client_id: Optional[str]) -> Optional[str]:
|
|
|
243
243
|
|
|
244
244
|
|
|
245
245
|
def _obtain_and_write_token(
|
|
246
|
-
auth_code:
|
|
247
|
-
code_verifier:
|
|
248
|
-
scopes:
|
|
249
|
-
redirect_uri:
|
|
246
|
+
auth_code: str | None = None,
|
|
247
|
+
code_verifier: str | None = None,
|
|
248
|
+
scopes: Sequence[str] | None = None,
|
|
249
|
+
redirect_uri: str | None = None,
|
|
250
250
|
) -> None:
|
|
251
251
|
"""Obtains and writes credentials token based on an authorization code."""
|
|
252
252
|
fetch_data = {}
|
|
@@ -283,7 +283,7 @@ def _obtain_and_write_token(
|
|
|
283
283
|
|
|
284
284
|
|
|
285
285
|
def _display_auth_instructions_for_noninteractive(
|
|
286
|
-
auth_url: str, code_verifier:
|
|
286
|
+
auth_url: str, code_verifier: bytes | str
|
|
287
287
|
) -> None:
|
|
288
288
|
"""Displays instructions for authenticating without blocking for user input."""
|
|
289
289
|
# Python 3 `bytes` should be decoded to `str` if used as an argument of
|
|
@@ -310,7 +310,7 @@ def _display_auth_instructions_for_noninteractive(
|
|
|
310
310
|
|
|
311
311
|
|
|
312
312
|
def _display_auth_instructions_with_print(
|
|
313
|
-
auth_url: str, coda:
|
|
313
|
+
auth_url: str, coda: str | None = None
|
|
314
314
|
) -> None:
|
|
315
315
|
"""Displays instructions for authenticating using a print statement."""
|
|
316
316
|
print(
|
|
@@ -325,11 +325,11 @@ def _display_auth_instructions_with_print(
|
|
|
325
325
|
|
|
326
326
|
|
|
327
327
|
def _display_auth_instructions_with_html(
|
|
328
|
-
auth_url: str, coda:
|
|
328
|
+
auth_url: str, coda: str | None = None
|
|
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>
|
|
@@ -382,8 +382,8 @@ def _no_gcloud() -> bool:
|
|
|
382
382
|
|
|
383
383
|
|
|
384
384
|
def _load_gcloud_credentials(
|
|
385
|
-
scopes:
|
|
386
|
-
quiet:
|
|
385
|
+
scopes: Sequence[str] | None = None,
|
|
386
|
+
quiet: bool | None = None,
|
|
387
387
|
run_gcloud_legacy: bool = False,
|
|
388
388
|
) -> None:
|
|
389
389
|
"""Initializes credentials by running gcloud flows."""
|
|
@@ -435,7 +435,7 @@ def _start_server(port: int):
|
|
|
435
435
|
class Handler(http.server.BaseHTTPRequestHandler):
|
|
436
436
|
"""Handles the OAuth callback and reports a success page."""
|
|
437
437
|
|
|
438
|
-
code:
|
|
438
|
+
code: str | None = None
|
|
439
439
|
|
|
440
440
|
def do_GET(self) -> None: # pylint: disable=invalid-name
|
|
441
441
|
Handler.code = urllib.parse.parse_qs(
|
|
@@ -460,7 +460,7 @@ def _start_server(port: int):
|
|
|
460
460
|
self.server = http.server.HTTPServer(('localhost', port), Handler)
|
|
461
461
|
self.url = 'http://localhost:%s' % self.server.server_address[1]
|
|
462
462
|
|
|
463
|
-
def fetch_code(self) ->
|
|
463
|
+
def fetch_code(self) -> str | None:
|
|
464
464
|
self.server.handle_request() # Blocks until a single request arrives.
|
|
465
465
|
self.server.server_close()
|
|
466
466
|
return Handler.code
|
|
@@ -469,13 +469,13 @@ def _start_server(port: int):
|
|
|
469
469
|
|
|
470
470
|
|
|
471
471
|
def authenticate(
|
|
472
|
-
cli_authorization_code:
|
|
473
|
-
quiet:
|
|
474
|
-
cli_code_verifier:
|
|
475
|
-
auth_mode:
|
|
476
|
-
scopes:
|
|
472
|
+
cli_authorization_code: str | None = None,
|
|
473
|
+
quiet: bool | None = None,
|
|
474
|
+
cli_code_verifier: str | None = None,
|
|
475
|
+
auth_mode: str | None = None,
|
|
476
|
+
scopes: Sequence[str] | None = None,
|
|
477
477
|
force: bool = False,
|
|
478
|
-
) ->
|
|
478
|
+
) -> bool | None:
|
|
479
479
|
"""Prompts the user to authorize access to Earth Engine via OAuth2.
|
|
480
480
|
|
|
481
481
|
Args:
|
|
@@ -564,11 +564,11 @@ class Flow:
|
|
|
564
564
|
"""Holds state for auth flows."""
|
|
565
565
|
code_verifier: str
|
|
566
566
|
scopes: Sequence[str]
|
|
567
|
-
server:
|
|
567
|
+
server: Any | None
|
|
568
568
|
auth_url: str
|
|
569
569
|
|
|
570
570
|
def __init__(
|
|
571
|
-
self, auth_mode: str = 'notebook', scopes:
|
|
571
|
+
self, auth_mode: str = 'notebook', scopes: Sequence[str] | None = None
|
|
572
572
|
):
|
|
573
573
|
"""Initializes auth URL and PKCE verifier, for use in save_code().
|
|
574
574
|
|
|
@@ -601,7 +601,7 @@ class Flow:
|
|
|
601
601
|
# pylint:disable-next=broad-exception-raised
|
|
602
602
|
raise ee_exception.EEException('Unknown auth_mode "%s"' % auth_mode)
|
|
603
603
|
|
|
604
|
-
def save_code(self, code:
|
|
604
|
+
def save_code(self, code: str | None = None) -> None:
|
|
605
605
|
"""Fetches auth code if not given, and saves the generated credentials."""
|
|
606
606
|
redirect_uri = None
|
|
607
607
|
if self.server and not code:
|
|
@@ -609,7 +609,7 @@ class Flow:
|
|
|
609
609
|
code = self.server.fetch_code() # Waits for oauth callback
|
|
610
610
|
_obtain_and_write_token(code, self.code_verifier, self.scopes, redirect_uri)
|
|
611
611
|
|
|
612
|
-
def display_instructions(self, quiet:
|
|
612
|
+
def display_instructions(self, quiet: bool | None = None) -> bool:
|
|
613
613
|
"""Prints to stdout, and returns True if a browser should be opened."""
|
|
614
614
|
|
|
615
615
|
if quiet:
|
ee/reducer.py
CHANGED
|
@@ -465,8 +465,10 @@ class Reducer(computedobject.ComputedObject):
|
|
|
465
465
|
|
|
466
466
|
def group(
|
|
467
467
|
self,
|
|
468
|
+
# pylint: disable=invalid-name
|
|
468
469
|
groupField: _arg_types.Integer | None = None,
|
|
469
470
|
groupName: _arg_types.String | None = None,
|
|
471
|
+
# pylint: enable=invalid-name
|
|
470
472
|
) -> Reducer:
|
|
471
473
|
"""Returns a reducer groups reducer records by the value of a given input.
|
|
472
474
|
|
ee/serializer.py
CHANGED
|
@@ -4,7 +4,7 @@ import collections
|
|
|
4
4
|
import datetime
|
|
5
5
|
import hashlib
|
|
6
6
|
import json
|
|
7
|
-
from typing import Any
|
|
7
|
+
from typing import Any
|
|
8
8
|
|
|
9
9
|
from ee import _cloud_api_utils
|
|
10
10
|
from ee import _utils
|
|
@@ -32,7 +32,7 @@ def DatetimeToMicroseconds(date: datetime.datetime) -> int:
|
|
|
32
32
|
|
|
33
33
|
class Serializer:
|
|
34
34
|
"""A serializer for EE object trees."""
|
|
35
|
-
unbound_name:
|
|
35
|
+
unbound_name: str | None
|
|
36
36
|
|
|
37
37
|
# Whether the encoding should factor out shared subtrees.
|
|
38
38
|
_is_compound: bool
|
|
@@ -48,7 +48,7 @@ class Serializer:
|
|
|
48
48
|
self,
|
|
49
49
|
is_compound: bool = True,
|
|
50
50
|
for_cloud_api: bool = False,
|
|
51
|
-
unbound_name:
|
|
51
|
+
unbound_name: str | None = None,
|
|
52
52
|
):
|
|
53
53
|
"""Constructs a serializer.
|
|
54
54
|
|
|
@@ -280,7 +280,7 @@ def encode(
|
|
|
280
280
|
obj: Any,
|
|
281
281
|
is_compound: bool = True,
|
|
282
282
|
for_cloud_api: bool = True,
|
|
283
|
-
unbound_name:
|
|
283
|
+
unbound_name: str | None = None,
|
|
284
284
|
) -> Any:
|
|
285
285
|
"""Serialize an object to a JSON-compatible structure for API calls.
|
|
286
286
|
|
|
@@ -358,7 +358,7 @@ class _ExpressionOptimizer:
|
|
|
358
358
|
- Collapse dicts and arrays of constants to constant dicts/arrays.
|
|
359
359
|
"""
|
|
360
360
|
|
|
361
|
-
def __init__(self, result: Any, values:
|
|
361
|
+
def __init__(self, result: Any, values: Any | None = None):
|
|
362
362
|
"""Builds an ExpressionOptimizer.
|
|
363
363
|
|
|
364
364
|
Args:
|
|
@@ -385,7 +385,7 @@ class _ExpressionOptimizer:
|
|
|
385
385
|
reference_counts = collections.defaultdict(int)
|
|
386
386
|
reference_counts[self._result] += 1
|
|
387
387
|
|
|
388
|
-
def _contained_reference(value: Any) ->
|
|
388
|
+
def _contained_reference(value: Any) -> Any | None:
|
|
389
389
|
"""Gets a contained reference from a ValueNode, if there is one."""
|
|
390
390
|
if 'functionDefinitionValue' in value:
|
|
391
391
|
return value['functionDefinitionValue']['body']
|
ee/table_converter.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Converters used in the table data fetching methods."""
|
|
2
2
|
|
|
3
3
|
from collections.abc import Iterator
|
|
4
|
-
from typing import Any
|
|
4
|
+
from typing import Any
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class TableConverter:
|
|
@@ -59,8 +59,8 @@ _TABLE_DATA_CONVERTERS: dict[str, type[TableConverter]] = {
|
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
def from_file_format(
|
|
62
|
-
file_format:
|
|
63
|
-
) ->
|
|
62
|
+
file_format: str | TableConverter
|
|
63
|
+
) -> TableConverter | None:
|
|
64
64
|
if isinstance(file_format, TableConverter):
|
|
65
65
|
return file_format
|
|
66
66
|
if file_format in _TABLE_DATA_CONVERTERS:
|
ee/terrain.py
CHANGED
|
@@ -13,7 +13,7 @@ class Terrain:
|
|
|
13
13
|
|
|
14
14
|
def __init__(self):
|
|
15
15
|
raise RuntimeError(
|
|
16
|
-
self.__name__
|
|
16
|
+
self.__class__.__name__
|
|
17
17
|
+ ' should not be used as an object. Only direct usage of Terrain'
|
|
18
18
|
' static methods is allowed. For example, use this: '
|
|
19
19
|
' `ee.Terrain.aspect(...)`'
|
ee/tests/batch_test.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"""Test for the ee.batch module."""
|
|
3
3
|
|
|
4
4
|
import json
|
|
5
|
-
from typing import Any
|
|
5
|
+
from typing import Any
|
|
6
6
|
import unittest
|
|
7
7
|
from unittest import mock
|
|
8
8
|
|
|
@@ -138,6 +138,14 @@ class TaskTest(unittest.TestCase):
|
|
|
138
138
|
):
|
|
139
139
|
self.assertFalse(task.active())
|
|
140
140
|
|
|
141
|
+
def test_success(self):
|
|
142
|
+
self.assertTrue(batch.Task.State.success(batch.Task.State.COMPLETED))
|
|
143
|
+
self.assertTrue(batch.Task.State.success('COMPLETED'))
|
|
144
|
+
for state in batch.Task.State:
|
|
145
|
+
if state != batch.Task.State.COMPLETED:
|
|
146
|
+
self.assertFalse(batch.Task.State.success(state))
|
|
147
|
+
self.assertFalse(batch.Task.State.success(state.value))
|
|
148
|
+
|
|
141
149
|
def test_repr_without_config(self):
|
|
142
150
|
task = batch.Task('an id', 'a task type', 'a state')
|
|
143
151
|
self.assertEqual('<Task "an id">', task.__repr__())
|
|
@@ -193,8 +201,8 @@ class ExportTest(unittest.TestCase):
|
|
|
193
201
|
class BatchTestCase(apitestcase.ApiTestCase):
|
|
194
202
|
"""A test case for batch functionality."""
|
|
195
203
|
|
|
196
|
-
start_call_params:
|
|
197
|
-
update_call_params:
|
|
204
|
+
start_call_params: Any | None
|
|
205
|
+
update_call_params: Any | None
|
|
198
206
|
|
|
199
207
|
def setUp(self):
|
|
200
208
|
super().setUp()
|
|
@@ -266,6 +274,7 @@ class BatchTestCase(apitestcase.ApiTestCase):
|
|
|
266
274
|
'name': (
|
|
267
275
|
'projects/earthengine-legacy/assets/users/foo/bar'
|
|
268
276
|
),
|
|
277
|
+
'overwrite': False,
|
|
269
278
|
}
|
|
270
279
|
},
|
|
271
280
|
'description': 'myExportImageTask',
|
|
@@ -417,6 +426,7 @@ class BatchTestCase(apitestcase.ApiTestCase):
|
|
|
417
426
|
'name': (
|
|
418
427
|
'projects/earthengine-legacy/assets/users/foo/bar'
|
|
419
428
|
),
|
|
429
|
+
'overwrite': False,
|
|
420
430
|
},
|
|
421
431
|
'pyramidingPolicyOverrides': {'B1': 'MIN'},
|
|
422
432
|
},
|
|
@@ -443,6 +453,7 @@ class BatchTestCase(apitestcase.ApiTestCase):
|
|
|
443
453
|
'name': (
|
|
444
454
|
'projects/earthengine-legacy/assets/users/foo/bar'
|
|
445
455
|
),
|
|
456
|
+
'overwrite': False,
|
|
446
457
|
},
|
|
447
458
|
'tileSize': {'value': 4},
|
|
448
459
|
},
|
|
@@ -452,6 +463,43 @@ class BatchTestCase(apitestcase.ApiTestCase):
|
|
|
452
463
|
task_ordered.config,
|
|
453
464
|
)
|
|
454
465
|
|
|
466
|
+
task_with_overwrite = ee.batch.Export.image.toAsset(
|
|
467
|
+
image=config['image'],
|
|
468
|
+
assetId=config['assetId'],
|
|
469
|
+
overwrite=True,
|
|
470
|
+
)
|
|
471
|
+
self.assertTrue(
|
|
472
|
+
task_with_overwrite.config['assetExportOptions'][
|
|
473
|
+
'earthEngineDestination'
|
|
474
|
+
]['overwrite']
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
task_with_priority = ee.batch.Export.image.toAsset(
|
|
478
|
+
image=config['image'],
|
|
479
|
+
assetId=config['assetId'],
|
|
480
|
+
priority=999,
|
|
481
|
+
)
|
|
482
|
+
self.assertIsNone(task_with_priority.id)
|
|
483
|
+
self.assertIsNone(task_with_priority.name)
|
|
484
|
+
self.assertEqual('EXPORT_IMAGE', task_with_priority.task_type)
|
|
485
|
+
self.assertEqual('UNSUBMITTED', task_with_priority.state)
|
|
486
|
+
self.assertEqual(
|
|
487
|
+
{
|
|
488
|
+
'expression': expected_expression,
|
|
489
|
+
'description': 'myExportImageTask',
|
|
490
|
+
'assetExportOptions': {
|
|
491
|
+
'earthEngineDestination': {
|
|
492
|
+
'name': (
|
|
493
|
+
'projects/earthengine-legacy/assets/users/foo/bar'
|
|
494
|
+
),
|
|
495
|
+
'overwrite': False,
|
|
496
|
+
}
|
|
497
|
+
},
|
|
498
|
+
'priority': {'value': 999},
|
|
499
|
+
},
|
|
500
|
+
task_with_priority.config,
|
|
501
|
+
)
|
|
502
|
+
|
|
455
503
|
def test_export_image_to_asset_cloud_api_with_tile_size(self):
|
|
456
504
|
"""Verifies the Asset export task created by Export.image.toAsset()."""
|
|
457
505
|
with apitestcase.UsingCloudApi():
|
|
@@ -481,6 +529,7 @@ class BatchTestCase(apitestcase.ApiTestCase):
|
|
|
481
529
|
'name': (
|
|
482
530
|
'projects/earthengine-legacy/assets/users/foo/bar'
|
|
483
531
|
),
|
|
532
|
+
'overwrite': False,
|
|
484
533
|
},
|
|
485
534
|
'tileSize': {'value': 4},
|
|
486
535
|
},
|
|
@@ -1125,11 +1174,25 @@ class BatchTestCase(apitestcase.ApiTestCase):
|
|
|
1125
1174
|
'name': (
|
|
1126
1175
|
'projects/earthengine-legacy/assets/users/foo/bar'
|
|
1127
1176
|
),
|
|
1177
|
+
'overwrite': False,
|
|
1128
1178
|
}
|
|
1129
1179
|
},
|
|
1130
1180
|
},
|
|
1131
1181
|
task.config,
|
|
1132
1182
|
)
|
|
1183
|
+
|
|
1184
|
+
task_with_overwrite = ee.batch.Export.table.toAsset(
|
|
1185
|
+
collection=ee.FeatureCollection('foo'),
|
|
1186
|
+
description='foo',
|
|
1187
|
+
assetId='users/foo/bar',
|
|
1188
|
+
overwrite=True,
|
|
1189
|
+
)
|
|
1190
|
+
self.assertTrue(
|
|
1191
|
+
task_with_overwrite.config['assetExportOptions'][
|
|
1192
|
+
'earthEngineDestination'
|
|
1193
|
+
]['overwrite']
|
|
1194
|
+
)
|
|
1195
|
+
|
|
1133
1196
|
task_with_priority = ee.batch.Export.table.toAsset(
|
|
1134
1197
|
collection=ee.FeatureCollection('foo'),
|
|
1135
1198
|
description='foo',
|
|
@@ -1145,6 +1208,7 @@ class BatchTestCase(apitestcase.ApiTestCase):
|
|
|
1145
1208
|
'name': (
|
|
1146
1209
|
'projects/earthengine-legacy/assets/users/foo/bar'
|
|
1147
1210
|
),
|
|
1211
|
+
'overwrite': False,
|
|
1148
1212
|
}
|
|
1149
1213
|
},
|
|
1150
1214
|
'priority': {'value': 999},
|
ee/tests/collection_test.py
CHANGED
|
@@ -47,6 +47,10 @@ class CollectionTestCase(apitestcase.ApiTestCase):
|
|
|
47
47
|
|
|
48
48
|
# We don't allow empty filters.
|
|
49
49
|
self.assertRaises(Exception, collection.filter)
|
|
50
|
+
with self.assertRaisesRegex(ee.EEException, 'Empty filters.'):
|
|
51
|
+
collection.filter(None) # pytype: disable=wrong-arg-types
|
|
52
|
+
with self.assertRaisesRegex(ee.EEException, 'Empty filters.'):
|
|
53
|
+
collection.filter('')
|
|
50
54
|
|
|
51
55
|
filtered = collection.filter(ee.Filter.eq('foo', 1))
|
|
52
56
|
self.assertEqual(ee.ApiFunction.lookup('Collection.filter'), filtered.func)
|
|
@@ -75,6 +79,37 @@ class CollectionTestCase(apitestcase.ApiTestCase):
|
|
|
75
79
|
collection.filter(ee.Filter.eq('foo', 13)),
|
|
76
80
|
collection.filterMetadata('foo', 'equals', 13))
|
|
77
81
|
|
|
82
|
+
def test_load_table(self):
|
|
83
|
+
"""Verifies Collection.loadTable()."""
|
|
84
|
+
table_id = 'a/table/id'
|
|
85
|
+
geometry_column = 'geom'
|
|
86
|
+
version = 123
|
|
87
|
+
result = ee.Collection.loadTable(
|
|
88
|
+
tableId=table_id, geometryColumn=geometry_column, version=version
|
|
89
|
+
)
|
|
90
|
+
self.assertEqual(ee.ApiFunction.lookup('Collection.loadTable'), result.func)
|
|
91
|
+
self.assertEqual(
|
|
92
|
+
{
|
|
93
|
+
'tableId': ee.String(table_id),
|
|
94
|
+
'geometryColumn': ee.String(geometry_column),
|
|
95
|
+
'version': ee.Number(version),
|
|
96
|
+
},
|
|
97
|
+
result.args,
|
|
98
|
+
)
|
|
99
|
+
self.assertIsInstance(result, ee.FeatureCollection)
|
|
100
|
+
|
|
101
|
+
result2 = ee.Collection.loadTable(tableId=table_id)
|
|
102
|
+
self.assertEqual(ee.ApiFunction.lookup('Collection.loadTable'), result2.func)
|
|
103
|
+
self.assertEqual(
|
|
104
|
+
{
|
|
105
|
+
'tableId': ee.String(table_id),
|
|
106
|
+
'geometryColumn': None,
|
|
107
|
+
'version': None,
|
|
108
|
+
},
|
|
109
|
+
result2.args,
|
|
110
|
+
)
|
|
111
|
+
self.assertIsInstance(result2, ee.FeatureCollection)
|
|
112
|
+
|
|
78
113
|
def test_mapping(self):
|
|
79
114
|
"""Verifies the behavior of the map() method."""
|
|
80
115
|
collection = ee.ImageCollection('foo')
|