earthengine-api 1.6.15__py3-none-any.whl → 1.7.0__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.

ee/data.py CHANGED
@@ -5,14 +5,14 @@
5
5
 
6
6
  from __future__ import annotations
7
7
 
8
- from collections.abc import Iterator, Sequence
8
+ from collections.abc import Callable, Iterator, Sequence
9
9
  import contextlib
10
10
  import json
11
11
  import platform
12
12
  import re
13
13
  import sys
14
14
  import threading
15
- from typing import Any, Callable, Optional, Union
15
+ from typing import Any
16
16
  import uuid
17
17
  import warnings
18
18
 
@@ -112,7 +112,7 @@ class _ThreadLocals(threading.local):
112
112
  # and the user would have to modify each call to profile, rather than
113
113
  # enabling profiling as a wrapper around the entire program (with
114
114
  # ee.data.profiling, defined below).
115
- self.profile_hook: Optional[Callable[[str], None]] = None
115
+ self.profile_hook: Callable[[str], None] | None = None
116
116
 
117
117
 
118
118
  _thread_locals = _ThreadLocals()
@@ -125,11 +125,11 @@ def _get_state() -> _state.EEState:
125
125
 
126
126
  def initialize(
127
127
  credentials: Any = None,
128
- api_base_url: Optional[str] = None,
129
- tile_base_url: Optional[str] = None,
130
- cloud_api_base_url: Optional[str] = None,
131
- cloud_api_key: Optional[str] = None,
132
- project: Optional[str] = None,
128
+ api_base_url: str | None = None,
129
+ tile_base_url: str | None = None,
130
+ cloud_api_base_url: str | None = None,
131
+ cloud_api_key: str | None = None,
132
+ project: str | None = None,
133
133
  http_transport: Any = None,
134
134
  ) -> None:
135
135
  """Initializes the data module, setting credentials and base URLs.
@@ -297,7 +297,7 @@ def _get_cloud_projects_raw() -> Any:
297
297
  return state.cloud_api_resource_raw.projects()
298
298
 
299
299
 
300
- def _make_request_headers() -> Optional[dict[str, Any]]:
300
+ def _make_request_headers() -> dict[str, Any] | None:
301
301
  """Adds headers based on client context."""
302
302
  state = _get_state()
303
303
  headers: dict[str, Any] = {}
@@ -329,7 +329,7 @@ def _handle_profiling_response(response: httplib2.Response) -> None:
329
329
 
330
330
 
331
331
  def _execute_cloud_call(
332
- call: googleapiclient.http.HttpRequest, num_retries: Optional[int] = None
332
+ call: googleapiclient.http.HttpRequest, num_retries: int | None = None
333
333
  ) -> Any:
334
334
  """Executes a Cloud API call and translates errors to EEExceptions.
335
335
 
@@ -399,7 +399,7 @@ def setUserAgent(user_agent: str) -> None:
399
399
  _get_state().user_agent = user_agent
400
400
 
401
401
 
402
- def getUserAgent() -> Optional[str]:
402
+ def getUserAgent() -> str | None:
403
403
  return _get_state().user_agent
404
404
 
405
405
 
@@ -449,7 +449,7 @@ def profiling(hook: Any) -> Iterator[None]:
449
449
 
450
450
 
451
451
  @deprecation.Deprecated('Use getAsset')
452
- def getInfo(asset_id: str) -> Optional[Any]:
452
+ def getInfo(asset_id: str) -> Any | None:
453
453
  """Load info for an asset, given an asset id.
454
454
 
455
455
  Args:
@@ -512,8 +512,8 @@ def getList(params: dict[str, Any]) -> Any:
512
512
 
513
513
 
514
514
  def listImages(
515
- params: Union[str, dict[str, Any]],
516
- ) -> dict[str, Optional[list[Any]]]:
515
+ params: str | dict[str, Any],
516
+ ) -> dict[str, list[Any] | None]:
517
517
  """Returns the images in an image collection or folder.
518
518
 
519
519
  Args:
@@ -550,7 +550,7 @@ def listImages(
550
550
  return images
551
551
 
552
552
 
553
- def listAssets(params: Union[str, dict[str, Any]]) -> dict[str, list[Any]]:
553
+ def listAssets(params: str | dict[str, Any]) -> dict[str, list[Any]]:
554
554
  """Returns the assets in a folder.
555
555
 
556
556
  Args:
@@ -603,7 +603,7 @@ def listAssets(params: Union[str, dict[str, Any]]) -> dict[str, list[Any]]:
603
603
  return assets
604
604
 
605
605
 
606
- def listBuckets(project: Optional[str] = None) -> Any:
606
+ def listBuckets(project: str | None = None) -> Any:
607
607
  """Returns top-level assets and folders for the Cloud Project or user.
608
608
 
609
609
  Args:
@@ -689,7 +689,7 @@ def getMapId(params: dict[str, Any]) -> dict[str, Any]:
689
689
  )
690
690
  state = _get_state()
691
691
  map_name = result['name']
692
- url_format = '%s/%s/%s/tiles/{z}/{x}/{y}' % (
692
+ url_format = '{}/{}/{}/tiles/{{z}}/{{x}}/{{y}}'.format(
693
693
  state.tile_base_url, _cloud_api_utils.VERSION, map_name)
694
694
  if state.cloud_api_key:
695
695
  url_format += f'?key={state.cloud_api_key}'
@@ -738,7 +738,7 @@ def getFeatureViewTilesKey(params: dict[str, Any]) -> dict[str, Any]:
738
738
  }
739
739
 
740
740
 
741
- def _extract_table_converter(params: dict[str, Any]) -> Optional[Any]:
741
+ def _extract_table_converter(params: dict[str, Any]) -> Any | None:
742
742
  if 'fileFormat' in params:
743
743
  file_format = params.get('fileFormat')
744
744
  converter = table_converter.from_file_format(file_format)
@@ -1070,7 +1070,7 @@ def computeValue(obj: computedobject.ComputedObject) -> Any:
1070
1070
 
1071
1071
  @deprecation.Deprecated('Use getThumbId and makeThumbUrl')
1072
1072
  def getThumbnail(
1073
- params: dict[str, Any], thumbType: Optional[str] = None
1073
+ params: dict[str, Any], thumbType: str | None = None
1074
1074
  ) -> Any:
1075
1075
  """Get a Thumbnail for a given asset.
1076
1076
 
@@ -1105,7 +1105,7 @@ def getThumbnail(
1105
1105
 
1106
1106
 
1107
1107
  def getThumbId(
1108
- params: dict[str, Any], thumbType: Optional[str] = None
1108
+ params: dict[str, Any], thumbType: str | None = None
1109
1109
  ) -> dict[str, str]:
1110
1110
  """Get a Thumbnail ID for a given asset.
1111
1111
 
@@ -1442,8 +1442,8 @@ def getAlgorithms() -> Any:
1442
1442
  @_utils.accept_opt_prefix('opt_path', 'opt_force', 'opt_properties')
1443
1443
  def createAsset(
1444
1444
  value: dict[str, Any],
1445
- path: Optional[str] = None,
1446
- properties: Optional[dict[str, Any]] = None,
1445
+ path: str | None = None,
1446
+ properties: dict[str, Any] | None = None,
1447
1447
  ) -> dict[str, Any]:
1448
1448
  """Creates an asset from a JSON value.
1449
1449
 
@@ -1589,7 +1589,7 @@ def getTaskList() -> list[Any]:
1589
1589
  for o in listOperations()]
1590
1590
 
1591
1591
 
1592
- def listOperations(project: Optional[str] = None) -> list[Any]:
1592
+ def listOperations(project: str | None = None) -> list[Any]:
1593
1593
  """Retrieves a list of the user's tasks.
1594
1594
 
1595
1595
  Args:
@@ -1616,7 +1616,7 @@ def listOperations(project: Optional[str] = None) -> list[Any]:
1616
1616
 
1617
1617
 
1618
1618
  @deprecation.Deprecated('Use getOperation')
1619
- def getTaskStatus(taskId: Union[list[str], str]) -> list[Any]:
1619
+ def getTaskStatus(taskId: list[str] | str) -> list[Any]:
1620
1620
  """Retrieve status of one or more long-running tasks.
1621
1621
 
1622
1622
  Args:
@@ -1868,7 +1868,7 @@ def _startIngestion(
1868
1868
  request_id: Any,
1869
1869
  params: dict[str, Any],
1870
1870
  allow_overwrite: bool = False,
1871
- import_mode: Optional[str] = _INTERNAL_IMPORT,
1871
+ import_mode: str | None = _INTERNAL_IMPORT,
1872
1872
  ) -> dict[str, Any]:
1873
1873
  """Starts an ingestion task or creates an external image."""
1874
1874
  request = {
@@ -2126,7 +2126,7 @@ def getIamPolicy(asset_id: str) -> Any:
2126
2126
 
2127
2127
 
2128
2128
  @deprecation.Deprecated('Use setIamPolicy')
2129
- def setAssetAcl(assetId: str, aclUpdate: Union[str, dict[str, Any]]) -> None:
2129
+ def setAssetAcl(assetId: str, aclUpdate: str | dict[str, Any]) -> None:
2130
2130
  """Sets the access control list of the asset with the given ID.
2131
2131
 
2132
2132
  The owner ACL cannot be changed, and the final ACL of the asset
@@ -2239,7 +2239,7 @@ def getProjectConfig() -> dict[str, Any]:
2239
2239
 
2240
2240
 
2241
2241
  def updateProjectConfig(
2242
- project_config: dict[str, Any], update_mask: Optional[Sequence[str]] = None
2242
+ project_config: dict[str, Any], update_mask: Sequence[str] | None = None
2243
2243
  ) -> dict[str, Any]:
2244
2244
  """Updates the project config for the current project.
2245
2245
 
@@ -2311,12 +2311,12 @@ def convert_asset_id_to_asset_name(asset_id: str) -> str:
2311
2311
  return _cloud_api_utils.convert_asset_id_to_asset_name(asset_id)
2312
2312
 
2313
2313
 
2314
- def getWorkloadTag() -> Optional[Union[int, str]]:
2314
+ def getWorkloadTag() -> int | str | None:
2315
2315
  """Returns the currently set workload tag."""
2316
2316
  return _get_state().workload_tag.get()
2317
2317
 
2318
2318
 
2319
- def setWorkloadTag(tag: Optional[Union[int, str]]) -> None:
2319
+ def setWorkloadTag(tag: int | str | None) -> None:
2320
2320
  """Sets the workload tag, used to label computation and exports.
2321
2321
 
2322
2322
  Workload tag must be 1 - 63 characters, beginning and ending with an
@@ -2330,7 +2330,7 @@ def setWorkloadTag(tag: Optional[Union[int, str]]) -> None:
2330
2330
 
2331
2331
 
2332
2332
  @contextlib.contextmanager
2333
- def workloadTagContext(tag: Optional[Union[int, str]]) -> Iterator[None]:
2333
+ def workloadTagContext(tag: int | str | None) -> Iterator[None]:
2334
2334
  """Produces a context manager which sets the workload tag, then resets it.
2335
2335
 
2336
2336
  Workload tag must be 1 - 63 characters, beginning and ending with an
@@ -2350,7 +2350,7 @@ def workloadTagContext(tag: Optional[Union[int, str]]) -> Iterator[None]:
2350
2350
  resetWorkloadTag()
2351
2351
 
2352
2352
 
2353
- def setDefaultWorkloadTag(tag: Optional[Union[int, str]]) -> None:
2353
+ def setDefaultWorkloadTag(tag: int | str | None) -> None:
2354
2354
  """Sets the workload tag, and as the default for which to reset back to.
2355
2355
 
2356
2356
  For example, calling `ee.data.resetWorkloadTag()` will reset the workload tag
ee/deprecation.py CHANGED
@@ -2,12 +2,13 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from collections.abc import Callable
5
6
  import dataclasses
6
7
  import datetime
7
8
  import functools
8
9
  import inspect
9
10
  import json
10
- from typing import Any, Callable
11
+ from typing import Any
11
12
  import urllib
12
13
  import warnings
13
14
 
@@ -36,7 +37,7 @@ def Deprecated(message: str):
36
37
  @functools.wraps(func)
37
38
  def Wrapper(*args, **kwargs):
38
39
  warnings.warn_explicit(
39
- '{}() is deprecated: {}'.format(func.__name__, message),
40
+ f'{func.__name__}() is deprecated: {message}',
40
41
  category=DeprecationWarning,
41
42
  filename=func.__code__.co_filename,
42
43
  lineno=func.__code__.co_firstlineno + 1,
ee/deserializer.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """A deserializer that decodes EE object trees from JSON DAGs."""
2
2
 
3
3
  import json
4
- from typing import Any, Union
4
+ from typing import Any
5
5
 
6
6
  from ee import apifunction
7
7
  from ee import computedobject
@@ -13,7 +13,7 @@ from ee import function
13
13
  from ee import geometry
14
14
 
15
15
 
16
- def fromJSON(json_obj: Union[bytes, str]) -> Any: # pylint: disable=g-bad-name
16
+ def fromJSON(json_obj: bytes | str) -> Any: # pylint: disable=g-bad-name
17
17
  """Deserialize an object from a JSON string appropriate for API calls.
18
18
 
19
19
  Args:
@@ -153,7 +153,7 @@ def _invocation(func: Any, args: dict[str, Any]) -> Any:
153
153
  raise ee_exception.EEException(f'Invalid function value: {func}')
154
154
 
155
155
 
156
- def fromCloudApiJSON(json_obj: Union[str, bytes]) -> Any: # pylint: disable=g-bad-name
156
+ def fromCloudApiJSON(json_obj: str | bytes) -> Any: # pylint: disable=g-bad-name
157
157
  """Deserializes an object from the JSON string used in Cloud API calls.
158
158
 
159
159
  Args:
@@ -180,7 +180,7 @@ def decodeCloudApi(json_obj: dict[str, Any]) -> Any:
180
180
  def lookup(reference, kind):
181
181
  if reference not in decoded:
182
182
  if reference not in json_obj['values']:
183
- raise ee_exception.EEException('Cannot find {} {}'.format(reference, kind))
183
+ raise ee_exception.EEException(f'Cannot find {reference} {kind}')
184
184
  decoded[reference] = decode_node(json_obj['values'][reference])
185
185
  return decoded[reference]
186
186
 
ee/ee_number.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """A wrapper for numbers."""
2
2
  from __future__ import annotations
3
3
 
4
- from typing import Any, Union
4
+ from typing import Any
5
5
 
6
6
  from ee import _arg_types
7
7
  from ee import _cloud_api_utils
@@ -586,9 +586,9 @@ class Number(computedobject.ComputedObject):
586
586
 
587
587
  return apifunction.ApiFunction.call_(self.name() + '.or', self, right)
588
588
 
589
+ @staticmethod
589
590
  def parse(
590
- # pylint: disable=redefined-builtin
591
- input: _arg_types.String,
591
+ input: _arg_types.String, # pylint: disable=redefined-builtin
592
592
  radix: _arg_types.Integer | None = None,
593
593
  ) -> Number:
594
594
  """Returns a number from a string.
@@ -772,27 +772,17 @@ class Number(computedobject.ComputedObject):
772
772
 
773
773
  return apifunction.ApiFunction.call_(self.name() + '.uint8', self)
774
774
 
775
- # pylint: disable=redefined-builtin
776
- # pytype: disable=invalid-annotation
777
- def unitScale(
778
- self,
779
- min: Union[int, float, computedobject.ComputedObject],
780
- max: Union[int, float, computedobject.ComputedObject],
781
- ) -> Number:
782
- """Scales the input so that [min, max] becomes [0, 1].
775
+ # pylint: disable-next=redefined-builtin
776
+ def unitScale(self, min: _arg_types.Number, max: _arg_types.Number) -> Number:
777
+ """Returns the input scaled so that [min, max] becomes [0, 1].
783
778
 
784
779
  Values outside the range are NOT clamped. If min == max, 0 is returned.
785
780
 
786
781
  Args:
787
782
  min: Minimum value of the input to be scaled to 0.
788
783
  max: Maximum value of the input to be scaled to 1.
789
-
790
- Returns:
791
- An ee.Number.
792
784
  """
793
785
 
794
786
  return apifunction.ApiFunction.call_(
795
787
  self.name() + '.unitScale', self, min, max
796
788
  )
797
- # pytype: enable=invalid-annotation
798
- # pylint: enable=redefined-builtin
ee/encodable.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """Interfaces implemented by serializable objects."""
2
2
 
3
- from typing import Any, Callable
3
+ from collections.abc import Callable
4
+ from typing import Any
4
5
 
5
6
 
6
7
  class Encodable:
ee/image_converter.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """Converters used in the image data fetching methods."""
2
2
 
3
3
  import io
4
- from typing import Any, Optional, Union
4
+ from typing import Any
5
5
 
6
6
 
7
7
  class ImageConverter:
@@ -49,8 +49,8 @@ _PIXEL_DATA_CONVERTERS: dict[str, type[ImageConverter]] = {
49
49
 
50
50
 
51
51
  def from_file_format(
52
- file_format: Union[str, ImageConverter]
53
- ) -> Optional[ImageConverter]:
52
+ file_format: str | ImageConverter,
53
+ ) -> ImageConverter | None:
54
54
  if isinstance(file_format, ImageConverter):
55
55
  return file_format
56
56
  if file_format in _PIXEL_DATA_CONVERTERS:
ee/imagecollection.py CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from collections.abc import Sequence
6
- from typing import Any, Callable
5
+ from collections.abc import Callable, Sequence
6
+ from typing import Any
7
7
 
8
8
  from ee import _arg_types
9
9
  from ee import _utils
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: Optional[_arg_types.Any] = None,
70
- projectId: Optional[_arg_types.String] = None,
71
- modelName: Optional[_arg_types.String] = None,
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: Optional[_arg_types.String] = None,
74
- region: Optional[_arg_types.String] = None,
71
+ version: _arg_types.String | None = None,
72
+ region: _arg_types.String | None = None,
75
73
  # pylint: disable=invalid-name
76
- inputProperties: Optional[_arg_types.List] = None,
77
- inputTypeOverride: Optional[_arg_types.Dictionary] = None,
78
- inputShapes: Optional[_arg_types.Dictionary] = None,
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: Optional[_arg_types.Projection] = None,
78
+ proj: _arg_types.Projection | None = None,
81
79
  # pylint: disable=invalid-name
82
- fixInputProj: Optional[_arg_types.Bool] = None,
83
- inputTileSize: Optional[_arg_types.List] = None,
84
- inputOverlapSize: Optional[_arg_types.List] = None,
85
- outputTileSize: Optional[_arg_types.List] = None,
86
- outputBands: Optional[_arg_types.Dictionary] = None,
87
- outputProperties: Optional[_arg_types.Dictionary] = None,
88
- outputMultiplier: Optional[_arg_types.Number] = None,
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: Optional[_arg_types.List] = None,
172
- inputTypeOverride: Optional[_arg_types.Dictionary] = None,
173
- inputShapes: Optional[_arg_types.Dictionary] = None,
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: Optional[_arg_types.Projection] = None,
173
+ proj: _arg_types.Projection | None = None,
176
174
  # pylint: disable=invalid-name
177
- fixInputProj: Optional[_arg_types.Bool] = None,
178
- inputTileSize: Optional[_arg_types.List] = None,
179
- inputOverlapSize: Optional[_arg_types.List] = None,
180
- outputTileSize: Optional[_arg_types.List] = None,
181
- outputBands: Optional[_arg_types.Dictionary] = None,
182
- outputProperties: Optional[_arg_types.Dictionary] = None,
183
- outputMultiplier: Optional[_arg_types.Number] = None,
184
- maxPayloadBytes: Optional[_arg_types.Integer] = None,
185
- payloadFormat: Optional[_arg_types.String] = None,
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, Optional, Union
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: Optional[Any]) -> bool:
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: Optional[Any],
110
- ) -> Optional[str]:
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() -> Optional[str]:
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: Optional[Any]) -> bool:
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: Optional[Sequence[str]] = None,
150
- redirect_uri: Optional[str] = None,
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: Optional[str] = None,
168
- client_secret: Optional[str] = None,
169
- redirect_uri: Optional[str] = None,
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 {}: {}'.format(dirname, e))
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)
@@ -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: Optional[str]) -> Optional[str]:
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: Optional[str] = None,
247
- code_verifier: Optional[str] = None,
248
- scopes: Optional[Sequence[str]] = None,
249
- redirect_uri: Optional[str] = None,
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: Union[bytes, str]
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: Optional[str] = None
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,7 +325,7 @@ def _display_auth_instructions_with_print(
325
325
 
326
326
 
327
327
  def _display_auth_instructions_with_html(
328
- auth_url: str, coda: Optional[str] = None
328
+ auth_url: str, coda: str | None = None
329
329
  ) -> None:
330
330
  """Displays instructions for authenticating using HTML code."""
331
331
  try:
@@ -382,8 +382,8 @@ def _no_gcloud() -> bool:
382
382
 
383
383
 
384
384
  def _load_gcloud_credentials(
385
- scopes: Optional[Sequence[str]] = None,
386
- quiet: Optional[bool] = None,
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: Optional[str] = None
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) -> Optional[str]:
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: Optional[str] = None,
473
- quiet: Optional[bool] = None,
474
- cli_code_verifier: Optional[str] = None,
475
- auth_mode: Optional[str] = None,
476
- scopes: Optional[Sequence[str]] = None,
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
- ) -> Optional[bool]:
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: Optional[Any]
567
+ server: Any | None
568
568
  auth_url: str
569
569
 
570
570
  def __init__(
571
- self, auth_mode: str = 'notebook', scopes: Optional[Sequence[str]] = None
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: Optional[str] = None) -> None:
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: Optional[bool] = None) -> bool:
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: