earthengine-api 1.6.11__py3-none-any.whl → 1.6.12__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.
- {earthengine_api-1.6.11.dist-info → earthengine_api-1.6.12.dist-info}/METADATA +1 -1
- {earthengine_api-1.6.11.dist-info → earthengine_api-1.6.12.dist-info}/RECORD +48 -46
- ee/__init__.py +5 -5
- ee/_cloud_api_utils.py +33 -10
- ee/_state.py +105 -0
- ee/apifunction.py +1 -1
- ee/apitestcase.py +15 -21
- ee/batch.py +1 -1
- ee/cli/commands.py +153 -63
- ee/cli/eecli.py +1 -1
- ee/cli/utils.py +25 -15
- ee/collection.py +27 -18
- ee/computedobject.py +5 -5
- ee/customfunction.py +3 -3
- ee/data.py +104 -210
- ee/ee_array.py +4 -2
- ee/ee_number.py +1 -1
- ee/ee_string.py +18 -26
- ee/ee_types.py +2 -2
- ee/element.py +1 -1
- ee/featurecollection.py +10 -7
- ee/filter.py +2 -2
- ee/geometry.py +20 -21
- ee/image.py +7 -12
- ee/imagecollection.py +3 -3
- ee/mapclient.py +9 -9
- ee/oauth.py +13 -6
- ee/tests/_cloud_api_utils_test.py +16 -0
- ee/tests/_helpers_test.py +9 -9
- ee/tests/_state_test.py +49 -0
- ee/tests/apifunction_test.py +5 -5
- ee/tests/batch_test.py +61 -50
- ee/tests/collection_test.py +13 -13
- ee/tests/data_test.py +65 -60
- ee/tests/dictionary_test.py +9 -9
- ee/tests/ee_number_test.py +32 -26
- ee/tests/ee_string_test.py +8 -0
- ee/tests/ee_test.py +37 -19
- ee/tests/element_test.py +2 -2
- ee/tests/feature_test.py +6 -6
- ee/tests/function_test.py +5 -5
- ee/tests/geometry_test.py +73 -51
- ee/tests/oauth_test.py +21 -2
- ee/tests/serializer_test.py +8 -8
- {earthengine_api-1.6.11.dist-info → earthengine_api-1.6.12.dist-info}/WHEEL +0 -0
- {earthengine_api-1.6.11.dist-info → earthengine_api-1.6.12.dist-info}/entry_points.txt +0 -0
- {earthengine_api-1.6.11.dist-info → earthengine_api-1.6.12.dist-info}/licenses/LICENSE +0 -0
- {earthengine_api-1.6.11.dist-info → earthengine_api-1.6.12.dist-info}/top_level.txt +0 -0
ee/data.py
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
# Using lowercase function naming to match the JavaScript names.
|
|
4
4
|
# pylint: disable=g-bad-name
|
|
5
5
|
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
6
8
|
from collections.abc import Iterator, Sequence
|
|
7
9
|
import contextlib
|
|
8
10
|
import json
|
|
@@ -23,6 +25,7 @@ import httplib2
|
|
|
23
25
|
import requests
|
|
24
26
|
|
|
25
27
|
from ee import _cloud_api_utils
|
|
28
|
+
from ee import _state
|
|
26
29
|
from ee import _utils
|
|
27
30
|
from ee import computedobject
|
|
28
31
|
from ee import deprecation
|
|
@@ -93,52 +96,6 @@ _NOT_INITIALIZED_MESSAGE = (
|
|
|
93
96
|
'Earth Engine client library not initialized. See http://goo.gle/ee-auth.'
|
|
94
97
|
)
|
|
95
98
|
|
|
96
|
-
# OAuth2 credentials object. This may be set by ee.Initialize().
|
|
97
|
-
_credentials: Optional[credentials_lib.Credentials] = None
|
|
98
|
-
|
|
99
|
-
# The base URL for all data calls. This is set by ee.Initialize().
|
|
100
|
-
_api_base_url: Optional[str] = None
|
|
101
|
-
|
|
102
|
-
# The base URL for map tiles. This is set by ee.Initialize().
|
|
103
|
-
_tile_base_url: Optional[str] = None
|
|
104
|
-
|
|
105
|
-
# The base URL for all Cloud API calls. This is set by ee.Initialize().
|
|
106
|
-
_cloud_api_base_url: Optional[str] = None
|
|
107
|
-
|
|
108
|
-
# Google Cloud API key. This may be set by ee.Initialize().
|
|
109
|
-
_cloud_api_key: Optional[str] = None
|
|
110
|
-
|
|
111
|
-
# A Requests session. This is set by ee.Initialize()
|
|
112
|
-
_requests_session: Optional[requests.Session] = None
|
|
113
|
-
|
|
114
|
-
# A resource object for making Cloud API calls.
|
|
115
|
-
_cloud_api_resource = None
|
|
116
|
-
|
|
117
|
-
# A resource object for making Cloud API calls and receiving raw return types.
|
|
118
|
-
_cloud_api_resource_raw = None
|
|
119
|
-
|
|
120
|
-
# The default user project to use when making Cloud API calls.
|
|
121
|
-
_cloud_api_user_project: str = DEFAULT_CLOUD_API_USER_PROJECT
|
|
122
|
-
|
|
123
|
-
# The API client version number to send when making requests.
|
|
124
|
-
_cloud_api_client_version: Optional[str] = None
|
|
125
|
-
|
|
126
|
-
# The http_transport to use.
|
|
127
|
-
_http_transport = None
|
|
128
|
-
|
|
129
|
-
# Whether the module has been initialized.
|
|
130
|
-
_initialized: bool = False
|
|
131
|
-
|
|
132
|
-
# Sets the number of milliseconds to wait for a request before considering
|
|
133
|
-
# it timed out. 0 means no limit.
|
|
134
|
-
_deadline_ms: int = 0
|
|
135
|
-
|
|
136
|
-
# Maximum number of times to retry a rate-limited request.
|
|
137
|
-
_max_retries: int = 5
|
|
138
|
-
|
|
139
|
-
# User agent to indicate which application is calling Earth Engine
|
|
140
|
-
_user_agent: Optional[str] = None
|
|
141
|
-
|
|
142
99
|
|
|
143
100
|
class _ThreadLocals(threading.local):
|
|
144
101
|
"""Storage for thread local variables."""
|
|
@@ -161,6 +118,11 @@ class _ThreadLocals(threading.local):
|
|
|
161
118
|
_thread_locals = _ThreadLocals()
|
|
162
119
|
|
|
163
120
|
|
|
121
|
+
def _get_state() -> _state.EEState:
|
|
122
|
+
"""Returns the current state, or a default state if not initialized."""
|
|
123
|
+
return _state.get_state()
|
|
124
|
+
|
|
125
|
+
|
|
164
126
|
def initialize(
|
|
165
127
|
credentials: Any = None,
|
|
166
128
|
api_base_url: Optional[str] = None,
|
|
@@ -188,57 +150,51 @@ def initialize(
|
|
|
188
150
|
project: The client project ID or number to use when making API calls.
|
|
189
151
|
http_transport: The http transport to use
|
|
190
152
|
"""
|
|
191
|
-
|
|
192
|
-
global _requests_session
|
|
193
|
-
global _cloud_api_base_url
|
|
194
|
-
global _cloud_api_key
|
|
195
|
-
global _cloud_api_user_project, _http_transport
|
|
196
|
-
global _cloud_api_client_version
|
|
197
|
-
|
|
153
|
+
state = _get_state()
|
|
198
154
|
# If already initialized, only replace the explicitly specified parts.
|
|
199
155
|
|
|
200
156
|
if credentials is not None:
|
|
201
|
-
|
|
157
|
+
state.credentials = credentials
|
|
202
158
|
|
|
203
159
|
if api_base_url is not None:
|
|
204
|
-
|
|
205
|
-
elif not
|
|
206
|
-
|
|
160
|
+
state.api_base_url = api_base_url
|
|
161
|
+
elif not state.initialized:
|
|
162
|
+
state.api_base_url = DEFAULT_API_BASE_URL
|
|
207
163
|
|
|
208
164
|
if tile_base_url is not None:
|
|
209
|
-
|
|
210
|
-
elif not
|
|
211
|
-
|
|
165
|
+
state.tile_base_url = tile_base_url
|
|
166
|
+
elif not state.initialized:
|
|
167
|
+
state.tile_base_url = DEFAULT_TILE_BASE_URL
|
|
212
168
|
|
|
213
169
|
if cloud_api_key is not None:
|
|
214
|
-
|
|
170
|
+
state.cloud_api_key = cloud_api_key
|
|
215
171
|
|
|
216
172
|
if cloud_api_base_url is not None:
|
|
217
|
-
|
|
218
|
-
elif not
|
|
219
|
-
|
|
173
|
+
state.cloud_api_base_url = cloud_api_base_url
|
|
174
|
+
elif not state.initialized:
|
|
175
|
+
state.cloud_api_base_url = DEFAULT_CLOUD_API_BASE_URL
|
|
220
176
|
|
|
221
177
|
if __version__ is not None:
|
|
222
178
|
version = __version__
|
|
223
|
-
|
|
179
|
+
state.cloud_api_client_version = version
|
|
224
180
|
|
|
225
|
-
|
|
181
|
+
state.http_transport = http_transport
|
|
226
182
|
|
|
227
|
-
if
|
|
228
|
-
|
|
183
|
+
if state.requests_session is None:
|
|
184
|
+
state.requests_session = requests.Session()
|
|
229
185
|
|
|
230
186
|
_install_cloud_api_resource()
|
|
231
187
|
|
|
232
188
|
if project is not None:
|
|
233
|
-
|
|
189
|
+
state.cloud_api_user_project = project
|
|
234
190
|
else:
|
|
235
|
-
|
|
191
|
+
state.cloud_api_user_project = DEFAULT_CLOUD_API_USER_PROJECT
|
|
236
192
|
|
|
237
|
-
|
|
193
|
+
state.initialized = True
|
|
238
194
|
|
|
239
195
|
|
|
240
196
|
def is_initialized() -> bool:
|
|
241
|
-
return
|
|
197
|
+
return _get_state().initialized
|
|
242
198
|
|
|
243
199
|
|
|
244
200
|
def get_persistent_credentials() -> credentials_lib.Credentials:
|
|
@@ -286,89 +242,78 @@ def get_persistent_credentials() -> credentials_lib.Credentials:
|
|
|
286
242
|
|
|
287
243
|
|
|
288
244
|
def reset() -> None:
|
|
289
|
-
"""Resets the
|
|
290
|
-
|
|
291
|
-
global _requests_session, _cloud_api_resource, _cloud_api_resource_raw
|
|
292
|
-
global _cloud_api_base_url, _cloud_api_user_project
|
|
293
|
-
global _cloud_api_key, _http_transport
|
|
294
|
-
_credentials = None
|
|
295
|
-
_api_base_url = None
|
|
296
|
-
_tile_base_url = None
|
|
297
|
-
if _requests_session is not None:
|
|
298
|
-
_requests_session.close()
|
|
299
|
-
_requests_session = None
|
|
300
|
-
_cloud_api_base_url = None
|
|
301
|
-
_cloud_api_key = None
|
|
302
|
-
_cloud_api_resource = None
|
|
303
|
-
_cloud_api_resource_raw = None
|
|
304
|
-
_cloud_api_user_project = DEFAULT_CLOUD_API_USER_PROJECT
|
|
305
|
-
_http_transport = None
|
|
306
|
-
_initialized = False
|
|
245
|
+
"""Resets the EE state, clearing credentials and custom base URLs."""
|
|
246
|
+
_state.reset_state()
|
|
307
247
|
|
|
308
248
|
|
|
309
249
|
def _get_projects_path() -> str:
|
|
310
250
|
"""Returns the projects path to use for constructing a request."""
|
|
311
|
-
return f'projects/{
|
|
251
|
+
return f'projects/{_get_state().cloud_api_user_project}'
|
|
312
252
|
|
|
313
253
|
|
|
314
254
|
def _install_cloud_api_resource() -> None:
|
|
315
255
|
"""Builds or rebuilds the Cloud API resource object, if needed."""
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
timeout = (
|
|
319
|
-
assert
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
credentials=
|
|
324
|
-
api_key=
|
|
256
|
+
state = _get_state()
|
|
257
|
+
|
|
258
|
+
timeout = (state.deadline_ms / 1000.0) or None
|
|
259
|
+
assert state.requests_session is not None
|
|
260
|
+
state.cloud_api_resource = _cloud_api_utils.build_cloud_resource(
|
|
261
|
+
state.cloud_api_base_url,
|
|
262
|
+
state.requests_session,
|
|
263
|
+
credentials=state.credentials,
|
|
264
|
+
api_key=state.cloud_api_key,
|
|
325
265
|
timeout=timeout,
|
|
326
|
-
num_retries=
|
|
266
|
+
num_retries=state.max_retries,
|
|
327
267
|
headers_supplier=_make_request_headers,
|
|
328
268
|
response_inspector=_handle_profiling_response,
|
|
329
|
-
http_transport=
|
|
269
|
+
http_transport=state.http_transport,
|
|
330
270
|
)
|
|
331
271
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
credentials=
|
|
336
|
-
api_key=
|
|
272
|
+
state.cloud_api_resource_raw = _cloud_api_utils.build_cloud_resource(
|
|
273
|
+
state.cloud_api_base_url,
|
|
274
|
+
state.requests_session,
|
|
275
|
+
credentials=state.credentials,
|
|
276
|
+
api_key=state.cloud_api_key,
|
|
337
277
|
timeout=timeout,
|
|
338
|
-
num_retries=
|
|
278
|
+
num_retries=state.max_retries,
|
|
339
279
|
headers_supplier=_make_request_headers,
|
|
340
280
|
response_inspector=_handle_profiling_response,
|
|
341
|
-
http_transport=
|
|
281
|
+
http_transport=state.http_transport,
|
|
342
282
|
raw=True,
|
|
343
283
|
)
|
|
344
284
|
|
|
345
285
|
|
|
346
286
|
def _get_cloud_projects() -> Any:
|
|
347
|
-
|
|
287
|
+
state = _get_state()
|
|
288
|
+
if state.cloud_api_resource is None:
|
|
348
289
|
raise ee_exception.EEException(_NOT_INITIALIZED_MESSAGE)
|
|
349
|
-
return
|
|
290
|
+
return state.cloud_api_resource.projects()
|
|
350
291
|
|
|
351
292
|
|
|
352
293
|
def _get_cloud_projects_raw() -> Any:
|
|
353
|
-
|
|
294
|
+
state = _get_state()
|
|
295
|
+
if state.cloud_api_resource_raw is None:
|
|
354
296
|
raise ee_exception.EEException(_NOT_INITIALIZED_MESSAGE)
|
|
355
|
-
return
|
|
297
|
+
return state.cloud_api_resource_raw.projects()
|
|
356
298
|
|
|
357
299
|
|
|
358
300
|
def _make_request_headers() -> Optional[dict[str, Any]]:
|
|
359
301
|
"""Adds headers based on client context."""
|
|
302
|
+
state = _get_state()
|
|
360
303
|
headers: dict[str, Any] = {}
|
|
361
304
|
client_version_header_values: list[Any] = []
|
|
362
|
-
if
|
|
363
|
-
client_version_header_values.append(
|
|
364
|
-
|
|
365
|
-
|
|
305
|
+
if state.cloud_api_client_version is not None:
|
|
306
|
+
client_version_header_values.append(
|
|
307
|
+
f'ee-py/{state.cloud_api_client_version}'
|
|
308
|
+
)
|
|
309
|
+
if state.user_agent is not None:
|
|
310
|
+
headers[_USER_AGENT_HEADER] = state.user_agent
|
|
366
311
|
client_version_header_values.append('python/' + platform.python_version())
|
|
367
312
|
headers[_API_CLIENT_VERSION_HEADER] = ' '.join(client_version_header_values)
|
|
368
313
|
if _thread_locals.profile_hook:
|
|
369
314
|
headers[_PROFILE_REQUEST_HEADER] = '1'
|
|
370
|
-
if
|
|
371
|
-
headers[_USER_PROJECT_OVERRIDE_HEADER] =
|
|
315
|
+
if state.cloud_api_user_project is not DEFAULT_CLOUD_API_USER_PROJECT:
|
|
316
|
+
headers[_USER_PROJECT_OVERRIDE_HEADER] = state.cloud_api_user_project
|
|
372
317
|
if headers:
|
|
373
318
|
return headers
|
|
374
319
|
return None
|
|
@@ -399,7 +344,7 @@ def _execute_cloud_call(
|
|
|
399
344
|
Raises:
|
|
400
345
|
EEException if the call fails.
|
|
401
346
|
"""
|
|
402
|
-
num_retries =
|
|
347
|
+
num_retries = _get_state().max_retries if num_retries is None else num_retries
|
|
403
348
|
try:
|
|
404
349
|
return call.execute(num_retries=num_retries)
|
|
405
350
|
except googleapiclient.errors.HttpError as e:
|
|
@@ -442,23 +387,20 @@ def _maybe_populate_workload_tag(body: dict[str, Any]) -> None:
|
|
|
442
387
|
|
|
443
388
|
def setCloudApiKey(cloud_api_key: str) -> None:
|
|
444
389
|
"""Sets the Cloud API key parameter ("api_key") for all requests."""
|
|
445
|
-
|
|
446
|
-
_cloud_api_key = cloud_api_key
|
|
390
|
+
_get_state().cloud_api_key = cloud_api_key
|
|
447
391
|
_install_cloud_api_resource()
|
|
448
392
|
|
|
449
393
|
|
|
450
394
|
def setCloudApiUserProject(cloud_api_user_project: str) -> None:
|
|
451
|
-
|
|
452
|
-
_cloud_api_user_project = cloud_api_user_project
|
|
395
|
+
_get_state().cloud_api_user_project = cloud_api_user_project
|
|
453
396
|
|
|
454
397
|
|
|
455
398
|
def setUserAgent(user_agent: str) -> None:
|
|
456
|
-
|
|
457
|
-
_user_agent = user_agent
|
|
399
|
+
_get_state().user_agent = user_agent
|
|
458
400
|
|
|
459
401
|
|
|
460
402
|
def getUserAgent() -> Optional[str]:
|
|
461
|
-
return
|
|
403
|
+
return _get_state().user_agent
|
|
462
404
|
|
|
463
405
|
|
|
464
406
|
def setDeadline(milliseconds: float) -> None:
|
|
@@ -468,8 +410,7 @@ def setDeadline(milliseconds: float) -> None:
|
|
|
468
410
|
milliseconds: The number of milliseconds to wait for a request
|
|
469
411
|
before considering it timed out. 0 means no limit.
|
|
470
412
|
"""
|
|
471
|
-
|
|
472
|
-
_deadline_ms = milliseconds
|
|
413
|
+
_get_state().deadline_ms = milliseconds
|
|
473
414
|
_install_cloud_api_resource()
|
|
474
415
|
|
|
475
416
|
|
|
@@ -483,8 +424,7 @@ def setMaxRetries(max_retries: int) -> None:
|
|
|
483
424
|
raise ValueError('max_retries must be non-negative')
|
|
484
425
|
if max_retries >= 100:
|
|
485
426
|
raise ValueError('Too many retries')
|
|
486
|
-
|
|
487
|
-
_max_retries = max_retries
|
|
427
|
+
_get_state().max_retries = max_retries
|
|
488
428
|
|
|
489
429
|
|
|
490
430
|
@contextlib.contextmanager
|
|
@@ -526,7 +466,7 @@ def getInfo(asset_id: str) -> Optional[Any]:
|
|
|
526
466
|
_get_cloud_projects()
|
|
527
467
|
.assets()
|
|
528
468
|
.get(name=name, prettyPrint=False)
|
|
529
|
-
.execute(num_retries=
|
|
469
|
+
.execute(num_retries=_get_state().max_retries)
|
|
530
470
|
)
|
|
531
471
|
except googleapiclient.errors.HttpError as e:
|
|
532
472
|
if e.resp.status == 404:
|
|
@@ -747,11 +687,12 @@ def getMapId(params: dict[str, Any]) -> dict[str, Any]:
|
|
|
747
687
|
.maps()
|
|
748
688
|
.create(parent=_get_projects_path(), **queryParams)
|
|
749
689
|
)
|
|
690
|
+
state = _get_state()
|
|
750
691
|
map_name = result['name']
|
|
751
692
|
url_format = '%s/%s/%s/tiles/{z}/{x}/{y}' % (
|
|
752
|
-
|
|
753
|
-
if
|
|
754
|
-
url_format += '?key
|
|
693
|
+
state.tile_base_url, _cloud_api_utils.VERSION, map_name)
|
|
694
|
+
if state.cloud_api_key:
|
|
695
|
+
url_format += f'?key={state.cloud_api_key}'
|
|
755
696
|
|
|
756
697
|
return {'mapid': map_name, 'token': '',
|
|
757
698
|
'tile_fetcher': TileFetcher(url_format, map_name=map_name)}
|
|
@@ -787,8 +728,9 @@ def getFeatureViewTilesKey(params: dict[str, Any]) -> dict[str, Any]:
|
|
|
787
728
|
)
|
|
788
729
|
name = result['name']
|
|
789
730
|
version = _cloud_api_utils.VERSION
|
|
790
|
-
format_tile_url = (
|
|
791
|
-
|
|
731
|
+
format_tile_url = lambda x, y, z: (
|
|
732
|
+
f'{_get_state().tile_base_url}/{version}/{name}/tiles/{z}/{x}/{y}'
|
|
733
|
+
)
|
|
792
734
|
token = name.rsplit('/', 1).pop()
|
|
793
735
|
return {
|
|
794
736
|
'token': token,
|
|
@@ -1256,11 +1198,12 @@ def makeThumbUrl(thumbId: dict[str, str]) -> str:
|
|
|
1256
1198
|
Returns:
|
|
1257
1199
|
A URL from which the thumbnail can be obtained.
|
|
1258
1200
|
"""
|
|
1201
|
+
state = _get_state()
|
|
1259
1202
|
url = '{}/{}/{}:getPixels'.format(
|
|
1260
|
-
|
|
1203
|
+
state.tile_base_url, _cloud_api_utils.VERSION, thumbId['thumbid']
|
|
1261
1204
|
)
|
|
1262
|
-
if
|
|
1263
|
-
url += '?key
|
|
1205
|
+
if state.cloud_api_key:
|
|
1206
|
+
url += f'?key={state.cloud_api_key}'
|
|
1264
1207
|
return url
|
|
1265
1208
|
|
|
1266
1209
|
|
|
@@ -1390,7 +1333,7 @@ def makeDownloadUrl(downloadId: dict[str, str]) -> str:
|
|
|
1390
1333
|
A URL from which the download can be obtained.
|
|
1391
1334
|
"""
|
|
1392
1335
|
return '{}/{}/{}:getPixels'.format(
|
|
1393
|
-
|
|
1336
|
+
_get_state().tile_base_url, _cloud_api_utils.VERSION, downloadId['docid']
|
|
1394
1337
|
)
|
|
1395
1338
|
|
|
1396
1339
|
|
|
@@ -1453,7 +1396,7 @@ def makeTableDownloadUrl(downloadId: dict[str, str]) -> str:
|
|
|
1453
1396
|
A Url from which the download can be obtained.
|
|
1454
1397
|
"""
|
|
1455
1398
|
return '{}/{}/{}:getFeatures'.format(
|
|
1456
|
-
|
|
1399
|
+
_get_state().tile_base_url, _cloud_api_utils.VERSION, downloadId['docid']
|
|
1457
1400
|
)
|
|
1458
1401
|
|
|
1459
1402
|
|
|
@@ -1461,11 +1404,11 @@ def getAlgorithms() -> Any:
|
|
|
1461
1404
|
"""Get the list of algorithms.
|
|
1462
1405
|
|
|
1463
1406
|
Returns:
|
|
1464
|
-
The dictionary of algorithms.
|
|
1407
|
+
The dictionary of algorithms. Each algorithm is a dictionary containing
|
|
1465
1408
|
the following fields:
|
|
1466
1409
|
"description" - (string) A text description of the algorithm.
|
|
1467
1410
|
"returns" - (string) The return type of the algorithm.
|
|
1468
|
-
"args" - An array of arguments.
|
|
1411
|
+
"args" - An array of arguments. Each argument specifies the following:
|
|
1469
1412
|
"name" - (string) The name of the argument.
|
|
1470
1413
|
"description" - (string) A text description of the argument.
|
|
1471
1414
|
"type" - (string) The type of the argument.
|
|
@@ -1691,19 +1634,20 @@ def getTaskStatus(taskId: Union[list[str], str]) -> list[Any]:
|
|
|
1691
1634
|
"""
|
|
1692
1635
|
if isinstance(taskId, str):
|
|
1693
1636
|
taskId = [taskId]
|
|
1637
|
+
state = _get_state()
|
|
1694
1638
|
result = []
|
|
1695
1639
|
for one_id in taskId:
|
|
1696
1640
|
# Don't use getOperation as it will translate the exception, and we need
|
|
1697
1641
|
# to handle 404s specially.
|
|
1698
1642
|
name = _cloud_api_utils.convert_task_id_to_operation_name(
|
|
1699
|
-
|
|
1643
|
+
state.cloud_api_user_project, one_id
|
|
1700
1644
|
)
|
|
1701
1645
|
try:
|
|
1702
1646
|
operation = (
|
|
1703
1647
|
_get_cloud_projects()
|
|
1704
1648
|
.operations()
|
|
1705
1649
|
.get(name=name)
|
|
1706
|
-
.execute(num_retries=
|
|
1650
|
+
.execute(num_retries=state.max_retries)
|
|
1707
1651
|
)
|
|
1708
1652
|
result.append(_cloud_api_utils.convert_operation_to_task(operation))
|
|
1709
1653
|
except googleapiclient.errors.HttpError as e:
|
|
@@ -1734,7 +1678,7 @@ def cancelTask(taskId: str) -> None:
|
|
|
1734
1678
|
"""Cancels a batch task."""
|
|
1735
1679
|
cancelOperation(
|
|
1736
1680
|
_cloud_api_utils.convert_task_id_to_operation_name(
|
|
1737
|
-
|
|
1681
|
+
_get_state().cloud_api_user_project, taskId
|
|
1738
1682
|
)
|
|
1739
1683
|
)
|
|
1740
1684
|
|
|
@@ -1910,7 +1854,7 @@ def _prepare_and_run_export(
|
|
|
1910
1854
|
if isinstance(params['expression'], encodable.Encodable):
|
|
1911
1855
|
params['expression'] = serializer.encode(
|
|
1912
1856
|
params['expression'], for_cloud_api=True)
|
|
1913
|
-
num_retries =
|
|
1857
|
+
num_retries = _get_state().max_retries if request_id else 0
|
|
1914
1858
|
return _execute_cloud_call(
|
|
1915
1859
|
export_endpoint(project=_get_projects_path(), body=params),
|
|
1916
1860
|
num_retries=num_retries)
|
|
@@ -1936,7 +1880,7 @@ def _startIngestion(
|
|
|
1936
1880
|
|
|
1937
1881
|
# It's only safe to retry the request if there's a unique ID to make it
|
|
1938
1882
|
# idempotent.
|
|
1939
|
-
num_retries =
|
|
1883
|
+
num_retries = _get_state().max_retries if request_id else 0
|
|
1940
1884
|
|
|
1941
1885
|
image = _get_cloud_projects().image()
|
|
1942
1886
|
if import_mode == _INTERNAL_IMPORT:
|
|
@@ -2071,7 +2015,7 @@ def startTableIngestion(
|
|
|
2071
2015
|
}
|
|
2072
2016
|
# It's only safe to retry the request if there's a unique ID to make it
|
|
2073
2017
|
# idempotent.
|
|
2074
|
-
num_retries =
|
|
2018
|
+
num_retries = _get_state().max_retries if request_id else 0
|
|
2075
2019
|
operation = _execute_cloud_call(
|
|
2076
2020
|
_get_cloud_projects()
|
|
2077
2021
|
.table()
|
|
@@ -2324,8 +2268,8 @@ def updateProjectConfig(
|
|
|
2324
2268
|
|
|
2325
2269
|
|
|
2326
2270
|
def authorizeHttp(http: Any) -> Any:
|
|
2327
|
-
if
|
|
2328
|
-
return google_auth_httplib2.AuthorizedHttp(
|
|
2271
|
+
if credentials := _get_state().credentials:
|
|
2272
|
+
return google_auth_httplib2.AuthorizedHttp(credentials)
|
|
2329
2273
|
else:
|
|
2330
2274
|
return http
|
|
2331
2275
|
|
|
@@ -2369,7 +2313,7 @@ def convert_asset_id_to_asset_name(asset_id: str) -> str:
|
|
|
2369
2313
|
|
|
2370
2314
|
def getWorkloadTag() -> Optional[Union[int, str]]:
|
|
2371
2315
|
"""Returns the currently set workload tag."""
|
|
2372
|
-
return
|
|
2316
|
+
return _get_state().workload_tag.get()
|
|
2373
2317
|
|
|
2374
2318
|
|
|
2375
2319
|
def setWorkloadTag(tag: Optional[Union[int, str]]) -> None:
|
|
@@ -2382,7 +2326,7 @@ def setWorkloadTag(tag: Optional[Union[int, str]]) -> None:
|
|
|
2382
2326
|
Args:
|
|
2383
2327
|
tag: The tag to set.
|
|
2384
2328
|
"""
|
|
2385
|
-
|
|
2329
|
+
_get_state().workload_tag.set(tag)
|
|
2386
2330
|
|
|
2387
2331
|
|
|
2388
2332
|
@contextlib.contextmanager
|
|
@@ -2421,8 +2365,9 @@ def setDefaultWorkloadTag(tag: Optional[Union[int, str]]) -> None:
|
|
|
2421
2365
|
Args:
|
|
2422
2366
|
tag: The tag to set.
|
|
2423
2367
|
"""
|
|
2424
|
-
|
|
2425
|
-
|
|
2368
|
+
state = _get_state()
|
|
2369
|
+
state.workload_tag.set_default(tag)
|
|
2370
|
+
state.workload_tag.set(tag)
|
|
2426
2371
|
|
|
2427
2372
|
|
|
2428
2373
|
@_utils.accept_opt_prefix('opt_resetDefault')
|
|
@@ -2435,58 +2380,7 @@ def resetWorkloadTag(resetDefault: bool = False) -> None:
|
|
|
2435
2380
|
Args:
|
|
2436
2381
|
resetDefault: Whether to reset the default back to empty.
|
|
2437
2382
|
"""
|
|
2383
|
+
state = _get_state()
|
|
2438
2384
|
if resetDefault:
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
# TODO(user): Consider only returning str even for ints.
|
|
2444
|
-
class _WorkloadTag:
|
|
2445
|
-
"""A helper class to manage the workload tag."""
|
|
2446
|
-
_tag: Optional[Union[int, str]]
|
|
2447
|
-
_default: Optional[Union[int, str]]
|
|
2448
|
-
|
|
2449
|
-
def __init__(self):
|
|
2450
|
-
# TODO(user): Consider using None as default and setting them above.
|
|
2451
|
-
self._tag = ''
|
|
2452
|
-
self._default = ''
|
|
2453
|
-
|
|
2454
|
-
def get(self) -> Union[int, str, None]:
|
|
2455
|
-
return self._tag
|
|
2456
|
-
|
|
2457
|
-
def set(self, tag: Optional[Union[int, str]]) -> None:
|
|
2458
|
-
self._tag = self.validate(tag)
|
|
2459
|
-
|
|
2460
|
-
def setDefault(self, newDefault: Optional[Union[int, str]]) -> None:
|
|
2461
|
-
self._default = self.validate(newDefault)
|
|
2462
|
-
|
|
2463
|
-
def reset(self) -> None:
|
|
2464
|
-
self._tag = self._default
|
|
2465
|
-
|
|
2466
|
-
def validate(self, tag: Optional[Union[int, str]]) -> str:
|
|
2467
|
-
"""Throws an error if setting an invalid tag.
|
|
2468
|
-
|
|
2469
|
-
Args:
|
|
2470
|
-
tag: the tag to validate.
|
|
2471
|
-
|
|
2472
|
-
Returns:
|
|
2473
|
-
The validated tag.
|
|
2474
|
-
|
|
2475
|
-
Raises:
|
|
2476
|
-
ValueError if the tag does not match the expected format.
|
|
2477
|
-
"""
|
|
2478
|
-
if not tag and tag != 0:
|
|
2479
|
-
return ''
|
|
2480
|
-
tag = str(tag)
|
|
2481
|
-
if not re.fullmatch(r'([a-z0-9]|[a-z0-9][-_a-z0-9]{0,61}[a-z0-9])', tag):
|
|
2482
|
-
validationMessage = (
|
|
2483
|
-
'Tags must be 1-63 characters, '
|
|
2484
|
-
'beginning and ending with a lowercase alphanumeric character '
|
|
2485
|
-
'([a-z0-9]) with dashes (-), underscores (_), '
|
|
2486
|
-
'and lowercase alphanumerics between.')
|
|
2487
|
-
raise ValueError(f'Invalid tag, "{tag}". {validationMessage}')
|
|
2488
|
-
return tag
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
# Tracks the currently set workload tag.
|
|
2492
|
-
_workloadTag = _WorkloadTag()
|
|
2385
|
+
state.workload_tag.set_default('')
|
|
2386
|
+
state.workload_tag.reset()
|
ee/ee_array.py
CHANGED
|
@@ -189,6 +189,8 @@ class Array(computedobject.ComputedObject):
|
|
|
189
189
|
|
|
190
190
|
return apifunction.ApiFunction.call_(self.name() + '.bitCount', self)
|
|
191
191
|
|
|
192
|
+
@staticmethod
|
|
193
|
+
# pylint: disable-next=redefined-builtin
|
|
192
194
|
def bitsToArray(input: _arg_types.Integer) -> Array:
|
|
193
195
|
"""Returns an Array from the bits of an integer.
|
|
194
196
|
|
|
@@ -1041,7 +1043,7 @@ class Array(computedobject.ComputedObject):
|
|
|
1041
1043
|
start: The coordinate of the first slice (inclusive) along 'axis'.
|
|
1042
1044
|
Negative numbers are used to position the start of slicing relative to
|
|
1043
1045
|
the end of the array, where -1 starts at the last position on the axis,
|
|
1044
|
-
-2 starts at the next to last position, etc.
|
|
1046
|
+
-2 starts at the next to last position, etc. Defaults to 0.
|
|
1045
1047
|
end: The coordinate (exclusive) at which to stop taking slices. By default
|
|
1046
1048
|
this will be the length of the given axis. Negative numbers are used to
|
|
1047
1049
|
position the end of slicing relative to the end of the array, where -1
|
|
@@ -1049,7 +1051,7 @@ class Array(computedobject.ComputedObject):
|
|
|
1049
1051
|
etc.
|
|
1050
1052
|
step: The separation between slices along 'axis'; a slice will be taken at
|
|
1051
1053
|
each whole multiple of 'step' from 'start' (inclusive) to 'end'
|
|
1052
|
-
(exclusive). Must be positive.
|
|
1054
|
+
(exclusive). Must be positive. Defaults to 1.
|
|
1053
1055
|
|
|
1054
1056
|
Returns:
|
|
1055
1057
|
An ee.Array.
|
ee/ee_number.py
CHANGED
|
@@ -781,7 +781,7 @@ class Number(computedobject.ComputedObject):
|
|
|
781
781
|
) -> Number:
|
|
782
782
|
"""Scales the input so that [min, max] becomes [0, 1].
|
|
783
783
|
|
|
784
|
-
Values outside the range are NOT clamped.
|
|
784
|
+
Values outside the range are NOT clamped. If min == max, 0 is returned.
|
|
785
785
|
|
|
786
786
|
Args:
|
|
787
787
|
min: Minimum value of the input to be scaled to 0.
|