earthengine-api 1.5.13rc0__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.

Files changed (102) hide show
  1. {earthengine_api-1.5.13rc0.dist-info → earthengine_api-1.7.4.dist-info}/METADATA +3 -3
  2. earthengine_api-1.7.4.dist-info/RECORD +109 -0
  3. {earthengine_api-1.5.13rc0.dist-info → earthengine_api-1.7.4.dist-info}/WHEEL +1 -1
  4. ee/__init__.py +29 -28
  5. ee/_arg_types.py +7 -6
  6. ee/_cloud_api_utils.py +95 -78
  7. ee/_helpers.py +17 -13
  8. ee/_state.py +105 -0
  9. ee/_utils.py +2 -1
  10. ee/apifunction.py +21 -19
  11. ee/apitestcase.py +33 -38
  12. ee/batch.py +87 -77
  13. ee/blob.py +10 -12
  14. ee/classifier.py +57 -59
  15. ee/cli/commands.py +178 -114
  16. ee/cli/eecli.py +1 -1
  17. ee/cli/utils.py +61 -42
  18. ee/clusterer.py +39 -41
  19. ee/collection.py +64 -54
  20. ee/computedobject.py +19 -16
  21. ee/confusionmatrix.py +9 -9
  22. ee/customfunction.py +13 -12
  23. ee/data.py +220 -322
  24. ee/daterange.py +10 -10
  25. ee/deprecation.py +21 -13
  26. ee/deserializer.py +25 -20
  27. ee/dictionary.py +11 -11
  28. ee/ee_array.py +22 -20
  29. ee/ee_date.py +23 -23
  30. ee/ee_list.py +15 -16
  31. ee/ee_number.py +11 -21
  32. ee/ee_string.py +24 -32
  33. ee/ee_types.py +4 -4
  34. ee/element.py +15 -15
  35. ee/encodable.py +7 -4
  36. ee/errormargin.py +4 -4
  37. ee/feature.py +68 -71
  38. ee/featurecollection.py +41 -40
  39. ee/filter.py +90 -92
  40. ee/function.py +8 -8
  41. ee/geometry.py +95 -93
  42. ee/image.py +238 -236
  43. ee/image_converter.py +4 -4
  44. ee/imagecollection.py +30 -27
  45. ee/join.py +13 -15
  46. ee/kernel.py +55 -57
  47. ee/mapclient.py +9 -9
  48. ee/model.py +29 -31
  49. ee/oauth.py +76 -63
  50. ee/pixeltype.py +6 -6
  51. ee/projection.py +5 -4
  52. ee/reducer.py +41 -41
  53. ee/serializer.py +14 -14
  54. ee/table_converter.py +7 -6
  55. ee/terrain.py +7 -9
  56. ee/tests/_cloud_api_utils_test.py +21 -6
  57. ee/tests/_helpers_test.py +57 -4
  58. ee/tests/_state_test.py +49 -0
  59. ee/tests/algorithms.json +85 -2
  60. ee/tests/apifunction_test.py +5 -5
  61. ee/tests/batch_test.py +135 -57
  62. ee/tests/blob_test.py +5 -5
  63. ee/tests/classifier_test.py +3 -3
  64. ee/tests/clusterer_test.py +3 -3
  65. ee/tests/collection_test.py +48 -13
  66. ee/tests/confusionmatrix_test.py +3 -3
  67. ee/tests/data_test.py +484 -55
  68. ee/tests/daterange_test.py +4 -4
  69. ee/tests/deprecation_test.py +6 -4
  70. ee/tests/deserializer_test.py +64 -5
  71. ee/tests/dictionary_test.py +12 -12
  72. ee/tests/ee_array_test.py +3 -3
  73. ee/tests/ee_date_test.py +4 -4
  74. ee/tests/ee_list_test.py +3 -3
  75. ee/tests/ee_number_test.py +75 -30
  76. ee/tests/ee_string_test.py +11 -3
  77. ee/tests/ee_test.py +40 -22
  78. ee/tests/element_test.py +2 -2
  79. ee/tests/errormargin_test.py +1 -1
  80. ee/tests/feature_test.py +10 -10
  81. ee/tests/featurecollection_test.py +3 -3
  82. ee/tests/filter_test.py +4 -4
  83. ee/tests/function_test.py +5 -5
  84. ee/tests/geometry_point_test.py +3 -3
  85. ee/tests/geometry_test.py +93 -52
  86. ee/tests/image_converter_test.py +1 -3
  87. ee/tests/image_test.py +3 -3
  88. ee/tests/imagecollection_test.py +3 -3
  89. ee/tests/join_test.py +3 -3
  90. ee/tests/kernel_test.py +7 -3
  91. ee/tests/model_test.py +17 -5
  92. ee/tests/oauth_test.py +189 -7
  93. ee/tests/pixeltype_test.py +6 -7
  94. ee/tests/projection_test.py +5 -6
  95. ee/tests/reducer_test.py +16 -3
  96. ee/tests/serializer_test.py +39 -12
  97. ee/tests/table_converter_test.py +51 -7
  98. ee/tests/terrain_test.py +11 -3
  99. earthengine_api-1.5.13rc0.dist-info/RECORD +0 -107
  100. {earthengine_api-1.5.13rc0.dist-info → earthengine_api-1.7.4.dist-info}/entry_points.txt +0 -0
  101. {earthengine_api-1.5.13rc0.dist-info → earthengine_api-1.7.4.dist-info}/licenses/LICENSE +0 -0
  102. {earthengine_api-1.5.13rc0.dist-info → earthengine_api-1.7.4.dist-info}/top_level.txt +0 -0
ee/batch.py CHANGED
@@ -9,10 +9,11 @@ The public function styling uses camelCase to match the JavaScript names.
9
9
 
10
10
  from __future__ import annotations
11
11
 
12
+ from collections.abc import Sequence
12
13
  import enum
13
14
  import json
14
15
  import re
15
- from typing import Any, Dict, List, Optional, Sequence, Union
16
+ from typing import Any
16
17
 
17
18
  from ee import _cloud_api_utils
18
19
  from ee import data
@@ -20,7 +21,7 @@ from ee import ee_exception
20
21
  from ee import geometry
21
22
 
22
23
 
23
- def _transform_operation_to_task(operation: Dict[str, Any]) -> Task:
24
+ def _transform_operation_to_task(operation: dict[str, Any]) -> Task:
24
25
  """Converts an operation to a task."""
25
26
  status = _cloud_api_utils.convert_operation_to_task(operation)
26
27
  return Task(
@@ -54,14 +55,14 @@ class Task:
54
55
  CANCELLED = 'CANCELLED'
55
56
 
56
57
  @classmethod
57
- def active(cls, state: Union[str, Task.State]) -> bool:
58
+ def active(cls, state: str | Task.State) -> bool:
58
59
  """Returns True if the given state is an active one."""
59
60
  if isinstance(state, str):
60
61
  state = cls(state)
61
62
  return state in (cls.READY, cls.RUNNING, cls.CANCEL_REQUESTED)
62
63
 
63
64
  @classmethod
64
- def success(cls, state: Union[str, Task.State]) -> bool:
65
+ def success(cls, state: str | Task.State) -> bool:
65
66
  """Returns True if the given state indicates a completed task."""
66
67
  if isinstance(state, str):
67
68
  state = cls(state)
@@ -74,22 +75,22 @@ class Task:
74
75
  FEATURE_VIEW = 'FEATURE_VIEW'
75
76
  BIGQUERY = 'BIGQUERY'
76
77
 
77
- config: Optional[Dict[str, Any]]
78
- id: Optional[str]
79
- name: Optional[str]
78
+ config: dict[str, Any] | None
79
+ id: str | None
80
+ name: str | None
80
81
  state: State
81
82
  task_type: Type
82
- workload_tag: Optional[Union[int, str]]
83
+ workload_tag: int | str | None
83
84
 
84
- _request_id: Optional[str]
85
+ _request_id: str | None
85
86
 
86
87
  def __init__(
87
88
  self,
88
- task_id: Optional[str],
89
+ task_id: str | None,
89
90
  task_type: Type,
90
91
  state: State,
91
- config: Optional[Dict[str, Any]] = None,
92
- name: Optional[str] = None,
92
+ config: dict[str, Any] | None = None,
93
+ name: str | None = None,
93
94
  ):
94
95
  """Creates a Task with the given ID and configuration.
95
96
 
@@ -99,7 +100,7 @@ class Task:
99
100
  - Unpickling a previously pickled Task object.
100
101
 
101
102
  If you're looking for a task's status but don't need a full task object,
102
- ee.data.getTaskStatus() may be appropriate.
103
+ ee.data.getOperation() may be appropriate.
103
104
 
104
105
  Args:
105
106
  task_id: The task ID, originally obtained through ee.data.newTaskId().
@@ -111,7 +112,7 @@ class Task:
111
112
  - description: The name of the task, a freeform string.
112
113
  - sourceUrl: An optional URL for the script that generated the task.
113
114
  Specific task types have other custom config fields.
114
- name: The name of the operation. Only relevant when using the cloud api.
115
+ name: The name of the operation.
115
116
  """
116
117
  self.id = self._request_id = task_id
117
118
  self.config = config and config.copy()
@@ -121,11 +122,10 @@ class Task:
121
122
  self.name = name
122
123
 
123
124
  @property
124
- def operation_name(self) -> Optional[str]:
125
+ def operation_name(self) -> str | None:
126
+ """The server-assigned name for this task."""
125
127
  if self.name:
126
128
  return self.name
127
- if self.id:
128
- return _cloud_api_utils.convert_task_id_to_operation_name(self.id)
129
129
  return None
130
130
 
131
131
  def start(self) -> None:
@@ -152,14 +152,13 @@ class Task:
152
152
  elif self.task_type == Task.Type.EXPORT_CLASSIFIER:
153
153
  result = data.exportClassifier(self._request_id, self.config)
154
154
  else:
155
- raise ee_exception.EEException(
156
- 'Unknown Task type "{}"'.format(self.task_type))
155
+ raise ee_exception.EEException(f'Unknown Task type "{self.task_type}"')
157
156
  if not self.id:
158
157
  self.id = _cloud_api_utils.convert_operation_name_to_task_id(
159
158
  result['name'])
160
159
  self.name = result['name']
161
160
 
162
- def status(self) -> Dict[str, Any]:
161
+ def status(self) -> dict[str, Any]:
163
162
  """Fetches the current status of the task.
164
163
 
165
164
  Returns:
@@ -190,7 +189,7 @@ class Task:
190
189
  data.cancelOperation(self.operation_name)
191
190
 
192
191
  @staticmethod
193
- def list() -> List[Task]:
192
+ def list() -> list[Task]:
194
193
  """Returns the tasks submitted to EE by the current user.
195
194
 
196
195
  These include all currently running tasks as well as recently canceled or
@@ -204,11 +203,13 @@ class Task:
204
203
  def __repr__(self) -> str:
205
204
  """Returns a string representation of the task."""
206
205
  if self.config and self.id:
207
- return '<Task %s %s: %s (%s)>' % (self.id, self.task_type,
208
- self.config['description'], self.state)
206
+ return '<Task {} {}: {} ({})>'.format(
207
+ self.id, self.task_type, self.config['description'], self.state
208
+ )
209
209
  elif self.config:
210
- return '<Task %s: %s (%s)>' % (self.task_type, self.config['description'],
211
- self.state)
210
+ return '<Task {}: {} ({})>'.format(
211
+ self.task_type, self.config['description'], self.state
212
+ )
212
213
  else:
213
214
  return '<Task "%s">' % self.id
214
215
 
@@ -231,7 +232,7 @@ class Export:
231
232
  cls,
232
233
  image: Any,
233
234
  description: str = 'myExportImageTask',
234
- config: Optional[Dict[str, Any]] = None,
235
+ config: dict[str, Any] | None = None,
235
236
  ):
236
237
  """Creates a task to export an EE Image to Google Drive or Cloud Storage.
237
238
 
@@ -307,6 +308,7 @@ class Export:
307
308
  crsTransform=None,
308
309
  maxPixels=None,
309
310
  priority=None,
311
+ overwrite=False,
310
312
  **kwargs,
311
313
  ) -> Task:
312
314
  """Creates a task to export an EE Image to an EE Asset.
@@ -343,6 +345,7 @@ class Export:
343
345
  priority: The priority of the task within the project. Higher priority
344
346
  tasks are scheduled sooner. Must be an integer between 0 and 9999.
345
347
  Defaults to 100.
348
+ overwrite: If an existing asset can be overwritten by this export.
346
349
  **kwargs: Holds other keyword arguments that may have been deprecated
347
350
  such as 'crs_transform'.
348
351
 
@@ -738,6 +741,7 @@ class Export:
738
741
  assetId=None,
739
742
  maxVertices=None,
740
743
  priority=None,
744
+ overwrite=False,
741
745
  **kwargs,
742
746
  ) -> Task:
743
747
  """Creates a task to export a FeatureCollection to an EE table asset.
@@ -752,6 +756,7 @@ class Export:
752
756
  priority: The priority of the task within the project. Higher priority
753
757
  tasks are scheduled sooner. Must be an integer between 0 and 9999.
754
758
  Defaults to 100.
759
+ overwrite: If an existing asset can be overwritten by this export.
755
760
  **kwargs: Holds other keyword arguments that may have been deprecated.
756
761
 
757
762
  Returns:
@@ -762,6 +767,7 @@ class Export:
762
767
  'assetId': assetId,
763
768
  'maxVertices': maxVertices,
764
769
  'priority': priority,
770
+ 'overwrite': overwrite,
765
771
  }
766
772
  config = {k: v for k, v, in config.items() if v is not None}
767
773
  config = _prepare_table_export_config(collection, config,
@@ -1152,8 +1158,8 @@ NON_FILE_DESTINATIONS = frozenset([
1152
1158
 
1153
1159
 
1154
1160
  def _prepare_image_export_config(
1155
- image: Any, config: Dict[str, Any], export_destination: str
1156
- ) -> Dict[str, Any]:
1161
+ image: Any, config: dict[str, Any], export_destination: str
1162
+ ) -> dict[str, Any]:
1157
1163
  """Performs all preparation steps for an image export.
1158
1164
 
1159
1165
  Args:
@@ -1231,15 +1237,14 @@ def _prepare_image_export_config(
1231
1237
  if config:
1232
1238
  if 'skipEmptyTiles' in config:
1233
1239
  raise ValueError('skipEmptyTiles is only supported for GeoTIFF exports.')
1234
- raise ee_exception.EEException(
1235
- 'Unknown configuration options: {}.'.format(config))
1240
+ raise ee_exception.EEException(f'Unknown configuration options: {config}.')
1236
1241
 
1237
1242
  return request
1238
1243
 
1239
1244
 
1240
1245
  def _prepare_map_export_config(
1241
- image: Any, config: Dict[str, Any]
1242
- ) -> Dict[str, Any]:
1246
+ image: Any, config: dict[str, Any]
1247
+ ) -> dict[str, Any]:
1243
1248
  """Performs all preparation steps for a map export.
1244
1249
 
1245
1250
  Args:
@@ -1279,14 +1284,13 @@ def _prepare_map_export_config(
1279
1284
  # for JSON encoding.
1280
1285
  request['priority'] = {'value': int(config.pop('priority'))}
1281
1286
  if config:
1282
- raise ee_exception.EEException(
1283
- 'Unknown configuration options: {}.'.format(config))
1287
+ raise ee_exception.EEException(f'Unknown configuration options: {config}.')
1284
1288
  return request
1285
1289
 
1286
1290
 
1287
1291
  def _prepare_table_export_config(
1288
- collection: Any, config: Dict[str, Any], export_destination
1289
- ) -> Dict[str, Any]:
1292
+ collection: Any, config: dict[str, Any], export_destination
1293
+ ) -> dict[str, Any]:
1290
1294
  """Performs all preparation steps for a table export.
1291
1295
 
1292
1296
  Args:
@@ -1351,14 +1355,13 @@ def _prepare_table_export_config(
1351
1355
  request['priority'] = {'value': int(config.pop('priority'))}
1352
1356
 
1353
1357
  if config:
1354
- raise ee_exception.EEException(
1355
- 'Unknown configuration options: {}.'.format(config))
1358
+ raise ee_exception.EEException(f'Unknown configuration options: {config}.')
1356
1359
  return request
1357
1360
 
1358
1361
 
1359
1362
  def _prepare_video_export_config(
1360
- collection: Any, config: Dict[str, Any], export_destination: str
1361
- ) -> Dict[str, Any]:
1363
+ collection: Any, config: dict[str, Any], export_destination: str
1364
+ ) -> dict[str, Any]:
1362
1365
  """Performs all preparation steps for a video export.
1363
1366
 
1364
1367
  Args:
@@ -1394,14 +1397,13 @@ def _prepare_video_export_config(
1394
1397
  request['priority'] = {'value': int(config.pop('priority'))}
1395
1398
 
1396
1399
  if config:
1397
- raise ee_exception.EEException(
1398
- 'Unknown configuration options: {}.'.format(config))
1400
+ raise ee_exception.EEException(f'Unknown configuration options: {config}.')
1399
1401
  return request
1400
1402
 
1401
1403
 
1402
1404
  def _build_image_file_export_options(
1403
- config: Dict[str, Any], export_destination: str
1404
- ) -> Dict[str, Any]:
1405
+ config: dict[str, Any], export_destination: str
1406
+ ) -> dict[str, Any]:
1405
1407
  """Builds an ImageFileExportOptions from values in a config dict.
1406
1408
 
1407
1409
  Args:
@@ -1427,7 +1429,8 @@ def _build_image_file_export_options(
1427
1429
  config)
1428
1430
  else:
1429
1431
  raise ee_exception.EEException(
1430
- '"{}" is not a valid export destination'.format(export_destination))
1432
+ f'"{export_destination}" is not a valid export destination'
1433
+ )
1431
1434
 
1432
1435
  file_format_options = config.pop(IMAGE_FORMAT_OPTIONS_FIELD, {})
1433
1436
 
@@ -1499,14 +1502,15 @@ def _build_image_file_export_options(
1499
1502
 
1500
1503
  if file_format_options:
1501
1504
  raise ee_exception.EEException(
1502
- 'Unknown file format options: {}.'.format(file_format_options))
1505
+ f'Unknown file format options: {file_format_options}.'
1506
+ )
1503
1507
 
1504
1508
  return file_export_options
1505
1509
 
1506
1510
 
1507
1511
  def _build_table_file_export_options(
1508
- config: Dict[str, Any], export_destination: str
1509
- ) -> Dict[str, Any]:
1512
+ config: dict[str, Any], export_destination: str
1513
+ ) -> dict[str, Any]:
1510
1514
  """Builds a TableFileExportOptions from values in a config dict.
1511
1515
 
1512
1516
  Args:
@@ -1531,11 +1535,12 @@ def _build_table_file_export_options(
1531
1535
  config)
1532
1536
  else:
1533
1537
  raise ee_exception.EEException(
1534
- '"{}" is not a valid export destination'.format(export_destination))
1538
+ f'"{export_destination}" is not a valid export destination'
1539
+ )
1535
1540
  return file_export_options
1536
1541
 
1537
1542
 
1538
- def _build_video_options(config: Dict[str, Any]) -> Dict[str, Any]:
1543
+ def _build_video_options(config: dict[str, Any]) -> dict[str, Any]:
1539
1544
  """Builds a VideoOptions from values in a config dict.
1540
1545
 
1541
1546
  Args:
@@ -1558,8 +1563,8 @@ def _build_video_options(config: Dict[str, Any]) -> Dict[str, Any]:
1558
1563
 
1559
1564
 
1560
1565
  def _build_video_file_export_options(
1561
- config: Dict[str, Any], export_destination: str
1562
- ) -> Dict[str, Any]:
1566
+ config: dict[str, Any], export_destination: str
1567
+ ) -> dict[str, Any]:
1563
1568
  """Builds a VideoFileExportOptions from values in a config dict.
1564
1569
 
1565
1570
  Args:
@@ -1584,13 +1589,14 @@ def _build_video_file_export_options(
1584
1589
  config)
1585
1590
  else:
1586
1591
  raise ee_exception.EEException(
1587
- '"{}" is not a valid export destination'.format(export_destination))
1592
+ f'"{export_destination}" is not a valid export destination'
1593
+ )
1588
1594
  return file_export_options
1589
1595
 
1590
1596
 
1591
1597
  def _prepare_classifier_export_config(
1592
- classifier: Any, config: Dict[str, Any], export_destination: str
1593
- ) -> Dict[str, Any]:
1598
+ classifier: Any, config: dict[str, Any], export_destination: str
1599
+ ) -> dict[str, Any]:
1594
1600
  """Performs all preparation steps for a classifier export.
1595
1601
 
1596
1602
  Args:
@@ -1620,7 +1626,7 @@ def _prepare_classifier_export_config(
1620
1626
  return request
1621
1627
 
1622
1628
 
1623
- def _build_drive_destination(config: Dict[str, Any]) -> Dict[str, Any]:
1629
+ def _build_drive_destination(config: dict[str, Any]) -> dict[str, Any]:
1624
1630
  """Builds a DriveDestination from values in a config dict.
1625
1631
 
1626
1632
  Args:
@@ -1639,7 +1645,7 @@ def _build_drive_destination(config: Dict[str, Any]) -> Dict[str, Any]:
1639
1645
  return drive_destination
1640
1646
 
1641
1647
 
1642
- def _build_cloud_storage_destination(config: Dict[str, Any]) -> Dict[str, Any]:
1648
+ def _build_cloud_storage_destination(config: dict[str, Any]) -> dict[str, Any]:
1643
1649
  """Builds a CloudStorageDestination from values in a config dict.
1644
1650
 
1645
1651
  Args:
@@ -1660,7 +1666,7 @@ def _build_cloud_storage_destination(config: Dict[str, Any]) -> Dict[str, Any]:
1660
1666
  return destination
1661
1667
 
1662
1668
 
1663
- def _build_bigquery_destination(config: Dict[str, Any]) -> Dict[str, Any]:
1669
+ def _build_bigquery_destination(config: dict[str, Any]) -> dict[str, Any]:
1664
1670
  """Builds a BigqueryDestination from values in a config dict.
1665
1671
 
1666
1672
  Args:
@@ -1679,7 +1685,7 @@ def _build_bigquery_destination(config: Dict[str, Any]) -> Dict[str, Any]:
1679
1685
  return destination
1680
1686
 
1681
1687
 
1682
- def _build_tile_options(config: Dict[str, Any]) -> Dict[str, Any]:
1688
+ def _build_tile_options(config: dict[str, Any]) -> dict[str, Any]:
1683
1689
  """Builds a TileOptions from values in a config dict.
1684
1690
 
1685
1691
  Args:
@@ -1722,7 +1728,7 @@ def _build_tile_options(config: Dict[str, Any]) -> Dict[str, Any]:
1722
1728
  return tile_options
1723
1729
 
1724
1730
 
1725
- def _build_earth_engine_destination(config: Dict[str, Any]) -> Dict[str, Any]:
1731
+ def _build_earth_engine_destination(config: dict[str, Any]) -> dict[str, Any]:
1726
1732
  """Builds an EarthEngineDestination from values in a config dict.
1727
1733
 
1728
1734
  Args:
@@ -1737,10 +1743,12 @@ def _build_earth_engine_destination(config: Dict[str, Any]) -> Dict[str, Any]:
1737
1743
  'name':
1738
1744
  _cloud_api_utils.convert_asset_id_to_asset_name(
1739
1745
  config.pop('assetId')),
1746
+ 'overwrite':
1747
+ config.pop('overwrite', False)
1740
1748
  }
1741
1749
 
1742
1750
 
1743
- def _build_feature_view_destination(config: Dict[str, Any]) -> Dict[str, Any]:
1751
+ def _build_feature_view_destination(config: dict[str, Any]) -> dict[str, Any]:
1744
1752
  """Builds a FeatureViewDestination from values in a config dict.
1745
1753
 
1746
1754
  Args:
@@ -1758,7 +1766,7 @@ def _build_feature_view_destination(config: Dict[str, Any]) -> Dict[str, Any]:
1758
1766
  return feature_view_destination
1759
1767
 
1760
1768
 
1761
- def _get_rank_by_one_thing_rule(rule_str: str) -> Dict[str, Any]:
1769
+ def _get_rank_by_one_thing_rule(rule_str: str) -> dict[str, Any]:
1762
1770
  """Returns a RankByOneThingRule dict created from the rank-by-one-thing rule.
1763
1771
 
1764
1772
  Args:
@@ -1773,10 +1781,11 @@ def _get_rank_by_one_thing_rule(rule_str: str) -> Dict[str, Any]:
1773
1781
  matches = re.findall(r'^([\S]+.*)\s+(ASC|DESC)$', rule_str.strip())
1774
1782
  if not matches:
1775
1783
  raise ee_exception.EEException(
1776
- ('Ranking rule format is invalid. Each rule should be defined by a '
1777
- 'rule type and a direction (ASC or DESC), separated by a space. '
1778
- 'Valid rule types are: .geometryType, .minZoomLevel, or a feature '
1779
- 'property name.'))
1784
+ 'Ranking rule format is invalid. Each rule should be defined by a '
1785
+ 'rule type and a direction (ASC or DESC), separated by a space. '
1786
+ 'Valid rule types are: .geometryType, .minZoomLevel, or a feature '
1787
+ 'property name.'
1788
+ )
1780
1789
 
1781
1790
  output = {}
1782
1791
  rule_type, rule_dir = matches[0]
@@ -1796,8 +1805,8 @@ def _get_rank_by_one_thing_rule(rule_str: str) -> Dict[str, Any]:
1796
1805
 
1797
1806
 
1798
1807
  def _get_ranking_rule(
1799
- rules: Optional[Union[str, List[str]]]
1800
- ) -> Optional[Dict[str, List[Dict[str, Any]]]]:
1808
+ rules: str | list[str] | None,
1809
+ ) -> dict[str, list[dict[str, Any]]] | None:
1801
1810
  """Returns a RankingRule dict created from the rank-by-one-thing rules.
1802
1811
 
1803
1812
  Args:
@@ -1819,11 +1828,12 @@ def _get_ranking_rule(
1819
1828
  return {'rankByOneThingRule': rank_by_one_thing_rules}
1820
1829
 
1821
1830
  raise ee_exception.EEException(
1822
- ('Unable to build ranking rule from rules. Rules should '
1823
- 'either be a comma-separated string or list of strings.'))
1831
+ 'Unable to build ranking rule from rules. Rules should '
1832
+ 'either be a comma-separated string or list of strings.'
1833
+ )
1824
1834
 
1825
1835
 
1826
- def _build_thinning_options(config: Dict[str, Any]) -> Optional[Dict[str, Any]]:
1836
+ def _build_thinning_options(config: dict[str, Any]) -> dict[str, Any] | None:
1827
1837
  """Returns a ThinningOptions dict created from the config.
1828
1838
 
1829
1839
  Args:
@@ -1843,7 +1853,7 @@ def _build_thinning_options(config: Dict[str, Any]) -> Optional[Dict[str, Any]]:
1843
1853
  return output
1844
1854
 
1845
1855
 
1846
- def _build_ranking_options(config: Dict[str, Any]) -> Optional[Dict[str, Any]]:
1856
+ def _build_ranking_options(config: dict[str, Any]) -> dict[str, Any] | None:
1847
1857
  """Returns a RankingOptions dict created from the config.
1848
1858
 
1849
1859
  Args:
@@ -1869,8 +1879,8 @@ def _build_ranking_options(config: Dict[str, Any]) -> Optional[Dict[str, Any]]:
1869
1879
 
1870
1880
 
1871
1881
  def build_ingestion_time_parameters(
1872
- input_params: Dict[str, Any]
1873
- ) -> Dict[str, Any]:
1882
+ input_params: dict[str, Any]
1883
+ ) -> dict[str, Any]:
1874
1884
  """Builds a FeatureViewIngestionTimeParameters from values in a params dict.
1875
1885
 
1876
1886
  Args:
@@ -1898,7 +1908,7 @@ def build_ingestion_time_parameters(
1898
1908
  return output_params
1899
1909
 
1900
1910
 
1901
- def _create_export_task(config: Dict[str, Any], task_type: Task.Type) -> Task:
1911
+ def _create_export_task(config: dict[str, Any], task_type: Task.Type) -> Task:
1902
1912
  """Creates an export task.
1903
1913
 
1904
1914
  Args:
@@ -1913,7 +1923,7 @@ def _create_export_task(config: Dict[str, Any], task_type: Task.Type) -> Task:
1913
1923
 
1914
1924
  def _capture_parameters(
1915
1925
  all_locals, parameters_to_exclude: Sequence[str]
1916
- ) -> Dict[str, Any]:
1926
+ ) -> dict[str, Any]:
1917
1927
  """Creates a parameter dict by copying all non-None locals.
1918
1928
 
1919
1929
  This is generally invoked as the first part of call processing, via
@@ -2027,7 +2037,7 @@ def _canonicalize_parameters(config, destination):
2027
2037
 
2028
2038
 
2029
2039
  def _canonicalize_region(
2030
- region: Union[str, geometry.Geometry, Any]
2040
+ region: str | geometry.Geometry | Any,
2031
2041
  ) -> geometry.Geometry:
2032
2042
  """Converts a region parameter to a form appropriate for export."""
2033
2043
  region_error = ee_exception.EEException(
ee/blob.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """A wrapper for Blobs."""
2
2
  from __future__ import annotations
3
3
 
4
- from typing import Any, Dict, Optional
4
+ from typing import Any
5
5
 
6
6
  from ee import _arg_types
7
7
  from ee import apifunction
@@ -46,24 +46,22 @@ class Blob(computedobject.ComputedObject):
46
46
  """
47
47
  self.initialize()
48
48
 
49
- args: Dict[str, Any] = {'url': url}
50
- func = apifunction.ApiFunction(self.name())
51
-
52
- if isinstance(url, str):
53
- if not url.startswith('gs://'):
54
- raise ValueError(f'{self.name()} url must start with "gs://": "{url}"')
55
-
56
- elif isinstance(url, computedobject.ComputedObject):
49
+ if isinstance(url, computedobject.ComputedObject):
57
50
  if self.is_func_returning_same(url):
58
51
  # If it is a call that is already returning a Blob, just cast.
59
52
  super().__init__(url.func, url.args, url.varName)
60
53
  return
61
-
54
+ elif isinstance(url, str):
55
+ if not url.startswith('gs://'):
56
+ raise ValueError(f'{self.name()} url must start with "gs://": "{url}"')
62
57
  else:
63
58
  raise ValueError(
64
- f'{self.name()} url must be a string: {type(url)} -> "{url}"'
59
+ f'{self.name()} url must be a string or ComputedObject: '
60
+ f'{type(url)} -> "{url}"'
65
61
  )
66
62
 
63
+ func = apifunction.ApiFunction(self.name())
64
+ args: dict[str, Any] = {'url': url}
67
65
  super().__init__(func, func.promoteArgs(args))
68
66
 
69
67
  @classmethod
@@ -84,7 +82,7 @@ class Blob(computedobject.ComputedObject):
84
82
  return 'Blob'
85
83
 
86
84
  def string(
87
- self, encoding: Optional[_arg_types.String] = None
85
+ self, encoding: _arg_types.String | None = None
88
86
  ) -> ee_string.String:
89
87
  """Returns the contents of the blob as a String.
90
88