Skip to content

Commit 625cbba

Browse files
schwehrXee authors
authored andcommitted
xee pyupgrade --py39-plus
PiperOrigin-RevId: 780112669
1 parent 4a3ea57 commit 625cbba

File tree

4 files changed

+94
-88
lines changed

4 files changed

+94
-88
lines changed

examples/dataflow/ee_to_zarr_dataflow.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717

1818
import logging
19-
from typing import Dict, List
2019

2120
from absl import app
2221
from absl import flags
@@ -55,7 +54,7 @@
5554

5655

5756
# pylint: disable=unused-argument
58-
def _parse_dataflow_flags(argv: List[str]) -> List[str]:
57+
def _parse_dataflow_flags(argv: list[str]) -> list[str]:
5958
parser = flags.argparse_flags.ArgumentParser(
6059
description='parser for dataflow flags',
6160
allow_abbrev=False,
@@ -66,7 +65,7 @@ def _parse_dataflow_flags(argv: List[str]) -> List[str]:
6665

6766
# Borrowed from the xbeam examples:
6867
# https://github.com/google/xarray-beam/blob/4f4fcb965a65b5d577601af311d0e0142ee38076/examples/xbeam_rechunk.py#L41
69-
def _parse_chunks_str(chunks_str: str) -> Dict[str, int]:
68+
def _parse_chunks_str(chunks_str: str) -> dict[str, int]:
7069
chunks = {}
7170
parts = chunks_str.split(',')
7271
for part in parts:

xee/ext.py

Lines changed: 82 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
from __future__ import annotations
2020

21+
from collections.abc import Iterable, Sequence
2122
import concurrent.futures
2223
import copy
2324
import functools
@@ -27,7 +28,7 @@
2728
import math
2829
import os
2930
import sys
30-
from typing import Any, Callable, Dict, Iterable, List, Literal, Optional, Sequence, Tuple, Union
31+
from typing import Any, Callable, Literal, Union
3132
from urllib import parse
3233
import warnings
3334

@@ -59,7 +60,7 @@
5960
#
6061
# The 'int' case let's users specify `io_chunks=-1`, which means to load the
6162
# data as a single chunk.
62-
Chunks = Union[int, Dict[Any, Any], Literal['auto'], None]
63+
Chunks = Union[int, dict[Any, Any], Literal['auto'], None]
6364

6465

6566
_BUILTIN_DTYPES = {
@@ -80,7 +81,7 @@
8081

8182

8283
# Used in ext_test.py.
83-
def _check_request_limit(chunks: Dict[str, int], dtype_size: int, limit: int):
84+
def _check_request_limit(chunks: dict[str, int], dtype_size: int, limit: int):
8485
"""Checks that the actual number of bytes exceeds the limit."""
8586
index, width, height = chunks['index'], chunks['width'], chunks['height']
8687
# Add one for the mask byte (Earth Engine bytes-per-pixel accounting).
@@ -104,25 +105,25 @@ class EarthEngineStore(common.AbstractDataStore):
104105
"""Read-only Data Store for Google Earth Engine."""
105106

106107
# "Safe" default chunks that won't exceed the request limit.
107-
PREFERRED_CHUNKS: Dict[str, int] = {
108+
PREFERRED_CHUNKS: dict[str, int] = {
108109
'index': 48,
109110
'width': 256,
110111
'height': 256,
111112
}
112113

113-
GETITEM_KWARGS: Dict[str, int] = {
114+
GETITEM_KWARGS: dict[str, int] = {
114115
'max_retries': 6,
115116
'initial_delay': 500,
116117
}
117118

118-
SCALE_UNITS: Dict[str, int] = {
119+
SCALE_UNITS: dict[str, int] = {
119120
'degree': 1,
120121
'metre': 10_000,
121122
'meter': 10_000,
122123
'm': 10_000,
123124
}
124125

125-
DIMENSION_NAMES: Dict[str, Tuple[str, str]] = {
126+
DIMENSION_NAMES: dict[str, tuple[str, str]] = {
126127
'degree': ('lon', 'lat'),
127128
'metre': ('X', 'Y'),
128129
'meter': ('X', 'Y'),
@@ -149,20 +150,20 @@ def open(
149150
mode: Literal['r'] = 'r',
150151
chunk_store: Chunks = None,
151152
n_images: int = -1,
152-
crs: Optional[str] = None,
153-
scale: Optional[float] = None,
154-
projection: Optional[ee.Projection] = None,
155-
geometry: ee.Geometry | Tuple[float, float, float, float] | None = None,
156-
primary_dim_name: Optional[str] = None,
157-
primary_dim_property: Optional[str] = None,
158-
mask_value: Optional[float] = None,
153+
crs: str | None = None,
154+
scale: float | None = None,
155+
projection: ee.Projection | None = None,
156+
geometry: ee.Geometry | tuple[float, float, float, float] | None = None,
157+
primary_dim_name: str | None = None,
158+
primary_dim_property: str | None = None,
159+
mask_value: float | None = None,
159160
request_byte_limit: int = REQUEST_BYTE_LIMIT,
160-
ee_init_kwargs: Optional[Dict[str, Any]] = None,
161+
ee_init_kwargs: dict[str, Any] | None = None,
161162
ee_init_if_necessary: bool = False,
162-
executor_kwargs: Optional[Dict[str, Any]] = None,
163-
getitem_kwargs: Optional[Dict[str, int]] = None,
163+
executor_kwargs: dict[str, Any] | None = None,
164+
getitem_kwargs: dict[str, int] | None = None,
164165
fast_time_slicing: bool = False,
165-
) -> 'EarthEngineStore':
166+
) -> EarthEngineStore:
166167
if mode != 'r':
167168
raise ValueError(
168169
f'mode {mode!r} is invalid: data can only be read from Earth Engine.'
@@ -192,18 +193,18 @@ def __init__(
192193
image_collection: ee.ImageCollection,
193194
chunks: Chunks = None,
194195
n_images: int = -1,
195-
crs: Optional[str] = None,
196-
scale: Union[float, int, None] = None,
197-
projection: Optional[ee.Projection] = None,
198-
geometry: ee.Geometry | Tuple[float, float, float, float] | None = None,
199-
primary_dim_name: Optional[str] = None,
200-
primary_dim_property: Optional[str] = None,
201-
mask_value: Optional[float] = None,
196+
crs: str | None = None,
197+
scale: float | int | None = None,
198+
projection: ee.Projection | None = None,
199+
geometry: ee.Geometry | tuple[float, float, float, float] | None = None,
200+
primary_dim_name: str | None = None,
201+
primary_dim_property: str | None = None,
202+
mask_value: float | None = None,
202203
request_byte_limit: int = REQUEST_BYTE_LIMIT,
203-
ee_init_kwargs: Optional[Dict[str, Any]] = None,
204+
ee_init_kwargs: dict[str, Any] | None = None,
204205
ee_init_if_necessary: bool = False,
205-
executor_kwargs: Optional[Dict[str, Any]] = None,
206-
getitem_kwargs: Optional[Dict[str, int]] = None,
206+
executor_kwargs: dict[str, Any] | None = None,
207+
getitem_kwargs: dict[str, int] | None = None,
207208
fast_time_slicing: bool = False,
208209
):
209210
self.ee_init_kwargs = ee_init_kwargs
@@ -279,7 +280,7 @@ def __init__(
279280
self.mask_value = mask_value
280281

281282
@functools.cached_property
282-
def get_info(self) -> Dict[str, Any]:
283+
def get_info(self) -> dict[str, Any]:
283284
"""Make all getInfo() calls to EE at once."""
284285

285286
rpcs = [
@@ -330,12 +331,12 @@ def get_info(self) -> Dict[str, Any]:
330331
return dict(zip((name for name, _ in rpcs), info))
331332

332333
@property
333-
def image_collection_properties(self) -> Tuple[List[str], List[str]]:
334+
def image_collection_properties(self) -> tuple[list[str], list[str]]:
334335
system_ids, primary_coord = self.get_info['properties']
335336
return (system_ids, primary_coord)
336337

337338
@property
338-
def image_ids(self) -> List[str]:
339+
def image_ids(self) -> list[str]:
339340
image_ids, _ = self.image_collection_properties
340341
return image_ids
341342

@@ -347,7 +348,7 @@ def _max_itemsize(self) -> int:
347348
@classmethod
348349
def _auto_chunks(
349350
cls, dtype_bytes: int, request_byte_limit: int = REQUEST_BYTE_LIMIT
350-
) -> Dict[str, int]:
351+
) -> dict[str, int]:
351352
"""Given the data type size and request limit, calculate optimal chunks."""
352353
# Taking the data type number of bytes into account, let's try to have the
353354
# height and width follow round numbers (powers of two) and allocate the
@@ -374,8 +375,8 @@ def _auto_chunks(
374375
return {'index': index, 'width': width, 'height': height}
375376

376377
def _assign_index_chunks(
377-
self, input_chunk_store: Dict[Any, Any]
378-
) -> Dict[Any, Any]:
378+
self, input_chunk_store: dict[Any, Any]
379+
) -> dict[Any, Any]:
379380
"""Assigns values of 'index', 'width', and 'height' to `self.chunks`.
380381
381382
This method first attempts to retrieve values for 'index', 'width',
@@ -416,7 +417,7 @@ def _assign_preferred_chunks(self) -> Chunks:
416417
chunks[y_dim_name] = self.chunks['height']
417418
return chunks
418419

419-
def transform(self, xs: float, ys: float) -> Tuple[float, float]:
420+
def transform(self, xs: float, ys: float) -> tuple[float, float]:
420421
transformer = pyproj.Transformer.from_crs(
421422
self.crs.geodetic_crs, self.crs, always_xy=True
422423
)
@@ -539,22 +540,29 @@ def image_to_array(
539540
data = np.where(data == current_mask_value, np.nan, data)
540541
return data
541542

542-
@functools.lru_cache()
543+
@functools.lru_cache
543544
def _band_attrs(self, band_name: str) -> types.BandInfo:
544545
try:
545-
return next((b for b in self._img_info['bands'] if b['id'] == band_name))
546+
return next(b for b in self._img_info['bands'] if b['id'] == band_name)
546547
except StopIteration as e:
547548
raise ValueError(f'Band {band_name!r} not found.') from e
548549

549-
@functools.lru_cache()
550-
def _bands(self) -> List[str]:
550+
@functools.lru_cache
551+
def _bands(self) -> list[str]:
551552
return [b['id'] for b in self._img_info['bands']]
552553

553-
def _make_attrs_valid(self, attrs: Dict[str, Any]) -> Dict[
554+
def _make_attrs_valid(self, attrs: dict[str, Any]) -> dict[
554555
str,
555-
Union[
556-
str, int, float, complex, np.ndarray, np.number, List[Any], Tuple[Any]
557-
],
556+
(
557+
str
558+
| int
559+
| float
560+
| complex
561+
| np.ndarray
562+
| np.number
563+
| list[Any]
564+
| tuple[Any] # pylint: disable=g-one-element-tuple
565+
),
558566
]:
559567
return {
560568
key: (
@@ -590,7 +598,7 @@ def get_dimensions(self) -> utils.Frozen[str, int]:
590598
def get_attrs(self) -> utils.Frozen[Any, Any]:
591599
return utils.FrozenDict(self._props)
592600

593-
def _get_primary_coordinates(self) -> List[Any]:
601+
def _get_primary_coordinates(self) -> list[Any]:
594602
"""Gets the primary dimension coordinate values from an ImageCollection."""
595603
_, primary_coords = self.image_collection_properties
596604

@@ -607,8 +615,8 @@ def _get_primary_coordinates(self) -> List[Any]:
607615
return primary_coords
608616

609617
def _get_tile_from_ee(
610-
self, tile_and_band: Tuple[Tuple[int, int, int], str]
611-
) -> Tuple[int, np.ndarray[Any, np.dtype]]:
618+
self, tile_and_band: tuple[tuple[int, int, int], str]
619+
) -> tuple[int, np.ndarray[Any, np.dtype]]:
612620
"""Get a numpy array from EE for a specific bounding box (a 'tile')."""
613621
(tile_index, tile_coords_start, tile_coords_end), band_id = tile_and_band
614622
bbox = self.project(
@@ -644,8 +652,8 @@ def _process_coordinate_data(
644652

645653
def _determine_bounds(
646654
self,
647-
geometry: ee.Geometry | Tuple[float, float, float, float] | None = None,
648-
) -> Tuple[float, float, float, float]:
655+
geometry: ee.Geometry | tuple[float, float, float, float] | None = None,
656+
) -> tuple[float, float, float, float]:
649657
if geometry is None:
650658
try:
651659
x_min_0, y_min_0, x_max_0, y_max_0 = self.crs.area_of_use.bounds
@@ -757,7 +765,7 @@ def _parse_dtype(data_type: types.DataType):
757765
return np.dtype(dt)
758766

759767

760-
def _ee_bounds_to_bounds(bounds: Dict[str, Any]) -> types.Bounds:
768+
def _ee_bounds_to_bounds(bounds: dict[str, Any]) -> types.Bounds:
761769
coords = np.array(bounds['coordinates'], dtype=np.float64)[0]
762770
x_min, y_min, x_max, y_max = (
763771
min(coords[:, 0]),
@@ -818,8 +826,8 @@ def __getitem__(self, key: indexing.ExplicitIndexer) -> np.typing.ArrayLike:
818826
)
819827

820828
def _key_to_slices(
821-
self, key: Tuple[Union[int, slice], ...]
822-
) -> Tuple[Tuple[slice, ...], Tuple[int, ...]]:
829+
self, key: tuple[int | slice, ...]
830+
) -> tuple[tuple[slice, ...], tuple[int, ...]]:
823831
"""Convert all key indexes to slices.
824832
825833
If any keys are integers, convert them to a slice (i.e. with a range of 1
@@ -889,7 +897,7 @@ def reduce_bands(x, acc):
889897
return target_image
890898

891899
def _raw_indexing_method(
892-
self, key: Tuple[Union[int, slice], ...]
900+
self, key: tuple[int | slice, ...]
893901
) -> np.typing.ArrayLike:
894902
key, squeeze_axes = self._key_to_slices(key)
895903

@@ -955,8 +963,8 @@ def _raw_indexing_method(
955963
return out
956964

957965
def _make_tile(
958-
self, tile_index: Tuple[types.TileIndex, types.BBox3d]
959-
) -> Tuple[types.TileIndex, np.ndarray]:
966+
self, tile_index: tuple[types.TileIndex, types.BBox3d]
967+
) -> tuple[types.TileIndex, np.ndarray]:
960968
"""Get a numpy array from EE for a specific 3D bounding box (a 'tile')."""
961969
tile_idx, (istart, iend, *bbox) = tile_index
962970
target_image = self._slice_collection(slice(istart, iend))
@@ -966,7 +974,7 @@ def _make_tile(
966974

967975
def _tile_indexes(
968976
self, index_range: slice, bbox: types.BBox
969-
) -> Iterable[Tuple[types.TileIndex, types.BBox3d]]:
977+
) -> Iterable[tuple[types.TileIndex, types.BBox3d]]:
970978
"""Calculate indexes to break up a (3D) bounding box into chunks."""
971979
tstep = self._apparent_chunks['index']
972980
wstep = self._apparent_chunks['width']
@@ -988,7 +996,7 @@ def _tile_indexes(
988996
class EarthEngineBackendEntrypoint(backends.BackendEntrypoint):
989997
"""Backend for Earth Engine."""
990998

991-
def _parse(self, filename_or_obj: Union[str, os.PathLike[Any]]) -> str:
999+
def _parse(self, filename_or_obj: str | os.PathLike[Any]) -> str:
9921000
parsed = parse.urlparse(str(filename_or_obj))
9931001
if parsed.scheme and parsed.scheme != 'ee':
9941002
raise ValueError(
@@ -998,7 +1006,7 @@ def _parse(self, filename_or_obj: Union[str, os.PathLike[Any]]) -> str:
9981006
return f'{parsed.netloc}{parsed.path}'
9991007

10001008
def guess_can_open(
1001-
self, filename_or_obj: Union[str, os.PathLike[Any], ee.ImageCollection]
1009+
self, filename_or_obj: str | os.PathLike[Any] | ee.ImageCollection
10021010
) -> bool: # type: ignore
10031011
"""Returns True if the candidate is a valid ImageCollection."""
10041012
if isinstance(filename_or_obj, ee.ImageCollection):
@@ -1013,28 +1021,28 @@ def guess_can_open(
10131021

10141022
def open_dataset(
10151023
self,
1016-
filename_or_obj: Union[str, os.PathLike[Any], ee.ImageCollection],
1017-
drop_variables: Optional[Tuple[str, ...]] = None,
1018-
io_chunks: Optional[Any] = None,
1024+
filename_or_obj: str | os.PathLike[Any] | ee.ImageCollection,
1025+
drop_variables: tuple[str, ...] | None = None,
1026+
io_chunks: Any | None = None,
10191027
n_images: int = -1,
10201028
mask_and_scale: bool = True,
10211029
decode_times: bool = True,
1022-
decode_timedelta: Optional[bool] = None,
1023-
use_cftime: Optional[bool] = None,
1030+
decode_timedelta: bool | None = None,
1031+
use_cftime: bool | None = None,
10241032
concat_characters: bool = True,
10251033
decode_coords: bool = True,
1026-
crs: Optional[str] = None,
1027-
scale: Union[float, int, None] = None,
1028-
projection: Optional[ee.Projection] = None,
1029-
geometry: ee.Geometry | Tuple[float, float, float, float] | None = None,
1030-
primary_dim_name: Optional[str] = None,
1031-
primary_dim_property: Optional[str] = None,
1032-
ee_mask_value: Optional[float] = None,
1034+
crs: str | None = None,
1035+
scale: float | int | None = None,
1036+
projection: ee.Projection | None = None,
1037+
geometry: ee.Geometry | tuple[float, float, float, float] | None = None,
1038+
primary_dim_name: str | None = None,
1039+
primary_dim_property: str | None = None,
1040+
ee_mask_value: float | None = None,
10331041
request_byte_limit: int = REQUEST_BYTE_LIMIT,
10341042
ee_init_if_necessary: bool = False,
1035-
ee_init_kwargs: Optional[Dict[str, Any]] = None,
1036-
executor_kwargs: Optional[Dict[str, Any]] = None,
1037-
getitem_kwargs: Optional[Dict[str, int]] = None,
1043+
ee_init_kwargs: dict[str, Any] | None = None,
1044+
executor_kwargs: dict[str, Any] | None = None,
1045+
getitem_kwargs: dict[str, int] | None = None,
10381046
fast_time_slicing: bool = False,
10391047
) -> xarray.Dataset: # type: ignore
10401048
"""Open an Earth Engine ImageCollection as an Xarray Dataset.
@@ -1170,8 +1178,8 @@ def open_dataset(
11701178

11711179

11721180
def _parse_ee_init_kwargs(
1173-
ee_init_kwargs: Optional[Dict[str, Any]],
1174-
) -> Dict[str, Any]:
1181+
ee_init_kwargs: dict[str, Any] | None,
1182+
) -> dict[str, Any]:
11751183
"""Parses Earth Engine Initialize kwargs.
11761184
11771185
Generate credentials if credentials_function is specified.

0 commit comments

Comments
 (0)