From e835e4e59a1ebd585a8f4617041a2f7d3491c1b1 Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Thu, 2 Jun 2022 18:55:06 +0200 Subject: [PATCH 01/21] type some DataWithCoords methods --- xarray/core/common.py | 101 ++++++++++++++++++++++++++++--------- xarray/core/computation.py | 3 +- xarray/core/options.py | 76 +++++++++++++++++----------- 3 files changed, 125 insertions(+), 55 deletions(-) diff --git a/xarray/core/common.py b/xarray/core/common.py index 0579a065855..16a7c07ddb4 100644 --- a/xarray/core/common.py +++ b/xarray/core/common.py @@ -39,7 +39,8 @@ if TYPE_CHECKING: from .dataarray import DataArray from .dataset import Dataset - from .types import T_DataWithCoords, T_Xarray + from .indexes import Index + from .types import ScalarOrArray, T_DataWithCoords, T_Xarray from .variable import Variable from .weighted import Weighted @@ -353,15 +354,16 @@ class DataWithCoords(AttrAccessMixin): """Shared base class for Dataset and DataArray.""" _close: Callable[[], None] | None + _indexes: dict[Hashable, Index] __slots__ = ("_close",) def squeeze( - self, + self: T_DataWithCoords, dim: Hashable | Iterable[Hashable] | None = None, drop: bool = False, axis: int | Iterable[int] | None = None, - ): + ) -> T_DataWithCoords: """Return a new object with squeezed data. Parameters @@ -370,7 +372,7 @@ def squeeze( Selects a subset of the length one dimensions. If a dimension is selected with length greater than one, an error is raised. If None, all length one dimensions are squeezed. - drop : bool, optional + drop : bool, default: False If ``drop=True``, drop squeezed coordinates instead of making them scalar. axis : None or int or iterable of int, optional @@ -389,12 +391,33 @@ def squeeze( dims = get_squeeze_dims(self, dim, axis) return self.isel(drop=drop, **{d: 0 for d in dims}) - def clip(self, min=None, max=None, *, keep_attrs: bool = None): + def clip( + self: T_DataWithCoords, + min: ScalarOrArray | None = None, + max: ScalarOrArray | None = None, + *, + keep_attrs: bool | None = None, + ) -> T_DataWithCoords: """ Return an array whose values are limited to ``[min, max]``. At least one of max or min must be given. - Refer to `numpy.clip` for full documentation. + Parameters + ---------- + min : None or Hashable, optional + Minimum value. If None, no lower clipping is performed. + max : None or Hashable, optional + Maximum value. If None, no upper clipping is performed. + keep_attrs : bool or None, optional + If True, the attributes (`attrs`) will be copied from + the original object to the new one. If False, the new + object will be returned without attributes. + + Returns + ------- + clipped : same type as caller + This object, but with with values < min are replaced with min, + and those > max with max. See Also -------- @@ -426,7 +449,11 @@ def _calc_assign_results( ) -> dict[Hashable, T]: return {k: v(self) if callable(v) else v for k, v in kwargs.items()} - def assign_coords(self, coords=None, **coords_kwargs): + def assign_coords( + self: T_DataWithCoords, + coords: Mapping[Any, Any] | None = None, + **coords_kwargs: Any, + ) -> T_DataWithCoords: """Assign new coordinates to this object. Returns a new object with all the original data in addition to the new @@ -434,7 +461,7 @@ def assign_coords(self, coords=None, **coords_kwargs): Parameters ---------- - coords : dict, optional + coords : dict-like or None, optional A dict where the keys are the names of the coordinates with the new values to assign. If the values are callable, they are computed on this object and assigned to new coordinate variables. @@ -556,13 +583,15 @@ def assign_coords(self, coords=None, **coords_kwargs): Dataset.assign Dataset.swap_dims """ - coords_kwargs = either_dict_or_kwargs(coords, coords_kwargs, "assign_coords") + coords_combined = either_dict_or_kwargs(coords, coords_kwargs, "assign_coords") data = self.copy(deep=False) - results = self._calc_assign_results(coords_kwargs) + results: dict[Hashable, Any] = self._calc_assign_results(coords_combined) data.coords.update(results) return data - def assign_attrs(self, *args, **kwargs): + def assign_attrs( + self: T_DataWithCoords, *args: Any, **kwargs: Any + ) -> T_DataWithCoords: """Assign new attrs to this object. Returns a new object equivalent to ``self.attrs.update(*args, **kwargs)``. @@ -590,8 +619,8 @@ def assign_attrs(self, *args, **kwargs): def pipe( self, func: Callable[..., T] | tuple[Callable[..., T], str], - *args, - **kwargs, + *args: Any, + **kwargs: Any, ) -> T: """ Apply ``func(self, *args, **kwargs)`` @@ -719,7 +748,9 @@ def pipe( else: return func(self, *args, **kwargs) - def groupby(self, group, squeeze: bool = True, restore_coord_dims: bool = None): + def groupby( + self, group: Any, squeeze: bool = True, restore_coord_dims: bool | None = None + ): """Returns a GroupBy object for performing grouped operations. Parameters @@ -727,7 +758,7 @@ def groupby(self, group, squeeze: bool = True, restore_coord_dims: bool = None): group : str, DataArray or IndexVariable Array whose unique values should be used to group this array. If a string, must be the name of a variable contained in this dataset. - squeeze : bool, optional + squeeze : bool, default: True If "group" is a dimension of any arrays in this dataset, `squeeze` controls whether the subarrays have a dimension of length 1 along that dimension or if the dimension is squeezed out. @@ -1234,7 +1265,9 @@ def resample( return resampler - def where(self, cond, other=dtypes.NA, drop: bool = False): + def where( + self: T_DataWithCoords, cond: Any, other: Any = dtypes.NA, drop: bool = False + ) -> T_DataWithCoords: """Filter elements from this object according to a condition. This operation follows the normal broadcasting and alignment rules that @@ -1248,7 +1281,7 @@ def where(self, cond, other=dtypes.NA, drop: bool = False): other : scalar, DataArray or Dataset, optional Value to use for locations in this object where ``cond`` is False. By default, these locations filled with NA. - drop : bool, optional + drop : bool, default: False If True, coordinate labels that only correspond to False values of the condition are dropped from the result. @@ -1330,7 +1363,7 @@ def where(self, cond, other=dtypes.NA, drop: bool = False): ) # align so we can use integer indexing - self, cond = align(self, cond) + self, cond = align(self, cond) # type: ignore[assignment] # get cond with the minimal size needed for the Dataset if isinstance(cond, Dataset): @@ -1363,15 +1396,24 @@ def set_close(self, close: Callable[[], None] | None) -> None: """ self._close = close - def close(self: Any) -> None: + def close(self) -> None: """Release any resources linked to this object.""" if self._close is not None: self._close() self._close = None - def isnull(self, keep_attrs: bool = None): + def isnull( + self: T_DataWithCoords, keep_attrs: bool | None = None + ) -> T_DataWithCoords: """Test each value in the array for whether it is a missing value. + Parameters + ---------- + keep_attrs : bool or None, optional + If True, the attributes (`attrs`) will be copied from + the original object to the new one. If False, the new + object will be returned without attributes. + Returns ------- isnull : DataArray or Dataset @@ -1405,9 +1447,18 @@ def isnull(self, keep_attrs: bool = None): keep_attrs=keep_attrs, ) - def notnull(self, keep_attrs: bool = None): + def notnull( + self: T_DataWithCoords, keep_attrs: bool | None = None + ) -> T_DataWithCoords: """Test each value in the array for whether it is not a missing value. + Parameters + ---------- + keep_attrs : bool or None, optional + If True, the attributes (`attrs`) will be copied from + the original object to the new one. If False, the new + object will be returned without attributes. + Returns ------- notnull : DataArray or Dataset @@ -1441,7 +1492,7 @@ def notnull(self, keep_attrs: bool = None): keep_attrs=keep_attrs, ) - def isin(self, test_elements): + def isin(self: T_DataWithCoords, test_elements: Any) -> T_DataWithCoords: """Tests each value in the array for whether it is in test elements. Parameters @@ -1492,7 +1543,7 @@ def isin(self, test_elements): ) def astype( - self: T, + self: T_DataWithCoords, dtype, *, order=None, @@ -1500,7 +1551,7 @@ def astype( subok=None, copy=None, keep_attrs=True, - ) -> T: + ) -> T_DataWithCoords: """ Copy of the xarray object, with data cast to a specified type. Leaves coordinate dtype unchanged. @@ -1567,7 +1618,7 @@ def astype( dask="allowed", ) - def __enter__(self: T) -> T: + def __enter__(self: T_DataWithCoords) -> T_DataWithCoords: return self def __exit__(self, exc_type, exc_value, traceback) -> None: diff --git a/xarray/core/computation.py b/xarray/core/computation.py index de7934dafdd..00aa9d83695 100644 --- a/xarray/core/computation.py +++ b/xarray/core/computation.py @@ -876,7 +876,8 @@ def apply_ufunc( the style of NumPy universal functions [1]_ (if this is not the case, set ``vectorize=True``). If this function returns multiple outputs, you must set ``output_core_dims`` as well. - *args : Dataset, DataArray, DataArrayGroupBy, DatasetGroupBy, Variable, numpy.ndarray, dask.array.Array or scalar + *args : Dataset, DataArray, DataArrayGroupBy, DatasetGroupBy, Variable, \ + numpy.ndarray, dask.array.Array or scalar Mix of labeled and/or unlabeled arrays to which to apply the function. input_core_dims : sequence of sequence, optional List of the same length as ``args`` giving the list of core dimensions diff --git a/xarray/core/options.py b/xarray/core/options.py index d31f2577601..b8f420e5117 100644 --- a/xarray/core/options.py +++ b/xarray/core/options.py @@ -8,29 +8,47 @@ from matplotlib.colors import Colormap except ImportError: Colormap = str - - -class T_Options(TypedDict): - arithmetic_join: Literal["inner", "outer", "left", "right", "exact"] - cmap_divergent: Union[str, "Colormap"] - cmap_sequential: Union[str, "Colormap"] - display_max_rows: int - display_values_threshold: int - display_style: Literal["text", "html"] - display_width: int - display_expand_attrs: Literal["default", True, False] - display_expand_coords: Literal["default", True, False] - display_expand_data_vars: Literal["default", True, False] - display_expand_data: Literal["default", True, False] - enable_cftimeindex: bool - file_cache_maxsize: int - keep_attrs: Literal["default", True, False] - warn_for_unclosed_files: bool - use_bottleneck: bool - use_flox: bool - - -OPTIONS: T_Options = { + Options = Literal[ + "arithmetic_join", + "cmap_divergent", + "cmap_sequential", + "display_max_rows", + "display_values_threshold", + "display_style", + "display_width", + "display_expand_attrs", + "display_expand_coords", + "display_expand_data_vars", + "display_expand_data", + "enable_cftimeindex", + "file_cache_maxsize", + "keep_attrs", + "warn_for_unclosed_files", + "use_bottleneck", + "use_flox", + ] + + class T_Options(TypedDict): + arithmetic_join: Literal["inner", "outer", "left", "right", "exact"] + cmap_divergent: Union[str, "Colormap"] + cmap_sequential: Union[str, "Colormap"] + display_max_rows: int + display_values_threshold: int + display_style: Literal["text", "html"] + display_width: int + display_expand_attrs: Literal["default", True, False] + display_expand_coords: Literal["default", True, False] + display_expand_data_vars: Literal["default", True, False] + display_expand_data: Literal["default", True, False] + enable_cftimeindex: bool + file_cache_maxsize: int + keep_attrs: Literal["default", True, False] + warn_for_unclosed_files: bool + use_bottleneck: bool + use_flox: bool + + +OPTIONS: "T_Options" = { "arithmetic_join": "inner", "cmap_divergent": "RdBu_r", "cmap_sequential": "viridis", @@ -45,16 +63,16 @@ class T_Options(TypedDict): "enable_cftimeindex": True, "file_cache_maxsize": 128, "keep_attrs": "default", + "warn_for_unclosed_files": False, "use_bottleneck": True, "use_flox": True, - "warn_for_unclosed_files": False, } _JOIN_OPTIONS = frozenset(["inner", "outer", "left", "right", "exact"]) _DISPLAY_OPTIONS = frozenset(["text", "html"]) -def _positive_integer(value): +def _positive_integer(value: int) -> bool: return isinstance(value, int) and value > 0 @@ -77,7 +95,7 @@ def _positive_integer(value): } -def _set_file_cache_maxsize(value): +def _set_file_cache_maxsize(value) -> None: from ..backends.file_manager import FILE_CACHE FILE_CACHE.maxsize = value @@ -97,12 +115,12 @@ def _warn_on_setting_enable_cftimeindex(enable_cftimeindex): } -def _get_boolean_with_default(option, default): +def _get_boolean_with_default(option: "Options", default: bool) -> bool: global_choice = OPTIONS[option] if global_choice == "default": return default - elif global_choice in [True, False]: + elif isinstance(global_choice, bool): return global_choice else: raise ValueError( @@ -110,7 +128,7 @@ def _get_boolean_with_default(option, default): ) -def _get_keep_attrs(default): +def _get_keep_attrs(default: bool) -> bool: return _get_boolean_with_default("keep_attrs", default) From b751b2b8112c9500a659757060014bc88e948a37 Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Thu, 2 Jun 2022 21:05:24 +0200 Subject: [PATCH 02/21] several dataset typing improvements --- xarray/core/dataset.py | 343 ++++++++++++++++++++++------------------- xarray/core/utils.py | 24 ++- 2 files changed, 207 insertions(+), 160 deletions(-) diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index 38e4d2eadef..ed37aaf316d 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -12,6 +12,7 @@ from operator import methodcaller from os import PathLike from typing import ( + IO, TYPE_CHECKING, Any, Callable, @@ -85,7 +86,6 @@ decode_numpy_dict_values, drop_dims_from_indexers, either_dict_or_kwargs, - hashable, infix_dims, is_dict_like, is_scalar, @@ -115,6 +115,7 @@ PadReflectOptions, QueryEngineOptions, QueryParserOptions, + ReindexMethodOptions, T_Dataset, T_Xarray, ) @@ -408,7 +409,9 @@ def __setitem__(self, key, value) -> None: self.dataset[dim_indexers] = value -class Dataset(DataWithCoords, DatasetReductions, DatasetArithmetic, Mapping): +class Dataset( + DataWithCoords, DatasetReductions, DatasetArithmetic, Mapping[Hashable, "DataArray"] +): """A multi-dimensional, in memory, array database. A dataset resembles an in-memory representation of a NetCDF file, @@ -562,10 +565,10 @@ def __init__( self, # could make a VariableArgs to use more generally, and refine these # categories - data_vars: Mapping[Any, Any] = None, - coords: Mapping[Any, Any] = None, - attrs: Mapping[Any, Any] = None, - ): + data_vars: Mapping[Any, Any] | None = None, + coords: Mapping[Any, Any] | None = None, + attrs: Mapping[Any, Any] | None = None, + ) -> None: # TODO(shoyer): expose indexes as a public argument in __init__ if data_vars is None: @@ -595,7 +598,7 @@ def __init__( self._indexes = indexes @classmethod - def load_store(cls, store, decoder=None) -> Dataset: + def load_store(cls: type[T_Dataset], store, decoder=None) -> T_Dataset: """Create a new dataset from the contents of a backends.*DataStore object """ @@ -607,7 +610,7 @@ def load_store(cls, store, decoder=None) -> Dataset: return obj @property - def variables(self) -> Mapping[Hashable, Variable]: + def variables(self) -> Frozen[Hashable, Variable]: """Low level interface to Dataset contents as dict of Variable objects. This ordered dictionary is frozen to prevent mutation that could @@ -629,18 +632,18 @@ def attrs(self, value: Mapping[Any, Any]) -> None: self._attrs = dict(value) @property - def encoding(self) -> dict: + def encoding(self) -> dict[Hashable, Any]: """Dictionary of global encoding attributes on this dataset""" if self._encoding is None: self._encoding = {} return self._encoding @encoding.setter - def encoding(self, value: Mapping) -> None: + def encoding(self, value: Mapping[Any, Any]) -> None: self._encoding = dict(value) @property - def dims(self) -> Mapping[Hashable, int]: + def dims(self) -> Frozen[Hashable, int]: """Mapping from dimension names to lengths. Cannot be modified directly, but is updated when adding new variables. @@ -652,7 +655,7 @@ def dims(self) -> Mapping[Hashable, int]: return Frozen(self._dims) @property - def sizes(self) -> Mapping[Hashable, int]: + def sizes(self) -> Frozen[Hashable, int]: """Mapping from dimension names to lengths. Cannot be modified directly, but is updated when adding new variables. @@ -666,7 +669,7 @@ def sizes(self) -> Mapping[Hashable, int]: """ return self.dims - def load(self, **kwargs) -> Dataset: + def load(self: T_Dataset, **kwargs) -> T_Dataset: """Manually trigger loading and/or computation of this dataset's data from disk or a remote source into memory and return this dataset. Unlike compute, the original dataset is modified and returned. @@ -766,7 +769,7 @@ def __dask_postcompute__(self): def __dask_postpersist__(self): return self._dask_postpersist, () - def _dask_postcompute(self, results: Iterable[Variable]) -> Dataset: + def _dask_postcompute(self: T_Dataset, results: Iterable[Variable]) -> T_Dataset: import dask variables = {} @@ -778,7 +781,7 @@ def _dask_postcompute(self, results: Iterable[Variable]) -> Dataset: v = rebuild(next(results_iter), *args) variables[k] = v - return Dataset._construct_direct( + return type(self)._construct_direct( variables, self._coord_names, self._dims, @@ -789,8 +792,8 @@ def _dask_postcompute(self, results: Iterable[Variable]) -> Dataset: ) def _dask_postpersist( - self, dsk: Mapping, *, rename: Mapping[str, str] = None - ) -> Dataset: + self: T_Dataset, dsk: Mapping, *, rename: Mapping[str, str] = None + ) -> T_Dataset: from dask import is_dask_collection from dask.highlevelgraph import HighLevelGraph from dask.optimization import cull @@ -829,7 +832,7 @@ def _dask_postpersist( kwargs = {"rename": rename} if rename else {} variables[k] = rebuild(dsk2, *args, **kwargs) - return Dataset._construct_direct( + return type(self)._construct_direct( variables, self._coord_names, self._dims, @@ -839,7 +842,7 @@ def _dask_postpersist( self._close, ) - def compute(self, **kwargs) -> Dataset: + def compute(self: T_Dataset, **kwargs) -> T_Dataset: """Manually trigger loading and/or computation of this dataset's data from disk or a remote source into memory and return a new dataset. Unlike load, the original dataset is left unaltered. @@ -861,7 +864,7 @@ def compute(self, **kwargs) -> Dataset: new = self.copy(deep=False) return new.load(**kwargs) - def _persist_inplace(self, **kwargs) -> Dataset: + def _persist_inplace(self: T_Dataset, **kwargs) -> T_Dataset: """Persist all Dask arrays in memory""" # access .data to coerce everything to numpy or dask arrays lazy_data = { @@ -878,7 +881,7 @@ def _persist_inplace(self, **kwargs) -> Dataset: return self - def persist(self, **kwargs) -> Dataset: + def persist(self: T_Dataset, **kwargs) -> T_Dataset: """Trigger computation, keeping data as dask arrays This operation can be used to trigger computation on underlying dask @@ -901,15 +904,15 @@ def persist(self, **kwargs) -> Dataset: @classmethod def _construct_direct( - cls, + cls: type[T_Dataset], variables: dict[Any, Variable], coord_names: set[Hashable], - dims: dict[Any, int] = None, - attrs: dict = None, - indexes: dict[Any, Index] = None, - encoding: dict = None, - close: Callable[[], None] = None, - ) -> Dataset: + dims: dict[Any, int] | None = None, + attrs: dict | None = None, + indexes: dict[Any, Index] | None = None, + encoding: dict | None = None, + close: Callable[[], None] | None = None, + ) -> T_Dataset: """Shortcut around __init__ for internal use when we want to skip costly validation """ @@ -928,15 +931,15 @@ def _construct_direct( return obj def _replace( - self, + self: T_Dataset, variables: dict[Hashable, Variable] = None, - coord_names: set[Hashable] = None, - dims: dict[Any, int] = None, + coord_names: set[Hashable] | None = None, + dims: dict[Any, int] | None = None, attrs: dict[Hashable, Any] | None | Default = _default, - indexes: dict[Hashable, Index] = None, + indexes: dict[Hashable, Index] | None = None, encoding: dict | None | Default = _default, inplace: bool = False, - ) -> Dataset: + ) -> T_Dataset: """Fastpath constructor for internal use. Returns an object with optionally with replaced attributes. @@ -978,13 +981,13 @@ def _replace( return obj def _replace_with_new_dims( - self, + self: T_Dataset, variables: dict[Hashable, Variable], - coord_names: set = None, + coord_names: set | None = None, attrs: dict[Hashable, Any] | None | Default = _default, - indexes: dict[Hashable, Index] = None, + indexes: dict[Hashable, Index] | None = None, inplace: bool = False, - ) -> Dataset: + ) -> T_Dataset: """Replace variables with recalculated dimensions.""" dims = calculate_dimensions(variables) return self._replace( @@ -992,13 +995,13 @@ def _replace_with_new_dims( ) def _replace_vars_and_dims( - self, + self: T_Dataset, variables: dict[Hashable, Variable], - coord_names: set = None, - dims: dict[Hashable, int] = None, + coord_names: set | None = None, + dims: dict[Hashable, int] | None = None, attrs: dict[Hashable, Any] | None | Default = _default, inplace: bool = False, - ) -> Dataset: + ) -> T_Dataset: """Deprecated version of _replace_with_new_dims(). Unlike _replace_with_new_dims(), this method always recalculates @@ -1011,13 +1014,13 @@ def _replace_vars_and_dims( ) def _overwrite_indexes( - self, + self: T_Dataset, indexes: Mapping[Hashable, Index], - variables: Mapping[Hashable, Variable] = None, - drop_variables: list[Hashable] = None, - drop_indexes: list[Hashable] = None, - rename_dims: Mapping[Hashable, Hashable] = None, - ) -> Dataset: + variables: Mapping[Hashable, Variable] | None = None, + drop_variables: list[Hashable] | None = None, + drop_indexes: list[Hashable] | None = None, + rename_dims: Mapping[Hashable, Hashable] | None = None, + ) -> T_Dataset: """Maybe replace indexes. This function may do a lot more depending on index query @@ -1084,7 +1087,9 @@ def _overwrite_indexes( else: return replaced - def copy(self, deep: bool = False, data: Mapping = None) -> Dataset: + def copy( + self: T_Dataset, deep: bool = False, data: Mapping | None = None + ) -> T_Dataset: """Returns a copy of this dataset. If `deep=True`, a deep copy is made of each of the component variables. @@ -1097,10 +1102,10 @@ def copy(self, deep: bool = False, data: Mapping = None) -> Dataset: Parameters ---------- - deep : bool, optional + deep : bool, default: False Whether each component variable is loaded into memory and copied onto the new object. Default is False. - data : dict-like, optional + data : dict-like or None, optional Data to use in the new object. Each item in `data` must have same shape as corresponding data variable in original. When `data` is used, `deep` is ignored for the data variables and only used for @@ -1215,7 +1220,7 @@ def copy(self, deep: bool = False, data: Mapping = None) -> Dataset: return self._replace(variables, indexes=indexes, attrs=attrs) - def as_numpy(self: Dataset) -> Dataset: + def as_numpy(self: T_Dataset) -> T_Dataset: """ Coerces wrapped data and coordinates into numpy arrays, returning a Dataset. @@ -1227,7 +1232,7 @@ def as_numpy(self: Dataset) -> Dataset: numpy_variables = {k: v.as_numpy() for k, v in self.variables.items()} return self._replace(variables=numpy_variables) - def _copy_listed(self, names: Iterable[Hashable]) -> Dataset: + def _copy_listed(self: T_Dataset, names: Iterable[Hashable]) -> T_Dataset: """Create a new Dataset with the listed variables from this dataset and the all relevant coordinates. Skips all validation. """ @@ -1291,10 +1296,10 @@ def _construct_dataarray(self, name: Hashable) -> DataArray: return DataArray(variable, coords, name=name, indexes=indexes, fastpath=True) - def __copy__(self) -> Dataset: + def __copy__(self: T_Dataset) -> T_Dataset: return self.copy(deep=False) - def __deepcopy__(self, memo=None) -> Dataset: + def __deepcopy__(self: T_Dataset, memo=None) -> T_Dataset: # memo does nothing but is required for compatibility with # copy.deepcopy return self.copy(deep=True) @@ -1348,39 +1353,37 @@ def loc(self) -> _LocIndexer: """ return _LocIndexer(self) - # FIXME https://github.com/python/mypy/issues/7328 - @overload - def __getitem__(self, key: Mapping) -> Dataset: # type: ignore[misc] - ... - @overload - def __getitem__(self, key: Hashable) -> DataArray: # type: ignore[misc] + def __getitem__(self, key: Hashable) -> DataArray: ... + # Mapping is Iterable @overload - def __getitem__(self, key: Any) -> Dataset: + def __getitem__(self: T_Dataset, key: Iterable[Hashable]) -> T_Dataset: ... - def __getitem__(self, key): - """Access variables or coordinates this dataset as a - :py:class:`~xarray.DataArray`. + def __getitem__( + self: T_Dataset, key: Mapping[Any, Any] | Hashable | Iterable[Hashable] + ) -> T_Dataset | DataArray: + """Access variables or coordinates of this dataset as a + :py:class:`~xarray.DataArray` or a subset of variables or a indexed dataset. Indexing with a list of names will return a new ``Dataset`` object. """ if utils.is_dict_like(key): - return self.isel(**cast(Mapping, key)) - - if hashable(key): + return self.isel(**key) + if utils.hashable(key): return self._construct_dataarray(key) - else: + if utils.iterable_of_hashable(key): return self._copy_listed(key) + raise ValueError(f"Unsupported key-type {type(key)}") def __setitem__(self, key: Hashable | list[Hashable] | Mapping, value) -> None: """Add an array to this dataset. Multiple arrays can be added at the same time, in which case each of the following operations is applied to the respective value. - If key is a dictionary, update all variables in the dataset + If key is dict-like, update all variables in the dataset one by one with the given value at the given location. If the given value is also a dataset, select corresponding variables in the given value and in the dataset to be changed. @@ -1415,33 +1418,37 @@ def __setitem__(self, key: Hashable | list[Hashable] | Mapping, value) -> None: else: raise e - elif isinstance(key, list): - if len(key) == 0: + elif utils.iterable_of_hashable(key): + keylist = list(key) + if len(keylist) == 0: raise ValueError("Empty list of variables to be set") - if len(key) == 1: - self.update({key[0]: value}) + if len(keylist) == 1: + self.update({keylist[0]: value}) else: - if len(key) != len(value): + if len(keylist) != len(value): raise ValueError( f"Different lengths of variables to be set " - f"({len(key)}) and data used as input for " + f"({len(keylist)}) and data used as input for " f"setting ({len(value)})" ) if isinstance(value, Dataset): - self.update(dict(zip(key, value.data_vars.values()))) + self.update(dict(zip(keylist, value.data_vars.values()))) elif isinstance(value, DataArray): raise ValueError("Cannot assign single DataArray to multiple keys") else: - self.update(dict(zip(key, value))) + self.update(dict(zip(keylist, value))) - else: + elif utils.hashable(key): if isinstance(value, Dataset): raise TypeError( - "Cannot assign a Dataset to a single key - only a DataArray or Variable object can be stored under" - "a single key." + "Cannot assign a Dataset to a single key - only a DataArray or Variable " + "object can be stored under a single key." ) self.update({key: value}) + else: + raise ValueError(f"Unsupported key-type {type(key)}") + def _setitem_check(self, key, value): """Consistency check for __setitem__ @@ -1617,7 +1624,7 @@ def data_vars(self) -> DataVariables: """Dictionary of DataArray objects corresponding to data variables""" return DataVariables(self) - def set_coords(self, names: Hashable | Iterable[Hashable]) -> Dataset: + def set_coords(self: T_Dataset, names: Hashable | Iterable[Hashable]) -> T_Dataset: """Given names of one or more variables, set them as coordinates Parameters @@ -1647,10 +1654,10 @@ def set_coords(self, names: Hashable | Iterable[Hashable]) -> Dataset: return obj def reset_coords( - self, + self: T_Dataset, names: Hashable | Iterable[Hashable] | None = None, drop: bool = False, - ) -> Dataset: + ) -> T_Dataset: """Given names of coordinates, reset them to become variables Parameters @@ -1658,7 +1665,7 @@ def reset_coords( names : hashable or iterable of hashable, optional Name(s) of non-index coordinates in this dataset to reset into variables. By default, all non-index coordinates are reset. - drop : bool, optional + drop : bool, default: False If True, remove coordinates instead of converting them into variables. @@ -2032,12 +2039,12 @@ def to_zarr( def __repr__(self) -> str: return formatting.dataset_repr(self) - def _repr_html_(self): + def _repr_html_(self) -> str: if OPTIONS["display_style"] == "text": return f"
{escape(repr(self))}
" return formatting_html.dataset_repr(self) - def info(self, buf=None) -> None: + def info(self, buf: IO | None = None) -> None: """ Concise summary of a Dataset variables and attributes. @@ -2090,7 +2097,7 @@ def chunks(self) -> Mapping[Hashable, tuple[int, ...]]: return get_chunksizes(self.variables.values()) @property - def chunksizes(self) -> Mapping[Any, tuple[int, ...]]: + def chunksizes(self) -> Mapping[Hashable, tuple[int, ...]]: """ Mapping from dimension names to block lengths for this dataset's data, or None if the underlying data is not a dask array. @@ -2107,16 +2114,16 @@ def chunksizes(self) -> Mapping[Any, tuple[int, ...]]: return get_chunksizes(self.variables.values()) def chunk( - self, + self: T_Dataset, chunks: ( int | Literal["auto"] | Mapping[Any, None | int | str | tuple[int, ...]] ) = {}, # {} even though it's technically unsafe, is being used intentionally here (#4667) name_prefix: str = "xarray-", - token: str = None, + token: str | None = None, lock: bool = False, inline_array: bool = False, **chunks_kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """Coerce all arrays in this dataset into dask arrays with the given chunks. @@ -2132,14 +2139,14 @@ def chunk( chunks : int, tuple of int, "auto" or mapping of hashable to int, optional Chunk sizes along each dimension, e.g., ``5``, ``"auto"``, or ``{"x": 5, "y": 5}``. - name_prefix : str, optional + name_prefix : str, default: "xarray-" Prefix for the name of any new dask arrays. token : str, optional Token uniquely identifying this dataset. - lock : optional + lock : bool, default: False Passed on to :py:func:`dask.array.from_array`, if the array is not already as dask array. - inline_array: optional + inline_array: bool, default: False Passed on to :py:func:`dask.array.from_array`, if the array is not already as dask array. **chunks_kwargs : {dim: chunks, ...}, optional @@ -2286,12 +2293,12 @@ def _get_indexers_coords_and_indexes(self, indexers): return attached_coords, attached_indexes def isel( - self, - indexers: Mapping[Any, Any] = None, + self: T_Dataset, + indexers: Mapping[Any, Any] | None = None, drop: bool = False, missing_dims: ErrorOptionsWithWarn = "raise", **indexers_kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """Returns a new dataset with each array indexed along the specified dimension(s). @@ -2317,6 +2324,7 @@ def isel( - "raise": raise an exception - "warn": raise a warning, and ignore the missing dimensions - "ignore": ignore the missing dimensions + **indexers_kwargs : {dim: indexer, ...}, optional The keyword arguments form of ``indexers``. One of indexers or indexers_kwargs must be provided. @@ -2376,12 +2384,12 @@ def isel( ) def _isel_fancy( - self, + self: T_Dataset, indexers: Mapping[Any, Any], *, drop: bool, missing_dims: ErrorOptionsWithWarn = "raise", - ) -> Dataset: + ) -> T_Dataset: valid_indexers = dict(self._validate_indexers(indexers, missing_dims)) variables: dict[Hashable, Variable] = {} @@ -2417,13 +2425,13 @@ def _isel_fancy( return self._replace_with_new_dims(variables, coord_names, indexes=indexes) def sel( - self, + self: T_Dataset, indexers: Mapping[Any, Any] = None, method: str = None, tolerance: int | float | Iterable[int | float] | None = None, drop: bool = False, **indexers_kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """Returns a new dataset with each array indexed by tick labels along the specified dimension(s). @@ -2503,10 +2511,10 @@ def sel( return result._overwrite_indexes(*query_results.as_tuple()[1:]) def head( - self, + self: T_Dataset, indexers: Mapping[Any, int] | int | None = None, **indexers_kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """Returns a new dataset with the first `n` values of each array for the specified dimension(s). @@ -2549,10 +2557,10 @@ def head( return self.isel(indexers_slices) def tail( - self, + self: T_Dataset, indexers: Mapping[Any, int] | int | None = None, **indexers_kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """Returns a new dataset with the last `n` values of each array for the specified dimension(s). @@ -2598,10 +2606,10 @@ def tail( return self.isel(indexers_slices) def thin( - self, + self: T_Dataset, indexers: Mapping[Any, int] | int | None = None, **indexers_kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """Returns a new dataset with each array indexed along every `n`-th value for the specified dimension(s) @@ -2732,13 +2740,13 @@ def _reindex_callback( return reindexed def reindex_like( - self, + self: T_Dataset, other: Dataset | DataArray, - method: str = None, + method: ReindexMethodOptions = None, tolerance: int | float | Iterable[int | float] | None = None, copy: bool = True, fill_value: Any = dtypes.NA, - ) -> Dataset: + ) -> T_Dataset: """Conform this object onto the indexes of another object, filling in missing values with ``fill_value``. The default fill value is NaN. @@ -2751,14 +2759,15 @@ def reindex_like( other object need not be the same as the indexes on this dataset. Any mis-matched index values will be filled in with NaN, and any mis-matched dimension names will simply be ignored. - method : {None, "nearest", "pad", "ffill", "backfill", "bfill"}, optional + method : {None, "nearest", "pad", "ffill", "backfill", "bfill", None}, optional Method to use for filling index values from other not found in this dataset: - * None (default): don't fill gaps - * pad / ffill: propagate last valid index value forward - * backfill / bfill: propagate next valid index value backward - * nearest: use nearest valid index value + - None (default): don't fill gaps + - "pad" / "ffill": propagate last valid index value forward + - "backfill" / "bfill": propagate next valid index value backward + - "nearest": use nearest valid index value + tolerance : optional Maximum distance between original and new labels for inexact matches. The values of the index at the matching locations must @@ -2767,7 +2776,7 @@ def reindex_like( to all values, or list-like, which applies variable tolerance per element. List-like must be the same size as the index and its dtype must exactly match the index’s type. - copy : bool, optional + copy : bool, default: True If ``copy=True``, data in the return value is always copied. If ``copy=False`` and reindexing is unnecessary, or can be performed with only slice operations, then the output may share memory with @@ -2797,14 +2806,14 @@ def reindex_like( ) def reindex( - self, - indexers: Mapping[Any, Any] = None, - method: str = None, + self: T_Dataset, + indexers: Mapping[Any, Any] | None = None, + method: ReindexMethodOptions = None, tolerance: int | float | Iterable[int | float] | None = None, copy: bool = True, fill_value: Any = dtypes.NA, **indexers_kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """Conform this object onto a new set of indexes, filling in missing values with ``fill_value``. The default fill value is NaN. @@ -2816,14 +2825,15 @@ def reindex( values will be filled in with NaN, and any mis-matched dimension names will simply be ignored. One of indexers or indexers_kwargs must be provided. - method : {None, "nearest", "pad", "ffill", "backfill", "bfill"}, optional + method : {None, "nearest", "pad", "ffill", "backfill", "bfill", None}, optional Method to use for filling index values in ``indexers`` not found in this dataset: - * None (default): don't fill gaps - * pad / ffill: propagate last valid index value forward - * backfill / bfill: propagate next valid index value backward - * nearest: use nearest valid index value + - None (default): don't fill gaps + - "pad" / "ffill": propagate last valid index value forward + - "backfill" / "bfill": propagate next valid index value backward + - "nearest": use nearest valid index value + tolerance : optional Maximum distance between original and new labels for inexact matches. The values of the index at the matching locations must @@ -2832,7 +2842,7 @@ def reindex( to all values, or list-like, which applies variable tolerance per element. List-like must be the same size as the index and its dtype must exactly match the index’s type. - copy : bool, optional + copy : bool, default: True If ``copy=True``, data in the return value is always copied. If ``copy=False`` and reindexing is unnecessary, or can be performed with only slice operations, then the output may share memory with @@ -3012,7 +3022,7 @@ def reindex( ) def _reindex( - self, + self: T_Dataset, indexers: Mapping[Any, Any] = None, method: str = None, tolerance: int | float | Iterable[int | float] | None = None, @@ -3020,7 +3030,7 @@ def _reindex( fill_value: Any = dtypes.NA, sparse: bool = False, **indexers_kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """ Same as reindex but supports sparse option. """ @@ -3036,14 +3046,14 @@ def _reindex( ) def interp( - self, - coords: Mapping[Any, Any] = None, + self: T_Dataset, + coords: Mapping[Any, Any] | None = None, method: InterpOptions = "linear", assume_sorted: bool = False, kwargs: Mapping[str, Any] = None, method_non_numeric: str = "nearest", **coords_kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """Interpolate a Dataset onto new coordinates Performs univariate or multivariate interpolation of a Dataset onto @@ -3062,17 +3072,20 @@ def interp( New coordinate can be a scalar, array-like or DataArray. If DataArrays are passed as new coordinates, their dimensions are used for the broadcasting. Missing values are skipped. - method : str, optional + method : {"linear", "nearest", "zero", "slinear", "quadratic", "cubic", "polynomial", \ + "barycentric", "krog", "pchip", "spline", "akima"}, default: linear The method used to interpolate. The method should be supported by the scipy interpolator: - - ``interp1d``: {"linear", "nearest", "zero", "slinear", - "quadratic", "cubic", "polynomial"} - - ``interpn``: {"linear", "nearest"} + - {"linear", "nearest", "zero", "slinear", "quadratic", "cubic", + "polynomial"} when ``interp1d`` is called. + - {"linear", "nearest"} when ``interpn`` is called. + - {"barycentric", "krog", "pchip", "spline", "akima"} when using + advanced interpolation classes. If ``"polynomial"`` is passed, the ``order`` keyword argument must also be provided. - assume_sorted : bool, optional + assume_sorted : bool, default: False If False, values of coordinates that are interpolated over can be in any order and they are sorted first. If True, interpolated coordinates are assumed to be an array of monotonically increasing @@ -3316,7 +3329,7 @@ def interp_like( other: Dataset | DataArray, method: InterpOptions = "linear", assume_sorted: bool = False, - kwargs: Mapping[str, Any] = None, + kwargs: Mapping[str, Any] | None = None, method_non_numeric: str = "nearest", ) -> Dataset: """Interpolate this object onto the coordinates of another object, @@ -3335,17 +3348,20 @@ def interp_like( Object with an 'indexes' attribute giving a mapping from dimension names to an 1d array-like, which provides coordinates upon which to index the variables in this dataset. Missing values are skipped. - method : str, optional + method : {"linear", "nearest", "zero", "slinear", "quadratic", "cubic", "polynomial", \ + "barycentric", "krog", "pchip", "spline", "akima"}, default: linear The method used to interpolate. The method should be supported by the scipy interpolator: - {"linear", "nearest", "zero", "slinear", "quadratic", "cubic", "polynomial"} when ``interp1d`` is called. - {"linear", "nearest"} when ``interpn`` is called. + - {"barycentric", "krog", "pchip", "spline", "akima"} when using + advanced interpolation classes. If ``"polynomial"`` is passed, the ``order`` keyword argument must also be provided. - assume_sorted : bool, optional + assume_sorted : bool, default: False If False, values of coordinates that are interpolated over can be in any order and they are sorted first. If True, interpolated coordinates are assumed to be an array of monotonically increasing @@ -3406,7 +3422,9 @@ def interp_like( ) # Helper methods for rename() - def _rename_vars(self, name_dict, dims_dict): + def _rename_vars( + self, name_dict, dims_dict + ) -> tuple[dict[Hashable, Variable], set[Hashable]]: variables = {} coord_names = set() for k, v in self.variables.items(): @@ -3420,10 +3438,12 @@ def _rename_vars(self, name_dict, dims_dict): coord_names.add(name) return variables, coord_names - def _rename_dims(self, name_dict): + def _rename_dims(self, name_dict: Mapping[Any, Hashable]) -> dict[Hashable, int]: return {name_dict.get(k, k): v for k, v in self.dims.items()} - def _rename_indexes(self, name_dict, dims_dict): + def _rename_indexes( + self, name_dict: Mapping[Any, Hashable], dims_dict: Mapping[Any, Hashable] + ) -> tuple[dict[Hashable, Index], dict[Hashable, Variable]]: if not self._indexes: return {}, {} @@ -3444,7 +3464,14 @@ def _rename_indexes(self, name_dict, dims_dict): return indexes, variables - def _rename_all(self, name_dict, dims_dict): + def _rename_all( + self, name_dict: Mapping[Any, Hashable], dims_dict: Mapping[Any, Hashable] + ) -> tuple[ + dict[Hashable, Variable], + set[Hashable], + dict[Hashable, int], + dict[Hashable, Index], + ]: variables, coord_names = self._rename_vars(name_dict, dims_dict) dims = self._rename_dims(dims_dict) @@ -3454,10 +3481,10 @@ def _rename_all(self, name_dict, dims_dict): return variables, coord_names, dims, indexes def rename( - self, - name_dict: Mapping[Any, Hashable] = None, + self: T_Dataset, + name_dict: Mapping[Any, Hashable] | None = None, **names: Hashable, - ) -> Dataset: + ) -> T_Dataset: """Returns a new object with renamed variables and dimensions. Parameters @@ -3495,8 +3522,10 @@ def rename( return self._replace(variables, coord_names, dims=dims, indexes=indexes) def rename_dims( - self, dims_dict: Mapping[Any, Hashable] = None, **dims: Hashable - ) -> Dataset: + self: T_Dataset, + dims_dict: Mapping[Any, Hashable] | None = None, + **dims: Hashable, + ) -> T_Dataset: """Returns a new object with renamed dimensions only. Parameters @@ -3540,8 +3569,8 @@ def rename_dims( return self._replace(variables, coord_names, dims=sizes, indexes=indexes) def rename_vars( - self, name_dict: Mapping[Any, Hashable] = None, **names: Hashable - ) -> Dataset: + self: T_Dataset, name_dict: Mapping[Any, Hashable] = None, **names: Hashable + ) -> T_Dataset: """Returns a new object with renamed variables including coordinates Parameters @@ -3578,8 +3607,8 @@ def rename_vars( return self._replace(variables, coord_names, dims=dims, indexes=indexes) def swap_dims( - self, dims_dict: Mapping[Any, Hashable] = None, **dims_kwargs - ) -> Dataset: + self: T_Dataset, dims_dict: Mapping[Any, Hashable] = None, **dims_kwargs + ) -> T_Dataset: """Returns a new object with swapped dimensions. Parameters @@ -3682,11 +3711,11 @@ def swap_dims( return self._replace_with_new_dims(variables, coord_names, indexes=indexes) def expand_dims( - self, + self: T_Dataset, dim: None | Hashable | Sequence[Hashable] | Mapping[Any, Any] = None, axis: None | int | Sequence[int] = None, **dim_kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """Return a new object with an additional axis (or axes) inserted at the corresponding position in the array shape. The new object is a view into the underlying array, not a copy. @@ -3817,11 +3846,11 @@ def expand_dims( ) def set_index( - self, - indexes: Mapping[Any, Hashable | Sequence[Hashable]] = None, + self: T_Dataset, + indexes: Mapping[Any, Hashable | Sequence[Hashable]] | None = None, append: bool = False, **indexes_kwargs: Hashable | Sequence[Hashable], - ) -> Dataset: + ) -> T_Dataset: """Set Dataset (multi-)indexes using one or more existing coordinates or variables. @@ -3831,7 +3860,7 @@ def set_index( Mapping from names matching dimensions and values given by (lists of) the names of existing coordinates or variables to set as new (multi-)index. - append : bool, optional + append : bool, default: False If True, append the supplied index(es) to the existing index(es). Otherwise replace the existing index(es) (default). **indexes_kwargs : optional diff --git a/xarray/core/utils.py b/xarray/core/utils.py index 121710d19aa..b253f1661ae 100644 --- a/xarray/core/utils.py +++ b/xarray/core/utils.py @@ -243,7 +243,7 @@ def remove_incompatible_items( # It's probably OK to give this as a TypeGuard; though it's not perfectly robust. -def is_dict_like(value: Any) -> TypeGuard[dict]: +def is_dict_like(value: Any) -> TypeGuard[Mapping]: return hasattr(value, "keys") and hasattr(value, "__getitem__") @@ -251,7 +251,7 @@ def is_full_slice(value: Any) -> bool: return isinstance(value, slice) and value == slice(None) -def is_list_like(value: Any) -> bool: +def is_list_like(value: Any) -> TypeGuard[list | tuple]: return isinstance(value, (list, tuple)) @@ -690,7 +690,7 @@ def is_uniform_spaced(arr, **kwargs) -> bool: return bool(np.isclose(diffs.min(), diffs.max(), **kwargs)) -def hashable(v: Any) -> bool: +def hashable(v: Any) -> TypeGuard[Hashable]: """Determine whether `v` can be hashed.""" try: hash(v) @@ -699,6 +699,24 @@ def hashable(v: Any) -> bool: return True +def iterable(v: Any) -> TypeGuard[Iterable[Any]]: + """Determine whether `v` is iterable.""" + try: + iter(v) + except TypeError: + return False + return True + + +def iterable_of_hashable(v: Any) -> TypeGuard[Iterable[Hashable]]: + """Determine whether `v` is an Iterable of Hashables.""" + try: + it = iter(v) + except TypeError: + return False + return all(hashable(elm) for elm in it) + + def decode_numpy_dict_values(attrs: Mapping[K, V]) -> dict[K, V]: """Convert attribute values from numpy objects to native Python objects, for use in to_dict From 2ff785c1cd92151e119548ec235133435ec01ddb Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Thu, 2 Jun 2022 22:50:30 +0200 Subject: [PATCH 03/21] even more typing in dataset --- xarray/core/coordinates.py | 52 +++---- xarray/core/dataarray.py | 2 +- xarray/core/dataset.py | 291 ++++++++++++++++++++---------------- xarray/core/variable.py | 2 +- xarray/tests/test_concat.py | 4 +- 5 files changed, 190 insertions(+), 161 deletions(-) diff --git a/xarray/core/coordinates.py b/xarray/core/coordinates.py index 458be214f81..fac1e64cd94 100644 --- a/xarray/core/coordinates.py +++ b/xarray/core/coordinates.py @@ -1,17 +1,7 @@ +from __future__ import annotations + from contextlib import contextmanager -from typing import ( - TYPE_CHECKING, - Any, - Dict, - Hashable, - Iterator, - Mapping, - Sequence, - Set, - Tuple, - Union, - cast, -) +from typing import TYPE_CHECKING, Any, Hashable, Iterator, Mapping, Sequence, cast import numpy as np import pandas as pd @@ -34,18 +24,18 @@ class Coordinates(Mapping[Any, "DataArray"]): __slots__ = () - def __getitem__(self, key: Hashable) -> "DataArray": + def __getitem__(self, key: Hashable) -> DataArray: raise NotImplementedError() def __setitem__(self, key: Hashable, value: Any) -> None: self.update({key: value}) @property - def _names(self) -> Set[Hashable]: + def _names(self) -> set[Hashable]: raise NotImplementedError() @property - def dims(self) -> Union[Mapping[Hashable, int], Tuple[Hashable, ...]]: + def dims(self) -> Mapping[Hashable, int] | tuple[Hashable, ...]: raise NotImplementedError() @property @@ -63,7 +53,7 @@ def variables(self): def _update_coords(self, coords, indexes): raise NotImplementedError() - def __iter__(self) -> Iterator["Hashable"]: + def __iter__(self) -> Iterator[Hashable]: # needs to be in the same order as the dataset variables for k in self.variables: if k in self._names: @@ -78,7 +68,7 @@ def __contains__(self, key: Hashable) -> bool: def __repr__(self) -> str: return formatting.coords_repr(self) - def to_dataset(self) -> "Dataset": + def to_dataset(self) -> Dataset: raise NotImplementedError() def to_index(self, ordered_dims: Sequence[Hashable] = None) -> pd.Index: @@ -194,7 +184,7 @@ def _merge_inplace(self, other): yield self._update_coords(variables, indexes) - def merge(self, other: "Coordinates") -> "Dataset": + def merge(self, other: Coordinates | None) -> Dataset: """Merge two sets of coordinates to create a new Dataset The method implements the logic used for joining coordinates in the @@ -241,11 +231,11 @@ class DatasetCoordinates(Coordinates): __slots__ = ("_data",) - def __init__(self, dataset: "Dataset"): + def __init__(self, dataset: Dataset): self._data = dataset @property - def _names(self) -> Set[Hashable]: + def _names(self) -> set[Hashable]: return self._data._coord_names @property @@ -258,19 +248,19 @@ def variables(self) -> Mapping[Hashable, Variable]: {k: v for k, v in self._data.variables.items() if k in self._names} ) - def __getitem__(self, key: Hashable) -> "DataArray": + def __getitem__(self, key: Hashable) -> DataArray: if key in self._data.data_vars: raise KeyError(key) return cast("DataArray", self._data[key]) - def to_dataset(self) -> "Dataset": + def to_dataset(self) -> Dataset: """Convert these coordinates into a new Dataset""" names = [name for name in self._data._variables if name in self._names] return self._data._copy_listed(names) def _update_coords( - self, coords: Dict[Hashable, Variable], indexes: Mapping[Any, Index] + self, coords: dict[Hashable, Variable], indexes: Mapping[Any, Index] ) -> None: variables = self._data._variables.copy() variables.update(coords) @@ -316,22 +306,22 @@ class DataArrayCoordinates(Coordinates): __slots__ = ("_data",) - def __init__(self, dataarray: "DataArray"): + def __init__(self, dataarray: DataArray): self._data = dataarray @property - def dims(self) -> Tuple[Hashable, ...]: + def dims(self) -> tuple[Hashable, ...]: return self._data.dims @property - def _names(self) -> Set[Hashable]: + def _names(self) -> set[Hashable]: return set(self._data._coords) - def __getitem__(self, key: Hashable) -> "DataArray": + def __getitem__(self, key: Hashable) -> DataArray: return self._data._getitem_coord(key) def _update_coords( - self, coords: Dict[Hashable, Variable], indexes: Mapping[Any, Index] + self, coords: dict[Hashable, Variable], indexes: Mapping[Any, Index] ) -> None: coords_plus_data = coords.copy() coords_plus_data[_THIS_ARRAY] = self._data.variable @@ -352,7 +342,7 @@ def _update_coords( def variables(self): return Frozen(self._data._coords) - def to_dataset(self) -> "Dataset": + def to_dataset(self) -> Dataset: from .dataset import Dataset coords = {k: v.copy(deep=False) for k, v in self._data._coords.items()} @@ -374,7 +364,7 @@ def _ipython_key_completions_(self): def assert_coordinate_consistent( - obj: Union["DataArray", "Dataset"], coords: Mapping[Any, Variable] + obj: DataArray | Dataset, coords: Mapping[Any, Variable] ) -> None: """Make sure the dimension coordinate of obj is consistent with coords. diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py index ee4516147de..bd50c4b5d5a 100644 --- a/xarray/core/dataarray.py +++ b/xarray/core/dataarray.py @@ -2668,7 +2668,7 @@ def interpolate_na( Parameters ---------- - dim : str + dim : Hashable or None, optional Specifies the dimension along which to interpolate. method : {"linear", "nearest", "zero", "slinear", "quadratic", "cubic", "polynomial", \ "barycentric", "krog", "pchip", "spline", "akima"}, default: "linear" diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index ed37aaf316d..c400aef868a 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -17,6 +17,7 @@ Any, Callable, Collection, + Generic, Hashable, Iterable, Iterator, @@ -77,6 +78,7 @@ from .npcompat import QUANTILE_METHODS, ArrayLike from .options import OPTIONS, _get_keep_attrs from .pycompat import is_duck_dask_array, sparse_array_type +from .types import T_Dataset from .utils import ( Default, Frozen, @@ -102,6 +104,7 @@ if TYPE_CHECKING: from ..backends import AbstractDataStore, ZarrStore from ..backends.api import T_NetcdfEngine, T_NetcdfTypes + from .coordinates import Coordinates from .dataarray import DataArray from .merge import CoercibleMapping from .types import ( @@ -116,7 +119,6 @@ QueryEngineOptions, QueryParserOptions, ReindexMethodOptions, - T_Dataset, T_Xarray, ) @@ -124,6 +126,10 @@ from dask.delayed import Delayed except ImportError: Delayed = None # type: ignore + try: + from dask.dataframe import DataFrame as DaskDataFrame + except ImportError: + DaskDataFrame = None # type: ignore # list of attributes of pd.DatetimeIndex that are ndarrays of time info @@ -386,13 +392,13 @@ def _ipython_key_completions_(self): ] -class _LocIndexer: +class _LocIndexer(Generic[T_Dataset]): __slots__ = ("dataset",) - def __init__(self, dataset: Dataset): + def __init__(self, dataset: T_Dataset): self.dataset = dataset - def __getitem__(self, key: Mapping[Any, Any]) -> Dataset: + def __getitem__(self, key: Mapping[Any, Any]) -> T_Dataset: if not utils.is_dict_like(key): raise TypeError("can only lookup dictionaries from Dataset.loc") return self.dataset.sel(key) @@ -1347,7 +1353,7 @@ def nbytes(self) -> int: return sum(v.nbytes for v in self.variables.values()) @property - def loc(self) -> _LocIndexer: + def loc(self: T_Dataset) -> _LocIndexer[T_Dataset]: """Attribute for location based indexing. Only supports __getitem__, and only when the key is a dict of the form {dim: labels}. """ @@ -3073,18 +3079,18 @@ def interp( If DataArrays are passed as new coordinates, their dimensions are used for the broadcasting. Missing values are skipped. method : {"linear", "nearest", "zero", "slinear", "quadratic", "cubic", "polynomial", \ - "barycentric", "krog", "pchip", "spline", "akima"}, default: linear - The method used to interpolate. The method should be supported by - the scipy interpolator: - - - {"linear", "nearest", "zero", "slinear", "quadratic", "cubic", - "polynomial"} when ``interp1d`` is called. - - {"linear", "nearest"} when ``interpn`` is called. - - {"barycentric", "krog", "pchip", "spline", "akima"} when using - advanced interpolation classes. - - If ``"polynomial"`` is passed, the ``order`` keyword argument must - also be provided. + "barycentric", "krog", "pchip", "spline", "akima"}, default: "linear" + String indicating which method to use for interpolation: + + - 'linear': linear interpolation. Additional keyword + arguments are passed to :py:func:`numpy.interp` + - 'nearest', 'zero', 'slinear', 'quadratic', 'cubic', 'polynomial': + are passed to :py:func:`scipy.interpolate.interp1d`. If + ``method='polynomial'``, the ``order`` keyword argument must also be + provided. + - 'barycentric', 'krog', 'pchip', 'spline', 'akima': use their + respective :py:class:`scipy.interpolate` classes. + assume_sorted : bool, default: False If False, values of coordinates that are interpolated over can be in any order and they are sorted first. If True, interpolated @@ -3349,18 +3355,18 @@ def interp_like( names to an 1d array-like, which provides coordinates upon which to index the variables in this dataset. Missing values are skipped. method : {"linear", "nearest", "zero", "slinear", "quadratic", "cubic", "polynomial", \ - "barycentric", "krog", "pchip", "spline", "akima"}, default: linear - The method used to interpolate. The method should be supported by - the scipy interpolator: - - - {"linear", "nearest", "zero", "slinear", "quadratic", "cubic", - "polynomial"} when ``interp1d`` is called. - - {"linear", "nearest"} when ``interpn`` is called. - - {"barycentric", "krog", "pchip", "spline", "akima"} when using - advanced interpolation classes. - - If ``"polynomial"`` is passed, the ``order`` keyword argument must - also be provided. + "barycentric", "krog", "pchip", "spline", "akima"}, default: "linear" + String indicating which method to use for interpolation: + + - 'linear': linear interpolation. Additional keyword + arguments are passed to :py:func:`numpy.interp` + - 'nearest', 'zero', 'slinear', 'quadratic', 'cubic', 'polynomial': + are passed to :py:func:`scipy.interpolate.interp1d`. If + ``method='polynomial'``, the ``order`` keyword argument must also be + provided. + - 'barycentric', 'krog', 'pchip', 'spline', 'akima': use their + respective :py:class:`scipy.interpolate` classes. + assume_sorted : bool, default: False If False, values of coordinates that are interpolated over can be in any order and they are sorted first. If True, interpolated @@ -3986,18 +3992,18 @@ def set_index( ) def reset_index( - self, + self: T_Dataset, dims_or_levels: Hashable | Sequence[Hashable], drop: bool = False, - ) -> Dataset: + ) -> T_Dataset: """Reset the specified index(es) or multi-index level(s). Parameters ---------- - dims_or_levels : str or list + dims_or_levels : Hashable or Sequence of Hashable Name(s) of the dimension(s) and/or multi-index level(s) that will be reset. - drop : bool, optional + drop : bool, default: False If True, remove the specified indexes and/or multi-index levels instead of extracting them as new coordinates (default: False). @@ -4062,10 +4068,10 @@ def reset_index( return self._replace(variables, coord_names=coord_names, indexes=indexes) def reorder_levels( - self, - dim_order: Mapping[Any, Sequence[int | Hashable]] = None, + self: T_Dataset, + dim_order: Mapping[Any, Sequence[int | Hashable]] | None = None, **dim_order_kwargs: Sequence[int | Hashable], - ) -> Dataset: + ) -> T_Dataset: """Rearrange index levels using input order. Parameters @@ -4165,7 +4171,13 @@ def _get_stack_index( return stack_index, stack_coords - def _stack_once(self, dims, new_dim, index_cls, create_index=True): + def _stack_once( + self: T_Dataset, + dims: Sequence[Hashable], + new_dim: Hashable, + index_cls: type[Index], + create_index: bool | None = True, + ) -> T_Dataset: if dims == ...: raise ValueError("Please use [...] for dims, rather than just ...") if ... in dims: @@ -4219,12 +4231,12 @@ def _stack_once(self, dims, new_dim, index_cls, create_index=True): ) def stack( - self, - dimensions: Mapping[Any, Sequence[Hashable]] = None, + self: T_Dataset, + dimensions: Mapping[Any, Sequence[Hashable]] | None = None, create_index: bool | None = True, index_cls: type[Index] = PandasMultiIndex, **dimensions_kwargs: Sequence[Hashable], - ) -> Dataset: + ) -> T_Dataset: """ Stack any number of existing dimensions into a single new dimension. @@ -4240,11 +4252,13 @@ def stack( Passing a list containing an ellipsis (`stacked_dim=[...]`) will stack over all dimensions. create_index : bool or None, default: True - If True, create a multi-index for each of the stacked dimensions. - If False, don't create any index. - If None, create a multi-index only if exactly one single (1-d) coordinate - index is found for every dimension to stack. - index_cls: class, optional + + - True: create a multi-index for each of the stacked dimensions. + - False: don't create any index. + - None. create a multi-index only if exactly one single (1-d) coordinate + index is found for every dimension to stack. + + index_cls: Index-class, default: PandasMultiIndex Can be used to pass a custom multi-index type (must be an Xarray index that implements `.stack()`). By default, a pandas multi-index wrapper is used. **dimensions_kwargs @@ -4269,9 +4283,9 @@ def stack( def to_stacked_array( self, new_dim: Hashable, - sample_dims: Collection, + sample_dims: Collection[Hashable], variable_dim: Hashable = "variable", - name: Hashable = None, + name: Hashable | None = None, ) -> DataArray: """Combine variables of differing dimensionality into a DataArray without broadcasting. @@ -4288,7 +4302,7 @@ def to_stacked_array( dataset must share these dimensions. For machine learning applications, these define the dimensions over which samples are drawn. - variable_dim : hashable, optional + variable_dim : hashable, default: "variable" Name of the level in the stacked coordinate which corresponds to the variables. name : hashable, optional @@ -4380,12 +4394,12 @@ def ensure_stackable(val): return data_array def _unstack_once( - self, + self: T_Dataset, dim: Hashable, index_and_vars: tuple[Index, dict[Hashable, Variable]], fill_value, sparse: bool = False, - ) -> Dataset: + ) -> T_Dataset: index, index_vars = index_and_vars variables: dict[Hashable, Variable] = {} indexes = {k: v for k, v in self._indexes.items() if k != dim} @@ -4420,12 +4434,12 @@ def _unstack_once( ) def _unstack_full_reindex( - self, + self: T_Dataset, dim: Hashable, index_and_vars: tuple[Index, dict[Hashable, Variable]], fill_value, sparse: bool, - ) -> Dataset: + ) -> T_Dataset: index, index_vars = index_and_vars variables: dict[Hashable, Variable] = {} indexes = {k: v for k, v in self._indexes.items() if k != dim} @@ -4471,11 +4485,11 @@ def _unstack_full_reindex( ) def unstack( - self, - dim: Hashable | Iterable[Hashable] = None, + self: T_Dataset, + dim: Hashable | Iterable[Hashable] | None = None, fill_value: Any = dtypes.NA, sparse: bool = False, - ) -> Dataset: + ) -> T_Dataset: """ Unstack existing dimensions corresponding to MultiIndexes into multiple new dimensions. @@ -4573,7 +4587,7 @@ def unstack( ) return result - def update(self, other: CoercibleMapping) -> Dataset: + def update(self: T_Dataset, other: CoercibleMapping) -> T_Dataset: """Update this dataset's variables with those from another dataset. Just like :py:meth:`dict.update` this is a in-place operation. @@ -4613,14 +4627,14 @@ def update(self, other: CoercibleMapping) -> Dataset: return self._replace(inplace=True, **merge_result._asdict()) def merge( - self, + self: T_Dataset, other: CoercibleMapping | DataArray, overwrite_vars: Hashable | Iterable[Hashable] = frozenset(), compat: CompatOptions = "no_conflicts", join: JoinOptions = "outer", fill_value: Any = dtypes.NA, combine_attrs: CombineAttrsOptions = "override", - ) -> Dataset: + ) -> T_Dataset: """Merge the arrays of two datasets into a single dataset. This method generally does not allow for overriding data, with the @@ -4719,8 +4733,11 @@ def _assert_all_in_dataset( ) def drop_vars( - self, names: Hashable | Iterable[Hashable], *, errors: ErrorOptions = "raise" - ) -> Dataset: + self: T_Dataset, + names: Hashable | Iterable[Hashable], + *, + errors: ErrorOptions = "raise", + ) -> T_Dataset: """Drop variables from this dataset. Parameters @@ -4772,8 +4789,13 @@ def drop_vars( ) def drop( - self, labels=None, dim=None, *, errors: ErrorOptions = "raise", **labels_kwargs - ): + self: T_Dataset, + labels=None, + dim=None, + *, + errors: ErrorOptions = "raise", + **labels_kwargs, + ) -> T_Dataset: """Backward compatible method based on `drop_vars` and `drop_sel` Using either `drop_vars` or `drop_sel` is encouraged @@ -4822,7 +4844,9 @@ def drop( ) return self.drop_sel(labels, errors=errors) - def drop_sel(self, labels=None, *, errors: ErrorOptions = "raise", **labels_kwargs): + def drop_sel( + self: T_Dataset, labels=None, *, errors: ErrorOptions = "raise", **labels_kwargs + ) -> T_Dataset: """Drop index labels from this dataset. Parameters @@ -4891,7 +4915,7 @@ def drop_sel(self, labels=None, *, errors: ErrorOptions = "raise", **labels_kwar ds = ds.loc[{dim: new_index}] return ds - def drop_isel(self, indexers=None, **indexers_kwargs): + def drop_isel(self: T_Dataset, indexers=None, **indexers_kwargs) -> T_Dataset: """Drop index positions from this Dataset. Parameters @@ -4957,11 +4981,11 @@ def drop_isel(self, indexers=None, **indexers_kwargs): return ds def drop_dims( - self, + self: T_Dataset, drop_dims: Hashable | Iterable[Hashable], *, errors: ErrorOptions = "raise", - ) -> Dataset: + ) -> T_Dataset: """Drop dimensions and associated variables from this dataset. Parameters @@ -4998,10 +5022,10 @@ def drop_dims( return self.drop_vars(drop_vars) def transpose( - self, + self: T_Dataset, *dims: Hashable, missing_dims: ErrorOptionsWithWarn = "raise", - ) -> Dataset: + ) -> T_Dataset: """Return a new Dataset object with all array dimensions transposed. Although the order of dimensions on each array will change, the dataset @@ -5047,12 +5071,12 @@ def transpose( return ds def dropna( - self, + self: T_Dataset, dim: Hashable, - how: str = "any", - thresh: int = None, - subset: Iterable[Hashable] = None, - ): + how: Literal["any", "all"] = "any", + thresh: int | None = None, + subset: Iterable[Hashable] | None = None, + ) -> T_Dataset: """Returns a new dataset with dropped labels for missing values along the provided dimension. @@ -5062,11 +5086,12 @@ def dropna( Dimension along which to drop missing values. Dropping along multiple dimensions simultaneously is not yet supported. how : {"any", "all"}, default: "any" - * any : if any NA values are present, drop that label - * all : if all values are NA, drop that label - thresh : int, default: None + - any : if any NA values are present, drop that label + - all : if all values are NA, drop that label + + thresh : int or None, optional If supplied, require this many non-NA values. - subset : iterable of hashable, optional + subset : iterable of hashable or None, optional Which variables to check for missing values. By default, all variables in the dataset are checked. @@ -5107,7 +5132,7 @@ def dropna( return self.isel({dim: mask}) - def fillna(self, value: Any) -> Dataset: + def fillna(self: T_Dataset, value: Any) -> T_Dataset: """Fill missing values in this object. This operation follows the normal broadcasting and alignment rules that @@ -5188,26 +5213,27 @@ def fillna(self, value: Any) -> Dataset: return out def interpolate_na( - self, - dim: Hashable = None, - method: str = "linear", + self: T_Dataset, + dim: Hashable | None = None, + method: InterpOptions = "linear", limit: int = None, use_coordinate: bool | Hashable = True, max_gap: ( int | float | str | pd.Timedelta | np.timedelta64 | datetime.timedelta ) = None, **kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """Fill in NaNs by interpolating according to different methods. Parameters ---------- - dim : str + dim : Hashable or None, optional Specifies the dimension along which to interpolate. - method : str, optional + method : {"linear", "nearest", "zero", "slinear", "quadratic", "cubic", "polynomial", \ + "barycentric", "krog", "pchip", "spline", "akima"}, default: "linear" String indicating which method to use for interpolation: - - 'linear': linear interpolation (Default). Additional keyword + - 'linear': linear interpolation. Additional keyword arguments are passed to :py:func:`numpy.interp` - 'nearest', 'zero', 'slinear', 'quadratic', 'cubic', 'polynomial': are passed to :py:func:`scipy.interpolate.interp1d`. If @@ -5216,7 +5242,7 @@ def interpolate_na( - 'barycentric', 'krog', 'pchip', 'spline', 'akima': use their respective :py:class:`scipy.interpolate` classes. - use_coordinate : bool, str, default: True + use_coordinate : bool or Hashable, default: True Specifies which index to use as the x values in the interpolation formulated as `y = f(x)`. If False, values are treated as if eqaully-spaced along ``dim``. If True, the IndexVariable `dim` is @@ -5321,7 +5347,7 @@ def interpolate_na( ) return new - def ffill(self, dim: Hashable, limit: int = None) -> Dataset: + def ffill(self: T_Dataset, dim: Hashable, limit: int | None = None) -> T_Dataset: """Fill NaN values by propagating values forward *Requires bottleneck.* @@ -5331,7 +5357,7 @@ def ffill(self, dim: Hashable, limit: int = None) -> Dataset: dim : Hashable Specifies the dimension along which to propagate values when filling. - limit : int, default: None + limit : int or None, optional The maximum number of consecutive NaN values to forward fill. In other words, if there is a gap with more than this number of consecutive NaNs, it will only be partially filled. Must be greater @@ -5347,17 +5373,17 @@ def ffill(self, dim: Hashable, limit: int = None) -> Dataset: new = _apply_over_vars_with_dim(ffill, self, dim=dim, limit=limit) return new - def bfill(self, dim: Hashable, limit: int = None) -> Dataset: + def bfill(self: T_Dataset, dim: Hashable, limit: int | None = None) -> T_Dataset: """Fill NaN values by propagating values backward *Requires bottleneck.* Parameters ---------- - dim : str + dim : Hashable Specifies the dimension along which to propagate values when filling. - limit : int, default: None + limit : int or None, optional The maximum number of consecutive NaN values to backward fill. In other words, if there is a gap with more than this number of consecutive NaNs, it will only be partially filled. Must be greater @@ -5373,7 +5399,7 @@ def bfill(self, dim: Hashable, limit: int = None) -> Dataset: new = _apply_over_vars_with_dim(bfill, self, dim=dim, limit=limit) return new - def combine_first(self, other: Dataset) -> Dataset: + def combine_first(self: T_Dataset, other: T_Dataset) -> T_Dataset: """Combine two Datasets, default to data_vars of self. The new coordinates follow the normal broadcasting and alignment rules @@ -5393,15 +5419,15 @@ def combine_first(self, other: Dataset) -> Dataset: return out def reduce( - self, + self: T_Dataset, func: Callable, dim: Hashable | Iterable[Hashable] = None, *, - keep_attrs: bool = None, + keep_attrs: bool | None = None, keepdims: bool = False, numeric_only: bool = False, **kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """Reduce this dataset by applying `func` along some dimension(s). Parameters @@ -5413,7 +5439,7 @@ def reduce( dim : str or sequence of str, optional Dimension(s) over which to apply `func`. By default `func` is applied over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, the dataset's attributes (`attrs`) will be copied from the original object to the new one. If False (default), the new object will be returned without attributes. @@ -5421,7 +5447,7 @@ def reduce( If True, the dimensions which are reduced are left in the result as dimensions of size one. Coordinates that use these dimensions are removed. - numeric_only : bool, optional + numeric_only : bool, default: False If True, only apply ``func`` to variables with a numeric dtype. **kwargs : Any Additional keyword arguments passed on to ``func``. @@ -5494,12 +5520,12 @@ def reduce( ) def map( - self, + self: T_Dataset, func: Callable, - keep_attrs: bool = None, + keep_attrs: bool | None = None, args: Iterable[Any] = (), **kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """Apply a function to each data variable in this dataset Parameters @@ -5508,11 +5534,11 @@ def map( Function which can be called in the form `func(x, *args, **kwargs)` to transform each DataArray `x` in this dataset into another DataArray. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, both the dataset's and variables' attributes (`attrs`) will be copied from the original objects to the new ones. If False, the new dataset and variables will be returned without copying the attributes. - args : tuple, optional + args : iterable, optional Positional arguments passed on to `func`. **kwargs : Any Keyword arguments passed on to `func`. @@ -5554,12 +5580,12 @@ def map( return type(self)(variables, attrs=attrs) def apply( - self, + self: T_Dataset, func: Callable, - keep_attrs: bool = None, + keep_attrs: bool | None = None, args: Iterable[Any] = (), **kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """ Backward compatible implementation of ``map`` @@ -5575,8 +5601,10 @@ def apply( return self.map(func, keep_attrs, args, **kwargs) def assign( - self, variables: Mapping[Any, Any] = None, **variables_kwargs: Hashable - ) -> Dataset: + self: T_Dataset, + variables: Mapping[Any, Any] | None = None, + **variables_kwargs: Hashable, + ) -> T_Dataset: """Assign new data variables to a Dataset, returning a new object with all the original variables in addition to the new ones. @@ -5661,12 +5689,14 @@ def assign( variables = either_dict_or_kwargs(variables, variables_kwargs, "assign") data = self.copy() # do all calculations first... - results = data._calc_assign_results(variables) + results: CoercibleMapping = data._calc_assign_results(variables) # ... and then assign data.update(results) return data - def to_array(self, dim="variable", name=None): + def to_array( + self, dim: Hashable = "variable", name: Hashable | None = None + ) -> DataArray: """Convert this dataset into an xarray.DataArray The data variables of this dataset will be broadcast against each other @@ -5715,7 +5745,7 @@ def _normalize_dim_order( Returns ------- - result + result : dict[Hashable, int] Validated dimensions mapping. """ @@ -5761,7 +5791,7 @@ def _to_dataframe(self, ordered_dims: Mapping[Any, int]): index = self.coords.to_index([*ordered_dims]) return pd.DataFrame(dict(zip(columns, data)), index=index) - def to_dataframe(self, dim_order: list[Hashable] = None) -> pd.DataFrame: + def to_dataframe(self, dim_order: Sequence[Hashable] | None = None) -> pd.DataFrame: """Convert this dataset into a pandas.DataFrame. Non-index variables in this dataset form the columns of the @@ -5770,7 +5800,7 @@ def to_dataframe(self, dim_order: list[Hashable] = None) -> pd.DataFrame: Parameters ---------- - dim_order + dim_order: Sequence of Hashable or None, optional Hierarchical dimension order for the resulting dataframe. All arrays are transposed to this order and then written out as flat vectors in contiguous order, so the last dimension in this list @@ -5862,7 +5892,9 @@ def _set_numpy_data_from_dataframe( self[name] = (dims, data) @classmethod - def from_dataframe(cls, dataframe: pd.DataFrame, sparse: bool = False) -> Dataset: + def from_dataframe( + cls: type[T_Dataset], dataframe: pd.DataFrame, sparse: bool = False + ) -> T_Dataset: """Convert a pandas.DataFrame into an xarray.Dataset Each column will be converted into an independent variable in the @@ -5938,7 +5970,9 @@ def from_dataframe(cls, dataframe: pd.DataFrame, sparse: bool = False) -> Datase obj._set_numpy_data_from_dataframe(idx, arrays, dims) return obj - def to_dask_dataframe(self, dim_order=None, set_index=False): + def to_dask_dataframe( + self, dim_order: Sequence[Hashable] | None = None, set_index: bool = False + ) -> DaskDataFrame: """ Convert this dataset into a dask.dataframe.DataFrame. @@ -5957,7 +5991,7 @@ def to_dask_dataframe(self, dim_order=None, set_index=False): If provided, must include all dimensions of this dataset. By default, dimensions are sorted alphabetically. - set_index : bool, optional + set_index : bool, default: False If set_index=True, the dask DataFrame is indexed by this dataset's coordinate. Since dask DataFrames do not support multi-indexes, set_index only works if the dataset only contains one dimension. @@ -6009,7 +6043,7 @@ def to_dask_dataframe(self, dim_order=None, set_index=False): return df - def to_dict(self, data: bool = True, encoding: bool = False) -> dict: + def to_dict(self, data: bool = True, encoding: bool = False) -> dict[str, Any]: """ Convert this dataset to a dictionary following xarray naming conventions. @@ -6020,15 +6054,17 @@ def to_dict(self, data: bool = True, encoding: bool = False) -> dict: Parameters ---------- - data : bool, optional + data : bool, default: True Whether to include the actual data in the dictionary. When set to False, returns just the schema. - encoding : bool, optional + encoding : bool, default: False Whether to include the Dataset's encoding in the dictionary. Returns ------- d : dict + Dict with keys: "coords", "attrs", "dims", "data_vars" and optionally + "encoding". See Also -------- @@ -6054,7 +6090,7 @@ def to_dict(self, data: bool = True, encoding: bool = False) -> dict: return d @classmethod - def from_dict(cls, d): + def from_dict(cls: type[T_Dataset], d: Mapping[Hashable, Any]) -> T_Dataset: """Convert a dictionary into an xarray.Dataset. Parameters @@ -6066,7 +6102,7 @@ def from_dict(cls, d): Returns ------- - obj : xarray.Dataset + obj : Dataset See also -------- @@ -6115,6 +6151,7 @@ def from_dict(cls, d): """ + variables: Iterable[tuple[Hashable, Any]] if not {"coords", "data_vars"}.issubset(set(d)): variables = d.items() else: @@ -6143,7 +6180,7 @@ def from_dict(cls, d): return obj - def _unary_op(self, f, *args, **kwargs): + def _unary_op(self: T_Dataset, f, *args, **kwargs) -> T_Dataset: variables = {} keep_attrs = kwargs.pop("keep_attrs", None) if keep_attrs is None: @@ -6158,19 +6195,19 @@ def _unary_op(self, f, *args, **kwargs): attrs = self._attrs if keep_attrs else None return self._replace_with_new_dims(variables, attrs=attrs) - def _binary_op(self, other, f, reflexive=False, join=None): + def _binary_op(self, other, f, reflexive=False, join=None) -> Dataset: from .dataarray import DataArray if isinstance(other, groupby.GroupBy): return NotImplemented align_type = OPTIONS["arithmetic_join"] if join is None else join if isinstance(other, (DataArray, Dataset)): - self, other = align(self, other, join=align_type, copy=False) + self, other = align(self, other, join=align_type, copy=False) # type: ignore[assignment] g = f if not reflexive else lambda x, y: f(y, x) ds = self._calculate_binary_op(g, other, join=align_type) return ds - def _inplace_binary_op(self, other, f): + def _inplace_binary_op(self: T_Dataset, other, f) -> T_Dataset: from .dataarray import DataArray if isinstance(other, groupby.GroupBy): @@ -6193,7 +6230,9 @@ def _inplace_binary_op(self, other, f): ) return self - def _calculate_binary_op(self, f, other, join="inner", inplace=False): + def _calculate_binary_op( + self, f, other, join="inner", inplace: bool = False + ) -> Dataset: def apply_over_both(lhs_data_vars, rhs_data_vars, lhs_vars, rhs_vars): if inplace and set(lhs_data_vars) != set(rhs_data_vars): raise ValueError( @@ -6221,7 +6260,7 @@ def apply_over_both(lhs_data_vars, rhs_data_vars, lhs_vars, rhs_vars): ) return Dataset(new_data_vars) - other_coords = getattr(other, "coords", None) + other_coords: Coordinates | None = getattr(other, "coords", None) ds = self.coords.merge(other_coords) if isinstance(other, Dataset): diff --git a/xarray/core/variable.py b/xarray/core/variable.py index 798e5a9f43e..2d115ff0ed9 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -2950,7 +2950,7 @@ def _broadcast_compat_variables(*variables): return tuple(var.set_dims(dims) if var.dims != dims else var for var in variables) -def broadcast_variables(*variables): +def broadcast_variables(*variables: Variable) -> tuple[Variable, ...]: """Given any number of variables, return variables with matching dimensions and broadcast data. diff --git a/xarray/tests/test_concat.py b/xarray/tests/test_concat.py index 28973e20cd0..e590eda8162 100644 --- a/xarray/tests/test_concat.py +++ b/xarray/tests/test_concat.py @@ -816,12 +816,12 @@ def test_concat_typing_check() -> None: TypeError, match="The elements in the input list need to be either all 'Dataset's or all 'DataArray's", ): - concat([ds, da], dim="foo") + concat([ds, da], dim="foo") # type: ignore with pytest.raises( TypeError, match="The elements in the input list need to be either all 'Dataset's or all 'DataArray's", ): - concat([da, ds], dim="foo") + concat([da, ds], dim="foo") # type: ignore def test_concat_not_all_indexes() -> None: From d2e38716d41d44704d1731a4bb586d6762da3065 Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 10:10:40 +0200 Subject: [PATCH 04/21] removed unused import Union --- xarray/core/_typed_ops.pyi | 2 +- xarray/util/generate_ops.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xarray/core/_typed_ops.pyi b/xarray/core/_typed_ops.pyi index e5b3c9112c7..037a5477879 100644 --- a/xarray/core/_typed_ops.pyi +++ b/xarray/core/_typed_ops.pyi @@ -1,7 +1,7 @@ """Stub file for mixin classes with arithmetic operators.""" # This file was generated using xarray.util.generate_ops. Do not edit manually. -from typing import NoReturn, TypeVar, Union, overload +from typing import NoReturn, TypeVar, overload import numpy as np diff --git a/xarray/util/generate_ops.py b/xarray/util/generate_ops.py index 0a382642708..f90346edad3 100644 --- a/xarray/util/generate_ops.py +++ b/xarray/util/generate_ops.py @@ -190,7 +190,7 @@ def inplace(): """Stub file for mixin classes with arithmetic operators.""" # This file was generated using xarray.util.generate_ops. Do not edit manually. -from typing import NoReturn, TypeVar, Union, overload +from typing import NoReturn, TypeVar, overload import numpy as np From 7cdc95a0a5a3b91355221c6a0b13fa3b3e1cf239 Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 10:17:16 +0200 Subject: [PATCH 05/21] update typing of _reductions --- xarray/core/_reductions.py | 1162 ++-------------------------- xarray/util/generate_reductions.py | 22 +- 2 files changed, 97 insertions(+), 1087 deletions(-) diff --git a/xarray/core/_reductions.py b/xarray/core/_reductions.py index d782363760a..76cc4ad7b4a 100644 --- a/xarray/core/_reductions.py +++ b/xarray/core/_reductions.py @@ -1,7 +1,9 @@ """Mixin classes with reduction operations.""" # This file was generated using xarray.util.generate_reductions. Do not edit manually. -from typing import TYPE_CHECKING, Any, Callable, Hashable, Optional, Sequence, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Callable, Hashable, Optional, Sequence from . import duck_array_ops from .options import OPTIONS @@ -23,9 +25,9 @@ class DatasetReductions: def reduce( self, func: Callable[..., Any], - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, - axis: Union[None, int, Sequence[int]] = None, + axis: None | int | Sequence[int] = None, keep_attrs: bool = None, keepdims: bool = False, **kwargs: Any, @@ -34,7 +36,7 @@ def reduce( def count( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -82,19 +84,8 @@ def count( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.count() - - Dimensions: () - Data variables: - da int64 5 """ return self.reduce( duck_array_ops.count, @@ -106,7 +97,7 @@ def count( def all( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -154,19 +145,8 @@ def all( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.all() - - Dimensions: () - Data variables: - da bool False """ return self.reduce( duck_array_ops.array_all, @@ -178,7 +158,7 @@ def all( def any( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -226,19 +206,8 @@ def any( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.any() - - Dimensions: () - Data variables: - da bool True """ return self.reduce( duck_array_ops.array_any, @@ -250,7 +219,7 @@ def any( def max( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -304,27 +273,12 @@ def max( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.max() - - Dimensions: () - Data variables: - da float64 3.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.max(skipna=False) - - Dimensions: () - Data variables: - da float64 nan """ return self.reduce( duck_array_ops.max, @@ -337,7 +291,7 @@ def max( def min( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -391,27 +345,12 @@ def min( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.min() - - Dimensions: () - Data variables: - da float64 1.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.min(skipna=False) - - Dimensions: () - Data variables: - da float64 nan """ return self.reduce( duck_array_ops.min, @@ -424,7 +363,7 @@ def min( def mean( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -482,27 +421,12 @@ def mean( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.mean() - - Dimensions: () - Data variables: - da float64 1.8 Use ``skipna`` to control whether NaNs are ignored. >>> ds.mean(skipna=False) - - Dimensions: () - Data variables: - da float64 nan """ return self.reduce( duck_array_ops.mean, @@ -515,7 +439,7 @@ def mean( def prod( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, min_count: Optional[int] = None, @@ -580,35 +504,16 @@ def prod( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.prod() - - Dimensions: () - Data variables: - da float64 12.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.prod(skipna=False) - - Dimensions: () - Data variables: - da float64 nan Specify ``min_count`` for finer control over when NaNs are ignored. >>> ds.prod(skipna=True, min_count=2) - - Dimensions: () - Data variables: - da float64 12.0 """ return self.reduce( duck_array_ops.prod, @@ -622,7 +527,7 @@ def prod( def sum( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, min_count: Optional[int] = None, @@ -687,35 +592,16 @@ def sum( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.sum() - - Dimensions: () - Data variables: - da float64 9.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.sum(skipna=False) - - Dimensions: () - Data variables: - da float64 nan Specify ``min_count`` for finer control over when NaNs are ignored. >>> ds.sum(skipna=True, min_count=2) - - Dimensions: () - Data variables: - da float64 9.0 """ return self.reduce( duck_array_ops.sum, @@ -729,7 +615,7 @@ def sum( def std( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, ddof: int = 0, @@ -791,35 +677,16 @@ def std( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.std() - - Dimensions: () - Data variables: - da float64 0.7483 Use ``skipna`` to control whether NaNs are ignored. >>> ds.std(skipna=False) - - Dimensions: () - Data variables: - da float64 nan Specify ``ddof=1`` for an unbiased estimate. >>> ds.std(skipna=True, ddof=1) - - Dimensions: () - Data variables: - da float64 0.8367 """ return self.reduce( duck_array_ops.std, @@ -833,7 +700,7 @@ def std( def var( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, ddof: int = 0, @@ -895,35 +762,16 @@ def var( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.var() - - Dimensions: () - Data variables: - da float64 0.56 Use ``skipna`` to control whether NaNs are ignored. >>> ds.var(skipna=False) - - Dimensions: () - Data variables: - da float64 nan Specify ``ddof=1`` for an unbiased estimate. >>> ds.var(skipna=True, ddof=1) - - Dimensions: () - Data variables: - da float64 0.7 """ return self.reduce( duck_array_ops.var, @@ -937,7 +785,7 @@ def var( def median( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -995,27 +843,12 @@ def median( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.median() - - Dimensions: () - Data variables: - da float64 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.median(skipna=False) - - Dimensions: () - Data variables: - da float64 nan """ return self.reduce( duck_array_ops.median, @@ -1033,9 +866,9 @@ class DataArrayReductions: def reduce( self, func: Callable[..., Any], - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, - axis: Union[None, int, Sequence[int]] = None, + axis: None | int | Sequence[int] = None, keep_attrs: bool = None, keepdims: bool = False, **kwargs: Any, @@ -1044,7 +877,7 @@ def reduce( def count( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -1091,15 +924,8 @@ def count( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.count() - - array(5) """ return self.reduce( duck_array_ops.count, @@ -1110,7 +936,7 @@ def count( def all( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -1157,15 +983,8 @@ def all( ... ), ... ) >>> da - - array([ True, True, True, True, True, False]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.all() - - array(False) """ return self.reduce( duck_array_ops.array_all, @@ -1176,7 +995,7 @@ def all( def any( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -1223,15 +1042,8 @@ def any( ... ), ... ) >>> da - - array([ True, True, True, True, True, False]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.any() - - array(True) """ return self.reduce( duck_array_ops.array_any, @@ -1242,7 +1054,7 @@ def any( def max( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -1295,21 +1107,12 @@ def max( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.max() - - array(3.) Use ``skipna`` to control whether NaNs are ignored. >>> da.max(skipna=False) - - array(nan) """ return self.reduce( duck_array_ops.max, @@ -1321,7 +1124,7 @@ def max( def min( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -1374,21 +1177,12 @@ def min( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.min() - - array(1.) Use ``skipna`` to control whether NaNs are ignored. >>> da.min(skipna=False) - - array(nan) """ return self.reduce( duck_array_ops.min, @@ -1400,7 +1194,7 @@ def min( def mean( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -1457,21 +1251,12 @@ def mean( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.mean() - - array(1.8) Use ``skipna`` to control whether NaNs are ignored. >>> da.mean(skipna=False) - - array(nan) """ return self.reduce( duck_array_ops.mean, @@ -1483,7 +1268,7 @@ def mean( def prod( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, min_count: Optional[int] = None, @@ -1547,27 +1332,16 @@ def prod( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.prod() - - array(12.) Use ``skipna`` to control whether NaNs are ignored. >>> da.prod(skipna=False) - - array(nan) Specify ``min_count`` for finer control over when NaNs are ignored. >>> da.prod(skipna=True, min_count=2) - - array(12.) """ return self.reduce( duck_array_ops.prod, @@ -1580,7 +1354,7 @@ def prod( def sum( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, min_count: Optional[int] = None, @@ -1644,27 +1418,16 @@ def sum( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.sum() - - array(9.) Use ``skipna`` to control whether NaNs are ignored. >>> da.sum(skipna=False) - - array(nan) Specify ``min_count`` for finer control over when NaNs are ignored. >>> da.sum(skipna=True, min_count=2) - - array(9.) """ return self.reduce( duck_array_ops.sum, @@ -1677,7 +1440,7 @@ def sum( def std( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, ddof: int = 0, @@ -1738,27 +1501,16 @@ def std( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.std() - - array(0.74833148) Use ``skipna`` to control whether NaNs are ignored. >>> da.std(skipna=False) - - array(nan) Specify ``ddof=1`` for an unbiased estimate. >>> da.std(skipna=True, ddof=1) - - array(0.83666003) """ return self.reduce( duck_array_ops.std, @@ -1771,7 +1523,7 @@ def std( def var( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, ddof: int = 0, @@ -1832,27 +1584,16 @@ def var( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.var() - - array(0.56) Use ``skipna`` to control whether NaNs are ignored. >>> da.var(skipna=False) - - array(nan) Specify ``ddof=1`` for an unbiased estimate. >>> da.var(skipna=True, ddof=1) - - array(0.7) """ return self.reduce( duck_array_ops.var, @@ -1865,7 +1606,7 @@ def var( def median( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -1922,21 +1663,12 @@ def median( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.median() - - array(2.) Use ``skipna`` to control whether NaNs are ignored. >>> da.median(skipna=False) - - array(nan) """ return self.reduce( duck_array_ops.median, @@ -1953,9 +1685,9 @@ class DatasetGroupByReductions: def reduce( self, func: Callable[..., Any], - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, - axis: Union[None, int, Sequence[int]] = None, + axis: None | int | Sequence[int] = None, keep_attrs: bool = None, keepdims: bool = False, **kwargs: Any, @@ -1964,14 +1696,14 @@ def reduce( def _flox_reduce( self, - dim: Union[None, Hashable, Sequence[Hashable]], + dim: None | Hashable | Sequence[Hashable], **kwargs, ) -> "Dataset": raise NotImplementedError() def count( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -2019,21 +1751,8 @@ def count( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.groupby("labels").count() - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) int64 1 2 2 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2055,7 +1774,7 @@ def count( def all( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -2103,21 +1822,8 @@ def all( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.groupby("labels").all() - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) bool False True True """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2139,7 +1845,7 @@ def all( def any( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -2187,21 +1893,8 @@ def any( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.groupby("labels").any() - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) bool True True True """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2223,7 +1916,7 @@ def any( def max( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -2277,31 +1970,12 @@ def max( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.groupby("labels").max() - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 1.0 2.0 3.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").max(skipna=False) - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 nan 2.0 3.0 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2325,7 +1999,7 @@ def max( def min( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -2379,31 +2053,12 @@ def min( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.groupby("labels").min() - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 1.0 2.0 1.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").min(skipna=False) - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 nan 2.0 1.0 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2427,7 +2082,7 @@ def min( def mean( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -2485,31 +2140,12 @@ def mean( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.groupby("labels").mean() - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 1.0 2.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").mean(skipna=False) - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 nan 2.0 2.0 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2533,7 +2169,7 @@ def mean( def prod( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, min_count: Optional[int] = None, @@ -2598,41 +2234,16 @@ def prod( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.groupby("labels").prod() - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 1.0 4.0 3.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").prod(skipna=False) - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 nan 4.0 3.0 Specify ``min_count`` for finer control over when NaNs are ignored. >>> ds.groupby("labels").prod(skipna=True, min_count=2) - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 nan 4.0 3.0 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2658,7 +2269,7 @@ def prod( def sum( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, min_count: Optional[int] = None, @@ -2723,41 +2334,16 @@ def sum( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.groupby("labels").sum() - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 1.0 4.0 4.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").sum(skipna=False) - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 nan 4.0 4.0 Specify ``min_count`` for finer control over when NaNs are ignored. >>> ds.groupby("labels").sum(skipna=True, min_count=2) - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 nan 4.0 4.0 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2783,7 +2369,7 @@ def sum( def std( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, ddof: int = 0, @@ -2845,41 +2431,16 @@ def std( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.groupby("labels").std() - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 0.0 0.0 1.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").std(skipna=False) - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 nan 0.0 1.0 Specify ``ddof=1`` for an unbiased estimate. >>> ds.groupby("labels").std(skipna=True, ddof=1) - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 nan 0.0 1.414 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2905,7 +2466,7 @@ def std( def var( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, ddof: int = 0, @@ -2967,41 +2528,16 @@ def var( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.groupby("labels").var() - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 0.0 0.0 1.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").var(skipna=False) - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 nan 0.0 1.0 Specify ``ddof=1`` for an unbiased estimate. >>> ds.groupby("labels").var(skipna=True, ddof=1) - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 nan 0.0 2.0 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3027,7 +2563,7 @@ def var( def median( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -3085,31 +2621,12 @@ def median( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.groupby("labels").median() - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 1.0 2.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").median(skipna=False) - - Dimensions: (labels: 3) - Coordinates: - * labels (labels) object 'a' 'b' 'c' - Data variables: - da (labels) float64 nan 2.0 2.0 """ return self.reduce( duck_array_ops.median, @@ -3127,9 +2644,9 @@ class DatasetResampleReductions: def reduce( self, func: Callable[..., Any], - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, - axis: Union[None, int, Sequence[int]] = None, + axis: None | int | Sequence[int] = None, keep_attrs: bool = None, keepdims: bool = False, **kwargs: Any, @@ -3138,14 +2655,14 @@ def reduce( def _flox_reduce( self, - dim: Union[None, Hashable, Sequence[Hashable]], + dim: None | Hashable | Sequence[Hashable], **kwargs, ) -> "Dataset": raise NotImplementedError() def count( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -3193,21 +2710,8 @@ def count( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.resample(time="3M").count() - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) int64 1 3 1 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3229,7 +2733,7 @@ def count( def all( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -3277,21 +2781,8 @@ def all( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.resample(time="3M").all() - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) bool True True False """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3313,7 +2804,7 @@ def all( def any( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -3361,21 +2852,8 @@ def any( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.resample(time="3M").any() - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) bool True True True """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3397,7 +2875,7 @@ def any( def max( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -3451,31 +2929,12 @@ def max( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.resample(time="3M").max() - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 1.0 3.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").max(skipna=False) - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 1.0 3.0 nan """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3499,7 +2958,7 @@ def max( def min( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -3553,31 +3012,12 @@ def min( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.resample(time="3M").min() - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 1.0 1.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").min(skipna=False) - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 1.0 1.0 nan """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3601,7 +3041,7 @@ def min( def mean( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -3659,31 +3099,12 @@ def mean( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.resample(time="3M").mean() - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 1.0 2.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").mean(skipna=False) - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 1.0 2.0 nan """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3707,7 +3128,7 @@ def mean( def prod( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, min_count: Optional[int] = None, @@ -3772,41 +3193,16 @@ def prod( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.resample(time="3M").prod() - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 1.0 6.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").prod(skipna=False) - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 1.0 6.0 nan Specify ``min_count`` for finer control over when NaNs are ignored. >>> ds.resample(time="3M").prod(skipna=True, min_count=2) - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 nan 6.0 nan """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3832,7 +3228,7 @@ def prod( def sum( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, min_count: Optional[int] = None, @@ -3897,41 +3293,16 @@ def sum( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.resample(time="3M").sum() - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 1.0 6.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").sum(skipna=False) - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 1.0 6.0 nan Specify ``min_count`` for finer control over when NaNs are ignored. >>> ds.resample(time="3M").sum(skipna=True, min_count=2) - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 nan 6.0 nan """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3957,7 +3328,7 @@ def sum( def std( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, ddof: int = 0, @@ -4019,41 +3390,16 @@ def std( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.resample(time="3M").std() - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 0.0 0.8165 0.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").std(skipna=False) - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 0.0 0.8165 nan Specify ``ddof=1`` for an unbiased estimate. >>> ds.resample(time="3M").std(skipna=True, ddof=1) - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 nan 1.0 nan """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4079,7 +3425,7 @@ def std( def var( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, ddof: int = 0, @@ -4141,41 +3487,16 @@ def var( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.resample(time="3M").var() - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 0.0 0.6667 0.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").var(skipna=False) - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 0.0 0.6667 nan Specify ``ddof=1`` for an unbiased estimate. >>> ds.resample(time="3M").var(skipna=True, ddof=1) - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 nan 1.0 nan """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4201,7 +3522,7 @@ def var( def median( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -4259,31 +3580,12 @@ def median( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds - - Dimensions: (time: 6) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> ds.resample(time="3M").median() - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 1.0 2.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").median(skipna=False) - - Dimensions: (time: 3) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 - Data variables: - da (time) float64 1.0 2.0 nan """ return self.reduce( duck_array_ops.median, @@ -4301,9 +3603,9 @@ class DataArrayGroupByReductions: def reduce( self, func: Callable[..., Any], - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, - axis: Union[None, int, Sequence[int]] = None, + axis: None | int | Sequence[int] = None, keep_attrs: bool = None, keepdims: bool = False, **kwargs: Any, @@ -4312,14 +3614,14 @@ def reduce( def _flox_reduce( self, - dim: Union[None, Hashable, Sequence[Hashable]], + dim: None | Hashable | Sequence[Hashable], **kwargs, ) -> "DataArray": raise NotImplementedError() def count( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -4366,17 +3668,8 @@ def count( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.groupby("labels").count() - - array([1, 2, 2]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4396,7 +3689,7 @@ def count( def all( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -4443,17 +3736,8 @@ def all( ... ), ... ) >>> da - - array([ True, True, True, True, True, False]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.groupby("labels").all() - - array([False, True, True]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4473,7 +3757,7 @@ def all( def any( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -4520,17 +3804,8 @@ def any( ... ), ... ) >>> da - - array([ True, True, True, True, True, False]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.groupby("labels").any() - - array([ True, True, True]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4550,7 +3825,7 @@ def any( def max( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -4603,25 +3878,12 @@ def max( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.groupby("labels").max() - - array([1., 2., 3.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").max(skipna=False) - - array([nan, 2., 3.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4643,7 +3905,7 @@ def max( def min( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -4696,25 +3958,12 @@ def min( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.groupby("labels").min() - - array([1., 2., 1.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").min(skipna=False) - - array([nan, 2., 1.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4736,7 +3985,7 @@ def min( def mean( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -4793,25 +4042,12 @@ def mean( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.groupby("labels").mean() - - array([1., 2., 2.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").mean(skipna=False) - - array([nan, 2., 2.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4833,7 +4069,7 @@ def mean( def prod( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, min_count: Optional[int] = None, @@ -4897,33 +4133,16 @@ def prod( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.groupby("labels").prod() - - array([1., 4., 3.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").prod(skipna=False) - - array([nan, 4., 3.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' Specify ``min_count`` for finer control over when NaNs are ignored. >>> da.groupby("labels").prod(skipna=True, min_count=2) - - array([nan, 4., 3.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4947,7 +4166,7 @@ def prod( def sum( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, min_count: Optional[int] = None, @@ -5011,33 +4230,16 @@ def sum( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.groupby("labels").sum() - - array([1., 4., 4.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").sum(skipna=False) - - array([nan, 4., 4.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' Specify ``min_count`` for finer control over when NaNs are ignored. >>> da.groupby("labels").sum(skipna=True, min_count=2) - - array([nan, 4., 4.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -5061,7 +4263,7 @@ def sum( def std( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, ddof: int = 0, @@ -5122,33 +4324,16 @@ def std( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.groupby("labels").std() - - array([0., 0., 1.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").std(skipna=False) - - array([nan, 0., 1.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' Specify ``ddof=1`` for an unbiased estimate. >>> da.groupby("labels").std(skipna=True, ddof=1) - - array([ nan, 0. , 1.41421356]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -5172,7 +4357,7 @@ def std( def var( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, ddof: int = 0, @@ -5233,33 +4418,16 @@ def var( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.groupby("labels").var() - - array([0., 0., 1.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").var(skipna=False) - - array([nan, 0., 1.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' Specify ``ddof=1`` for an unbiased estimate. >>> da.groupby("labels").var(skipna=True, ddof=1) - - array([nan, 0., 2.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -5283,7 +4451,7 @@ def var( def median( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -5340,25 +4508,12 @@ def median( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.groupby("labels").median() - - array([1., 2., 2.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").median(skipna=False) - - array([nan, 2., 2.]) - Coordinates: - * labels (labels) object 'a' 'b' 'c' """ return self.reduce( duck_array_ops.median, @@ -5375,9 +4530,9 @@ class DataArrayResampleReductions: def reduce( self, func: Callable[..., Any], - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, - axis: Union[None, int, Sequence[int]] = None, + axis: None | int | Sequence[int] = None, keep_attrs: bool = None, keepdims: bool = False, **kwargs: Any, @@ -5386,14 +4541,14 @@ def reduce( def _flox_reduce( self, - dim: Union[None, Hashable, Sequence[Hashable]], + dim: None | Hashable | Sequence[Hashable], **kwargs, ) -> "DataArray": raise NotImplementedError() def count( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -5440,17 +4595,8 @@ def count( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.resample(time="3M").count() - - array([1, 3, 1]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -5470,7 +4616,7 @@ def count( def all( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -5517,17 +4663,8 @@ def all( ... ), ... ) >>> da - - array([ True, True, True, True, True, False]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.resample(time="3M").all() - - array([ True, True, False]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -5547,7 +4684,7 @@ def all( def any( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, keep_attrs: bool = None, **kwargs, @@ -5594,17 +4731,8 @@ def any( ... ), ... ) >>> da - - array([ True, True, True, True, True, False]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.resample(time="3M").any() - - array([ True, True, True]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -5624,7 +4752,7 @@ def any( def max( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -5677,25 +4805,12 @@ def max( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.resample(time="3M").max() - - array([1., 3., 2.]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").max(skipna=False) - - array([ 1., 3., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -5717,7 +4832,7 @@ def max( def min( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -5770,25 +4885,12 @@ def min( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.resample(time="3M").min() - - array([1., 1., 2.]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").min(skipna=False) - - array([ 1., 1., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -5810,7 +4912,7 @@ def min( def mean( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -5867,25 +4969,12 @@ def mean( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.resample(time="3M").mean() - - array([1., 2., 2.]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").mean(skipna=False) - - array([ 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -5907,7 +4996,7 @@ def mean( def prod( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, min_count: Optional[int] = None, @@ -5971,33 +5060,16 @@ def prod( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.resample(time="3M").prod() - - array([1., 6., 2.]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").prod(skipna=False) - - array([ 1., 6., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Specify ``min_count`` for finer control over when NaNs are ignored. >>> da.resample(time="3M").prod(skipna=True, min_count=2) - - array([nan, 6., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -6021,7 +5093,7 @@ def prod( def sum( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, min_count: Optional[int] = None, @@ -6085,33 +5157,16 @@ def sum( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.resample(time="3M").sum() - - array([1., 6., 2.]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").sum(skipna=False) - - array([ 1., 6., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Specify ``min_count`` for finer control over when NaNs are ignored. >>> da.resample(time="3M").sum(skipna=True, min_count=2) - - array([nan, 6., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -6135,7 +5190,7 @@ def sum( def std( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, ddof: int = 0, @@ -6196,33 +5251,16 @@ def std( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.resample(time="3M").std() - - array([0. , 0.81649658, 0. ]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").std(skipna=False) - - array([0. , 0.81649658, nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Specify ``ddof=1`` for an unbiased estimate. >>> da.resample(time="3M").std(skipna=True, ddof=1) - - array([nan, 1., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -6246,7 +5284,7 @@ def std( def var( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, ddof: int = 0, @@ -6307,33 +5345,16 @@ def var( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.resample(time="3M").var() - - array([0. , 0.66666667, 0. ]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").var(skipna=False) - - array([0. , 0.66666667, nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Specify ``ddof=1`` for an unbiased estimate. >>> da.resample(time="3M").var(skipna=True, ddof=1) - - array([nan, 1., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -6357,7 +5378,7 @@ def var( def median( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, skipna: bool = None, keep_attrs: bool = None, @@ -6414,25 +5435,12 @@ def median( ... ), ... ) >>> da - - array([ 1., 2., 3., 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 - labels (time) >> da.resample(time="3M").median() - - array([1., 2., 2.]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").median(skipna=False) - - array([ 1., 2., nan]) - Coordinates: - * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ return self.reduce( duck_array_ops.median, diff --git a/xarray/util/generate_reductions.py b/xarray/util/generate_reductions.py index 96b91c16906..5350c683562 100644 --- a/xarray/util/generate_reductions.py +++ b/xarray/util/generate_reductions.py @@ -20,7 +20,9 @@ """Mixin classes with reduction operations.""" # This file was generated using xarray.util.generate_reductions. Do not edit manually. -from typing import TYPE_CHECKING, Any, Callable, Hashable, Optional, Sequence, Union +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Callable, Hashable, Optional, Sequence from . import duck_array_ops from .options import OPTIONS @@ -43,9 +45,9 @@ class {obj}{cls}Reductions: def reduce( self, func: Callable[..., Any], - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, - axis: Union[None, int, Sequence[int]] = None, + axis: None | int | Sequence[int] = None, keep_attrs: bool = None, keepdims: bool = False, **kwargs: Any, @@ -60,9 +62,9 @@ class {obj}{cls}Reductions: def reduce( self, func: Callable[..., Any], - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, - axis: Union[None, int, Sequence[int]] = None, + axis: None | int | Sequence[int] = None, keep_attrs: bool = None, keepdims: bool = False, **kwargs: Any, @@ -71,7 +73,7 @@ def reduce( def _flox_reduce( self, - dim: Union[None, Hashable, Sequence[Hashable]], + dim: None | Hashable | Sequence[Hashable], **kwargs, ) -> "{obj}": raise NotImplementedError()""" @@ -84,9 +86,9 @@ class {obj}{cls}Reductions: def reduce( self, func: Callable[..., Any], - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, - axis: Union[None, int, Sequence[int]] = None, + axis: None | int | Sequence[int] = None, keep_attrs: bool = None, keepdims: bool = False, **kwargs: Any, @@ -95,7 +97,7 @@ def reduce( def _flox_reduce( self, - dim: Union[None, Hashable, Sequence[Hashable]], + dim: None | Hashable | Sequence[Hashable], **kwargs, ) -> "{obj}": raise NotImplementedError()""" @@ -103,7 +105,7 @@ def _flox_reduce( TEMPLATE_REDUCTION_SIGNATURE = ''' def {method}( self, - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *,{extra_kwargs} keep_attrs: bool = None, **kwargs, From 46efa47d2508532dc7e91203c5a6d5a257e0e88e Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 10:34:32 +0200 Subject: [PATCH 06/21] update typing of _reductions --- xarray/core/_reductions.py | 922 ++++++++++++++--------------- xarray/util/generate_reductions.py | 30 +- 2 files changed, 476 insertions(+), 476 deletions(-) diff --git a/xarray/core/_reductions.py b/xarray/core/_reductions.py index 76cc4ad7b4a..72bb5748281 100644 --- a/xarray/core/_reductions.py +++ b/xarray/core/_reductions.py @@ -3,7 +3,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Callable, Hashable, Optional, Sequence +from typing import TYPE_CHECKING, Any, Callable, Hashable, Sequence from . import duck_array_ops from .options import OPTIONS @@ -28,7 +28,7 @@ def reduce( dim: None | Hashable | Sequence[Hashable] = None, *, axis: None | int | Sequence[int] = None, - keep_attrs: bool = None, + keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, ) -> "Dataset": @@ -38,8 +38,8 @@ def count( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``count`` along some dimension(s). @@ -49,11 +49,11 @@ def count( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``count``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``count`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -99,8 +99,8 @@ def all( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``all`` along some dimension(s). @@ -110,11 +110,11 @@ def all( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``all``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``all`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -160,8 +160,8 @@ def any( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``any`` along some dimension(s). @@ -171,11 +171,11 @@ def any( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``any``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``any`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -221,9 +221,9 @@ def max( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``max`` along some dimension(s). @@ -233,16 +233,16 @@ def max( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``max``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``max`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -293,9 +293,9 @@ def min( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``min`` along some dimension(s). @@ -305,16 +305,16 @@ def min( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``min``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``min`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -365,9 +365,9 @@ def mean( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``mean`` along some dimension(s). @@ -377,16 +377,16 @@ def mean( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``mean``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``mean`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -441,10 +441,10 @@ def prod( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - min_count: Optional[int] = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + min_count: int | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``prod`` along some dimension(s). @@ -454,22 +454,22 @@ def prod( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``prod``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - min_count : int, default: None + min_count : int or None, optional The required number of valid values to perform the operation. If fewer than min_count non-NA values are present the result will be NA. Only used if skipna is set to True or defaults to True for the array's dtype. Changed in version 0.17.0: if specified on an integer array and skipna=True, the result will be a float array. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``prod`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -529,10 +529,10 @@ def sum( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - min_count: Optional[int] = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + min_count: int | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``sum`` along some dimension(s). @@ -542,22 +542,22 @@ def sum( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``sum``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - min_count : int, default: None + min_count : int or None, optional The required number of valid values to perform the operation. If fewer than min_count non-NA values are present the result will be NA. Only used if skipna is set to True or defaults to True for the array's dtype. Changed in version 0.17.0: if specified on an integer array and skipna=True, the result will be a float array. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``sum`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -617,10 +617,10 @@ def std( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, + skipna: bool | None = None, ddof: int = 0, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``std`` along some dimension(s). @@ -630,7 +630,7 @@ def std( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``std``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been @@ -638,11 +638,11 @@ def std( ddof : int, default: 0 “Delta Degrees of Freedom”: the divisor used in the calculation is ``N - ddof``, where ``N`` represents the number of elements. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``std`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -702,10 +702,10 @@ def var( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, + skipna: bool | None = None, ddof: int = 0, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``var`` along some dimension(s). @@ -715,7 +715,7 @@ def var( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``var``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been @@ -723,11 +723,11 @@ def var( ddof : int, default: 0 “Delta Degrees of Freedom”: the divisor used in the calculation is ``N - ddof``, where ``N`` represents the number of elements. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``var`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -787,9 +787,9 @@ def median( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``median`` along some dimension(s). @@ -799,16 +799,16 @@ def median( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``median``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``median`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -869,7 +869,7 @@ def reduce( dim: None | Hashable | Sequence[Hashable] = None, *, axis: None | int | Sequence[int] = None, - keep_attrs: bool = None, + keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, ) -> "DataArray": @@ -879,8 +879,8 @@ def count( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``count`` along some dimension(s). @@ -890,11 +890,11 @@ def count( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``count``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``count`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -938,8 +938,8 @@ def all( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``all`` along some dimension(s). @@ -949,11 +949,11 @@ def all( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``all``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``all`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -997,8 +997,8 @@ def any( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``any`` along some dimension(s). @@ -1008,11 +1008,11 @@ def any( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``any``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``any`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -1056,9 +1056,9 @@ def max( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``max`` along some dimension(s). @@ -1068,16 +1068,16 @@ def max( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``max``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``max`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -1126,9 +1126,9 @@ def min( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``min`` along some dimension(s). @@ -1138,16 +1138,16 @@ def min( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``min``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``min`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -1196,9 +1196,9 @@ def mean( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``mean`` along some dimension(s). @@ -1208,16 +1208,16 @@ def mean( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``mean``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``mean`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -1270,10 +1270,10 @@ def prod( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - min_count: Optional[int] = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + min_count: int | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``prod`` along some dimension(s). @@ -1283,22 +1283,22 @@ def prod( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``prod``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - min_count : int, default: None + min_count : int or None, optional The required number of valid values to perform the operation. If fewer than min_count non-NA values are present the result will be NA. Only used if skipna is set to True or defaults to True for the array's dtype. Changed in version 0.17.0: if specified on an integer array and skipna=True, the result will be a float array. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``prod`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -1356,10 +1356,10 @@ def sum( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - min_count: Optional[int] = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + min_count: int | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``sum`` along some dimension(s). @@ -1369,22 +1369,22 @@ def sum( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``sum``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - min_count : int, default: None + min_count : int or None, optional The required number of valid values to perform the operation. If fewer than min_count non-NA values are present the result will be NA. Only used if skipna is set to True or defaults to True for the array's dtype. Changed in version 0.17.0: if specified on an integer array and skipna=True, the result will be a float array. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``sum`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -1442,10 +1442,10 @@ def std( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, + skipna: bool | None = None, ddof: int = 0, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``std`` along some dimension(s). @@ -1455,7 +1455,7 @@ def std( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``std``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been @@ -1463,11 +1463,11 @@ def std( ddof : int, default: 0 “Delta Degrees of Freedom”: the divisor used in the calculation is ``N - ddof``, where ``N`` represents the number of elements. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``std`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -1525,10 +1525,10 @@ def var( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, + skipna: bool | None = None, ddof: int = 0, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``var`` along some dimension(s). @@ -1538,7 +1538,7 @@ def var( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``var``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been @@ -1546,11 +1546,11 @@ def var( ddof : int, default: 0 “Delta Degrees of Freedom”: the divisor used in the calculation is ``N - ddof``, where ``N`` represents the number of elements. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``var`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -1608,9 +1608,9 @@ def median( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``median`` along some dimension(s). @@ -1620,16 +1620,16 @@ def median( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``median``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``median`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -1688,7 +1688,7 @@ def reduce( dim: None | Hashable | Sequence[Hashable] = None, *, axis: None | int | Sequence[int] = None, - keep_attrs: bool = None, + keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, ) -> "Dataset": @@ -1697,7 +1697,7 @@ def reduce( def _flox_reduce( self, dim: None | Hashable | Sequence[Hashable], - **kwargs, + **kwargs: Any, ) -> "Dataset": raise NotImplementedError() @@ -1705,8 +1705,8 @@ def count( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``count`` along some dimension(s). @@ -1716,11 +1716,11 @@ def count( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``count``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``count`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -1776,8 +1776,8 @@ def all( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``all`` along some dimension(s). @@ -1787,11 +1787,11 @@ def all( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``all``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``all`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -1847,8 +1847,8 @@ def any( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``any`` along some dimension(s). @@ -1858,11 +1858,11 @@ def any( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``any``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``any`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -1918,9 +1918,9 @@ def max( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``max`` along some dimension(s). @@ -1930,16 +1930,16 @@ def max( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``max``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``max`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -2001,9 +2001,9 @@ def min( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``min`` along some dimension(s). @@ -2013,16 +2013,16 @@ def min( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``min``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``min`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -2084,9 +2084,9 @@ def mean( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``mean`` along some dimension(s). @@ -2096,16 +2096,16 @@ def mean( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``mean``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``mean`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -2171,10 +2171,10 @@ def prod( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - min_count: Optional[int] = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + min_count: int | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``prod`` along some dimension(s). @@ -2184,22 +2184,22 @@ def prod( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``prod``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - min_count : int, default: None + min_count : int or None, optional The required number of valid values to perform the operation. If fewer than min_count non-NA values are present the result will be NA. Only used if skipna is set to True or defaults to True for the array's dtype. Changed in version 0.17.0: if specified on an integer array and skipna=True, the result will be a float array. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``prod`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -2271,10 +2271,10 @@ def sum( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - min_count: Optional[int] = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + min_count: int | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``sum`` along some dimension(s). @@ -2284,22 +2284,22 @@ def sum( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``sum``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - min_count : int, default: None + min_count : int or None, optional The required number of valid values to perform the operation. If fewer than min_count non-NA values are present the result will be NA. Only used if skipna is set to True or defaults to True for the array's dtype. Changed in version 0.17.0: if specified on an integer array and skipna=True, the result will be a float array. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``sum`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -2371,10 +2371,10 @@ def std( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, + skipna: bool | None = None, ddof: int = 0, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``std`` along some dimension(s). @@ -2384,7 +2384,7 @@ def std( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``std``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been @@ -2392,11 +2392,11 @@ def std( ddof : int, default: 0 “Delta Degrees of Freedom”: the divisor used in the calculation is ``N - ddof``, where ``N`` represents the number of elements. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``std`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -2468,10 +2468,10 @@ def var( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, + skipna: bool | None = None, ddof: int = 0, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``var`` along some dimension(s). @@ -2481,7 +2481,7 @@ def var( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``var``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been @@ -2489,11 +2489,11 @@ def var( ddof : int, default: 0 “Delta Degrees of Freedom”: the divisor used in the calculation is ``N - ddof``, where ``N`` represents the number of elements. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``var`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -2565,9 +2565,9 @@ def median( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``median`` along some dimension(s). @@ -2577,16 +2577,16 @@ def median( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``median``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``median`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -2647,7 +2647,7 @@ def reduce( dim: None | Hashable | Sequence[Hashable] = None, *, axis: None | int | Sequence[int] = None, - keep_attrs: bool = None, + keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, ) -> "Dataset": @@ -2656,7 +2656,7 @@ def reduce( def _flox_reduce( self, dim: None | Hashable | Sequence[Hashable], - **kwargs, + **kwargs: Any, ) -> "Dataset": raise NotImplementedError() @@ -2664,8 +2664,8 @@ def count( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``count`` along some dimension(s). @@ -2675,11 +2675,11 @@ def count( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``count``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``count`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -2735,8 +2735,8 @@ def all( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``all`` along some dimension(s). @@ -2746,11 +2746,11 @@ def all( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``all``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``all`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -2806,8 +2806,8 @@ def any( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``any`` along some dimension(s). @@ -2817,11 +2817,11 @@ def any( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``any``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``any`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -2877,9 +2877,9 @@ def max( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``max`` along some dimension(s). @@ -2889,16 +2889,16 @@ def max( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``max``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``max`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -2960,9 +2960,9 @@ def min( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``min`` along some dimension(s). @@ -2972,16 +2972,16 @@ def min( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``min``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``min`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -3043,9 +3043,9 @@ def mean( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``mean`` along some dimension(s). @@ -3055,16 +3055,16 @@ def mean( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``mean``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``mean`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -3130,10 +3130,10 @@ def prod( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - min_count: Optional[int] = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + min_count: int | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``prod`` along some dimension(s). @@ -3143,22 +3143,22 @@ def prod( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``prod``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - min_count : int, default: None + min_count : int or None, optional The required number of valid values to perform the operation. If fewer than min_count non-NA values are present the result will be NA. Only used if skipna is set to True or defaults to True for the array's dtype. Changed in version 0.17.0: if specified on an integer array and skipna=True, the result will be a float array. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``prod`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -3230,10 +3230,10 @@ def sum( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - min_count: Optional[int] = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + min_count: int | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``sum`` along some dimension(s). @@ -3243,22 +3243,22 @@ def sum( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``sum``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - min_count : int, default: None + min_count : int or None, optional The required number of valid values to perform the operation. If fewer than min_count non-NA values are present the result will be NA. Only used if skipna is set to True or defaults to True for the array's dtype. Changed in version 0.17.0: if specified on an integer array and skipna=True, the result will be a float array. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``sum`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -3330,10 +3330,10 @@ def std( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, + skipna: bool | None = None, ddof: int = 0, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``std`` along some dimension(s). @@ -3343,7 +3343,7 @@ def std( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``std``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been @@ -3351,11 +3351,11 @@ def std( ddof : int, default: 0 “Delta Degrees of Freedom”: the divisor used in the calculation is ``N - ddof``, where ``N`` represents the number of elements. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``std`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -3427,10 +3427,10 @@ def var( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, + skipna: bool | None = None, ddof: int = 0, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``var`` along some dimension(s). @@ -3440,7 +3440,7 @@ def var( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``var``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been @@ -3448,11 +3448,11 @@ def var( ddof : int, default: 0 “Delta Degrees of Freedom”: the divisor used in the calculation is ``N - ddof``, where ``N`` represents the number of elements. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``var`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -3524,9 +3524,9 @@ def median( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "Dataset": """ Reduce this Dataset's data by applying ``median`` along some dimension(s). @@ -3536,16 +3536,16 @@ def median( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``median``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``median`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -3606,7 +3606,7 @@ def reduce( dim: None | Hashable | Sequence[Hashable] = None, *, axis: None | int | Sequence[int] = None, - keep_attrs: bool = None, + keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, ) -> "DataArray": @@ -3615,7 +3615,7 @@ def reduce( def _flox_reduce( self, dim: None | Hashable | Sequence[Hashable], - **kwargs, + **kwargs: Any, ) -> "DataArray": raise NotImplementedError() @@ -3623,8 +3623,8 @@ def count( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``count`` along some dimension(s). @@ -3634,11 +3634,11 @@ def count( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``count``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``count`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -3691,8 +3691,8 @@ def all( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``all`` along some dimension(s). @@ -3702,11 +3702,11 @@ def all( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``all``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``all`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -3759,8 +3759,8 @@ def any( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``any`` along some dimension(s). @@ -3770,11 +3770,11 @@ def any( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``any``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``any`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -3827,9 +3827,9 @@ def max( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``max`` along some dimension(s). @@ -3839,16 +3839,16 @@ def max( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``max``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``max`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -3907,9 +3907,9 @@ def min( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``min`` along some dimension(s). @@ -3919,16 +3919,16 @@ def min( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``min``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``min`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -3987,9 +3987,9 @@ def mean( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``mean`` along some dimension(s). @@ -3999,16 +3999,16 @@ def mean( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``mean``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``mean`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -4071,10 +4071,10 @@ def prod( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - min_count: Optional[int] = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + min_count: int | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``prod`` along some dimension(s). @@ -4084,22 +4084,22 @@ def prod( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``prod``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - min_count : int, default: None + min_count : int or None, optional The required number of valid values to perform the operation. If fewer than min_count non-NA values are present the result will be NA. Only used if skipna is set to True or defaults to True for the array's dtype. Changed in version 0.17.0: if specified on an integer array and skipna=True, the result will be a float array. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``prod`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -4168,10 +4168,10 @@ def sum( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - min_count: Optional[int] = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + min_count: int | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``sum`` along some dimension(s). @@ -4181,22 +4181,22 @@ def sum( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``sum``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - min_count : int, default: None + min_count : int or None, optional The required number of valid values to perform the operation. If fewer than min_count non-NA values are present the result will be NA. Only used if skipna is set to True or defaults to True for the array's dtype. Changed in version 0.17.0: if specified on an integer array and skipna=True, the result will be a float array. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``sum`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -4265,10 +4265,10 @@ def std( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, + skipna: bool | None = None, ddof: int = 0, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``std`` along some dimension(s). @@ -4278,7 +4278,7 @@ def std( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``std``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been @@ -4286,11 +4286,11 @@ def std( ddof : int, default: 0 “Delta Degrees of Freedom”: the divisor used in the calculation is ``N - ddof``, where ``N`` represents the number of elements. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``std`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -4359,10 +4359,10 @@ def var( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, + skipna: bool | None = None, ddof: int = 0, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``var`` along some dimension(s). @@ -4372,7 +4372,7 @@ def var( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``var``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been @@ -4380,11 +4380,11 @@ def var( ddof : int, default: 0 “Delta Degrees of Freedom”: the divisor used in the calculation is ``N - ddof``, where ``N`` represents the number of elements. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``var`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -4453,9 +4453,9 @@ def median( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``median`` along some dimension(s). @@ -4465,16 +4465,16 @@ def median( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``median``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``median`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -4533,7 +4533,7 @@ def reduce( dim: None | Hashable | Sequence[Hashable] = None, *, axis: None | int | Sequence[int] = None, - keep_attrs: bool = None, + keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, ) -> "DataArray": @@ -4542,7 +4542,7 @@ def reduce( def _flox_reduce( self, dim: None | Hashable | Sequence[Hashable], - **kwargs, + **kwargs: Any, ) -> "DataArray": raise NotImplementedError() @@ -4550,8 +4550,8 @@ def count( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``count`` along some dimension(s). @@ -4561,11 +4561,11 @@ def count( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``count``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``count`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -4618,8 +4618,8 @@ def all( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``all`` along some dimension(s). @@ -4629,11 +4629,11 @@ def all( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``all``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``all`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -4686,8 +4686,8 @@ def any( self, dim: None | Hashable | Sequence[Hashable] = None, *, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``any`` along some dimension(s). @@ -4697,11 +4697,11 @@ def any( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``any``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``any`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -4754,9 +4754,9 @@ def max( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``max`` along some dimension(s). @@ -4766,16 +4766,16 @@ def max( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``max``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``max`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -4834,9 +4834,9 @@ def min( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``min`` along some dimension(s). @@ -4846,16 +4846,16 @@ def min( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``min``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``min`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -4914,9 +4914,9 @@ def mean( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``mean`` along some dimension(s). @@ -4926,16 +4926,16 @@ def mean( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``mean``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``mean`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -4998,10 +4998,10 @@ def prod( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - min_count: Optional[int] = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + min_count: int | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``prod`` along some dimension(s). @@ -5011,22 +5011,22 @@ def prod( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``prod``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - min_count : int, default: None + min_count : int or None, optional The required number of valid values to perform the operation. If fewer than min_count non-NA values are present the result will be NA. Only used if skipna is set to True or defaults to True for the array's dtype. Changed in version 0.17.0: if specified on an integer array and skipna=True, the result will be a float array. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``prod`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -5095,10 +5095,10 @@ def sum( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - min_count: Optional[int] = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + min_count: int | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``sum`` along some dimension(s). @@ -5108,22 +5108,22 @@ def sum( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``sum``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - min_count : int, default: None + min_count : int or None, optional The required number of valid values to perform the operation. If fewer than min_count non-NA values are present the result will be NA. Only used if skipna is set to True or defaults to True for the array's dtype. Changed in version 0.17.0: if specified on an integer array and skipna=True, the result will be a float array. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``sum`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -5192,10 +5192,10 @@ def std( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, + skipna: bool | None = None, ddof: int = 0, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``std`` along some dimension(s). @@ -5205,7 +5205,7 @@ def std( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``std``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been @@ -5213,11 +5213,11 @@ def std( ddof : int, default: 0 “Delta Degrees of Freedom”: the divisor used in the calculation is ``N - ddof``, where ``N`` represents the number of elements. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``std`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -5286,10 +5286,10 @@ def var( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, + skipna: bool | None = None, ddof: int = 0, - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``var`` along some dimension(s). @@ -5299,7 +5299,7 @@ def var( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``var``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been @@ -5307,11 +5307,11 @@ def var( ddof : int, default: 0 “Delta Degrees of Freedom”: the divisor used in the calculation is ``N - ddof``, where ``N`` represents the number of elements. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``var`` on this object's data. These could include dask-specific kwargs like ``split_every``. @@ -5380,9 +5380,9 @@ def median( self, dim: None | Hashable | Sequence[Hashable] = None, *, - skipna: bool = None, - keep_attrs: bool = None, - **kwargs, + skipna: bool | None = None, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "DataArray": """ Reduce this DataArray's data by applying ``median`` along some dimension(s). @@ -5392,16 +5392,16 @@ def median( dim : hashable or iterable of hashable, default: None Name of dimension[s] along which to apply ``median``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions. - skipna : bool, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64). - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes. - **kwargs : dict + **kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``median`` on this object's data. These could include dask-specific kwargs like ``split_every``. diff --git a/xarray/util/generate_reductions.py b/xarray/util/generate_reductions.py index 5350c683562..e526832a0d5 100644 --- a/xarray/util/generate_reductions.py +++ b/xarray/util/generate_reductions.py @@ -22,7 +22,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Callable, Hashable, Optional, Sequence +from typing import TYPE_CHECKING, Any, Callable, Hashable, Sequence from . import duck_array_ops from .options import OPTIONS @@ -48,7 +48,7 @@ def reduce( dim: None | Hashable | Sequence[Hashable] = None, *, axis: None | int | Sequence[int] = None, - keep_attrs: bool = None, + keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, ) -> "{obj}": @@ -65,7 +65,7 @@ def reduce( dim: None | Hashable | Sequence[Hashable] = None, *, axis: None | int | Sequence[int] = None, - keep_attrs: bool = None, + keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, ) -> "{obj}": @@ -74,7 +74,7 @@ def reduce( def _flox_reduce( self, dim: None | Hashable | Sequence[Hashable], - **kwargs, + **kwargs: Any, ) -> "{obj}": raise NotImplementedError()""" @@ -89,7 +89,7 @@ def reduce( dim: None | Hashable | Sequence[Hashable] = None, *, axis: None | int | Sequence[int] = None, - keep_attrs: bool = None, + keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, ) -> "{obj}": @@ -98,7 +98,7 @@ def reduce( def _flox_reduce( self, dim: None | Hashable | Sequence[Hashable], - **kwargs, + **kwargs: Any, ) -> "{obj}": raise NotImplementedError()""" @@ -107,8 +107,8 @@ def {method}( self, dim: None | Hashable | Sequence[Hashable] = None, *,{extra_kwargs} - keep_attrs: bool = None, - **kwargs, + keep_attrs: bool | None = None, + **kwargs: Any, ) -> "{obj}": """ Reduce this {obj}'s data by applying ``{method}`` along some dimension(s). @@ -141,13 +141,13 @@ def {method}( Name of dimension[s] along which to apply ``{method}``. For e.g. ``dim="x"`` or ``dim=["x", "y"]``. If None, will reduce over all dimensions.""" -_SKIPNA_DOCSTRING = """skipna : bool, default: None +_SKIPNA_DOCSTRING = """skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for float dtypes; other dtypes either do not have a sentinel missing value (int) or ``skipna=True`` has not been implemented (object, datetime64 or timedelta64).""" -_MINCOUNT_DOCSTRING = """min_count : int, default: None +_MINCOUNT_DOCSTRING = """min_count : int or None, optional The required number of valid values to perform the operation. If fewer than min_count non-NA values are present the result will be NA. Only used if skipna is set to True or defaults to True for the @@ -158,12 +158,12 @@ def {method}( “Delta Degrees of Freedom”: the divisor used in the calculation is ``N - ddof``, where ``N`` represents the number of elements.""" -_KEEP_ATTRS_DOCSTRING = """keep_attrs : bool, optional +_KEEP_ATTRS_DOCSTRING = """keep_attrs : bool or None, optional If True, ``attrs`` will be copied from the original - object to the new one. If False (default), the new object will be + object to the new one. If False, the new object will be returned without attributes.""" -_KWARGS_DOCSTRING = """**kwargs : dict +_KWARGS_DOCSTRING = """**kwargs : Any Additional keyword arguments passed on to the appropriate array function for calculating ``{method}`` on this object's data. These could include dask-specific kwargs like ``split_every``.""" @@ -175,7 +175,7 @@ def {method}( ExtraKwarg = collections.namedtuple("ExtraKwarg", "docs kwarg call example") skipna = ExtraKwarg( docs=_SKIPNA_DOCSTRING, - kwarg="skipna: bool = None,", + kwarg="skipna: bool | None = None,", call="skipna=skipna,", example="""\n Use ``skipna`` to control whether NaNs are ignored. @@ -184,7 +184,7 @@ def {method}( ) min_count = ExtraKwarg( docs=_MINCOUNT_DOCSTRING, - kwarg="min_count: Optional[int] = None,", + kwarg="min_count: int | None = None,", call="min_count=min_count,", example="""\n Specify ``min_count`` for finer control over when NaNs are ignored. From 1f26d57e237c6c58762cba535104e2b1bb7f2f2b Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 10:41:06 +0200 Subject: [PATCH 07/21] add from __future__ import annotations everywhere --- xarray/core/arithmetic.py | 2 ++ xarray/core/dask_array_compat.py | 2 ++ xarray/core/dask_array_ops.py | 2 ++ xarray/core/dtypes.py | 2 ++ xarray/core/duck_array_ops.py | 2 ++ xarray/core/extensions.py | 2 ++ xarray/core/formatting.py | 10 ++++++---- xarray/core/formatting_html.py | 2 ++ xarray/core/nanops.py | 2 ++ xarray/core/nputils.py | 2 ++ xarray/core/ops.py | 1 + xarray/core/options.py | 12 +++++++----- xarray/core/pdcompat.py | 1 + xarray/core/pycompat.py | 2 ++ xarray/core/resample.py | 8 +++++--- xarray/core/resample_cftime.py | 1 + xarray/core/rolling.py | 8 +++++--- 17 files changed, 46 insertions(+), 15 deletions(-) diff --git a/xarray/core/arithmetic.py b/xarray/core/arithmetic.py index bf8d6ccaeb6..ff7af02abfc 100644 --- a/xarray/core/arithmetic.py +++ b/xarray/core/arithmetic.py @@ -1,4 +1,6 @@ """Base classes implementing arithmetic for xarray objects.""" +from __future__ import annotations + import numbers import numpy as np diff --git a/xarray/core/dask_array_compat.py b/xarray/core/dask_array_compat.py index e114c238b72..b53947e88eb 100644 --- a/xarray/core/dask_array_compat.py +++ b/xarray/core/dask_array_compat.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import warnings import numpy as np diff --git a/xarray/core/dask_array_ops.py b/xarray/core/dask_array_ops.py index fa497dbca20..8739067b083 100644 --- a/xarray/core/dask_array_ops.py +++ b/xarray/core/dask_array_ops.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from . import dtypes, nputils diff --git a/xarray/core/dtypes.py b/xarray/core/dtypes.py index 1e87e782fb2..d5371e9629a 100644 --- a/xarray/core/dtypes.py +++ b/xarray/core/dtypes.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import functools import numpy as np diff --git a/xarray/core/duck_array_ops.py b/xarray/core/duck_array_ops.py index 5f09abdbcfd..6e73ee41b40 100644 --- a/xarray/core/duck_array_ops.py +++ b/xarray/core/duck_array_ops.py @@ -3,6 +3,8 @@ Currently, this means Dask or NumPy arrays. None of these functions should accept or return xarray objects. """ +from __future__ import annotations + import contextlib import datetime import inspect diff --git a/xarray/core/extensions.py b/xarray/core/extensions.py index 3debefe2e0d..84d184dcaca 100644 --- a/xarray/core/extensions.py +++ b/xarray/core/extensions.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import warnings from .dataarray import DataArray diff --git a/xarray/core/formatting.py b/xarray/core/formatting.py index e372e3bdd40..bd08f0bf9d8 100644 --- a/xarray/core/formatting.py +++ b/xarray/core/formatting.py @@ -1,11 +1,13 @@ """String formatting routines for __repr__. """ +from __future__ import annotations + import contextlib import functools from collections import defaultdict from datetime import datetime, timedelta from itertools import chain, zip_longest -from typing import Collection, Hashable, Optional +from typing import Collection, Hashable import numpy as np import pandas as pd @@ -425,7 +427,7 @@ def dim_summary(obj): def _element_formatter( elements: Collection[Hashable], col_width: int, - max_rows: Optional[int] = None, + max_rows: int | None = None, delimiter: str = ", ", ) -> str: """ @@ -477,12 +479,12 @@ def _element_formatter( return "".join(out) -def dim_summary_limited(obj, col_width: int, max_rows: Optional[int] = None) -> str: +def dim_summary_limited(obj, col_width: int, max_rows: int | None = None) -> str: elements = [f"{k}: {v}" for k, v in obj.sizes.items()] return _element_formatter(elements, col_width, max_rows) -def unindexed_dims_repr(dims, coords, max_rows: Optional[int] = None): +def unindexed_dims_repr(dims, coords, max_rows: int | None = None): unindexed_dims = [d for d in dims if d not in coords] if unindexed_dims: dims_start = "Dimensions without coordinates: " diff --git a/xarray/core/formatting_html.py b/xarray/core/formatting_html.py index db62466a8d3..ed36547e3b5 100644 --- a/xarray/core/formatting_html.py +++ b/xarray/core/formatting_html.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import uuid from collections import OrderedDict from functools import lru_cache, partial diff --git a/xarray/core/nanops.py b/xarray/core/nanops.py index fa96bd6e150..d02d129aeba 100644 --- a/xarray/core/nanops.py +++ b/xarray/core/nanops.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import warnings import numpy as np diff --git a/xarray/core/nputils.py b/xarray/core/nputils.py index 1feb97c5aa4..d1131168c1f 100644 --- a/xarray/core/nputils.py +++ b/xarray/core/nputils.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import warnings import numpy as np diff --git a/xarray/core/ops.py b/xarray/core/ops.py index 8265035a25c..07b5a0b56fe 100644 --- a/xarray/core/ops.py +++ b/xarray/core/ops.py @@ -4,6 +4,7 @@ NumPy's __array_ufunc__ and mixin classes instead of the unintuitive "inject" functions. """ +from __future__ import annotations import operator diff --git a/xarray/core/options.py b/xarray/core/options.py index b8f420e5117..6798c447a2d 100644 --- a/xarray/core/options.py +++ b/xarray/core/options.py @@ -1,5 +1,7 @@ +from __future__ import annotations + import warnings -from typing import TYPE_CHECKING, Literal, TypedDict, Union +from typing import TYPE_CHECKING, Literal, TypedDict from .utils import FrozenDict @@ -30,8 +32,8 @@ class T_Options(TypedDict): arithmetic_join: Literal["inner", "outer", "left", "right", "exact"] - cmap_divergent: Union[str, "Colormap"] - cmap_sequential: Union[str, "Colormap"] + cmap_divergent: str | Colormap + cmap_sequential: str | Colormap display_max_rows: int display_values_threshold: int display_style: Literal["text", "html"] @@ -48,7 +50,7 @@ class T_Options(TypedDict): use_flox: bool -OPTIONS: "T_Options" = { +OPTIONS: T_Options = { "arithmetic_join": "inner", "cmap_divergent": "RdBu_r", "cmap_sequential": "viridis", @@ -115,7 +117,7 @@ def _warn_on_setting_enable_cftimeindex(enable_cftimeindex): } -def _get_boolean_with_default(option: "Options", default: bool) -> bool: +def _get_boolean_with_default(option: Options, default: bool) -> bool: global_choice = OPTIONS[option] if global_choice == "default": diff --git a/xarray/core/pdcompat.py b/xarray/core/pdcompat.py index fb4d951888b..7a4b3c405ae 100644 --- a/xarray/core/pdcompat.py +++ b/xarray/core/pdcompat.py @@ -33,6 +33,7 @@ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +from __future__ import annotations def count_not_none(*args) -> int: diff --git a/xarray/core/pycompat.py b/xarray/core/pycompat.py index 972d9500777..09ee13e4941 100644 --- a/xarray/core/pycompat.py +++ b/xarray/core/pycompat.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from importlib import import_module import numpy as np diff --git a/xarray/core/resample.py b/xarray/core/resample.py index bcc4bfb90cd..e38deb3e440 100644 --- a/xarray/core/resample.py +++ b/xarray/core/resample.py @@ -1,5 +1,7 @@ +from __future__ import annotations + import warnings -from typing import Any, Callable, Hashable, Sequence, Union +from typing import Any, Callable, Hashable, Sequence import numpy as np @@ -345,9 +347,9 @@ def apply(self, func, args=(), shortcut=None, **kwargs): def reduce( self, func: Callable[..., Any], - dim: Union[None, Hashable, Sequence[Hashable]] = None, + dim: None | Hashable | Sequence[Hashable] = None, *, - axis: Union[None, int, Sequence[int]] = None, + axis: None | int | Sequence[int] = None, keep_attrs: bool = None, keepdims: bool = False, **kwargs: Any, diff --git a/xarray/core/resample_cftime.py b/xarray/core/resample_cftime.py index 4a413902b90..11eceda77ee 100644 --- a/xarray/core/resample_cftime.py +++ b/xarray/core/resample_cftime.py @@ -35,6 +35,7 @@ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. +from __future__ import annotations import datetime diff --git a/xarray/core/rolling.py b/xarray/core/rolling.py index f2ac9d979ae..bfbf7c8f34e 100644 --- a/xarray/core/rolling.py +++ b/xarray/core/rolling.py @@ -1,7 +1,9 @@ +from __future__ import annotations + import functools import itertools import warnings -from typing import Any, Callable, Dict +from typing import Any, Callable import numpy as np @@ -928,7 +930,7 @@ def _reduce_method( Return a wrapped function for injecting reduction methods. see ops.inject_reduce_methods """ - kwargs: Dict[str, Any] = {} + kwargs: dict[str, Any] = {} if include_skipna: kwargs["skipna"] = None @@ -1012,7 +1014,7 @@ def _reduce_method( Return a wrapped function for injecting reduction methods. see ops.inject_reduce_methods """ - kwargs: Dict[str, Any] = {} + kwargs: dict[str, Any] = {} if include_skipna: kwargs["skipna"] = None From 64df5555528bcbefef789a88a59fa7697ba476cf Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 10:42:51 +0200 Subject: [PATCH 08/21] add from __future__ import annotations to plot --- xarray/plot/dataset_plot.py | 2 ++ xarray/plot/facetgrid.py | 2 ++ xarray/plot/plot.py | 2 ++ xarray/plot/utils.py | 6 ++++-- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/xarray/plot/dataset_plot.py b/xarray/plot/dataset_plot.py index 527ae121dcf..aeb53126265 100644 --- a/xarray/plot/dataset_plot.py +++ b/xarray/plot/dataset_plot.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import functools import numpy as np diff --git a/xarray/plot/facetgrid.py b/xarray/plot/facetgrid.py index f3daeeb7f3f..01ba00b2b94 100644 --- a/xarray/plot/facetgrid.py +++ b/xarray/plot/facetgrid.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import functools import itertools import warnings diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py index af860b22635..ae0adfff00b 100644 --- a/xarray/plot/plot.py +++ b/xarray/plot/plot.py @@ -6,6 +6,8 @@ DataArray.plot._____ Dataset.plot._____ """ +from __future__ import annotations + import functools import numpy as np diff --git a/xarray/plot/utils.py b/xarray/plot/utils.py index d942f6656ba..eb45d94d753 100644 --- a/xarray/plot/utils.py +++ b/xarray/plot/utils.py @@ -1,9 +1,11 @@ +from __future__ import annotations + import itertools import textwrap import warnings from datetime import datetime from inspect import getfullargspec -from typing import Any, Iterable, Mapping, Tuple, Union +from typing import Any, Iterable, Mapping import numpy as np import pandas as pd @@ -836,7 +838,7 @@ def _process_cmap_cbar_kwargs( data, cmap=None, colors=None, - cbar_kwargs: Union[Iterable[Tuple[str, Any]], Mapping[str, Any]] = None, + cbar_kwargs: Iterable[tuple[str, Any]] | Mapping[str, Any] = None, levels=None, _is_facetgrid=False, **kwargs, From bfa82f151426f98d1205a56b1ce46ac7be89101e Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 10:45:51 +0200 Subject: [PATCH 09/21] add from __future__ import annotations to backends --- xarray/backends/cfgrib_.py | 2 ++ xarray/backends/file_manager.py | 6 ++++-- xarray/backends/h5netcdf_.py | 2 ++ xarray/backends/locks.py | 6 ++++-- xarray/backends/lru_cache.py | 8 +++++--- xarray/backends/memory.py | 2 ++ xarray/backends/netCDF4_.py | 2 ++ xarray/backends/netcdf3.py | 2 ++ xarray/backends/plugins.py | 2 ++ xarray/backends/pseudonetcdf_.py | 2 ++ xarray/backends/pydap_.py | 2 ++ xarray/backends/pynio_.py | 2 ++ xarray/backends/rasterio_.py | 2 ++ xarray/backends/scipy_.py | 2 ++ xarray/backends/store.py | 2 ++ xarray/backends/zarr.py | 2 ++ 16 files changed, 39 insertions(+), 7 deletions(-) diff --git a/xarray/backends/cfgrib_.py b/xarray/backends/cfgrib_.py index e7aeaaba83a..8e8c8616aec 100644 --- a/xarray/backends/cfgrib_.py +++ b/xarray/backends/cfgrib_.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os import warnings diff --git a/xarray/backends/file_manager.py b/xarray/backends/file_manager.py index 06be03e4e44..e49555f780e 100644 --- a/xarray/backends/file_manager.py +++ b/xarray/backends/file_manager.py @@ -1,8 +1,10 @@ +from __future__ import annotations + import contextlib import io import threading import warnings -from typing import Any, Dict +from typing import Any from ..core import utils from ..core.options import OPTIONS @@ -16,7 +18,7 @@ assert FILE_CACHE.maxsize, "file cache must be at least size one" -REF_COUNTS: Dict[Any, int] = {} +REF_COUNTS: dict[Any, int] = {} _DEFAULT_MODE = utils.ReprObject("") diff --git a/xarray/backends/h5netcdf_.py b/xarray/backends/h5netcdf_.py index 70fc3a76266..2780465ffed 100644 --- a/xarray/backends/h5netcdf_.py +++ b/xarray/backends/h5netcdf_.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import functools import io import os diff --git a/xarray/backends/locks.py b/xarray/backends/locks.py index 1cc93779843..e9b80f03ce8 100644 --- a/xarray/backends/locks.py +++ b/xarray/backends/locks.py @@ -1,7 +1,9 @@ +from __future__ import annotations + import multiprocessing import threading import weakref -from typing import Any, MutableMapping, Optional +from typing import Any, MutableMapping try: from dask.utils import SerializableLock @@ -62,7 +64,7 @@ def _get_lock_maker(scheduler=None): return _LOCK_MAKERS[scheduler] -def _get_scheduler(get=None, collection=None) -> Optional[str]: +def _get_scheduler(get=None, collection=None) -> str | None: """Determine the dask scheduler that is being used. None is returned if no dask scheduler is active. diff --git a/xarray/backends/lru_cache.py b/xarray/backends/lru_cache.py index 48030903036..0f7f4c23b2e 100644 --- a/xarray/backends/lru_cache.py +++ b/xarray/backends/lru_cache.py @@ -1,6 +1,8 @@ +from __future__ import annotations + import threading from collections import OrderedDict -from typing import Any, Callable, Iterator, MutableMapping, Optional, TypeVar +from typing import Any, Callable, Iterator, MutableMapping, TypeVar K = TypeVar("K") V = TypeVar("V") @@ -21,10 +23,10 @@ class LRUCache(MutableMapping[K, V]): the cache, e.g., ``cache.maxsize = new_size``. """ - _cache: "OrderedDict[K, V]" + _cache: OrderedDict[K, V] _maxsize: int _lock: threading.RLock - _on_evict: Optional[Callable[[K, V], Any]] + _on_evict: Callable[[K, V], Any] | None __slots__ = ("_cache", "_lock", "_maxsize", "_on_evict") diff --git a/xarray/backends/memory.py b/xarray/backends/memory.py index 17095d09651..6b00a78dd64 100644 --- a/xarray/backends/memory.py +++ b/xarray/backends/memory.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import copy import numpy as np diff --git a/xarray/backends/netCDF4_.py b/xarray/backends/netCDF4_.py index bc28e89b018..19047d17c6c 100644 --- a/xarray/backends/netCDF4_.py +++ b/xarray/backends/netCDF4_.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import functools import operator import os diff --git a/xarray/backends/netcdf3.py b/xarray/backends/netcdf3.py index 5fdd0534d57..572962f7ad5 100644 --- a/xarray/backends/netcdf3.py +++ b/xarray/backends/netcdf3.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import unicodedata import numpy as np diff --git a/xarray/backends/plugins.py b/xarray/backends/plugins.py index 44953b875d9..c1f70b24c80 100644 --- a/xarray/backends/plugins.py +++ b/xarray/backends/plugins.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import functools import inspect import itertools diff --git a/xarray/backends/pseudonetcdf_.py b/xarray/backends/pseudonetcdf_.py index a2ca7f0206c..088feb3f3e0 100644 --- a/xarray/backends/pseudonetcdf_.py +++ b/xarray/backends/pseudonetcdf_.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np from ..core import indexing diff --git a/xarray/backends/pydap_.py b/xarray/backends/pydap_.py index a5a1430abf2..60e3d047b61 100644 --- a/xarray/backends/pydap_.py +++ b/xarray/backends/pydap_.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np from ..core import indexing diff --git a/xarray/backends/pynio_.py b/xarray/backends/pynio_.py index 4e912f3e1ef..c2bbbd893ea 100644 --- a/xarray/backends/pynio_.py +++ b/xarray/backends/pynio_.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np from ..core import indexing diff --git a/xarray/backends/rasterio_.py b/xarray/backends/rasterio_.py index 7f3791ffca2..218d2bac178 100644 --- a/xarray/backends/rasterio_.py +++ b/xarray/backends/rasterio_.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os import warnings diff --git a/xarray/backends/scipy_.py b/xarray/backends/scipy_.py index df3ee364546..cded2f6a0b6 100644 --- a/xarray/backends/scipy_.py +++ b/xarray/backends/scipy_.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import gzip import io import os diff --git a/xarray/backends/store.py b/xarray/backends/store.py index b774d2bce95..39b84b6c202 100644 --- a/xarray/backends/store.py +++ b/xarray/backends/store.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from .. import conventions from ..core.dataset import Dataset from .common import BACKEND_ENTRYPOINTS, AbstractDataStore, BackendEntrypoint diff --git a/xarray/backends/zarr.py b/xarray/backends/zarr.py index 104f8aca58f..b987760634d 100644 --- a/xarray/backends/zarr.py +++ b/xarray/backends/zarr.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json import os import warnings From bf120461ff928f7eba325686b6c9511be3a14082 Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 10:47:17 +0200 Subject: [PATCH 10/21] add from __future__ import annotations to coding --- xarray/coding/calendar_ops.py | 2 ++ xarray/coding/frequencies.py | 1 + xarray/coding/strings.py | 2 ++ xarray/coding/times.py | 4 +++- xarray/coding/variables.py | 2 ++ 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/xarray/coding/calendar_ops.py b/xarray/coding/calendar_ops.py index 7b973c8d7ab..a78ce3052bb 100644 --- a/xarray/coding/calendar_ops.py +++ b/xarray/coding/calendar_ops.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np import pandas as pd diff --git a/xarray/coding/frequencies.py b/xarray/coding/frequencies.py index e9efef8eb7a..c43f39f1cc3 100644 --- a/xarray/coding/frequencies.py +++ b/xarray/coding/frequencies.py @@ -39,6 +39,7 @@ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +from __future__ import annotations import numpy as np import pandas as pd diff --git a/xarray/coding/strings.py b/xarray/coding/strings.py index e4b1e906160..0a11388e42f 100644 --- a/xarray/coding/strings.py +++ b/xarray/coding/strings.py @@ -1,4 +1,6 @@ """Coders for strings.""" +from __future__ import annotations + from functools import partial import numpy as np diff --git a/xarray/coding/times.py b/xarray/coding/times.py index eb8c1dbc42a..00f565e7352 100644 --- a/xarray/coding/times.py +++ b/xarray/coding/times.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import re import warnings from datetime import datetime, timedelta @@ -348,7 +350,7 @@ def _infer_time_units_from_diff(unique_timedeltas): return "seconds" -def infer_calendar_name(dates) -> "CFCalendar": +def infer_calendar_name(dates) -> CFCalendar: """Given an array of datetimes, infer the CF calendar name""" if is_np_datetime_like(dates.dtype): return "proleptic_gregorian" diff --git a/xarray/coding/variables.py b/xarray/coding/variables.py index 1ebaab1be02..3e3d8b07e3d 100644 --- a/xarray/coding/variables.py +++ b/xarray/coding/variables.py @@ -1,4 +1,6 @@ """Coders for individual Variable objects.""" +from __future__ import annotations + import warnings from functools import partial from typing import Any, Hashable From afd351d547ac8043ec0080bef8a1165bb8811560 Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 13:35:34 +0200 Subject: [PATCH 11/21] fix typing of test_accessor_str --- xarray/core/accessor_str.py | 46 +- xarray/plot/utils.py | 2 +- xarray/tests/test_accessor_str.py | 915 +++++++++++++++++------------- 3 files changed, 530 insertions(+), 433 deletions(-) diff --git a/xarray/core/accessor_str.py b/xarray/core/accessor_str.py index 7f65b3add9b..3174ed95b8e 100644 --- a/xarray/core/accessor_str.py +++ b/xarray/core/accessor_str.py @@ -224,7 +224,7 @@ def _apply( output_sizes: Mapping[Any, int] = None, func_args: tuple = (), func_kwargs: Mapping = {}, - ) -> Any: + ) -> T_DataArray: return _apply_str_ufunc( obj=self._obj, func=func, @@ -240,7 +240,7 @@ def _re_compile( *, pat: str | bytes | Pattern | Any, flags: int = 0, - case: bool = None, + case: bool | None = None, ) -> Pattern | Any: is_compiled_re = isinstance(pat, re.Pattern) @@ -288,7 +288,7 @@ def len(self) -> T_DataArray: def __getitem__( self, key: int | slice, - ) -> Any: + ) -> T_DataArray: if isinstance(key, slice): return self.slice(start=key.start, stop=key.stop, step=key.step) else: @@ -300,13 +300,13 @@ def __add__(self, other: Any) -> T_DataArray: def __mul__( self, num: int | Any, - ) -> Any: + ) -> T_DataArray: return self.repeat(num) def __mod__( self, other: Any, - ) -> Any: + ) -> T_DataArray: if isinstance(other, dict): other = {key: self._stringify(val) for key, val in other.items()} return self._apply(func=lambda x: x % other) @@ -320,7 +320,7 @@ def get( self, i: int | Any, default: str | bytes = "", - ) -> Any: + ) -> T_DataArray: """ Extract character number `i` from each string in the array. @@ -332,9 +332,8 @@ def get( i : int or array-like of int Position of element to extract. If array-like, it is broadcast. - default : optional - Value for out-of-range index. If not specified (None) defaults to - an empty string. + default : str or bytes, default: "" + Value for out-of-range index. Returns ------- @@ -351,10 +350,10 @@ def f(x, iind): def slice( self, - start: int | Any = None, - stop: int | Any = None, - step: int | Any = None, - ) -> Any: + start: int | Any | None = None, + stop: int | Any | None = None, + step: int | Any | None = None, + ) -> T_DataArray: """ Slice substrings from each string in the array. @@ -382,10 +381,10 @@ def slice( def slice_replace( self, - start: int | Any = None, - stop: int | Any = None, + start: int | Any | None = None, + stop: int | Any | None = None, repl: str | bytes | Any = "", - ) -> Any: + ) -> T_DataArray: """ Replace a positional slice of a string with another value. @@ -402,7 +401,7 @@ def slice_replace( Right index position to use for the slice. If not specified (None), the slice is unbounded on the right, i.e. slice until the end of the string. If array-like, it is broadcast. - repl : str or array-like of str, optional + repl : str or array-like of str, default: "" String for replacement. If not specified, the sliced region is replaced with an empty string. If array-like, it is broadcast. @@ -1316,14 +1315,15 @@ def wrap(self, width: int | Any, **kwargs) -> T_DataArray: func = lambda x, itw: "\n".join(itw.wrap(x)) return self._apply(func=func, func_args=(tw,)) - def translate(self, table: Mapping[str | bytes, str | bytes]) -> T_DataArray: + # Mapping is only covariant in its values, maybe use a custom CovariantMapping? + def translate(self, table: Mapping[Any, str | bytes | int | None]) -> T_DataArray: """ Map characters of each string through the given mapping table. Parameters ---------- - table : dict - A a mapping of Unicode ordinals to Unicode ordinals, strings, + table : dict-like from and to str or bytes or int + A a mapping of Unicode ordinals to Unicode ordinals, strings, int or None. Unmapped characters are left untouched. Characters mapped to None are deleted. :meth:`str.maketrans` is a helper function for making translation tables. @@ -1604,7 +1604,7 @@ def extract( dim: Hashable, case: bool = None, flags: int = 0, - ) -> Any: + ) -> T_DataArray: r""" Extract the first match of capture groups in the regex pat as a new dimension in a DataArray. @@ -1749,7 +1749,7 @@ def extractall( match_dim: Hashable, case: bool = None, flags: int = 0, - ) -> Any: + ) -> T_DataArray: r""" Extract all matches of capture groups in the regex pat as new dimensions in a DataArray. @@ -1922,7 +1922,7 @@ def findall( pat: str | bytes | Pattern | Any, case: bool = None, flags: int = 0, - ) -> Any: + ) -> T_DataArray: r""" Find all occurrences of pattern or regular expression in the DataArray. diff --git a/xarray/plot/utils.py b/xarray/plot/utils.py index eb45d94d753..aef21f0be42 100644 --- a/xarray/plot/utils.py +++ b/xarray/plot/utils.py @@ -838,7 +838,7 @@ def _process_cmap_cbar_kwargs( data, cmap=None, colors=None, - cbar_kwargs: Iterable[tuple[str, Any]] | Mapping[str, Any] = None, + cbar_kwargs: Iterable[tuple[str, Any]] | Mapping[str, Any] | None = None, levels=None, _is_facetgrid=False, **kwargs, diff --git a/xarray/tests/test_accessor_str.py b/xarray/tests/test_accessor_str.py index e3c45d732e4..ec1d6cbdc7a 100644 --- a/xarray/tests/test_accessor_str.py +++ b/xarray/tests/test_accessor_str.py @@ -36,10 +36,10 @@ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# type: ignore[assignment] +from __future__ import annotations import re +from typing import Callable import numpy as np import pytest @@ -49,7 +49,9 @@ from . import assert_equal, assert_identical, requires_dask -@pytest.fixture(params=[np.str_, np.bytes_]) +@pytest.fixture( + params=[pytest.param(np.str_, id="str"), pytest.param(np.bytes_, id="bytes")] +) def dtype(request): return request.param @@ -409,7 +411,7 @@ def test_replace_callable() -> None: # test broadcast values = xr.DataArray(["Foo Bar Baz"], dims=["x"]) pat = r"(?P\w+) (?P\w+) (?P\w+)" - repl = xr.DataArray( + repl2 = xr.DataArray( [ lambda m: m.group("first").swapcase(), lambda m: m.group("middle").swapcase(), @@ -417,7 +419,7 @@ def test_replace_callable() -> None: ], dims=["Y"], ) - result = values.str.replace(pat, repl) + result = values.str.replace(pat, repl2) exp = xr.DataArray([["fOO", "bAR", "bAZ"]], dims=["x", "Y"]) assert result.dtype == exp.dtype assert_equal(result, exp) @@ -438,11 +440,11 @@ def test_replace_unicode() -> None: [[b"abcd, \xc3\xa0".decode("utf-8"), b"BAcd,\xc3\xa0".decode("utf-8")]], dims=["X", "Y"], ) - pat = xr.DataArray( + pat2 = xr.DataArray( [re.compile(r"(?<=\w),(?=\w)", flags=re.UNICODE), r"ab"], dims=["Y"] ) repl = xr.DataArray([", ", "BA"], dims=["Y"]) - result = values.str.replace(pat, repl) + result = values.str.replace(pat2, repl) assert result.dtype == expected.dtype assert_equal(result, expected) @@ -463,16 +465,16 @@ def test_replace_compiled_regex(dtype) -> None: assert_equal(result, expected) # broadcast - pat = xr.DataArray( + pat2 = xr.DataArray( [re.compile(dtype("BAD[_]*")), re.compile(dtype("AD[_]*"))], dims=["y"] ) - result = values.str.replace(pat, "") + result = values.str.replace(pat2, "") expected = xr.DataArray([["foobar", "fooBbarB"]], dims=["x", "y"]).astype(dtype) assert result.dtype == expected.dtype assert_equal(result, expected) repl = xr.DataArray(["", "spam"], dims=["y"]).astype(dtype) - result = values.str.replace(pat, repl, n=1) + result = values.str.replace(pat2, repl, n=1) expected = xr.DataArray([["foobarBAD", "fooBspambarBAD"]], dims=["x", "y"]).astype( dtype ) @@ -482,28 +484,28 @@ def test_replace_compiled_regex(dtype) -> None: # case and flags provided to str.replace will have no effect # and will produce warnings values = xr.DataArray(["fooBAD__barBAD__bad"]).astype(dtype) - pat = re.compile(dtype("BAD[_]*")) + pat3 = re.compile(dtype("BAD[_]*")) with pytest.raises( ValueError, match="Flags cannot be set when pat is a compiled regex." ): - result = values.str.replace(pat, "", flags=re.IGNORECASE) + result = values.str.replace(pat3, "", flags=re.IGNORECASE) with pytest.raises( ValueError, match="Case cannot be set when pat is a compiled regex." ): - result = values.str.replace(pat, "", case=False) + result = values.str.replace(pat3, "", case=False) with pytest.raises( ValueError, match="Case cannot be set when pat is a compiled regex." ): - result = values.str.replace(pat, "", case=True) + result = values.str.replace(pat3, "", case=True) # test with callable values = xr.DataArray(["fooBAD__barBAD"]).astype(dtype) - repl = lambda m: m.group(0).swapcase() - pat = re.compile(dtype("[a-z][A-Z]{2}")) - result = values.str.replace(pat, repl, n=2) + repl2 = lambda m: m.group(0).swapcase() + pat4 = re.compile(dtype("[a-z][A-Z]{2}")) + result = values.str.replace(pat4, repl2, n=2) expected = xr.DataArray(["foObaD__baRbaD"]).astype(dtype) assert result.dtype == expected.dtype assert_equal(result, expected) @@ -678,8 +680,10 @@ def test_extract_extractall_name_collision_raises(dtype) -> None: def test_extract_single_case(dtype) -> None: pat_str = r"(\w+)_Xy_\d*" - pat_re = pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") - pat_re = re.compile(pat_re) + pat_re: str | bytes = ( + pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") + ) + pat_compiled = re.compile(pat_re) value = xr.DataArray( [ @@ -704,8 +708,8 @@ def test_extract_single_case(dtype) -> None: res_str_dim = value.str.extract(pat=pat_str, dim="XX") res_str_none_case = value.str.extract(pat=pat_str, dim=None, case=True) res_str_dim_case = value.str.extract(pat=pat_str, dim="XX", case=True) - res_re_none = value.str.extract(pat=pat_re, dim=None) - res_re_dim = value.str.extract(pat=pat_re, dim="XX") + res_re_none = value.str.extract(pat=pat_compiled, dim=None) + res_re_dim = value.str.extract(pat=pat_compiled, dim="XX") assert res_str_none.dtype == targ_none.dtype assert res_str_dim.dtype == targ_dim.dtype @@ -724,8 +728,10 @@ def test_extract_single_case(dtype) -> None: def test_extract_single_nocase(dtype) -> None: pat_str = r"(\w+)?_Xy_\d*" - pat_re = pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") - pat_re = re.compile(pat_re, flags=re.IGNORECASE) + pat_re: str | bytes = ( + pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") + ) + pat_compiled = re.compile(pat_re, flags=re.IGNORECASE) value = xr.DataArray( [ @@ -749,7 +755,7 @@ def test_extract_single_nocase(dtype) -> None: res_str_none = value.str.extract(pat=pat_str, dim=None, case=False) res_str_dim = value.str.extract(pat=pat_str, dim="XX", case=False) res_re_none = value.str.extract(pat=pat_re, dim=None) - res_re_dim = value.str.extract(pat=pat_re, dim="XX") + res_re_dim = value.str.extract(pat=pat_compiled, dim="XX") assert res_re_dim.dtype == targ_none.dtype assert res_str_dim.dtype == targ_dim.dtype @@ -764,8 +770,10 @@ def test_extract_single_nocase(dtype) -> None: def test_extract_multi_case(dtype) -> None: pat_str = r"(\w+)_Xy_(\d*)" - pat_re = pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") - pat_re = re.compile(pat_re) + pat_re: str | bytes = ( + pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") + ) + pat_compiled = re.compile(pat_re) value = xr.DataArray( [ @@ -788,7 +796,7 @@ def test_extract_multi_case(dtype) -> None: ).astype(dtype) res_str = value.str.extract(pat=pat_str, dim="XX") - res_re = value.str.extract(pat=pat_re, dim="XX") + res_re = value.str.extract(pat=pat_compiled, dim="XX") res_str_case = value.str.extract(pat=pat_str, dim="XX", case=True) assert res_str.dtype == expected.dtype @@ -802,8 +810,10 @@ def test_extract_multi_case(dtype) -> None: def test_extract_multi_nocase(dtype) -> None: pat_str = r"(\w+)_Xy_(\d*)" - pat_re = pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") - pat_re = re.compile(pat_re, flags=re.IGNORECASE) + pat_re: str | bytes = ( + pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") + ) + pat_compiled = re.compile(pat_re, flags=re.IGNORECASE) value = xr.DataArray( [ @@ -826,7 +836,7 @@ def test_extract_multi_nocase(dtype) -> None: ).astype(dtype) res_str = value.str.extract(pat=pat_str, dim="XX", case=False) - res_re = value.str.extract(pat=pat_re, dim="XX") + res_re = value.str.extract(pat=pat_compiled, dim="XX") assert res_str.dtype == expected.dtype assert res_re.dtype == expected.dtype @@ -845,17 +855,17 @@ def test_extract_broadcast(dtype) -> None: [r"(\w+)_Xy_(\d*)", r"(\w+)_xY_(\d*)"], dims=["Y"], ).astype(dtype) - pat_re = value.str._re_compile(pat=pat_str) + pat_compiled = value.str._re_compile(pat=pat_str) - expected = [ + expected_list = [ [["a", "0"], ["", ""]], [["", ""], ["ab", "10"]], [["abc", "01"], ["", ""]], ] - expected = xr.DataArray(expected, dims=["X", "Y", "Zz"]).astype(dtype) + expected = xr.DataArray(expected_list, dims=["X", "Y", "Zz"]).astype(dtype) res_str = value.str.extract(pat=pat_str, dim="Zz") - res_re = value.str.extract(pat=pat_re, dim="Zz") + res_re = value.str.extract(pat=pat_compiled, dim="Zz") assert res_str.dtype == expected.dtype assert res_re.dtype == expected.dtype @@ -866,8 +876,10 @@ def test_extract_broadcast(dtype) -> None: def test_extractall_single_single_case(dtype) -> None: pat_str = r"(\w+)_Xy_\d*" - pat_re = pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") - pat_re = re.compile(pat_re) + pat_re: str | bytes = ( + pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") + ) + pat_compiled = re.compile(pat_re) value = xr.DataArray( [["a_Xy_0", "ab_xY_10", "abc_Xy_01"], ["abcd_Xy_", "", "abcdef_Xy_101"]], @@ -880,7 +892,7 @@ def test_extractall_single_single_case(dtype) -> None: ).astype(dtype) res_str = value.str.extractall(pat=pat_str, group_dim="XX", match_dim="YY") - res_re = value.str.extractall(pat=pat_re, group_dim="XX", match_dim="YY") + res_re = value.str.extractall(pat=pat_compiled, group_dim="XX", match_dim="YY") res_str_case = value.str.extractall( pat=pat_str, group_dim="XX", match_dim="YY", case=True ) @@ -896,8 +908,10 @@ def test_extractall_single_single_case(dtype) -> None: def test_extractall_single_single_nocase(dtype) -> None: pat_str = r"(\w+)_Xy_\d*" - pat_re = pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") - pat_re = re.compile(pat_re, flags=re.I) + pat_re: str | bytes = ( + pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") + ) + pat_compiled = re.compile(pat_re, flags=re.I) value = xr.DataArray( [["a_Xy_0", "ab_xY_10", "abc_Xy_01"], ["abcd_Xy_", "", "abcdef_Xy_101"]], @@ -912,7 +926,7 @@ def test_extractall_single_single_nocase(dtype) -> None: res_str = value.str.extractall( pat=pat_str, group_dim="XX", match_dim="YY", case=False ) - res_re = value.str.extractall(pat=pat_re, group_dim="XX", match_dim="YY") + res_re = value.str.extractall(pat=pat_compiled, group_dim="XX", match_dim="YY") assert res_str.dtype == expected.dtype assert res_re.dtype == expected.dtype @@ -923,8 +937,10 @@ def test_extractall_single_single_nocase(dtype) -> None: def test_extractall_single_multi_case(dtype) -> None: pat_str = r"(\w+)_Xy_\d*" - pat_re = pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") - pat_re = re.compile(pat_re) + pat_re: str | bytes = ( + pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") + ) + pat_compiled = re.compile(pat_re) value = xr.DataArray( [ @@ -951,7 +967,7 @@ def test_extractall_single_multi_case(dtype) -> None: ).astype(dtype) res_str = value.str.extractall(pat=pat_str, group_dim="XX", match_dim="YY") - res_re = value.str.extractall(pat=pat_re, group_dim="XX", match_dim="YY") + res_re = value.str.extractall(pat=pat_compiled, group_dim="XX", match_dim="YY") res_str_case = value.str.extractall( pat=pat_str, group_dim="XX", match_dim="YY", case=True ) @@ -967,8 +983,10 @@ def test_extractall_single_multi_case(dtype) -> None: def test_extractall_single_multi_nocase(dtype) -> None: pat_str = r"(\w+)_Xy_\d*" - pat_re = pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") - pat_re = re.compile(pat_re, flags=re.I) + pat_re: str | bytes = ( + pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") + ) + pat_compiled = re.compile(pat_re, flags=re.I) value = xr.DataArray( [ @@ -1001,7 +1019,7 @@ def test_extractall_single_multi_nocase(dtype) -> None: res_str = value.str.extractall( pat=pat_str, group_dim="XX", match_dim="YY", case=False ) - res_re = value.str.extractall(pat=pat_re, group_dim="XX", match_dim="YY") + res_re = value.str.extractall(pat=pat_compiled, group_dim="XX", match_dim="YY") assert res_str.dtype == expected.dtype assert res_re.dtype == expected.dtype @@ -1012,8 +1030,10 @@ def test_extractall_single_multi_nocase(dtype) -> None: def test_extractall_multi_single_case(dtype) -> None: pat_str = r"(\w+)_Xy_(\d*)" - pat_re = pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") - pat_re = re.compile(pat_re) + pat_re: str | bytes = ( + pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") + ) + pat_compiled = re.compile(pat_re) value = xr.DataArray( [["a_Xy_0", "ab_xY_10", "abc_Xy_01"], ["abcd_Xy_", "", "abcdef_Xy_101"]], @@ -1029,7 +1049,7 @@ def test_extractall_multi_single_case(dtype) -> None: ).astype(dtype) res_str = value.str.extractall(pat=pat_str, group_dim="XX", match_dim="YY") - res_re = value.str.extractall(pat=pat_re, group_dim="XX", match_dim="YY") + res_re = value.str.extractall(pat=pat_compiled, group_dim="XX", match_dim="YY") res_str_case = value.str.extractall( pat=pat_str, group_dim="XX", match_dim="YY", case=True ) @@ -1045,8 +1065,10 @@ def test_extractall_multi_single_case(dtype) -> None: def test_extractall_multi_single_nocase(dtype) -> None: pat_str = r"(\w+)_Xy_(\d*)" - pat_re = pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") - pat_re = re.compile(pat_re, flags=re.I) + pat_re: str | bytes = ( + pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") + ) + pat_compiled = re.compile(pat_re, flags=re.I) value = xr.DataArray( [["a_Xy_0", "ab_xY_10", "abc_Xy_01"], ["abcd_Xy_", "", "abcdef_Xy_101"]], @@ -1064,7 +1086,7 @@ def test_extractall_multi_single_nocase(dtype) -> None: res_str = value.str.extractall( pat=pat_str, group_dim="XX", match_dim="YY", case=False ) - res_re = value.str.extractall(pat=pat_re, group_dim="XX", match_dim="YY") + res_re = value.str.extractall(pat=pat_compiled, group_dim="XX", match_dim="YY") assert res_str.dtype == expected.dtype assert res_re.dtype == expected.dtype @@ -1075,8 +1097,10 @@ def test_extractall_multi_single_nocase(dtype) -> None: def test_extractall_multi_multi_case(dtype) -> None: pat_str = r"(\w+)_Xy_(\d*)" - pat_re = pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") - pat_re = re.compile(pat_re) + pat_re: str | bytes = ( + pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") + ) + pat_compiled = re.compile(pat_re) value = xr.DataArray( [ @@ -1107,7 +1131,7 @@ def test_extractall_multi_multi_case(dtype) -> None: ).astype(dtype) res_str = value.str.extractall(pat=pat_str, group_dim="XX", match_dim="YY") - res_re = value.str.extractall(pat=pat_re, group_dim="XX", match_dim="YY") + res_re = value.str.extractall(pat=pat_compiled, group_dim="XX", match_dim="YY") res_str_case = value.str.extractall( pat=pat_str, group_dim="XX", match_dim="YY", case=True ) @@ -1123,8 +1147,10 @@ def test_extractall_multi_multi_case(dtype) -> None: def test_extractall_multi_multi_nocase(dtype) -> None: pat_str = r"(\w+)_Xy_(\d*)" - pat_re = pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") - pat_re = re.compile(pat_re, flags=re.I) + pat_re: str | bytes = ( + pat_str if dtype == np.unicode_ else bytes(pat_str, encoding="UTF-8") + ) + pat_compiled = re.compile(pat_re, flags=re.I) value = xr.DataArray( [ @@ -1157,7 +1183,7 @@ def test_extractall_multi_multi_nocase(dtype) -> None: res_str = value.str.extractall( pat=pat_str, group_dim="XX", match_dim="YY", case=False ) - res_re = value.str.extractall(pat=pat_re, group_dim="XX", match_dim="YY") + res_re = value.str.extractall(pat=pat_compiled, group_dim="XX", match_dim="YY") assert res_str.dtype == expected.dtype assert res_re.dtype == expected.dtype @@ -1178,12 +1204,12 @@ def test_extractall_broadcast(dtype) -> None: ).astype(dtype) pat_re = value.str._re_compile(pat=pat_str) - expected = [ + expected_list = [ [[["a", "0"]], [["", ""]]], [[["", ""]], [["ab", "10"]]], [[["abc", "01"]], [["", ""]]], ] - expected = xr.DataArray(expected, dims=["X", "Y", "ZX", "ZY"]).astype(dtype) + expected = xr.DataArray(expected_list, dims=["X", "Y", "ZX", "ZY"]).astype(dtype) res_str = value.str.extractall(pat=pat_str, group_dim="ZX", match_dim="ZY") res_re = value.str.extractall(pat=pat_re, group_dim="ZX", match_dim="ZY") @@ -1204,10 +1230,10 @@ def test_findall_single_single_case(dtype) -> None: dims=["X", "Y"], ).astype(dtype) - expected = [[["a"], [], ["abc"]], [["abcd"], [], ["abcdef"]]] - expected = [[[dtype(x) for x in y] for y in z] for z in expected] - expected = np.array(expected, dtype=np.object_) - expected = xr.DataArray(expected, dims=["X", "Y"]) + expected_list: list[list[list]] = [[["a"], [], ["abc"]], [["abcd"], [], ["abcdef"]]] + expected_dtype = [[[dtype(x) for x in y] for y in z] for z in expected_list] + expected_np = np.array(expected_dtype, dtype=np.object_) + expected = xr.DataArray(expected_np, dims=["X", "Y"]) res_str = value.str.findall(pat=pat_str) res_re = value.str.findall(pat=pat_re) @@ -1231,10 +1257,13 @@ def test_findall_single_single_nocase(dtype) -> None: dims=["X", "Y"], ).astype(dtype) - expected = [[["a"], ["ab"], ["abc"]], [["abcd"], [], ["abcdef"]]] - expected = [[[dtype(x) for x in y] for y in z] for z in expected] - expected = np.array(expected, dtype=np.object_) - expected = xr.DataArray(expected, dims=["X", "Y"]) + expected_list: list[list[list]] = [ + [["a"], ["ab"], ["abc"]], + [["abcd"], [], ["abcdef"]], + ] + expected_dtype = [[[dtype(x) for x in y] for y in z] for z in expected_list] + expected_np = np.array(expected_dtype, dtype=np.object_) + expected = xr.DataArray(expected_np, dims=["X", "Y"]) res_str = value.str.findall(pat=pat_str, case=False) res_re = value.str.findall(pat=pat_re) @@ -1262,7 +1291,7 @@ def test_findall_single_multi_case(dtype) -> None: dims=["X", "Y"], ).astype(dtype) - expected = [ + expected_list: list[list[list]] = [ [["a"], ["bab", "baab"], ["abc", "cbc"]], [ ["abcd", "dcd", "dccd"], @@ -1270,9 +1299,9 @@ def test_findall_single_multi_case(dtype) -> None: ["abcdef", "fef"], ], ] - expected = [[[dtype(x) for x in y] for y in z] for z in expected] - expected = np.array(expected, dtype=np.object_) - expected = xr.DataArray(expected, dims=["X", "Y"]) + expected_dtype = [[[dtype(x) for x in y] for y in z] for z in expected_list] + expected_np = np.array(expected_dtype, dtype=np.object_) + expected = xr.DataArray(expected_np, dims=["X", "Y"]) res_str = value.str.findall(pat=pat_str) res_re = value.str.findall(pat=pat_re) @@ -1303,7 +1332,7 @@ def test_findall_single_multi_nocase(dtype) -> None: dims=["X", "Y"], ).astype(dtype) - expected = [ + expected_list: list[list[list]] = [ [ ["a"], ["ab", "bab", "baab"], @@ -1315,9 +1344,9 @@ def test_findall_single_multi_nocase(dtype) -> None: ["abcdef", "fef"], ], ] - expected = [[[dtype(x) for x in y] for y in z] for z in expected] - expected = np.array(expected, dtype=np.object_) - expected = xr.DataArray(expected, dims=["X", "Y"]) + expected_dtype = [[[dtype(x) for x in y] for y in z] for z in expected_list] + expected_np = np.array(expected_dtype, dtype=np.object_) + expected = xr.DataArray(expected_np, dims=["X", "Y"]) res_str = value.str.findall(pat=pat_str, case=False) res_re = value.str.findall(pat=pat_re) @@ -1338,13 +1367,15 @@ def test_findall_multi_single_case(dtype) -> None: dims=["X", "Y"], ).astype(dtype) - expected = [ + expected_list: list[list[list[list]]] = [ [[["a", "0"]], [], [["abc", "01"]]], [[["abcd", ""]], [], [["abcdef", "101"]]], ] - expected = [[[tuple(dtype(x) for x in y) for y in z] for z in w] for w in expected] - expected = np.array(expected, dtype=np.object_) - expected = xr.DataArray(expected, dims=["X", "Y"]) + expected_dtype = [ + [[tuple(dtype(x) for x in y) for y in z] for z in w] for w in expected_list + ] + expected_np = np.array(expected_dtype, dtype=np.object_) + expected = xr.DataArray(expected_np, dims=["X", "Y"]) res_str = value.str.findall(pat=pat_str) res_re = value.str.findall(pat=pat_re) @@ -1368,13 +1399,15 @@ def test_findall_multi_single_nocase(dtype) -> None: dims=["X", "Y"], ).astype(dtype) - expected = [ + expected_list: list[list[list[list]]] = [ [[["a", "0"]], [["ab", "10"]], [["abc", "01"]]], [[["abcd", ""]], [], [["abcdef", "101"]]], ] - expected = [[[tuple(dtype(x) for x in y) for y in z] for z in w] for w in expected] - expected = np.array(expected, dtype=np.object_) - expected = xr.DataArray(expected, dims=["X", "Y"]) + expected_dtype = [ + [[tuple(dtype(x) for x in y) for y in z] for z in w] for w in expected_list + ] + expected_np = np.array(expected_dtype, dtype=np.object_) + expected = xr.DataArray(expected_np, dims=["X", "Y"]) res_str = value.str.findall(pat=pat_str, case=False) res_re = value.str.findall(pat=pat_re) @@ -1402,7 +1435,7 @@ def test_findall_multi_multi_case(dtype) -> None: dims=["X", "Y"], ).astype(dtype) - expected = [ + expected_list: list[list[list[list]]] = [ [ [["a", "0"]], [["bab", "110"], ["baab", "1100"]], @@ -1414,9 +1447,11 @@ def test_findall_multi_multi_case(dtype) -> None: [["abcdef", "101"], ["fef", "5543210"]], ], ] - expected = [[[tuple(dtype(x) for x in y) for y in z] for z in w] for w in expected] - expected = np.array(expected, dtype=np.object_) - expected = xr.DataArray(expected, dims=["X", "Y"]) + expected_dtype = [ + [[tuple(dtype(x) for x in y) for y in z] for z in w] for w in expected_list + ] + expected_np = np.array(expected_dtype, dtype=np.object_) + expected = xr.DataArray(expected_np, dims=["X", "Y"]) res_str = value.str.findall(pat=pat_str) res_re = value.str.findall(pat=pat_re) @@ -1447,7 +1482,7 @@ def test_findall_multi_multi_nocase(dtype) -> None: dims=["X", "Y"], ).astype(dtype) - expected = [ + expected_list: list[list[list[list]]] = [ [ [["a", "0"]], [["ab", "10"], ["bab", "110"], ["baab", "1100"]], @@ -1459,9 +1494,11 @@ def test_findall_multi_multi_nocase(dtype) -> None: [["abcdef", "101"], ["fef", "5543210"]], ], ] - expected = [[[tuple(dtype(x) for x in y) for y in z] for z in w] for w in expected] - expected = np.array(expected, dtype=np.object_) - expected = xr.DataArray(expected, dims=["X", "Y"]) + expected_dtype = [ + [[tuple(dtype(x) for x in y) for y in z] for z in w] for w in expected_list + ] + expected_np = np.array(expected_dtype, dtype=np.object_) + expected = xr.DataArray(expected_np, dims=["X", "Y"]) res_str = value.str.findall(pat=pat_str, case=False) res_re = value.str.findall(pat=pat_re) @@ -1485,10 +1522,10 @@ def test_findall_broadcast(dtype) -> None: ).astype(dtype) pat_re = value.str._re_compile(pat=pat_str) - expected = [[["a"], ["0"]], [[], []], [["abc"], ["01"]]] - expected = [[[dtype(x) for x in y] for y in z] for z in expected] - expected = np.array(expected, dtype=np.object_) - expected = xr.DataArray(expected, dims=["X", "Y"]) + expected_list: list[list[list]] = [[["a"], ["0"]], [[], []], [["abc"], ["01"]]] + expected_dtype = [[[dtype(x) for x in y] for y in z] for z in expected_list] + expected_np = np.array(expected_dtype, dtype=np.object_) + expected = xr.DataArray(expected_np, dims=["X", "Y"]) res_str = value.str.findall(pat=pat_str) res_re = value.str.findall(pat=pat_re) @@ -1654,50 +1691,58 @@ def test_empty_str_methods() -> None: assert_equal(empty_str, empty.str.translate(table)) -def test_ismethods(dtype) -> None: - values = ["A", "b", "Xy", "4", "3A", "", "TT", "55", "-", " "] - - exp_alnum = [True, True, True, True, True, False, True, True, False, False] - exp_alpha = [True, True, True, False, False, False, True, False, False, False] - exp_digit = [False, False, False, True, False, False, False, True, False, False] - exp_space = [False, False, False, False, False, False, False, False, False, True] - exp_lower = [False, True, False, False, False, False, False, False, False, False] - exp_upper = [True, False, False, False, True, False, True, False, False, False] - exp_title = [True, False, True, False, True, False, False, False, False, False] - - values = xr.DataArray(values).astype(dtype) - - exp_alnum = xr.DataArray(exp_alnum) - exp_alpha = xr.DataArray(exp_alpha) - exp_digit = xr.DataArray(exp_digit) - exp_space = xr.DataArray(exp_space) - exp_lower = xr.DataArray(exp_lower) - exp_upper = xr.DataArray(exp_upper) - exp_title = xr.DataArray(exp_title) - - res_alnum = values.str.isalnum() - res_alpha = values.str.isalpha() - res_digit = values.str.isdigit() - res_lower = values.str.islower() - res_space = values.str.isspace() - res_title = values.str.istitle() - res_upper = values.str.isupper() - - assert res_alnum.dtype == exp_alnum.dtype - assert res_alpha.dtype == exp_alpha.dtype - assert res_digit.dtype == exp_digit.dtype - assert res_lower.dtype == exp_lower.dtype - assert res_space.dtype == exp_space.dtype - assert res_title.dtype == exp_title.dtype - assert res_upper.dtype == exp_upper.dtype - - assert_equal(res_alnum, exp_alnum) - assert_equal(res_alpha, exp_alpha) - assert_equal(res_digit, exp_digit) - assert_equal(res_lower, exp_lower) - assert_equal(res_space, exp_space) - assert_equal(res_title, exp_title) - assert_equal(res_upper, exp_upper) +@pytest.mark.parametrize( + ["func", "expected"], + [ + pytest.param( + lambda x: x.str.isalnum(), + [True, True, True, True, True, False, True, True, False, False], + id="isalnum", + ), + pytest.param( + lambda x: x.str.isalpha(), + [True, True, True, False, False, False, True, False, False, False], + id="isalpha", + ), + pytest.param( + lambda x: x.str.isdigit(), + [False, False, False, True, False, False, False, True, False, False], + id="isdigit", + ), + pytest.param( + lambda x: x.str.islower(), + [False, True, False, False, False, False, False, False, False, False], + id="islower", + ), + pytest.param( + lambda x: x.str.isspace(), + [False, False, False, False, False, False, False, False, False, True], + id="isspace", + ), + pytest.param( + lambda x: x.str.istitle(), + [True, False, True, False, True, False, False, False, False, False], + id="istitle", + ), + pytest.param( + lambda x: x.str.isupper(), + [True, False, False, False, True, False, True, False, False, False], + id="isupper", + ), + ], +) +def test_ismethods( + dtype, func: Callable[[xr.DataArray], xr.DataArray], expected: list[bool] +) -> None: + values = xr.DataArray( + ["A", "b", "Xy", "4", "3A", "", "TT", "55", "-", " "] + ).astype(dtype) + + expected_da = xr.DataArray(expected) + actual = func(values) + + assert actual.dtype == expected_da.dtype + assert_equal(actual, expected_da) def test_isnumeric() -> None: @@ -1705,13 +1750,9 @@ def test_isnumeric() -> None: # 0x2605: ★ not number # 0x1378: ፸ ETHIOPIC NUMBER SEVENTY # 0xFF13: 3 Em 3 - values = ["A", "3", "¼", "★", "፸", "3", "four"] - exp_numeric = [False, True, True, False, True, True, False] - exp_decimal = [False, True, False, False, False, True, False] - - values = xr.DataArray(values) - exp_numeric = xr.DataArray(exp_numeric) - exp_decimal = xr.DataArray(exp_decimal) + values = xr.DataArray(["A", "3", "¼", "★", "፸", "3", "four"]) + exp_numeric = xr.DataArray([False, True, True, False, True, True, False]) + exp_decimal = xr.DataArray([False, True, False, False, False, True, False]) res_numeric = values.str.isnumeric() res_decimal = values.str.isdecimal() @@ -2430,7 +2471,7 @@ def test_partition_whitespace(dtype) -> None: dims=["X", "Y"], ).astype(dtype) - exp_part_dim = [ + exp_part_dim_list = [ [ ["abc", " ", "def"], ["spam", " ", "eggs swallow"], @@ -2443,7 +2484,7 @@ def test_partition_whitespace(dtype) -> None: ], ] - exp_rpart_dim = [ + exp_rpart_dim_list = [ [ ["abc", " ", "def"], ["spam eggs", " ", "swallow"], @@ -2456,8 +2497,10 @@ def test_partition_whitespace(dtype) -> None: ], ] - exp_part_dim = xr.DataArray(exp_part_dim, dims=["X", "Y", "ZZ"]).astype(dtype) - exp_rpart_dim = xr.DataArray(exp_rpart_dim, dims=["X", "Y", "ZZ"]).astype(dtype) + exp_part_dim = xr.DataArray(exp_part_dim_list, dims=["X", "Y", "ZZ"]).astype(dtype) + exp_rpart_dim = xr.DataArray(exp_rpart_dim_list, dims=["X", "Y", "ZZ"]).astype( + dtype + ) res_part_dim = values.str.partition(dim="ZZ") res_rpart_dim = values.str.rpartition(dim="ZZ") @@ -2478,7 +2521,7 @@ def test_partition_comma(dtype) -> None: dims=["X", "Y"], ).astype(dtype) - exp_part_dim = [ + exp_part_dim_list = [ [ ["abc", ", ", "def"], ["spam", ", ", "eggs, swallow"], @@ -2491,7 +2534,7 @@ def test_partition_comma(dtype) -> None: ], ] - exp_rpart_dim = [ + exp_rpart_dim_list = [ [ ["abc", ", ", "def"], ["spam, eggs", ", ", "swallow"], @@ -2504,8 +2547,10 @@ def test_partition_comma(dtype) -> None: ], ] - exp_part_dim = xr.DataArray(exp_part_dim, dims=["X", "Y", "ZZ"]).astype(dtype) - exp_rpart_dim = xr.DataArray(exp_rpart_dim, dims=["X", "Y", "ZZ"]).astype(dtype) + exp_part_dim = xr.DataArray(exp_part_dim_list, dims=["X", "Y", "ZZ"]).astype(dtype) + exp_rpart_dim = xr.DataArray(exp_rpart_dim_list, dims=["X", "Y", "ZZ"]).astype( + dtype + ) res_part_dim = values.str.partition(sep=", ", dim="ZZ") res_rpart_dim = values.str.rpartition(sep=", ", dim="ZZ") @@ -2527,7 +2572,46 @@ def test_partition_empty(dtype) -> None: assert_equal(res, expected) -def test_split_whitespace(dtype) -> None: +@pytest.mark.parametrize( + ["func", "expected"], + [ + pytest.param( + lambda x: x.str.split(dim=None), + [ + [["abc", "def"], ["spam", "eggs", "swallow"], ["red_blue"]], + [["test0", "test1", "test2", "test3"], [], ["abra", "ka", "da", "bra"]], + ], + id="split_full", + ), + pytest.param( + lambda x: x.str.rsplit(dim=None), + [ + [["abc", "def"], ["spam", "eggs", "swallow"], ["red_blue"]], + [["test0", "test1", "test2", "test3"], [], ["abra", "ka", "da", "bra"]], + ], + id="rsplit_full", + ), + pytest.param( + lambda x: x.str.split(dim=None, maxsplit=1), + [ + [["abc", "def"], ["spam", "eggs\tswallow"], ["red_blue"]], + [["test0", "test1\ntest2\n\ntest3"], [], ["abra", "ka\nda\tbra"]], + ], + id="split_1", + ), + pytest.param( + lambda x: x.str.rsplit(dim=None, maxsplit=1), + [ + [["abc", "def"], ["spam\t\teggs", "swallow"], ["red_blue"]], + [["test0\ntest1\ntest2", "test3"], [], ["abra ka\nda", "bra"]], + ], + id="rsplit_1", + ), + ], +) +def test_split_whitespace_nodim( + dtype, func: Callable[[xr.DataArray], xr.DataArray], expected: xr.DataArray +) -> None: values = xr.DataArray( [ ["abc def", "spam\t\teggs\tswallow", "red_blue"], @@ -2536,136 +2620,162 @@ def test_split_whitespace(dtype) -> None: dims=["X", "Y"], ).astype(dtype) - exp_split_dim_full = [ - [ - ["abc", "def", "", ""], - ["spam", "eggs", "swallow", ""], - ["red_blue", "", "", ""], - ], - [ - ["test0", "test1", "test2", "test3"], - ["", "", "", ""], - ["abra", "ka", "da", "bra"], - ], - ] + expected_dtype = [[[dtype(x) for x in y] for y in z] for z in expected] + expected_np = np.array(expected_dtype, dtype=np.object_) + expected_da = xr.DataArray(expected_np, dims=["X", "Y"]) - exp_rsplit_dim_full = [ - [ - ["", "", "abc", "def"], - ["", "spam", "eggs", "swallow"], - ["", "", "", "red_blue"], - ], - [ - ["test0", "test1", "test2", "test3"], - ["", "", "", ""], - ["abra", "ka", "da", "bra"], - ], - ] + actual = func(values) - exp_split_dim_1 = [ - [["abc", "def"], ["spam", "eggs\tswallow"], ["red_blue", ""]], - [["test0", "test1\ntest2\n\ntest3"], ["", ""], ["abra", "ka\nda\tbra"]], - ] + assert actual.dtype == expected_da.dtype + assert_equal(actual, expected_da) - exp_rsplit_dim_1 = [ - [["abc", "def"], ["spam\t\teggs", "swallow"], ["", "red_blue"]], - [["test0\ntest1\ntest2", "test3"], ["", ""], ["abra ka\nda", "bra"]], - ] - - exp_split_none_full = [ - [["abc", "def"], ["spam", "eggs", "swallow"], ["red_blue"]], - [["test0", "test1", "test2", "test3"], [], ["abra", "ka", "da", "bra"]], - ] - - exp_rsplit_none_full = [ - [["abc", "def"], ["spam", "eggs", "swallow"], ["red_blue"]], - [["test0", "test1", "test2", "test3"], [], ["abra", "ka", "da", "bra"]], - ] - exp_split_none_1 = [ - [["abc", "def"], ["spam", "eggs\tswallow"], ["red_blue"]], - [["test0", "test1\ntest2\n\ntest3"], [], ["abra", "ka\nda\tbra"]], - ] +@pytest.mark.parametrize( + ["func", "expected"], + [ + pytest.param( + lambda x: x.str.split(dim="ZZ"), + [ + [ + ["abc", "def", "", ""], + ["spam", "eggs", "swallow", ""], + ["red_blue", "", "", ""], + ], + [ + ["test0", "test1", "test2", "test3"], + ["", "", "", ""], + ["abra", "ka", "da", "bra"], + ], + ], + id="split_full", + ), + pytest.param( + lambda x: x.str.rsplit(dim="ZZ"), + [ + [ + ["", "", "abc", "def"], + ["", "spam", "eggs", "swallow"], + ["", "", "", "red_blue"], + ], + [ + ["test0", "test1", "test2", "test3"], + ["", "", "", ""], + ["abra", "ka", "da", "bra"], + ], + ], + id="rsplit_full", + ), + pytest.param( + lambda x: x.str.split(dim="ZZ", maxsplit=1), + [ + [["abc", "def"], ["spam", "eggs\tswallow"], ["red_blue", ""]], + [["test0", "test1\ntest2\n\ntest3"], ["", ""], ["abra", "ka\nda\tbra"]], + ], + id="split_1", + ), + pytest.param( + lambda x: x.str.rsplit(dim="ZZ", maxsplit=1), + [ + [["abc", "def"], ["spam\t\teggs", "swallow"], ["", "red_blue"]], + [["test0\ntest1\ntest2", "test3"], ["", ""], ["abra ka\nda", "bra"]], + ], + id="rsplit_1", + ), + ], +) +def test_split_whitespace_dim( + dtype, func: Callable[[xr.DataArray], xr.DataArray], expected: xr.DataArray +) -> None: + values = xr.DataArray( + [ + ["abc def", "spam\t\teggs\tswallow", "red_blue"], + ["test0\ntest1\ntest2\n\ntest3", "", "abra ka\nda\tbra"], + ], + dims=["X", "Y"], + ).astype(dtype) - exp_rsplit_none_1 = [ - [["abc", "def"], ["spam\t\teggs", "swallow"], ["red_blue"]], - [["test0\ntest1\ntest2", "test3"], [], ["abra ka\nda", "bra"]], - ] + expected_dtype = [[[dtype(x) for x in y] for y in z] for z in expected] + expected_np = np.array(expected_dtype, dtype=np.object_) + expected_da = xr.DataArray(expected_np, dims=["X", "Y", "ZZ"]).astype(dtype) - exp_split_none_full = [ - [[dtype(x) for x in y] for y in z] for z in exp_split_none_full - ] - exp_rsplit_none_full = [ - [[dtype(x) for x in y] for y in z] for z in exp_rsplit_none_full - ] - exp_split_none_1 = [[[dtype(x) for x in y] for y in z] for z in exp_split_none_1] - exp_rsplit_none_1 = [[[dtype(x) for x in y] for y in z] for z in exp_rsplit_none_1] + actual = func(values) - exp_split_none_full = np.array(exp_split_none_full, dtype=np.object_) - exp_rsplit_none_full = np.array(exp_rsplit_none_full, dtype=np.object_) - exp_split_none_1 = np.array(exp_split_none_1, dtype=np.object_) - exp_rsplit_none_1 = np.array(exp_rsplit_none_1, dtype=np.object_) + assert actual.dtype == expected_da.dtype + assert_equal(actual, expected_da) - exp_split_dim_full = xr.DataArray(exp_split_dim_full, dims=["X", "Y", "ZZ"]).astype( - dtype - ) - exp_rsplit_dim_full = xr.DataArray( - exp_rsplit_dim_full, dims=["X", "Y", "ZZ"] - ).astype(dtype) - exp_split_dim_1 = xr.DataArray(exp_split_dim_1, dims=["X", "Y", "ZZ"]).astype(dtype) - exp_rsplit_dim_1 = xr.DataArray(exp_rsplit_dim_1, dims=["X", "Y", "ZZ"]).astype( - dtype - ) - exp_split_none_full = xr.DataArray(exp_split_none_full, dims=["X", "Y"]) - exp_rsplit_none_full = xr.DataArray(exp_rsplit_none_full, dims=["X", "Y"]) - exp_split_none_1 = xr.DataArray(exp_split_none_1, dims=["X", "Y"]) - exp_rsplit_none_1 = xr.DataArray(exp_rsplit_none_1, dims=["X", "Y"]) - - res_split_dim_full = values.str.split(dim="ZZ") - res_rsplit_dim_full = values.str.rsplit(dim="ZZ") - res_split_dim_1 = values.str.split(dim="ZZ", maxsplit=1) - res_rsplit_dim_1 = values.str.rsplit(dim="ZZ", maxsplit=1) - res_split_dim_10 = values.str.split(dim="ZZ", maxsplit=10) - res_rsplit_dim_10 = values.str.rsplit(dim="ZZ", maxsplit=10) - - res_split_none_full = values.str.split(dim=None) - res_rsplit_none_full = values.str.rsplit(dim=None) - res_split_none_1 = values.str.split(dim=None, maxsplit=1) - res_rsplit_none_1 = values.str.rsplit(dim=None, maxsplit=1) - res_split_none_10 = values.str.split(dim=None, maxsplit=10) - res_rsplit_none_10 = values.str.rsplit(dim=None, maxsplit=10) - - assert res_split_dim_full.dtype == exp_split_dim_full.dtype - assert res_rsplit_dim_full.dtype == exp_rsplit_dim_full.dtype - assert res_split_dim_1.dtype == exp_split_dim_1.dtype - assert res_rsplit_dim_1.dtype == exp_rsplit_dim_1.dtype - assert res_split_dim_10.dtype == exp_split_dim_full.dtype - assert res_rsplit_dim_10.dtype == exp_rsplit_dim_full.dtype - - assert res_split_none_full.dtype == exp_split_none_full.dtype - assert res_rsplit_none_full.dtype == exp_rsplit_none_full.dtype - assert res_split_none_1.dtype == exp_split_none_1.dtype - assert res_rsplit_none_1.dtype == exp_rsplit_none_1.dtype - assert res_split_none_10.dtype == exp_split_none_full.dtype - assert res_rsplit_none_10.dtype == exp_rsplit_none_full.dtype - - assert_equal(res_split_dim_full, exp_split_dim_full) - assert_equal(res_rsplit_dim_full, exp_rsplit_dim_full) - assert_equal(res_split_dim_1, exp_split_dim_1) - assert_equal(res_rsplit_dim_1, exp_rsplit_dim_1) - assert_equal(res_split_dim_10, exp_split_dim_full) - assert_equal(res_rsplit_dim_10, exp_rsplit_dim_full) - - assert_equal(res_split_none_full, exp_split_none_full) - assert_equal(res_rsplit_none_full, exp_rsplit_none_full) - assert_equal(res_split_none_1, exp_split_none_1) - assert_equal(res_rsplit_none_1, exp_rsplit_none_1) - assert_equal(res_split_none_10, exp_split_none_full) - assert_equal(res_rsplit_none_10, exp_rsplit_none_full) - - -def test_split_comma(dtype) -> None: +@pytest.mark.parametrize( + ["func", "expected"], + [ + pytest.param( + lambda x: x.str.split(sep=",", dim=None), + [ + [["abc", "def"], ["spam", "", "eggs", "swallow"], ["red_blue"]], + [ + ["test0", "test1", "test2", "test3"], + [""], + ["abra", "ka", "da", "bra"], + ], + ], + id="split_full", + ), + pytest.param( + lambda x: x.str.rsplit(sep=",", dim=None), + [ + [["abc", "def"], ["spam", "", "eggs", "swallow"], ["red_blue"]], + [ + ["test0", "test1", "test2", "test3"], + [""], + ["abra", "ka", "da", "bra"], + ], + ], + id="rsplit_full", + ), + pytest.param( + lambda x: x.str.split(sep=",", dim=None, maxsplit=1), + [ + [["abc", "def"], ["spam", ",eggs,swallow"], ["red_blue"]], + [["test0", "test1,test2,test3"], [""], ["abra", "ka,da,bra"]], + ], + id="split_1", + ), + pytest.param( + lambda x: x.str.rsplit(sep=",", dim=None, maxsplit=1), + [ + [["abc", "def"], ["spam,,eggs", "swallow"], ["red_blue"]], + [["test0,test1,test2", "test3"], [""], ["abra,ka,da", "bra"]], + ], + id="rsplit_1", + ), + pytest.param( + lambda x: x.str.split(sep=",", dim=None, maxsplit=10), + [ + [["abc", "def"], ["spam", "", "eggs", "swallow"], ["red_blue"]], + [ + ["test0", "test1", "test2", "test3"], + [""], + ["abra", "ka", "da", "bra"], + ], + ], + id="split_10", + ), + pytest.param( + lambda x: x.str.rsplit(sep=",", dim=None, maxsplit=10), + [ + [["abc", "def"], ["spam", "", "eggs", "swallow"], ["red_blue"]], + [ + ["test0", "test1", "test2", "test3"], + [""], + ["abra", "ka", "da", "bra"], + ], + ], + id="rsplit_10", + ), + ], +) +def test_split_comma_nodim( + dtype, func: Callable[[xr.DataArray], xr.DataArray], expected: xr.DataArray +) -> None: values = xr.DataArray( [ ["abc,def", "spam,,eggs,swallow", "red_blue"], @@ -2674,133 +2784,120 @@ def test_split_comma(dtype) -> None: dims=["X", "Y"], ).astype(dtype) - exp_split_dim_full = [ - [ - ["abc", "def", "", ""], - ["spam", "", "eggs", "swallow"], - ["red_blue", "", "", ""], - ], - [ - ["test0", "test1", "test2", "test3"], - ["", "", "", ""], - ["abra", "ka", "da", "bra"], - ], - ] - - exp_rsplit_dim_full = [ - [ - ["", "", "abc", "def"], - ["spam", "", "eggs", "swallow"], - ["", "", "", "red_blue"], - ], - [ - ["test0", "test1", "test2", "test3"], - ["", "", "", ""], - ["abra", "ka", "da", "bra"], - ], - ] - - exp_split_dim_1 = [ - [["abc", "def"], ["spam", ",eggs,swallow"], ["red_blue", ""]], - [["test0", "test1,test2,test3"], ["", ""], ["abra", "ka,da,bra"]], - ] + expected_dtype = [[[dtype(x) for x in y] for y in z] for z in expected] + expected_np = np.array(expected_dtype, dtype=np.object_) + expected_da = xr.DataArray(expected_np, dims=["X", "Y"]) - exp_rsplit_dim_1 = [ - [["abc", "def"], ["spam,,eggs", "swallow"], ["", "red_blue"]], - [["test0,test1,test2", "test3"], ["", ""], ["abra,ka,da", "bra"]], - ] + actual = func(values) - exp_split_none_full = [ - [["abc", "def"], ["spam", "", "eggs", "swallow"], ["red_blue"]], - [["test0", "test1", "test2", "test3"], [""], ["abra", "ka", "da", "bra"]], - ] + assert actual.dtype == expected_da.dtype + assert_equal(actual, expected_da) - exp_rsplit_none_full = [ - [["abc", "def"], ["spam", "", "eggs", "swallow"], ["red_blue"]], - [["test0", "test1", "test2", "test3"], [""], ["abra", "ka", "da", "bra"]], - ] - - exp_split_none_1 = [ - [["abc", "def"], ["spam", ",eggs,swallow"], ["red_blue"]], - [["test0", "test1,test2,test3"], [""], ["abra", "ka,da,bra"]], - ] - - exp_rsplit_none_1 = [ - [["abc", "def"], ["spam,,eggs", "swallow"], ["red_blue"]], - [["test0,test1,test2", "test3"], [""], ["abra,ka,da", "bra"]], - ] - exp_split_none_full = [ - [[dtype(x) for x in y] for y in z] for z in exp_split_none_full - ] - exp_rsplit_none_full = [ - [[dtype(x) for x in y] for y in z] for z in exp_rsplit_none_full - ] - exp_split_none_1 = [[[dtype(x) for x in y] for y in z] for z in exp_split_none_1] - exp_rsplit_none_1 = [[[dtype(x) for x in y] for y in z] for z in exp_rsplit_none_1] +@pytest.mark.parametrize( + ["func", "expected"], + [ + pytest.param( + lambda x: x.str.split(sep=",", dim="ZZ"), + [ + [ + ["abc", "def", "", ""], + ["spam", "", "eggs", "swallow"], + ["red_blue", "", "", ""], + ], + [ + ["test0", "test1", "test2", "test3"], + ["", "", "", ""], + ["abra", "ka", "da", "bra"], + ], + ], + id="split_full", + ), + pytest.param( + lambda x: x.str.rsplit(sep=",", dim="ZZ"), + [ + [ + ["", "", "abc", "def"], + ["spam", "", "eggs", "swallow"], + ["", "", "", "red_blue"], + ], + [ + ["test0", "test1", "test2", "test3"], + ["", "", "", ""], + ["abra", "ka", "da", "bra"], + ], + ], + id="rsplit_full", + ), + pytest.param( + lambda x: x.str.split(sep=",", dim="ZZ", maxsplit=1), + [ + [["abc", "def"], ["spam", ",eggs,swallow"], ["red_blue", ""]], + [["test0", "test1,test2,test3"], ["", ""], ["abra", "ka,da,bra"]], + ], + id="split_1", + ), + pytest.param( + lambda x: x.str.rsplit(sep=",", dim="ZZ", maxsplit=1), + [ + [["abc", "def"], ["spam,,eggs", "swallow"], ["", "red_blue"]], + [["test0,test1,test2", "test3"], ["", ""], ["abra,ka,da", "bra"]], + ], + id="rsplit_1", + ), + pytest.param( + lambda x: x.str.split(sep=",", dim="ZZ", maxsplit=10), + [ + [ + ["abc", "def", "", ""], + ["spam", "", "eggs", "swallow"], + ["red_blue", "", "", ""], + ], + [ + ["test0", "test1", "test2", "test3"], + ["", "", "", ""], + ["abra", "ka", "da", "bra"], + ], + ], + id="split_10", + ), + pytest.param( + lambda x: x.str.rsplit(sep=",", dim="ZZ", maxsplit=10), + [ + [ + ["", "", "abc", "def"], + ["spam", "", "eggs", "swallow"], + ["", "", "", "red_blue"], + ], + [ + ["test0", "test1", "test2", "test3"], + ["", "", "", ""], + ["abra", "ka", "da", "bra"], + ], + ], + id="rsplit_10", + ), + ], +) +def test_split_comma_dim( + dtype, func: Callable[[xr.DataArray], xr.DataArray], expected: xr.DataArray +) -> None: + values = xr.DataArray( + [ + ["abc,def", "spam,,eggs,swallow", "red_blue"], + ["test0,test1,test2,test3", "", "abra,ka,da,bra"], + ], + dims=["X", "Y"], + ).astype(dtype) - exp_split_none_full = np.array(exp_split_none_full, dtype=np.object_) - exp_rsplit_none_full = np.array(exp_rsplit_none_full, dtype=np.object_) - exp_split_none_1 = np.array(exp_split_none_1, dtype=np.object_) - exp_rsplit_none_1 = np.array(exp_rsplit_none_1, dtype=np.object_) + expected_dtype = [[[dtype(x) for x in y] for y in z] for z in expected] + expected_np = np.array(expected_dtype, dtype=np.object_) + expected_da = xr.DataArray(expected_np, dims=["X", "Y", "ZZ"]).astype(dtype) - exp_split_dim_full = xr.DataArray(exp_split_dim_full, dims=["X", "Y", "ZZ"]).astype( - dtype - ) - exp_rsplit_dim_full = xr.DataArray( - exp_rsplit_dim_full, dims=["X", "Y", "ZZ"] - ).astype(dtype) - exp_split_dim_1 = xr.DataArray(exp_split_dim_1, dims=["X", "Y", "ZZ"]).astype(dtype) - exp_rsplit_dim_1 = xr.DataArray(exp_rsplit_dim_1, dims=["X", "Y", "ZZ"]).astype( - dtype - ) + actual = func(values) - exp_split_none_full = xr.DataArray(exp_split_none_full, dims=["X", "Y"]) - exp_rsplit_none_full = xr.DataArray(exp_rsplit_none_full, dims=["X", "Y"]) - exp_split_none_1 = xr.DataArray(exp_split_none_1, dims=["X", "Y"]) - exp_rsplit_none_1 = xr.DataArray(exp_rsplit_none_1, dims=["X", "Y"]) - - res_split_dim_full = values.str.split(sep=",", dim="ZZ") - res_rsplit_dim_full = values.str.rsplit(sep=",", dim="ZZ") - res_split_dim_1 = values.str.split(sep=",", dim="ZZ", maxsplit=1) - res_rsplit_dim_1 = values.str.rsplit(sep=",", dim="ZZ", maxsplit=1) - res_split_dim_10 = values.str.split(sep=",", dim="ZZ", maxsplit=10) - res_rsplit_dim_10 = values.str.rsplit(sep=",", dim="ZZ", maxsplit=10) - - res_split_none_full = values.str.split(sep=",", dim=None) - res_rsplit_none_full = values.str.rsplit(sep=",", dim=None) - res_split_none_1 = values.str.split(sep=",", dim=None, maxsplit=1) - res_rsplit_none_1 = values.str.rsplit(sep=",", dim=None, maxsplit=1) - res_split_none_10 = values.str.split(sep=",", dim=None, maxsplit=10) - res_rsplit_none_10 = values.str.rsplit(sep=",", dim=None, maxsplit=10) - - assert res_split_dim_full.dtype == exp_split_dim_full.dtype - assert res_rsplit_dim_full.dtype == exp_rsplit_dim_full.dtype - assert res_split_dim_1.dtype == exp_split_dim_1.dtype - assert res_rsplit_dim_1.dtype == exp_rsplit_dim_1.dtype - assert res_split_dim_10.dtype == exp_split_dim_full.dtype - assert res_rsplit_dim_10.dtype == exp_rsplit_dim_full.dtype - - assert res_split_none_full.dtype == exp_split_none_full.dtype - assert res_rsplit_none_full.dtype == exp_rsplit_none_full.dtype - assert res_split_none_1.dtype == exp_split_none_1.dtype - assert res_rsplit_none_1.dtype == exp_rsplit_none_1.dtype - assert res_split_none_10.dtype == exp_split_none_full.dtype - assert res_rsplit_none_10.dtype == exp_rsplit_none_full.dtype - - assert_equal(res_split_dim_full, exp_split_dim_full) - assert_equal(res_rsplit_dim_full, exp_rsplit_dim_full) - assert_equal(res_split_dim_1, exp_split_dim_1) - assert_equal(res_rsplit_dim_1, exp_rsplit_dim_1) - assert_equal(res_split_dim_10, exp_split_dim_full) - assert_equal(res_rsplit_dim_10, exp_rsplit_dim_full) - - assert_equal(res_split_none_full, exp_split_none_full) - assert_equal(res_rsplit_none_full, exp_rsplit_none_full) - assert_equal(res_split_none_1, exp_split_none_1) - assert_equal(res_rsplit_none_1, exp_rsplit_none_1) - assert_equal(res_split_none_10, exp_split_none_full) - assert_equal(res_rsplit_none_10, exp_rsplit_none_full) + assert actual.dtype == expected_da.dtype + assert_equal(actual, expected_da) def test_splitters_broadcast(dtype) -> None: @@ -2889,7 +2986,7 @@ def test_get_dummies(dtype) -> None: vals_line = np.array(["a", "ab", "abc", "abcd", "ab~abc"]).astype(dtype) vals_comma = np.array(["a", "ab", "abc", "abcd", "ab|abc"]).astype(dtype) - expected = [ + expected_list = [ [ [True, False, True, False, True], [False, True, False, False, False], @@ -2901,8 +2998,8 @@ def test_get_dummies(dtype) -> None: [True, False, False, False, False], ], ] - expected = np.array(expected) - expected = xr.DataArray(expected, dims=["X", "Y", "ZZ"]) + expected_np = np.array(expected_list) + expected = xr.DataArray(expected_np, dims=["X", "Y", "ZZ"]) targ_line = expected.copy() targ_comma = expected.copy() targ_line.coords["ZZ"] = vals_line @@ -2932,14 +3029,14 @@ def test_get_dummies_broadcast(dtype) -> None: dims=["Y"], ).astype(dtype) - expected = [ + expected_list = [ [[False, False, True], [True, True, False]], [[True, False, False], [True, False, False]], [[True, False, True], [True, True, False]], [[False, False, True], [True, False, False]], ] - expected = np.array(expected) - expected = xr.DataArray(expected, dims=["X", "Y", "ZZ"]) + expected_np = np.array(expected_list) + expected = xr.DataArray(expected_np, dims=["X", "Y", "ZZ"]) expected.coords["ZZ"] = np.array(["x", "x|x", "x~x"]).astype(dtype) res = values.str.get_dummies(dim="ZZ", sep=sep) @@ -2973,17 +3070,17 @@ def test_splitters_empty_str(dtype) -> None: dims=["X", "Y", "ZZ"], ).astype(dtype) - targ_partition_none = [ + targ_partition_none_list = [ [["", "", ""], ["", "", ""], ["", "", ""]], [["", "", ""], ["", "", ""], ["", "", "", ""]], ] - targ_partition_none = [ - [[dtype(x) for x in y] for y in z] for z in targ_partition_none + targ_partition_none_list = [ + [[dtype(x) for x in y] for y in z] for z in targ_partition_none_list ] - targ_partition_none = np.array(targ_partition_none, dtype=np.object_) - del targ_partition_none[-1, -1][-1] + targ_partition_none_np = np.array(targ_partition_none_list, dtype=np.object_) + del targ_partition_none_np[-1, -1][-1] targ_partition_none = xr.DataArray( - targ_partition_none, + targ_partition_none_np, dims=["X", "Y"], ) From fad626d31378d302b8b09570f0d3495e760a7f4a Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 13:41:14 +0200 Subject: [PATCH 12/21] add from __future__ import annotations to all tests --- xarray/tests/test_accessor_dt.py | 2 ++ xarray/tests/test_backends.py | 7 ++++--- xarray/tests/test_backends_api.py | 2 ++ xarray/tests/test_backends_common.py | 2 ++ xarray/tests/test_backends_file_manager.py | 15 ++++++++------- xarray/tests/test_backends_locks.py | 2 ++ xarray/tests/test_backends_lru_cache.py | 2 ++ xarray/tests/test_calendar_ops.py | 2 ++ xarray/tests/test_cftime_offsets.py | 2 ++ xarray/tests/test_cftimeindex.py | 2 ++ xarray/tests/test_cftimeindex_resample.py | 2 ++ xarray/tests/test_coarsen.py | 2 ++ xarray/tests/test_coding.py | 2 ++ xarray/tests/test_coding_strings.py | 2 ++ xarray/tests/test_coding_times.py | 2 ++ xarray/tests/test_combine.py | 2 ++ xarray/tests/test_concat.py | 8 +++++--- xarray/tests/test_conventions.py | 2 ++ xarray/tests/test_cupy.py | 2 ++ xarray/tests/test_dask.py | 2 ++ xarray/tests/test_dataarray.py | 2 ++ xarray/tests/test_dataset.py | 2 ++ xarray/tests/test_distributed.py | 2 ++ xarray/tests/test_dtypes.py | 2 ++ xarray/tests/test_duck_array_ops.py | 2 ++ xarray/tests/test_extensions.py | 2 ++ xarray/tests/test_formatting.py | 2 ++ xarray/tests/test_formatting_html.py | 8 ++++---- xarray/tests/test_groupby.py | 5 +++-- xarray/tests/test_indexes.py | 10 ++++++---- xarray/tests/test_indexing.py | 2 ++ xarray/tests/test_interp.py | 2 ++ xarray/tests/test_merge.py | 2 ++ xarray/tests/test_missing.py | 2 ++ xarray/tests/test_nputils.py | 2 ++ xarray/tests/test_options.py | 2 ++ xarray/tests/test_plot.py | 6 ++++-- xarray/tests/test_plugins.py | 2 ++ xarray/tests/test_print_versions.py | 2 ++ xarray/tests/test_sparse.py | 2 ++ xarray/tests/test_testing.py | 2 ++ xarray/tests/test_tutorial.py | 2 ++ xarray/tests/test_ufuncs.py | 2 ++ xarray/tests/test_units.py | 2 ++ xarray/tests/test_utils.py | 2 ++ xarray/tests/test_variable.py | 2 ++ xarray/tests/test_weighted.py | 2 ++ 47 files changed, 114 insertions(+), 25 deletions(-) diff --git a/xarray/tests/test_accessor_dt.py b/xarray/tests/test_accessor_dt.py index 92a8b8a0e39..6bac98f7c4f 100644 --- a/xarray/tests/test_accessor_dt.py +++ b/xarray/tests/test_accessor_dt.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np import pandas as pd import pytest diff --git a/xarray/tests/test_backends.py b/xarray/tests/test_backends.py index 62c7c1aac31..94c2bb183b6 100644 --- a/xarray/tests/test_backends.py +++ b/xarray/tests/test_backends.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import contextlib import gzip import itertools @@ -13,7 +15,6 @@ from contextlib import ExitStack from io import BytesIO from pathlib import Path -from typing import Optional import numpy as np import pandas as pd @@ -266,8 +267,8 @@ def test_dtype_coercion_error(self): class DatasetIOBase: - engine: Optional[str] = None - file_format: Optional[str] = None + engine: str | None = None + file_format: str | None = None def create_store(self): raise NotImplementedError() diff --git a/xarray/tests/test_backends_api.py b/xarray/tests/test_backends_api.py index 0ba446818e5..e14234bcaf9 100644 --- a/xarray/tests/test_backends_api.py +++ b/xarray/tests/test_backends_api.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from numbers import Number import numpy as np diff --git a/xarray/tests/test_backends_common.py b/xarray/tests/test_backends_common.py index 75729a8f046..c7dba36ea58 100644 --- a/xarray/tests/test_backends_common.py +++ b/xarray/tests/test_backends_common.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from xarray.backends.common import robust_getitem diff --git a/xarray/tests/test_backends_file_manager.py b/xarray/tests/test_backends_file_manager.py index 6b8c4da01de..f0bb4289ae2 100644 --- a/xarray/tests/test_backends_file_manager.py +++ b/xarray/tests/test_backends_file_manager.py @@ -1,7 +1,8 @@ +from __future__ import annotations + import gc import pickle import threading -from typing import Dict from unittest import mock import pytest @@ -41,7 +42,7 @@ def test_file_manager_mock_write(file_cache) -> None: def test_file_manager_autoclose(expected_warning) -> None: mock_file = mock.Mock() opener = mock.Mock(return_value=mock_file) - cache: Dict = {} + cache: dict = {} manager = CachingFileManager(opener, "filename", cache=cache) manager.acquire() @@ -59,7 +60,7 @@ def test_file_manager_autoclose(expected_warning) -> None: def test_file_manager_autoclose_while_locked() -> None: opener = mock.Mock() lock = threading.Lock() - cache: Dict = {} + cache: dict = {} manager = CachingFileManager(opener, "filename", lock=lock, cache=cache) manager.acquire() @@ -84,8 +85,8 @@ def test_file_manager_repr() -> None: def test_file_manager_refcounts() -> None: mock_file = mock.Mock() opener = mock.Mock(spec=open, return_value=mock_file) - cache: Dict = {} - ref_counts: Dict = {} + cache: dict = {} + ref_counts: dict = {} manager = CachingFileManager(opener, "filename", cache=cache, ref_counts=ref_counts) assert ref_counts[manager._key] == 1 @@ -117,8 +118,8 @@ def test_file_manager_refcounts() -> None: def test_file_manager_replace_object() -> None: opener = mock.Mock() - cache: Dict = {} - ref_counts: Dict = {} + cache: dict = {} + ref_counts: dict = {} manager = CachingFileManager(opener, "filename", cache=cache, ref_counts=ref_counts) manager.acquire() diff --git a/xarray/tests/test_backends_locks.py b/xarray/tests/test_backends_locks.py index 0aa5f99f282..341a9c4aab5 100644 --- a/xarray/tests/test_backends_locks.py +++ b/xarray/tests/test_backends_locks.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import threading from xarray.backends import locks diff --git a/xarray/tests/test_backends_lru_cache.py b/xarray/tests/test_backends_lru_cache.py index 2b0c7742e5c..5735e0327a0 100644 --- a/xarray/tests/test_backends_lru_cache.py +++ b/xarray/tests/test_backends_lru_cache.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Any from unittest import mock diff --git a/xarray/tests/test_calendar_ops.py b/xarray/tests/test_calendar_ops.py index 0f0948aafc5..ff791a03505 100644 --- a/xarray/tests/test_calendar_ops.py +++ b/xarray/tests/test_calendar_ops.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np import pytest diff --git a/xarray/tests/test_cftime_offsets.py b/xarray/tests/test_cftime_offsets.py index 3879959675f..246be9d3514 100644 --- a/xarray/tests/test_cftime_offsets.py +++ b/xarray/tests/test_cftime_offsets.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from itertools import product import numpy as np diff --git a/xarray/tests/test_cftimeindex.py b/xarray/tests/test_cftimeindex.py index 2c6a0796c5f..639594d6829 100644 --- a/xarray/tests/test_cftimeindex.py +++ b/xarray/tests/test_cftimeindex.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pickle from datetime import timedelta from textwrap import dedent diff --git a/xarray/tests/test_cftimeindex_resample.py b/xarray/tests/test_cftimeindex_resample.py index af15f997643..35447a39f3c 100644 --- a/xarray/tests/test_cftimeindex_resample.py +++ b/xarray/tests/test_cftimeindex_resample.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import datetime import numpy as np diff --git a/xarray/tests/test_coarsen.py b/xarray/tests/test_coarsen.py index 7d6613421d5..e465b92ccfb 100644 --- a/xarray/tests/test_coarsen.py +++ b/xarray/tests/test_coarsen.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np import pandas as pd import pytest diff --git a/xarray/tests/test_coding.py b/xarray/tests/test_coding.py index 1c2e5aa505a..3af43f78e38 100644 --- a/xarray/tests/test_coding.py +++ b/xarray/tests/test_coding.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from contextlib import suppress import numpy as np diff --git a/xarray/tests/test_coding_strings.py b/xarray/tests/test_coding_strings.py index ef0b03f9681..92199884a03 100644 --- a/xarray/tests/test_coding_strings.py +++ b/xarray/tests/test_coding_strings.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from contextlib import suppress import numpy as np diff --git a/xarray/tests/test_coding_times.py b/xarray/tests/test_coding_times.py index a5344fe4c85..7d36f4e3f5e 100644 --- a/xarray/tests/test_coding_times.py +++ b/xarray/tests/test_coding_times.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import warnings from datetime import timedelta from itertools import product diff --git a/xarray/tests/test_combine.py b/xarray/tests/test_combine.py index 7e50e0d8b53..0e43868d488 100644 --- a/xarray/tests/test_combine.py +++ b/xarray/tests/test_combine.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from datetime import datetime from itertools import product diff --git a/xarray/tests/test_concat.py b/xarray/tests/test_concat.py index e590eda8162..17da311fa34 100644 --- a/xarray/tests/test_concat.py +++ b/xarray/tests/test_concat.py @@ -1,5 +1,7 @@ +from __future__ import annotations + from copy import deepcopy -from typing import TYPE_CHECKING, Any, List +from typing import TYPE_CHECKING, Any import numpy as np import pandas as pd @@ -132,14 +134,14 @@ def test_concat_dim_precedence(self, data) -> None: def test_concat_data_vars_typing(self) -> None: # Testing typing, can be removed if the next function works with annotations. data = Dataset({"foo": ("x", np.random.randn(10))}) - objs: List[Dataset] = [data.isel(x=slice(5)), data.isel(x=slice(5, None))] + objs: list[Dataset] = [data.isel(x=slice(5)), data.isel(x=slice(5, None))] actual = concat(objs, dim="x", data_vars="minimal") assert_identical(data, actual) def test_concat_data_vars(self): # TODO: annotating this func fails data = Dataset({"foo": ("x", np.random.randn(10))}) - objs: List[Dataset] = [data.isel(x=slice(5)), data.isel(x=slice(5, None))] + objs: list[Dataset] = [data.isel(x=slice(5)), data.isel(x=slice(5, None))] for data_vars in ["minimal", "different", "all", [], ["foo"]]: actual = concat(objs, dim="x", data_vars=data_vars) assert_identical(data, actual) diff --git a/xarray/tests/test_conventions.py b/xarray/tests/test_conventions.py index b8b9d19e238..c871cc74f4b 100644 --- a/xarray/tests/test_conventions.py +++ b/xarray/tests/test_conventions.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import contextlib import warnings diff --git a/xarray/tests/test_cupy.py b/xarray/tests/test_cupy.py index 79a540cdb38..94776902c11 100644 --- a/xarray/tests/test_cupy.py +++ b/xarray/tests/test_cupy.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np import pandas as pd import pytest diff --git a/xarray/tests/test_dask.py b/xarray/tests/test_dask.py index df69e8d9d6e..0d6ee7e503a 100644 --- a/xarray/tests/test_dask.py +++ b/xarray/tests/test_dask.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import operator import pickle import sys diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index e488f5afad9..d4f7b0f096f 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pickle import sys import warnings diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index 950f15e91df..40035be98ab 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pickle import sys import warnings diff --git a/xarray/tests/test_distributed.py b/xarray/tests/test_distributed.py index cde24c101ea..8b2beaf4767 100644 --- a/xarray/tests/test_distributed.py +++ b/xarray/tests/test_distributed.py @@ -1,4 +1,6 @@ """ isort:skip_file """ +from __future__ import annotations + import pickle import numpy as np diff --git a/xarray/tests/test_dtypes.py b/xarray/tests/test_dtypes.py index 53ed2c87133..1c942a1e6c8 100644 --- a/xarray/tests/test_dtypes.py +++ b/xarray/tests/test_dtypes.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np import pytest diff --git a/xarray/tests/test_duck_array_ops.py b/xarray/tests/test_duck_array_ops.py index 392f1b91914..e8550bb12b2 100644 --- a/xarray/tests/test_duck_array_ops.py +++ b/xarray/tests/test_duck_array_ops.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import datetime as dt import warnings diff --git a/xarray/tests/test_extensions.py b/xarray/tests/test_extensions.py index 5ca3a35e238..6f91cdf661e 100644 --- a/xarray/tests/test_extensions.py +++ b/xarray/tests/test_extensions.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pickle import pytest diff --git a/xarray/tests/test_formatting.py b/xarray/tests/test_formatting.py index a5c044d8ea7..fb70aa40cad 100644 --- a/xarray/tests/test_formatting.py +++ b/xarray/tests/test_formatting.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import sys from textwrap import dedent diff --git a/xarray/tests/test_formatting_html.py b/xarray/tests/test_formatting_html.py index c67619e18c7..039c6269350 100644 --- a/xarray/tests/test_formatting_html.py +++ b/xarray/tests/test_formatting_html.py @@ -1,4 +1,4 @@ -from typing import Dict, List +from __future__ import annotations import numpy as np import pandas as pd @@ -63,15 +63,15 @@ def test_short_data_repr_html_dask(dask_dataarray) -> None: def test_format_dims_no_dims() -> None: - dims: Dict = {} - dims_with_index: List = [] + dims: dict = {} + dims_with_index: list = [] formatted = fh.format_dims(dims, dims_with_index) assert formatted == "" def test_format_dims_unsafe_dim_name() -> None: dims = {"": 3, "y": 2} - dims_with_index: List = [] + dims_with_index: list = [] formatted = fh.format_dims(dims, dims_with_index) assert "<x>" in formatted diff --git a/xarray/tests/test_groupby.py b/xarray/tests/test_groupby.py index 8c745dc640d..f0b16bc42c7 100644 --- a/xarray/tests/test_groupby.py +++ b/xarray/tests/test_groupby.py @@ -1,5 +1,6 @@ +from __future__ import annotations + import warnings -from typing import Union import numpy as np import pandas as pd @@ -432,7 +433,7 @@ def test_groupby_quantile_interpolation_deprecated(as_dataset) -> None: array = xr.DataArray(data=[1, 2, 3, 4], coords={"x": [1, 1, 2, 2]}, dims="x") - arr: Union[xr.DataArray, xr.Dataset] + arr: xr.DataArray | xr.Dataset arr = array.to_dataset(name="name") if as_dataset else array with pytest.warns( diff --git a/xarray/tests/test_indexes.py b/xarray/tests/test_indexes.py index 7edcaa15105..26a807922e7 100644 --- a/xarray/tests/test_indexes.py +++ b/xarray/tests/test_indexes.py @@ -1,5 +1,7 @@ +from __future__ import annotations + import copy -from typing import Any, Dict, List +from typing import Any import numpy as np import pandas as pd @@ -533,7 +535,7 @@ def test_copy(self) -> None: class TestIndexes: @pytest.fixture - def unique_indexes(self) -> List[PandasIndex]: + def unique_indexes(self) -> list[PandasIndex]: x_idx = PandasIndex(pd.Index([1, 2, 3], name="x"), "x") y_idx = PandasIndex(pd.Index([4, 5, 6], name="y"), "y") z_pd_midx = pd.MultiIndex.from_product( @@ -546,14 +548,14 @@ def unique_indexes(self) -> List[PandasIndex]: @pytest.fixture def indexes(self, unique_indexes) -> Indexes[Index]: x_idx, y_idx, z_midx = unique_indexes - indexes: Dict[Any, Index] = { + indexes: dict[Any, Index] = { "x": x_idx, "y": y_idx, "z": z_midx, "one": z_midx, "two": z_midx, } - variables: Dict[Any, Variable] = {} + variables: dict[Any, Variable] = {} for idx in unique_indexes: variables.update(idx.create_variables()) diff --git a/xarray/tests/test_indexing.py b/xarray/tests/test_indexing.py index 0b40bd18223..24f9e3b085d 100644 --- a/xarray/tests/test_indexing.py +++ b/xarray/tests/test_indexing.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import itertools from typing import Any diff --git a/xarray/tests/test_interp.py b/xarray/tests/test_interp.py index d62254dd327..b3c94e33efb 100644 --- a/xarray/tests/test_interp.py +++ b/xarray/tests/test_interp.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from itertools import combinations, permutations from typing import cast diff --git a/xarray/tests/test_merge.py b/xarray/tests/test_merge.py index 6dca04ed069..3c8b12b5257 100644 --- a/xarray/tests/test_merge.py +++ b/xarray/tests/test_merge.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np import pytest diff --git a/xarray/tests/test_missing.py b/xarray/tests/test_missing.py index 3721c92317d..8b7ab27e394 100644 --- a/xarray/tests/test_missing.py +++ b/xarray/tests/test_missing.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import itertools import numpy as np diff --git a/xarray/tests/test_nputils.py b/xarray/tests/test_nputils.py index ba8e70ea514..dbe8ee3944d 100644 --- a/xarray/tests/test_nputils.py +++ b/xarray/tests/test_nputils.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np from numpy.testing import assert_array_equal diff --git a/xarray/tests/test_options.py b/xarray/tests/test_options.py index 8ae79732ffa..3cecf1b52ec 100644 --- a/xarray/tests/test_options.py +++ b/xarray/tests/test_options.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest import xarray diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index 8ded4c6515f..da4b8a623d6 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -1,8 +1,10 @@ +from __future__ import annotations + import contextlib import inspect from copy import copy from datetime import datetime -from typing import Any, Dict, Union +from typing import Any import numpy as np import pandas as pd @@ -1155,7 +1157,7 @@ class Common2dMixin: """ # Needs to be overridden in TestSurface for facet grid plots - subplot_kws: Union[Dict[Any, Any], None] = None + subplot_kws: dict[Any, Any] | None = None @pytest.fixture(autouse=True) def setUp(self): diff --git a/xarray/tests/test_plugins.py b/xarray/tests/test_plugins.py index 218ed1ea2e5..845866f6e53 100644 --- a/xarray/tests/test_plugins.py +++ b/xarray/tests/test_plugins.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from importlib.metadata import EntryPoint from unittest import mock diff --git a/xarray/tests/test_print_versions.py b/xarray/tests/test_print_versions.py index 42ebe5b2ac2..f964eb88948 100644 --- a/xarray/tests/test_print_versions.py +++ b/xarray/tests/test_print_versions.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import io import xarray diff --git a/xarray/tests/test_sparse.py b/xarray/tests/test_sparse.py index bac1f6407fc..294588a1f69 100644 --- a/xarray/tests/test_sparse.py +++ b/xarray/tests/test_sparse.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pickle from textwrap import dedent diff --git a/xarray/tests/test_testing.py b/xarray/tests/test_testing.py index 1470706d0eb..90e12292966 100644 --- a/xarray/tests/test_testing.py +++ b/xarray/tests/test_testing.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import warnings import numpy as np diff --git a/xarray/tests/test_tutorial.py b/xarray/tests/test_tutorial.py index e4c4378afdd..d7761988e78 100644 --- a/xarray/tests/test_tutorial.py +++ b/xarray/tests/test_tutorial.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from xarray import DataArray, tutorial diff --git a/xarray/tests/test_ufuncs.py b/xarray/tests/test_ufuncs.py index 28e5c6cbcb1..29b8fa6a895 100644 --- a/xarray/tests/test_ufuncs.py +++ b/xarray/tests/test_ufuncs.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np import pytest diff --git a/xarray/tests/test_units.py b/xarray/tests/test_units.py index 679733e1ecf..f1b77296b82 100644 --- a/xarray/tests/test_units.py +++ b/xarray/tests/test_units.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import functools import operator diff --git a/xarray/tests/test_utils.py b/xarray/tests/test_utils.py index 0a720b23d3b..6a39c028d2f 100644 --- a/xarray/tests/test_utils.py +++ b/xarray/tests/test_utils.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from datetime import datetime from typing import Hashable diff --git a/xarray/tests/test_variable.py b/xarray/tests/test_variable.py index 886b0360c04..1fc34588d9f 100644 --- a/xarray/tests/test_variable.py +++ b/xarray/tests/test_variable.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import warnings from copy import copy, deepcopy from datetime import datetime, timedelta diff --git a/xarray/tests/test_weighted.py b/xarray/tests/test_weighted.py index 63dd1ec0c94..b7d482b59f5 100644 --- a/xarray/tests/test_weighted.py +++ b/xarray/tests/test_weighted.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import numpy as np import pytest From e1d3e8756675c6eb49752097058ed847e4158757 Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 16:02:07 +0200 Subject: [PATCH 13/21] type all of dataset --- xarray/core/computation.py | 33 ++++- xarray/core/dataarray.py | 22 ++-- xarray/core/dataset.py | 238 ++++++++++++++++++++----------------- xarray/core/types.py | 2 +- 4 files changed, 172 insertions(+), 123 deletions(-) diff --git a/xarray/core/computation.py b/xarray/core/computation.py index 00aa9d83695..b4a268b5c98 100644 --- a/xarray/core/computation.py +++ b/xarray/core/computation.py @@ -17,6 +17,8 @@ Iterable, Mapping, Sequence, + TypeVar, + Union, overload, ) @@ -38,7 +40,7 @@ from .coordinates import Coordinates from .dataarray import DataArray from .dataset import Dataset - from .types import CombineAttrsOptions, JoinOptions, T_Xarray + from .types import CombineAttrsOptions, JoinOptions _NO_FILL_VALUE = utils.ReprObject("") _DEFAULT_NAME = utils.ReprObject("") @@ -2053,7 +2055,32 @@ def _calc_idxminmax( return res -def unify_chunks(*objects: T_Xarray) -> tuple[T_Xarray, ...]: +_T = TypeVar("_T", bound=Union["Dataset", "DataArray"]) +_U = TypeVar("_U", bound=Union["Dataset", "DataArray"]) +_V = TypeVar("_V", bound=Union["Dataset", "DataArray"]) + + +@overload +def unify_chunks(__obj: _T) -> tuple[_T]: + ... + + +@overload +def unify_chunks(__obj1: _T, __obj2: _U) -> tuple[_T, _U]: + ... + + +@overload +def unify_chunks(__obj1: _T, __obj2: _U, __obj3: _V) -> tuple[_T, _U, _V]: + ... + + +@overload +def unify_chunks(*objects: Dataset | DataArray) -> tuple[Dataset | DataArray, ...]: + ... + + +def unify_chunks(*objects: Dataset | DataArray) -> tuple[Dataset | DataArray, ...]: """ Given any number of Dataset and/or DataArray objects, returns new objects with unified chunk size along all chunked dimensions. @@ -2101,7 +2128,7 @@ def unify_chunks(*objects: T_Xarray) -> tuple[T_Xarray, ...]: _, dask_data = unify_chunks(*unify_chunks_args) dask_data_iter = iter(dask_data) - out = [] + out: list[Dataset | DataArray] = [] for obj, ds in zip(objects, datasets): for k, v in ds._variables.items(): if v.chunks is not None: diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py index bd50c4b5d5a..1952925d822 100644 --- a/xarray/core/dataarray.py +++ b/xarray/core/dataarray.py @@ -3564,7 +3564,10 @@ def _title_for_slice(self, truncate: int = 50) -> str: return title def diff( - self: T_DataArray, dim: Hashable, n: int = 1, label: Hashable = "upper" + self: T_DataArray, + dim: Hashable, + n: int = 1, + label: Literal["upper", "lower"] = "upper", ) -> T_DataArray: """Calculate the n-th order discrete difference along given axis. @@ -3574,11 +3577,10 @@ def diff( Dimension over which to calculate the finite difference. n : int, default: 1 The number of times values are differenced. - label : Hashable, default: "upper" + label : {"upper", "lower"}, default: "upper" The new coordinate in dimension ``dim`` will have the values of either the minuend's or subtrahend's coordinate - for values 'upper' and 'lower', respectively. Other - values are not supported. + for values 'upper' and 'lower', respectively. Returns ------- @@ -4005,7 +4007,7 @@ def differentiate( self: T_DataArray, coord: Hashable, edge_order: Literal[1, 2] = 1, - datetime_unit: DatetimeUnitOptions | None = None, + datetime_unit: DatetimeUnitOptions = None, ) -> T_DataArray: """ Differentiate the array with the second order accurate central differences. @@ -4021,7 +4023,7 @@ def differentiate( edge_order : {1, 2}, default: 1 N-th order accurate differences at the boundaries. datetime_unit : {"Y", "M", "W", "D", "h", "m", "s", "ms", \ - "us", "ns", "ps", "fs", "as"} or None, optional + "us", "ns", "ps", "fs", "as", None}, optional Unit to compute gradient. Only valid for datetime coordinate. Returns @@ -4068,7 +4070,7 @@ def differentiate( def integrate( self, coord: Hashable | Sequence[Hashable] = None, - datetime_unit: DatetimeUnitOptions | None = None, + datetime_unit: DatetimeUnitOptions = None, ) -> DataArray: """Integrate along the given coordinate using the trapezoidal rule. @@ -4081,7 +4083,7 @@ def integrate( coord : Hashable, or sequence of Hashable Coordinate(s) used for the integration. datetime_unit : {'Y', 'M', 'W', 'D', 'h', 'm', 's', 'ms', 'us', 'ns', \ - 'ps', 'fs', 'as'}, optional + 'ps', 'fs', 'as', None}, optional Specify the unit if a datetime coordinate is used. Returns @@ -4124,7 +4126,7 @@ def integrate( def cumulative_integrate( self, coord: Hashable | Sequence[Hashable] = None, - datetime_unit: DatetimeUnitOptions | None = None, + datetime_unit: DatetimeUnitOptions = None, ) -> DataArray: """Integrate cumulatively along the given coordinate using the trapezoidal rule. @@ -4140,7 +4142,7 @@ def cumulative_integrate( coord : Hashable, or sequence of Hashable Coordinate(s) used for the integration. datetime_unit : {'Y', 'M', 'W', 'D', 'h', 'm', 's', 'ms', 'us', 'ns', \ - 'ps', 'fs', 'as'}, optional + 'ps', 'fs', 'as', None}, optional Specify the unit if a datetime coordinate is used. Returns diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index c400aef868a..298a515e2a9 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -108,8 +108,10 @@ from .dataarray import DataArray from .merge import CoercibleMapping from .types import ( + CFCalendar, CombineAttrsOptions, CompatOptions, + DatetimeUnitOptions, ErrorOptions, ErrorOptionsWithWarn, InterpOptions, @@ -5705,9 +5707,9 @@ def to_array( Parameters ---------- - dim : str, optional + dim : Hashable, default: "variable" Name of the new dimension. - name : str, optional + name : Hashable or None, optional Name of the new data array. Returns @@ -6090,7 +6092,7 @@ def to_dict(self, data: bool = True, encoding: bool = False) -> dict[str, Any]: return d @classmethod - def from_dict(cls: type[T_Dataset], d: Mapping[Hashable, Any]) -> T_Dataset: + def from_dict(cls: type[T_Dataset], d: Mapping[Any, Any]) -> T_Dataset: """Convert a dictionary into an xarray.Dataset. Parameters @@ -6258,7 +6260,7 @@ def apply_over_both(lhs_data_vars, rhs_data_vars, lhs_vars, rhs_vars): new_data_vars = apply_over_both( self.data_vars, other, self.data_vars, other ) - return Dataset(new_data_vars) + return type(self)(new_data_vars) other_coords: Coordinates | None = getattr(other, "coords", None) ds = self.coords.merge(other_coords) @@ -6280,24 +6282,28 @@ def _copy_attrs_from(self, other): if v in self.variables: self.variables[v].attrs = other.variables[v].attrs - def diff(self, dim, n=1, label="upper"): + def diff( + self: T_Dataset, + dim: Hashable, + n: int = 1, + label: Literal["upper", "lower"] = "upper", + ) -> T_Dataset: """Calculate the n-th order discrete difference along given axis. Parameters ---------- - dim : str + dim : Hashable Dimension over which to calculate the finite difference. - n : int, optional + n : int, default: 1 The number of times values are differenced. - label : str, optional + label : {"upper", "lower"}, default: "upper" The new coordinate in dimension ``dim`` will have the values of either the minuend's or subtrahend's coordinate - for values 'upper' and 'lower', respectively. Other - values are not supported. + for values 'upper' and 'lower', respectively. Returns ------- - difference : same type as caller + difference : Dataset The n-th order finite difference of this object. Notes @@ -6331,18 +6337,18 @@ def diff(self, dim, n=1, label="upper"): raise ValueError(f"order `n` must be non-negative but got {n}") # prepare slices - kwargs_start = {dim: slice(None, -1)} - kwargs_end = {dim: slice(1, None)} + slice_start = {dim: slice(None, -1)} + slice_end = {dim: slice(1, None)} # prepare new coordinate if label == "upper": - kwargs_new = kwargs_end + slice_new = slice_end elif label == "lower": - kwargs_new = kwargs_start + slice_new = slice_start else: raise ValueError("The 'label' argument has to be either 'upper' or 'lower'") - indexes, index_vars = isel_indexes(self.xindexes, kwargs_new) + indexes, index_vars = isel_indexes(self.xindexes, slice_new) variables = {} for name, var in self.variables.items(): @@ -6350,9 +6356,9 @@ def diff(self, dim, n=1, label="upper"): variables[name] = index_vars[name] elif dim in var.dims: if name in self.data_vars: - variables[name] = var.isel(**kwargs_end) - var.isel(**kwargs_start) + variables[name] = var.isel(slice_end) - var.isel(slice_start) else: - variables[name] = var.isel(**kwargs_new) + variables[name] = var.isel(slice_new) else: variables[name] = var @@ -6364,11 +6370,11 @@ def diff(self, dim, n=1, label="upper"): return difference def shift( - self, - shifts: Mapping[Hashable, int] = None, + self: T_Dataset, + shifts: Mapping[Any, int] | None = None, fill_value: Any = dtypes.NA, **shifts_kwargs: int, - ) -> Dataset: + ) -> T_Dataset: """Shift this dataset by an offset along one or more dimensions. @@ -6434,11 +6440,11 @@ def shift( return self._replace(variables) def roll( - self, - shifts: Mapping[Hashable, int] = None, + self: T_Dataset, + shifts: Mapping[Any, int] | None = None, roll_coords: bool = False, **shifts_kwargs: int, - ) -> Dataset: + ) -> T_Dataset: """Roll this dataset by an offset along one or more dimensions. Unlike shift, roll treats the given dimensions as periodic, so will not @@ -6517,7 +6523,11 @@ def roll( return self._replace(variables, indexes=indexes) - def sortby(self, variables, ascending=True): + def sortby( + self: T_Dataset, + variables: Hashable | DataArray | list[Hashable | DataArray], + ascending: bool = True, + ) -> T_Dataset: """ Sort object by labels or values (along an axis). @@ -6537,10 +6547,10 @@ def sortby(self, variables, ascending=True): Parameters ---------- - variables : str, DataArray, or list of str or DataArray + variables : Hashable, DataArray, or list of hashable or DataArray 1D DataArray objects or name(s) of 1D variable(s) in coords/data_vars whose values are used to sort the dataset. - ascending : bool, optional + ascending : bool, default: True Whether to sort by ascending or descending order. Returns @@ -6581,10 +6591,10 @@ def sortby(self, variables, ascending=True): variables = [variables] else: variables = variables - variables = [v if isinstance(v, DataArray) else self[v] for v in variables] - aligned_vars = align(self, *variables, join="left") - aligned_self = aligned_vars[0] - aligned_other_vars = aligned_vars[1:] + arrays = [v if isinstance(v, DataArray) else self[v] for v in variables] + aligned_vars = align(self, *arrays, join="left") # type: ignore[type-var] + aligned_self: T_Dataset = aligned_vars[0] # type: ignore[assignment] + aligned_other_vars: tuple[DataArray, ...] = aligned_vars[1:] # type: ignore[assignment] vars_by_dim = defaultdict(list) for data_array in aligned_other_vars: if data_array.ndim != 1: @@ -6596,10 +6606,10 @@ def sortby(self, variables, ascending=True): for key, arrays in vars_by_dim.items(): order = np.lexsort(tuple(reversed(arrays))) indices[key] = order if ascending else order[::-1] - return aligned_self.isel(**indices) + return aligned_self.isel(indices) def quantile( - self, + self: T_Dataset, q: ArrayLike, dim: str | Iterable[Hashable] | None = None, method: QUANTILE_METHODS = "linear", @@ -6607,7 +6617,7 @@ def quantile( keep_attrs: bool = None, skipna: bool = None, interpolation: QUANTILE_METHODS = None, - ): + ) -> T_Dataset: """Compute the qth quantile of the data along the specified dimension. Returns the qth quantiles(s) of the array elements for each variable @@ -6776,7 +6786,12 @@ def quantile( ) return new.assign_coords(quantile=q) - def rank(self, dim, pct=False, keep_attrs=None): + def rank( + self: T_Dataset, + dim: Hashable, + pct: bool = False, + keep_attrs: bool | None = None, + ) -> T_Dataset: """Ranks the data. Equal values are assigned a rank that is the average of the ranks that @@ -6790,13 +6805,13 @@ def rank(self, dim, pct=False, keep_attrs=None): Parameters ---------- - dim : str + dim : Hashable Dimension over which to compute rank. - pct : bool, optional + pct : bool, default: False If True, compute percentage ranks, otherwise compute integer ranks. - keep_attrs : bool, optional + keep_attrs : bool or None, optional If True, the dataset's attributes (`attrs`) will be copied from - the original object to the new one. If False (default), the new + the original object to the new one. If False, the new object will be returned without attributes. Returns @@ -6827,7 +6842,12 @@ def rank(self, dim, pct=False, keep_attrs=None): attrs = self.attrs if keep_attrs else None return self._replace(variables, coord_names, attrs=attrs) - def differentiate(self, coord, edge_order: Literal[1, 2] = 1, datetime_unit=None): + def differentiate( + self: T_Dataset, + coord: Hashable, + edge_order: Literal[1, 2] = 1, + datetime_unit: DatetimeUnitOptions | None = None, + ) -> T_Dataset: """ Differentiate with the second order accurate central differences. @@ -6837,12 +6857,12 @@ def differentiate(self, coord, edge_order: Literal[1, 2] = 1, datetime_unit=None Parameters ---------- - coord : str + coord : Hashable The coordinate to be used to compute the gradient. edge_order : {1, 2}, default: 1 N-th order accurate differences at the boundaries. datetime_unit : None or {"Y", "M", "W", "D", "h", "m", "s", "ms", \ - "us", "ns", "ps", "fs", "as"}, default: None + "us", "ns", "ps", "fs", "as", None}, default: None Unit to compute gradient. Only valid for datetime coordinate. Returns @@ -6890,10 +6910,10 @@ def differentiate(self, coord, edge_order: Literal[1, 2] = 1, datetime_unit=None return self._replace(variables) def integrate( - self, + self: T_Dataset, coord: Hashable | Sequence[Hashable], - datetime_unit: str = None, - ) -> Dataset: + datetime_unit: DatetimeUnitOptions = None, + ) -> T_Dataset: """Integrate along the given coordinate using the trapezoidal rule. .. note:: @@ -6905,7 +6925,7 @@ def integrate( coord : hashable, or sequence of hashable Coordinate(s) used for the integration. datetime_unit : {'Y', 'M', 'W', 'D', 'h', 'm', 's', 'ms', 'us', 'ns', \ - 'ps', 'fs', 'as'}, optional + 'ps', 'fs', 'as', None}, optional Specify the unit if datetime coordinate is used. Returns @@ -7006,10 +7026,10 @@ def _integrate_one(self, coord, datetime_unit=None, cumulative=False): ) def cumulative_integrate( - self, + self: T_Dataset, coord: Hashable | Sequence[Hashable], - datetime_unit: str = None, - ) -> Dataset: + datetime_unit: DatetimeUnitOptions = None, + ) -> T_Dataset: """Integrate along the given coordinate using the trapezoidal rule. .. note:: @@ -7025,7 +7045,7 @@ def cumulative_integrate( coord : hashable, or sequence of hashable Coordinate(s) used for the integration. datetime_unit : {'Y', 'M', 'W', 'D', 'h', 'm', 's', 'ms', 'us', 'ns', \ - 'ps', 'fs', 'as'}, optional + 'ps', 'fs', 'as', None}, optional Specify the unit if datetime coordinate is used. Returns @@ -7081,16 +7101,16 @@ def cumulative_integrate( return result @property - def real(self): + def real(self: T_Dataset) -> T_Dataset: return self.map(lambda x: x.real, keep_attrs=True) @property - def imag(self): + def imag(self: T_Dataset) -> T_Dataset: return self.map(lambda x: x.imag, keep_attrs=True) plot = utils.UncachedAccessor(_Dataset_PlotMethods) - def filter_by_attrs(self, **kwargs): + def filter_by_attrs(self: T_Dataset, **kwargs) -> T_Dataset: """Returns a ``Dataset`` with variables that match specific conditions. Can pass in ``key=value`` or ``key=callable``. A Dataset is returned @@ -7185,7 +7205,7 @@ def filter_by_attrs(self, **kwargs): selection.append(var_name) return self[selection] - def unify_chunks(self) -> Dataset: + def unify_chunks(self: T_Dataset) -> T_Dataset: """Unify chunk size along all chunked dimensions of this Dataset. Returns @@ -7203,7 +7223,7 @@ def map_blocks( self, func: Callable[..., T_Xarray], args: Sequence[Any] = (), - kwargs: Mapping[str, Any] = None, + kwargs: Mapping[str, Any] | None = None, template: DataArray | Dataset | None = None, ) -> T_Xarray: """ @@ -7226,10 +7246,10 @@ def map_blocks( args : sequence Passed to func after unpacking and subsetting any xarray objects by blocks. xarray objects in args must be aligned with obj, otherwise an error is raised. - kwargs : mapping + kwargs : Mapping or None Passed verbatim to func after unpacking. xarray objects, if any, will not be subset to blocks. Passing dask collections in kwargs is not allowed. - template : DataArray or Dataset, optional + template : DataArray, Dataset or None, optional xarray object representing the final result after compute is called. If not provided, the function will be first run on mocked-up data, that looks like this object but has sizes 0, to determine properties of the returned object such as dtype, @@ -7307,7 +7327,7 @@ def map_blocks( return map_blocks(func, self, args, kwargs, template) def polyfit( - self, + self: T_Dataset, dim: Hashable, deg: int, skipna: bool | None = None, @@ -7315,7 +7335,7 @@ def polyfit( w: Hashable | Any = None, full: bool = False, cov: bool | Literal["unscaled"] = False, - ): + ) -> T_Dataset: """ Least squares polynomial fit. @@ -7500,10 +7520,10 @@ def polyfit( covariance = DataArray(Vbase, dims=("cov_i", "cov_j")) * fac variables[name + "polyfit_covariance"] = covariance - return Dataset(data_vars=variables, attrs=self.attrs.copy()) + return type(self)(data_vars=variables, attrs=self.attrs.copy()) def pad( - self, + self: T_Dataset, pad_width: Mapping[Any, int | tuple[int, int]] = None, mode: PadModeOptions = "constant", stat_length: int @@ -7516,7 +7536,7 @@ def pad( end_values: int | tuple[int, int] | Mapping[Any, tuple[int, int]] | None = None, reflect_type: PadReflectOptions = None, **pad_width_kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """Pad this dataset along one or more dimensions. .. warning:: @@ -7678,12 +7698,12 @@ def pad( return self._replace_with_new_dims(variables, indexes=indexes) def idxmin( - self, - dim: Hashable = None, - skipna: bool = None, + self: T_Dataset, + dim: Hashable | None = None, + skipna: bool | None = None, fill_value: Any = dtypes.NA, - keep_attrs: bool = None, - ) -> Dataset: + keep_attrs: bool | None = None, + ) -> T_Dataset: """Return the coordinate label of the minimum value along a dimension. Returns a new `Dataset` named after the dimension with the values of @@ -7695,10 +7715,10 @@ def idxmin( Parameters ---------- - dim : str, optional + dim : Hashable, optional Dimension over which to apply `idxmin`. This is optional for 1D variables, but required for variables with 2 or more dimensions. - skipna : bool or None, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for ``float``, ``complex``, and ``object`` dtypes; other dtypes either do not have a sentinel missing value @@ -7709,9 +7729,9 @@ def idxmin( null. By default this is NaN. The fill value and result are automatically converted to a compatible dtype if possible. Ignored if ``skipna`` is False. - keep_attrs : bool, default: False + keep_attrs : bool or None, optional If True, the attributes (``attrs``) will be copied from the - original object to the new one. If False (default), the new object + original object to the new one. If False, the new object will be returned without attributes. Returns @@ -7775,12 +7795,12 @@ def idxmin( ) def idxmax( - self, - dim: Hashable = None, - skipna: bool = None, + self: T_Dataset, + dim: Hashable | None = None, + skipna: bool | None = None, fill_value: Any = dtypes.NA, - keep_attrs: bool = None, - ) -> Dataset: + keep_attrs: bool | None = None, + ) -> T_Dataset: """Return the coordinate label of the maximum value along a dimension. Returns a new `Dataset` named after the dimension with the values of @@ -7795,7 +7815,7 @@ def idxmax( dim : str, optional Dimension over which to apply `idxmax`. This is optional for 1D variables, but required for variables with 2 or more dimensions. - skipna : bool or None, default: None + skipna : bool or None, optional If True, skip missing values (as marked by NaN). By default, only skips missing values for ``float``, ``complex``, and ``object`` dtypes; other dtypes either do not have a sentinel missing value @@ -7806,9 +7826,9 @@ def idxmax( null. By default this is NaN. The fill value and result are automatically converted to a compatible dtype if possible. Ignored if ``skipna`` is False. - keep_attrs : bool, default: False + keep_attrs : bool or None, optional If True, the attributes (``attrs``) will be copied from the - original object to the new one. If False (default), the new object + original object to the new one. If False, the new object will be returned without attributes. Returns @@ -7871,7 +7891,7 @@ def idxmax( ) ) - def argmin(self, dim=None, **kwargs): + def argmin(self: T_Dataset, dim: Hashable | None = None, **kwargs) -> T_Dataset: """Indices of the minima of the member variables. If there are multiple minima, the indices of the first one found will be @@ -7879,7 +7899,7 @@ def argmin(self, dim=None, **kwargs): Parameters ---------- - dim : str, optional + dim : Hashable, optional The dimension over which to find the minimum. By default, finds minimum over all dimensions - for now returning an int for backward compatibility, but this is deprecated, in future will be an error, since DataArray.argmin will @@ -7928,7 +7948,7 @@ def argmin(self, dim=None, **kwargs): "Dataset.argmin() with a sequence or ... for dim" ) - def argmax(self, dim=None, **kwargs): + def argmax(self: T_Dataset, dim: Hashable | None = None, **kwargs) -> T_Dataset: """Indices of the maxima of the member variables. If there are multiple maxima, the indices of the first one found will be @@ -7987,13 +8007,13 @@ def argmax(self, dim=None, **kwargs): ) def query( - self, + self: T_Dataset, queries: Mapping[Any, Any] | None = None, parser: QueryParserOptions = "pandas", engine: QueryEngineOptions = None, missing_dims: ErrorOptionsWithWarn = "raise", **queries_kwargs: Any, - ) -> Dataset: + ) -> T_Dataset: """Return a new dataset with each array indexed along the specified dimension(s), where the indexers are given as strings containing Python expressions to be evaluated against the data variables in the @@ -8083,16 +8103,16 @@ def query( return self.isel(indexers, missing_dims=missing_dims) def curvefit( - self, + self: T_Dataset, coords: str | DataArray | Iterable[str | DataArray], func: Callable[..., Any], - reduce_dims: Hashable | Iterable[Hashable] = None, + reduce_dims: Hashable | Iterable[Hashable] | None = None, skipna: bool = True, - p0: dict[str, Any] = None, - bounds: dict[str, Any] = None, - param_names: Sequence[str] = None, - kwargs: dict[str, Any] = None, - ): + p0: dict[str, Any] | None = None, + bounds: dict[str, Any] | None = None, + param_names: Sequence[str] | None = None, + kwargs: dict[str, Any] | None = None, + ) -> T_Dataset: """ Curve fitting optimization for arbitrary functions. @@ -8116,7 +8136,7 @@ def curvefit( calling `ds.curvefit(coords='time', reduce_dims=['lat', 'lon'], ...)` will aggregate all lat and lon points and fit the specified function along the time dimension. - skipna : bool, optional + skipna : bool, default: True Whether to skip missing values when fitting. Default is True. p0 : dict-like, optional Optional dictionary of parameter names to initial guesses passed to the @@ -8225,7 +8245,7 @@ def _wrapper(Y, *coords_, **kwargs): popt, pcov = curve_fit(func, x, y, **kwargs) return popt, pcov - result = Dataset() + result = type(self)() for name, da in self.data_vars.items(): if name is _THIS_ARRAY: name = "" @@ -8262,10 +8282,10 @@ def _wrapper(Y, *coords_, **kwargs): return result def drop_duplicates( - self, + self: T_Dataset, dim: Hashable | Iterable[Hashable], - keep: Literal["first", "last"] | Literal[False] = "first", - ): + keep: Literal["first", "last", False] = "first", + ) -> T_Dataset: """Returns a new Dataset with duplicate dimension values removed. Parameters @@ -8303,13 +8323,13 @@ def drop_duplicates( return self.isel(indexes) def convert_calendar( - self, - calendar: str, - dim: str = "time", - align_on: str | None = None, + self: T_Dataset, + calendar: CFCalendar, + dim: Hashable = "time", + align_on: Literal["date", "year", None] = None, missing: Any | None = None, use_cftime: bool | None = None, - ) -> Dataset: + ) -> T_Dataset: """Convert the Dataset to another calendar. Only converts the individual timestamps, does not modify any data except @@ -8331,12 +8351,12 @@ def convert_calendar( --------- calendar : str The target calendar name. - dim : str + dim : Hashable, default: "time" Name of the time coordinate. - align_on : {None, 'date', 'year'} + align_on : {None, 'date', 'year'}, optional Must be specified when either source or target is a `360_day` calendar, ignored otherwise. See Notes. - missing : Optional[any] + missing : Any or None, optional By default, i.e. if the value is None, this method will simply attempt to convert the dates in the source calendar to the same dates in the target calendar, and drop any of those that are not possible to @@ -8347,7 +8367,7 @@ def convert_calendar( that the source data have an inferable frequency; for more information see :py:func:`xarray.infer_freq`. For certain frequency, source, and target calendar combinations, this could result in many missing values, see notes. - use_cftime : boolean, optional + use_cftime : bool or None, optional Whether to use cftime objects in the output, only used if `calendar` is one of {"proleptic_gregorian", "gregorian" or "standard"}. If True, the new time axis uses cftime objects. @@ -8426,10 +8446,10 @@ def convert_calendar( ) def interp_calendar( - self, + self: T_Dataset, target: pd.DatetimeIndex | CFTimeIndex | DataArray, - dim: str = "time", - ) -> Dataset: + dim: Hashable = "time", + ) -> T_Dataset: """Interpolates the Dataset to another calendar based on decimal year measure. Each timestamp in `source` and `target` are first converted to their decimal @@ -8446,7 +8466,7 @@ def interp_calendar( target: DataArray or DatetimeIndex or CFTimeIndex The target time coordinate of a valid dtype (np.datetime64 or cftime objects) - dim : str + dim : Hashable, default: "time" The time coordinate name. Return diff --git a/xarray/core/types.py b/xarray/core/types.py index f4f86bafc93..30e3653556a 100644 --- a/xarray/core/types.py +++ b/xarray/core/types.py @@ -56,7 +56,7 @@ InterpOptions = Union[Interp1dOptions, InterpolantOptions] DatetimeUnitOptions = Literal[ - "Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "ps", "fs", "as" + "Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "ps", "fs", "as", None ] QueryEngineOptions = Literal["python", "numexpr", None] From e194162ffeb11fbf0c6a7cb925072949621db813 Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 17:00:13 +0200 Subject: [PATCH 14/21] type all dataset tests --- xarray/backends/api.py | 2 +- xarray/core/dataset.py | 14 +- xarray/tests/test_dataset.py | 918 ++++++++++++++++++----------------- 3 files changed, 476 insertions(+), 458 deletions(-) diff --git a/xarray/backends/api.py b/xarray/backends/api.py index 1426cd320d9..409bec3a0b0 100644 --- a/xarray/backends/api.py +++ b/xarray/backends/api.py @@ -366,7 +366,7 @@ def _dataset_from_backend_dataset( def open_dataset( - filename_or_obj: str | os.PathLike, + filename_or_obj: str | os.PathLike | AbstractDataStore, *, engine: T_Engine = None, chunks: T_Chunks = None, diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index 298a515e2a9..534615e0ff0 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -3718,12 +3718,14 @@ def swap_dims( return self._replace_with_new_dims(variables, coord_names, indexes=indexes) + # change type of self and return to T_Dataset once + # https://github.com/python/mypy/issues/12846 is resolved def expand_dims( - self: T_Dataset, + self, dim: None | Hashable | Sequence[Hashable] | Mapping[Any, Any] = None, axis: None | int | Sequence[int] = None, **dim_kwargs: Any, - ) -> T_Dataset: + ) -> Dataset: """Return a new object with an additional axis (or axes) inserted at the corresponding position in the array shape. The new object is a view into the underlying array, not a copy. @@ -3853,12 +3855,14 @@ def expand_dims( variables, coord_names=coord_names, indexes=indexes ) + # change type of self and return to T_Dataset once + # https://github.com/python/mypy/issues/12846 is resolved def set_index( - self: T_Dataset, + self, indexes: Mapping[Any, Hashable | Sequence[Hashable]] | None = None, append: bool = False, **indexes_kwargs: Hashable | Sequence[Hashable], - ) -> T_Dataset: + ) -> Dataset: """Set Dataset (multi-)indexes using one or more existing coordinates or variables. @@ -5605,7 +5609,7 @@ def apply( def assign( self: T_Dataset, variables: Mapping[Any, Any] | None = None, - **variables_kwargs: Hashable, + **variables_kwargs: Any, ) -> T_Dataset: """Assign new data variables to a Dataset, returning a new object with all the original variables in addition to the new ones. diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index 40035be98ab..66b01a9b338 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -6,6 +6,7 @@ from copy import copy, deepcopy from io import StringIO from textwrap import dedent +from typing import Any, Hashable import numpy as np import pandas as pd @@ -67,7 +68,7 @@ ] -def create_append_test_data(seed=None): +def create_append_test_data(seed=None) -> tuple[Dataset, Dataset, Dataset]: rs = np.random.RandomState(seed) lat = [2, 1, 0] @@ -147,8 +148,8 @@ def create_append_test_data(seed=None): return ds, ds_to_append, ds_with_new_var -def create_append_string_length_mismatch_test_data(dtype): - def make_datasets(data, data_to_append): +def create_append_string_length_mismatch_test_data(dtype) -> tuple[Dataset, Dataset]: + def make_datasets(data, data_to_append) -> tuple[Dataset, Dataset]: ds = xr.Dataset( {"temperature": (["time"], data)}, coords={"time": [0, 1, 2]}, @@ -172,16 +173,18 @@ def make_datasets(data, data_to_append): return make_datasets(u2_strings, u5_strings) elif dtype == "S": return make_datasets(s2_strings, s3_strings) + else: + raise ValueError(f"unsupported dtype {dtype}.") -def create_test_multiindex(): +def create_test_multiindex() -> Dataset: mindex = pd.MultiIndex.from_product( [["a", "b"], [1, 2]], names=("level_1", "level_2") ) return Dataset({}, {"x": mindex}) -def create_test_stacked_array(): +def create_test_stacked_array() -> tuple[DataArray, DataArray]: x = DataArray(pd.Index(np.r_[:10], name="x")) y = DataArray(pd.Index(np.r_[:20], name="y")) a = x * y @@ -194,7 +197,7 @@ def __init__(self): super().__init__() self._indexvars = set() - def store(self, variables, *args, **kwargs): + def store(self, variables, *args, **kwargs) -> None: super().store(variables, *args, **kwargs) for k, v in variables.items(): if isinstance(v, IndexVariable): @@ -211,7 +214,7 @@ def lazy_inaccessible(k, v): class TestDataset: - def test_repr(self): + def test_repr(self) -> None: data = create_test_data(seed=123) data.attrs["foo"] = "bar" # need to insert str dtype at runtime to handle different endianness @@ -269,7 +272,7 @@ def test_repr(self): data = Dataset(attrs={"foo": "bar" * 1000}) assert len(repr(data)) < 1000 - def test_repr_multiindex(self): + def test_repr_multiindex(self) -> None: data = create_test_multiindex() expected = dedent( """\ @@ -306,14 +309,14 @@ def test_repr_multiindex(self): print(actual) assert expected == actual - def test_repr_period_index(self): + def test_repr_period_index(self) -> None: data = create_test_data(seed=456) data.coords["time"] = pd.period_range("2000-01-01", periods=20, freq="B") # check that creating the repr doesn't raise an error #GH645 repr(data) - def test_unicode_data(self): + def test_unicode_data(self) -> None: # regression test for GH834 data = Dataset({"foø": ["ba®"]}, attrs={"å": "∑"}) repr(data) # should not raise @@ -334,7 +337,7 @@ def test_unicode_data(self): actual = str(data) assert expected == actual - def test_repr_nep18(self): + def test_repr_nep18(self) -> None: class Array: def __init__(self): self.shape = (2,) @@ -357,7 +360,7 @@ def __repr__(self): ) assert expected == repr(dataset) - def test_info(self): + def test_info(self) -> None: ds = create_test_data(seed=123) ds = ds.drop_vars("dim3") # string type prints differently in PY2 vs PY3 ds.attrs["unicode_attr"] = "ba®" @@ -395,7 +398,7 @@ def test_info(self): assert expected == actual buf.close() - def test_constructor(self): + def test_constructor(self) -> None: x1 = ("x", 2 * np.arange(100)) x2 = ("x", np.arange(1000)) z = (["x", "y"], np.arange(1000).reshape(100, 10)) @@ -414,7 +417,7 @@ def test_constructor(self): actual = Dataset({"z": expected["z"]}) assert_identical(expected, actual) - def test_constructor_invalid_dims(self): + def test_constructor_invalid_dims(self) -> None: # regression for GH1120 with pytest.raises(MergeError): Dataset( @@ -422,7 +425,7 @@ def test_constructor_invalid_dims(self): coords=dict(y=DataArray([0.1, 0.2, 0.3, 0.4], dims="x")), ) - def test_constructor_1d(self): + def test_constructor_1d(self) -> None: expected = Dataset({"x": (["x"], 5.0 + np.arange(5))}) actual = Dataset({"x": 5.0 + np.arange(5)}) assert_identical(expected, actual) @@ -430,7 +433,7 @@ def test_constructor_1d(self): actual = Dataset({"x": [5, 6, 7, 8, 9]}) assert_identical(expected, actual) - def test_constructor_0d(self): + def test_constructor_0d(self) -> None: expected = Dataset({"x": ([], 1)}) for arg in [1, np.array(1), expected["x"]]: actual = Dataset({"x": arg}) @@ -458,7 +461,7 @@ class Arbitrary: actual = Dataset({"x": arg}) assert_identical(expected, actual) - def test_constructor_auto_align(self): + def test_constructor_auto_align(self) -> None: a = DataArray([1, 2], [("x", [0, 1])]) b = DataArray([3, 4], [("x", [1, 2])]) @@ -488,7 +491,7 @@ def test_constructor_auto_align(self): with pytest.raises(ValueError, match=r"conflicting sizes"): Dataset({"a": a, "b": b, "e": e}) - def test_constructor_pandas_sequence(self): + def test_constructor_pandas_sequence(self) -> None: ds = self.make_example_math_dataset() pandas_objs = { @@ -505,7 +508,7 @@ def test_constructor_pandas_sequence(self): del ds_based_on_pandas["x"] assert_equal(ds, ds_based_on_pandas) - def test_constructor_pandas_single(self): + def test_constructor_pandas_single(self) -> None: das = [ DataArray(np.random.rand(4), dims=["a"]), # series @@ -514,11 +517,11 @@ def test_constructor_pandas_single(self): for a in das: pandas_obj = a.to_pandas() - ds_based_on_pandas = Dataset(pandas_obj) + ds_based_on_pandas = Dataset(pandas_obj) # type: ignore # TODO: improve typing of __init__ for dim in ds_based_on_pandas.data_vars: assert_array_equal(ds_based_on_pandas[dim], pandas_obj[dim]) - def test_constructor_compat(self): + def test_constructor_compat(self) -> None: data = {"x": DataArray(0, coords={"y": 1}), "y": ("z", [1, 1, 1])} expected = Dataset({"x": 0}, {"y": ("z", [1, 1, 1])}) actual = Dataset(data) @@ -551,7 +554,7 @@ def test_constructor_compat(self): expected = Dataset({"x": 0}, {"y": [1, 1]}) assert_identical(expected, actual) - def test_constructor_with_coords(self): + def test_constructor_with_coords(self) -> None: with pytest.raises(ValueError, match=r"found in both data_vars and"): Dataset({"a": ("x", [1])}, {"a": ("x", [1])}) @@ -566,7 +569,7 @@ def test_constructor_with_coords(self): Dataset({}, {"x": mindex, "y": mindex}) Dataset({}, {"x": mindex, "level_1": range(4)}) - def test_properties(self): + def test_properties(self) -> None: ds = create_test_data() assert ds.dims == {"dim1": 8, "dim2": 9, "dim3": 10, "time": 20} assert ds.sizes == ds.dims @@ -608,21 +611,24 @@ def test_properties(self): assert "dim1" not in ds.coords assert len(ds.coords) == 4 - assert Dataset({"x": np.int64(1), "y": np.float32([1, 2])}).nbytes == 16 + assert ( + Dataset({"x": np.int64(1), "y": np.array([1, 2], dtype=np.float32)}).nbytes + == 16 + ) - def test_asarray(self): + def test_asarray(self) -> None: ds = Dataset({"x": 0}) with pytest.raises(TypeError, match=r"cannot directly convert"): np.asarray(ds) - def test_get_index(self): + def test_get_index(self) -> None: ds = Dataset({"foo": (("x", "y"), np.zeros((2, 3)))}, coords={"x": ["a", "b"]}) assert ds.get_index("x").equals(pd.Index(["a", "b"])) assert ds.get_index("y").equals(pd.Index([0, 1, 2])) with pytest.raises(KeyError): ds.get_index("z") - def test_attr_access(self): + def test_attr_access(self) -> None: ds = Dataset( {"tmin": ("x", [42], {"units": "Celsius"})}, attrs={"title": "My test data"} ) @@ -640,7 +646,7 @@ def test_attr_access(self): assert ds.attrs["tmin"] == -999 assert_identical(ds.tmin, ds["tmin"]) - def test_variable(self): + def test_variable(self) -> None: a = Dataset() d = np.random.random((10, 3)) a["foo"] = (("time", "x"), d) @@ -654,7 +660,7 @@ def test_variable(self): with pytest.raises(ValueError): a["qux"] = (("time", "x"), d.T) - def test_modify_inplace(self): + def test_modify_inplace(self) -> None: a = Dataset() vec = np.random.random((10,)) attributes = {"foo": "bar"} @@ -680,7 +686,7 @@ def test_modify_inplace(self): a["y"] = ("y", scal) assert "y" not in a.dims - def test_coords_properties(self): + def test_coords_properties(self) -> None: # use int64 for repr consistency on windows data = Dataset( { @@ -721,7 +727,7 @@ def test_coords_properties(self): assert {"x": 2, "y": 3} == data.coords.dims - def test_coords_modify(self): + def test_coords_modify(self) -> None: data = Dataset( { "x": ("x", [-1, -2]), @@ -764,25 +770,25 @@ def test_coords_modify(self): del actual.coords["x"] assert "x" not in actual.xindexes - def test_update_index(self): + def test_update_index(self) -> None: actual = Dataset(coords={"x": [1, 2, 3]}) actual["x"] = ["a", "b", "c"] assert actual.xindexes["x"].to_pandas_index().equals(pd.Index(["a", "b", "c"])) - def test_coords_setitem_with_new_dimension(self): + def test_coords_setitem_with_new_dimension(self) -> None: actual = Dataset() actual.coords["foo"] = ("x", [1, 2, 3]) expected = Dataset(coords={"foo": ("x", [1, 2, 3])}) assert_identical(expected, actual) - def test_coords_setitem_multiindex(self): + def test_coords_setitem_multiindex(self) -> None: data = create_test_multiindex() with pytest.raises( ValueError, match=r"cannot set or update variable.*corrupt.*index " ): data.coords["level_1"] = range(4) - def test_coords_set(self): + def test_coords_set(self) -> None: one_coord = Dataset({"x": ("x", [0]), "yy": ("x", [1]), "zzz": ("x", [2])}) two_coords = Dataset({"zzz": ("x", [2])}, {"x": ("x", [0]), "yy": ("x", [1])}) all_coords = Dataset( @@ -821,13 +827,13 @@ def test_coords_set(self): expected = two_coords.drop_vars("zzz") assert_identical(expected, actual) - def test_coords_to_dataset(self): + def test_coords_to_dataset(self) -> None: orig = Dataset({"foo": ("y", [-1, 0, 1])}, {"x": 10, "y": [2, 3, 4]}) expected = Dataset(coords={"x": 10, "y": [2, 3, 4]}) actual = orig.coords.to_dataset() assert_identical(expected, actual) - def test_coords_merge(self): + def test_coords_merge(self) -> None: orig_coords = Dataset(coords={"a": ("x", [1, 2]), "x": [0, 1]}).coords other_coords = Dataset(coords={"b": ("x", ["a", "b"]), "x": [0, 1]}).coords expected = Dataset( @@ -861,7 +867,7 @@ def test_coords_merge(self): actual = other_coords.merge(orig_coords) assert_identical(orig_coords.to_dataset(), actual) - def test_coords_merge_mismatched_shape(self): + def test_coords_merge_mismatched_shape(self) -> None: orig_coords = Dataset(coords={"a": ("x", [1, 1])}).coords other_coords = Dataset(coords={"a": 1}).coords expected = orig_coords.to_dataset() @@ -882,7 +888,7 @@ def test_coords_merge_mismatched_shape(self): actual = orig_coords.merge(other_coords) assert_identical(expected, actual) - def test_data_vars_properties(self): + def test_data_vars_properties(self) -> None: ds = Dataset() ds["foo"] = (("x",), [1.0]) ds["bar"] = 2.0 @@ -901,7 +907,7 @@ def test_data_vars_properties(self): actual = repr(ds.data_vars) assert expected == actual - def test_equals_and_identical(self): + def test_equals_and_identical(self) -> None: data = create_test_data(seed=42) assert data.equals(data) assert data.identical(data) @@ -922,27 +928,27 @@ def test_equals_and_identical(self): assert not data2.equals(data) assert not data2.identical(data) - def test_equals_failures(self): + def test_equals_failures(self) -> None: data = create_test_data() assert not data.equals("foo") assert not data.identical(123) assert not data.broadcast_equals({1: 2}) - def test_broadcast_equals(self): + def test_broadcast_equals(self) -> None: data1 = Dataset(coords={"x": 0}) data2 = Dataset(coords={"x": [0]}) assert data1.broadcast_equals(data2) assert not data1.equals(data2) assert not data1.identical(data2) - def test_attrs(self): + def test_attrs(self) -> None: data = create_test_data(seed=42) data.attrs = {"foobar": "baz"} assert data.attrs["foobar"], "baz" assert isinstance(data.attrs, dict) @requires_dask - def test_chunk(self): + def test_chunk(self) -> None: data = create_test_data() for v in data.variables.values(): assert isinstance(v.data, np.ndarray) @@ -955,7 +961,11 @@ def test_chunk(self): else: assert isinstance(v.data, da.Array) - expected_chunks = {"dim1": (8,), "dim2": (9,), "dim3": (10,)} + expected_chunks: dict[Hashable, tuple[int, ...]] = { + "dim1": (8,), + "dim2": (9,), + "dim3": (10,), + } assert reblocked.chunks == expected_chunks # test kwargs form of chunks @@ -995,7 +1005,7 @@ def get_dask_names(ds): data.chunk({"foo": 10}) @requires_dask - def test_dask_is_lazy(self): + def test_dask_is_lazy(self) -> None: store = InaccessibleVariableDataStore() create_test_data().dump_to_store(store) ds = open_dataset(store).chunk() @@ -1016,7 +1026,7 @@ def test_dask_is_lazy(self): ds.set_coords("var1") ds.drop_vars("var1") - def test_isel(self): + def test_isel(self) -> None: data = create_test_data() slicers = {"dim1": slice(None, None, 2), "dim2": slice(0, 2)} ret = data.isel(**slicers) @@ -1078,7 +1088,7 @@ def test_isel(self): assert set(data.coords) == set(ret.coords) assert set(data.xindexes) == set(list(ret.xindexes) + ["time"]) - def test_isel_fancy(self): + def test_isel_fancy(self) -> None: # isel with fancy indexing. data = create_test_data() @@ -1231,7 +1241,7 @@ def test_isel_fancy(self): expected = xr.Dataset({"a": 2}) assert_identical(actual, expected) - def test_isel_dataarray(self): + def test_isel_dataarray(self) -> None: """Test for indexing by DataArray""" data = create_test_data() # indexing with DataArray with same-name coordinates. @@ -1330,7 +1340,7 @@ def test_isel_fancy_convert_index_variable(self) -> None: assert "x" not in actual.xindexes assert not isinstance(actual.x.variable, IndexVariable) - def test_sel(self): + def test_sel(self) -> None: data = create_test_data() int_slicers = {"dim1": slice(None, None, 2), "dim2": slice(2), "dim3": slice(3)} loc_slicers = { @@ -1359,7 +1369,7 @@ def test_sel(self): assert_equal(data.isel(td=0), data.sel(td=pd.Timedelta("0h"))) assert_equal(data.isel(td=slice(1, 3)), data.sel(td=slice("1 days", "2 days"))) - def test_sel_dataarray(self): + def test_sel_dataarray(self) -> None: data = create_test_data() ind = DataArray([0.0, 0.5, 1.0], dims=["dim2"]) @@ -1432,7 +1442,7 @@ def test_sel_dataarray(self): assert_equal(actual.drop_vars("new_dim"), expected) assert np.allclose(actual["new_dim"].values, ind["new_dim"].values) - def test_sel_dataarray_mindex(self): + def test_sel_dataarray_mindex(self) -> None: midx = pd.MultiIndex.from_product([list("abc"), [0, 1]], names=("one", "two")) mds = xr.Dataset( {"var": (("x", "y"), np.random.rand(6, 3))}, @@ -1476,7 +1486,7 @@ def test_sel_dataarray_mindex(self): ) ) - def test_sel_categorical(self): + def test_sel_categorical(self) -> None: ind = pd.Series(["foo", "bar"], dtype="category") df = pd.DataFrame({"ind": ind, "values": [1, 2]}) ds = df.set_index("ind").to_xarray() @@ -1484,7 +1494,7 @@ def test_sel_categorical(self): expected = ds.isel(ind=1) assert_identical(expected, actual) - def test_sel_categorical_error(self): + def test_sel_categorical_error(self) -> None: ind = pd.Series(["foo", "bar"], dtype="category") df = pd.DataFrame({"ind": ind, "values": [1, 2]}) ds = df.set_index("ind").to_xarray() @@ -1493,7 +1503,7 @@ def test_sel_categorical_error(self): with pytest.raises(ValueError): ds.sel(ind="bar", tolerance="nearest") - def test_categorical_index(self): + def test_categorical_index(self) -> None: cat = pd.CategoricalIndex( ["foo", "bar", "foo"], categories=["foo", "bar", "baz", "qux", "quux", "corge"], @@ -1503,18 +1513,18 @@ def test_categorical_index(self): coords={"cat": ("cat", cat), "c": ("cat", [0, 1, 1])}, ) # test slice - actual = ds.sel(cat="foo") - expected = ds.isel(cat=[0, 2]) - assert_identical(expected, actual) + actual1 = ds.sel(cat="foo") + expected1 = ds.isel(cat=[0, 2]) + assert_identical(expected1, actual1) # make sure the conversion to the array works - actual = ds.sel(cat="foo")["cat"].values - assert (actual == np.array(["foo", "foo"])).all() + actual2 = ds.sel(cat="foo")["cat"].values + assert (actual2 == np.array(["foo", "foo"])).all() ds = ds.set_index(index=["cat", "c"]) - actual = ds.unstack("index") - assert actual["var"].shape == (2, 2) + actual3 = ds.unstack("index") + assert actual3["var"].shape == (2, 2) - def test_categorical_reindex(self): + def test_categorical_reindex(self) -> None: cat = pd.CategoricalIndex( ["foo", "bar", "baz"], categories=["foo", "bar", "baz", "qux", "quux", "corge"], @@ -1526,7 +1536,7 @@ def test_categorical_reindex(self): actual = ds.reindex(cat=["foo"])["cat"].values assert (actual == np.array(["foo"])).all() - def test_categorical_multiindex(self): + def test_categorical_multiindex(self) -> None: i1 = pd.Series([0, 0]) cat = pd.CategoricalDtype(categories=["foo", "baz", "bar"]) i2 = pd.Series(["baz", "bar"], dtype=cat) @@ -1537,7 +1547,7 @@ def test_categorical_multiindex(self): actual = df.to_xarray() assert actual["values"].shape == (1, 2) - def test_sel_drop(self): + def test_sel_drop(self) -> None: data = Dataset({"foo": ("x", [1, 2, 3])}, {"x": [0, 1, 2]}) expected = Dataset({"foo": 1}) selected = data.sel(x=0, drop=True) @@ -1552,7 +1562,7 @@ def test_sel_drop(self): selected = data.sel(x=0, drop=True) assert_identical(expected, selected) - def test_sel_drop_mindex(self): + def test_sel_drop_mindex(self) -> None: midx = pd.MultiIndex.from_arrays([["a", "a"], [1, 2]], names=("foo", "bar")) data = Dataset(coords={"x": midx}) @@ -1562,7 +1572,7 @@ def test_sel_drop_mindex(self): actual = data.sel(foo="a", drop=False) assert_equal(actual.foo, DataArray("a", coords={"foo": "a"})) - def test_isel_drop(self): + def test_isel_drop(self) -> None: data = Dataset({"foo": ("x", [1, 2, 3])}, {"x": [0, 1, 2]}) expected = Dataset({"foo": 1}) selected = data.isel(x=0, drop=True) @@ -1572,7 +1582,7 @@ def test_isel_drop(self): selected = data.isel(x=0, drop=False) assert_identical(expected, selected) - def test_head(self): + def test_head(self) -> None: data = create_test_data() expected = data.isel(time=slice(5), dim2=slice(6)) @@ -1598,7 +1608,7 @@ def test_head(self): with pytest.raises(ValueError, match=r"expected positive int"): data.head(time=-3) - def test_tail(self): + def test_tail(self) -> None: data = create_test_data() expected = data.isel(time=slice(-5, None), dim2=slice(-6, None)) @@ -1624,7 +1634,7 @@ def test_tail(self): with pytest.raises(ValueError, match=r"expected positive int"): data.tail(time=-3) - def test_thin(self): + def test_thin(self) -> None: data = create_test_data() expected = data.isel(time=slice(None, None, 5), dim2=slice(None, None, 6)) @@ -1645,7 +1655,7 @@ def test_thin(self): data.thin(time=-3) @pytest.mark.filterwarnings("ignore::DeprecationWarning") - def test_sel_fancy(self): + def test_sel_fancy(self) -> None: data = create_test_data() # add in a range() index @@ -1738,7 +1748,7 @@ def test_sel_fancy(self): with pytest.raises(KeyError): data.sel(x=[2.5], y=[2.0], method="pad", tolerance=1e-3) - def test_sel_method(self): + def test_sel_method(self) -> None: data = create_test_data() expected = data.sel(dim2=1) @@ -1766,7 +1776,7 @@ def test_sel_method(self): with pytest.raises(ValueError, match=r"cannot supply"): data.sel(dim1=0, method="nearest") - def test_loc(self): + def test_loc(self) -> None: data = create_test_data() expected = data.sel(dim3="a") actual = data.loc[dict(dim3="a")] @@ -1774,13 +1784,15 @@ def test_loc(self): with pytest.raises(TypeError, match=r"can only lookup dict"): data.loc["a"] - def test_selection_multiindex(self): + def test_selection_multiindex(self) -> None: mindex = pd.MultiIndex.from_product( [["a", "b"], [1, 2], [-1, -2]], names=("one", "two", "three") ) mdata = Dataset(data_vars={"var": ("x", range(8))}, coords={"x": mindex}) - def test_sel(lab_indexer, pos_indexer, replaced_idx=False, renamed_dim=None): + def test_sel( + lab_indexer, pos_indexer, replaced_idx=False, renamed_dim=None + ) -> None: ds = mdata.sel(x=lab_indexer) expected_ds = mdata.isel(x=pos_indexer) if not replaced_idx: @@ -1811,7 +1823,7 @@ def test_sel(lab_indexer, pos_indexer, replaced_idx=False, renamed_dim=None): assert_identical(mdata.sel(x={"one": "a", "two": 1}), mdata.sel(one="a", two=1)) - def test_broadcast_like(self): + def test_broadcast_like(self) -> None: original1 = DataArray( np.random.randn(5), [("x", range(5))], name="a" ).to_dataset() @@ -1826,7 +1838,7 @@ def test_broadcast_like(self): assert_identical(original2.broadcast_like(original1), expected2) - def test_to_pandas(self): + def test_to_pandas(self) -> None: # 0D -> series actual = Dataset({"a": 1, "b": 2}).to_pandas() expected = pd.Series([1, 2], ["a", "b"]) @@ -1847,7 +1859,7 @@ def test_to_pandas(self): with pytest.raises(ValueError, match=r"cannot convert Datasets"): Dataset({"a": (["t", "r"], x2d), "b": (["t", "r"], y2d)}).to_pandas() - def test_reindex_like(self): + def test_reindex_like(self) -> None: data = create_test_data() data["letters"] = ("dim3", 10 * ["a"]) @@ -1867,7 +1879,7 @@ def test_reindex_like(self): actual = data.reindex_like(expected) assert_identical(actual, expected) - def test_reindex(self): + def test_reindex(self) -> None: data = create_test_data() assert_identical(data, data.reindex()) @@ -1946,7 +1958,7 @@ def test_reindex(self): actual = ds.reindex(x=[0, 1, 3], y=[0, 1]) assert_identical(expected, actual) - def test_reindex_attrs_encoding(self): + def test_reindex_attrs_encoding(self) -> None: ds = Dataset( {"data": ("x", [1, 2, 3])}, {"x": ("x", [0, 1, 2], {"foo": "bar"}, {"bar": "baz"})}, @@ -1959,7 +1971,7 @@ def test_reindex_attrs_encoding(self): assert_identical(actual, expected) assert actual.x.encoding == expected.x.encoding - def test_reindex_warning(self): + def test_reindex_warning(self) -> None: data = create_test_data() with pytest.raises(ValueError): @@ -1973,7 +1985,7 @@ def test_reindex_warning(self): data.reindex(dim2=ind) assert len(ws) == 0 - def test_reindex_variables_copied(self): + def test_reindex_variables_copied(self) -> None: data = create_test_data() reindexed_data = data.reindex(copy=False) for k in data.variables: @@ -2007,7 +2019,7 @@ def test_reindex_method(self) -> None: assert_identical(expected, actual) @pytest.mark.parametrize("fill_value", [dtypes.NA, 2, 2.0, {"x": 2, "z": 1}]) - def test_reindex_fill_value(self, fill_value): + def test_reindex_fill_value(self, fill_value) -> None: ds = Dataset({"x": ("y", [10, 20]), "z": ("y", [-20, -10]), "y": [0, 1]}) y = [0, 1, 2] actual = ds.reindex(y=y, fill_value=fill_value) @@ -2030,7 +2042,7 @@ def test_reindex_fill_value(self, fill_value): assert_identical(expected, actual) @pytest.mark.parametrize("fill_value", [dtypes.NA, 2, 2.0, {"x": 2, "z": 1}]) - def test_reindex_like_fill_value(self, fill_value): + def test_reindex_like_fill_value(self, fill_value) -> None: ds = Dataset({"x": ("y", [10, 20]), "z": ("y", [-20, -10]), "y": [0, 1]}) y = [0, 1, 2] alt = Dataset({"y": y}) @@ -2054,7 +2066,7 @@ def test_reindex_like_fill_value(self, fill_value): assert_identical(expected, actual) @pytest.mark.parametrize("dtype", [str, bytes]) - def test_reindex_str_dtype(self, dtype): + def test_reindex_str_dtype(self, dtype) -> None: data = Dataset({"data": ("x", [1, 2]), "x": np.array(["a", "b"], dtype=dtype)}) actual = data.reindex(x=data.x) @@ -2064,7 +2076,7 @@ def test_reindex_str_dtype(self, dtype): assert actual.x.dtype == expected.x.dtype @pytest.mark.parametrize("fill_value", [dtypes.NA, 2, 2.0, {"foo": 2, "bar": 1}]) - def test_align_fill_value(self, fill_value): + def test_align_fill_value(self, fill_value) -> None: x = Dataset({"foo": DataArray([1, 2], dims=["x"], coords={"x": [1, 2]})}) y = Dataset({"bar": DataArray([1, 2], dims=["x"], coords={"x": [1, 3]})}) x2, y2 = align(x, y, join="outer", fill_value=fill_value) @@ -2095,7 +2107,7 @@ def test_align_fill_value(self, fill_value): assert_identical(expected_x2, x2) assert_identical(expected_y2, y2) - def test_align(self): + def test_align(self) -> None: left = create_test_data() right = left.copy(deep=True) right["dim3"] = ("dim3", list("cdefghijkl")) @@ -2136,11 +2148,11 @@ def test_align(self): assert np.isnan(left2["var3"][-2:]).all() with pytest.raises(ValueError, match=r"invalid value for join"): - align(left, right, join="foobar") + align(left, right, join="foobar") # type: ignore[arg-type] with pytest.raises(TypeError): - align(left, right, foo="bar") + align(left, right, foo="bar") # type: ignore[call-arg] - def test_align_exact(self): + def test_align_exact(self) -> None: left = xr.Dataset(coords={"x": [0, 1]}) right = xr.Dataset(coords={"x": [1, 2]}) @@ -2151,7 +2163,7 @@ def test_align_exact(self): with pytest.raises(ValueError, match=r"cannot align.*join.*exact.*not equal.*"): xr.align(left, right, join="exact") - def test_align_override(self): + def test_align_override(self) -> None: left = xr.Dataset(coords={"x": [0, 1, 2]}) right = xr.Dataset(coords={"x": [0.1, 1.1, 2.1], "y": [1, 2, 3]}) expected_right = xr.Dataset(coords={"x": [0, 1, 2], "y": [1, 2, 3]}) @@ -2175,7 +2187,7 @@ def test_align_override(self): ): xr.align(left.isel(x=0).expand_dims("x"), right, join="override") - def test_align_exclude(self): + def test_align_exclude(self) -> None: x = Dataset( { "foo": DataArray( @@ -2213,7 +2225,7 @@ def test_align_exclude(self): assert_identical(expected_x2, x2) assert_identical(expected_y2, y2) - def test_align_nocopy(self): + def test_align_nocopy(self) -> None: x = Dataset({"foo": DataArray([1, 2, 3], coords=[("x", [1, 2, 3])])}) y = Dataset({"foo": DataArray([1, 2], coords=[("x", [1, 2])])}) expected_x2 = x @@ -2231,7 +2243,7 @@ def test_align_nocopy(self): assert_identical(expected_x2, x2) assert_identical(expected_y2, y2) - def test_align_indexes(self): + def test_align_indexes(self) -> None: x = Dataset({"foo": DataArray([1, 2, 3], dims="x", coords=[("x", [1, 2, 3])])}) (x2,) = align(x, indexes={"x": [2, 3, 1]}) expected_x2 = Dataset( @@ -2240,7 +2252,7 @@ def test_align_indexes(self): assert_identical(expected_x2, x2) - def test_align_non_unique(self): + def test_align_non_unique(self) -> None: x = Dataset({"foo": ("x", [3, 4, 5]), "x": [0, 0, 1]}) x1, x2 = align(x, x) assert_identical(x1, x) @@ -2250,7 +2262,7 @@ def test_align_non_unique(self): with pytest.raises(ValueError, match=r"cannot reindex or align"): align(x, y) - def test_align_str_dtype(self): + def test_align_str_dtype(self) -> None: a = Dataset({"foo": ("x", [0, 1])}, coords={"x": ["a", "b"]}) b = Dataset({"foo": ("x", [1, 2])}, coords={"x": ["b", "c"]}) @@ -2270,7 +2282,7 @@ def test_align_str_dtype(self): assert_identical(expected_b, actual_b) assert expected_b.x.dtype == actual_b.x.dtype - def test_broadcast(self): + def test_broadcast(self) -> None: ds = Dataset( {"foo": 0, "bar": ("x", [1]), "baz": ("y", [2, 3])}, {"c": ("x", [4])} ) @@ -2294,12 +2306,12 @@ def test_broadcast(self): assert_identical(expected_y, actual_y) array_y = ds_y["bar"] - expected_y = expected_y["bar"] - actual_x, actual_y = broadcast(ds_x, array_y) - assert_identical(expected_x, actual_x) - assert_identical(expected_y, actual_y) + expected_y2 = expected_y["bar"] + actual_x2, actual_y2 = broadcast(ds_x, array_y) + assert_identical(expected_x, actual_x2) + assert_identical(expected_y2, actual_y2) - def test_broadcast_nocopy(self): + def test_broadcast_nocopy(self) -> None: # Test that data is not copied if not needed x = Dataset({"foo": (("x", "y"), [[1, 1]])}) y = Dataset({"bar": ("y", [2, 3])}) @@ -2312,7 +2324,7 @@ def test_broadcast_nocopy(self): assert_identical(x, actual_x) assert source_ndarray(actual_x["foo"].data) is source_ndarray(x["foo"].data) - def test_broadcast_exclude(self): + def test_broadcast_exclude(self) -> None: x = Dataset( { "foo": DataArray( @@ -2354,7 +2366,7 @@ def test_broadcast_exclude(self): assert_identical(expected_x2, x2) assert_identical(expected_y2, y2) - def test_broadcast_misaligned(self): + def test_broadcast_misaligned(self) -> None: x = Dataset({"foo": DataArray([1, 2, 3], coords=[("x", [-1, -2, -3])])}) y = Dataset( { @@ -2387,7 +2399,7 @@ def test_broadcast_misaligned(self): assert_identical(expected_x2, x2) assert_identical(expected_y2, y2) - def test_broadcast_multi_index(self): + def test_broadcast_multi_index(self) -> None: # GH6430 ds = Dataset( {"foo": (("x", "y", "z"), np.ones((3, 4, 2)))}, @@ -2399,7 +2411,7 @@ def test_broadcast_multi_index(self): assert broadcasted.xindexes["x"] is broadcasted.xindexes["space"] assert broadcasted.xindexes["y"] is broadcasted.xindexes["space"] - def test_variable_indexing(self): + def test_variable_indexing(self) -> None: data = create_test_data() v = data["var1"] d1 = data["dim1"] @@ -2412,7 +2424,7 @@ def test_variable_indexing(self): assert_equal(v[:3, :2], v[range(3), range(2)]) assert_equal(v[:3, :2], v.loc[d1[:3], d2[:2]]) - def test_drop_variables(self): + def test_drop_variables(self) -> None: data = create_test_data() assert_identical(data, data.drop_vars([])) @@ -2453,14 +2465,14 @@ def test_drop_variables(self): actual = data.drop({"time", "not_found_here"}, errors="ignore") assert_identical(expected, actual) - def test_drop_multiindex_level(self): + def test_drop_multiindex_level(self) -> None: data = create_test_multiindex() expected = data.drop_vars(["x", "level_1", "level_2"]) with pytest.warns(DeprecationWarning): actual = data.drop_vars("level_1") assert_identical(expected, actual) - def test_drop_index_labels(self): + def test_drop_index_labels(self) -> None: data = Dataset({"A": (["x", "y"], np.random.randn(2, 3)), "x": ["a", "b"]}) with pytest.warns(DeprecationWarning): @@ -2484,7 +2496,7 @@ def test_drop_index_labels(self): with pytest.raises(ValueError): with pytest.warns(DeprecationWarning): - data.drop(["c"], dim="x", errors="wrong_value") + data.drop(["c"], dim="x", errors="wrong_value") # type: ignore[arg-type] with pytest.warns(DeprecationWarning): actual = data.drop(["a", "b", "c"], "x", errors="ignore") @@ -2507,7 +2519,7 @@ def test_drop_index_labels(self): with pytest.raises(KeyError, match=r"not found in axis"): data.drop_sel(x=0) - def test_drop_labels_by_keyword(self): + def test_drop_labels_by_keyword(self) -> None: data = Dataset( {"A": (["x", "y"], np.random.randn(2, 6)), "x": ["a", "b"], "y": range(6)} ) @@ -2543,7 +2555,7 @@ def test_drop_labels_by_keyword(self): with pytest.raises(ValueError): data.drop(dim="x", x="a") - def test_drop_labels_by_position(self): + def test_drop_labels_by_position(self) -> None: data = Dataset( {"A": (["x", "y"], np.random.randn(2, 6)), "x": ["a", "b"], "y": range(6)} ) @@ -2571,7 +2583,7 @@ def test_drop_labels_by_position(self): with pytest.raises(KeyError): data.drop_isel(z=1) - def test_drop_dims(self): + def test_drop_dims(self) -> None: data = xr.Dataset( { "A": (["x", "y"], np.random.randn(2, 3)), @@ -2606,13 +2618,13 @@ def test_drop_dims(self): assert_identical(data, actual) with pytest.raises(ValueError): - actual = data.drop_dims("z", errors="wrong_value") + actual = data.drop_dims("z", errors="wrong_value") # type: ignore[arg-type] actual = data.drop_dims(["x", "y", "z"], errors="ignore") expected = data.drop_vars(["A", "B", "x"]) assert_identical(expected, actual) - def test_copy(self): + def test_copy(self) -> None: data = create_test_data() data.attrs["Test"] = [1, 2, 3] @@ -2641,7 +2653,7 @@ def test_copy(self): assert data.attrs["Test"] is not copied.attrs["Test"] - def test_copy_with_data(self): + def test_copy_with_data(self) -> None: orig = create_test_data() new_data = {k: np.random.randn(*v.shape) for k, v in orig.data_vars.items()} actual = orig.copy(data=new_data) @@ -2673,7 +2685,7 @@ def test_copy_with_data(self): ], ], ) - def test_copy_coords(self, deep, expected_orig): + def test_copy_coords(self, deep, expected_orig) -> None: """The test fails for the shallow copy, and apparently only on Windows for some reason. In windows coords seem to be immutable unless it's one dataset deep copied from another.""" @@ -2695,7 +2707,7 @@ def test_copy_coords(self, deep, expected_orig): assert_identical(ds.coords["a"], expected_orig) - def test_copy_with_data_errors(self): + def test_copy_with_data_errors(self) -> None: orig = create_test_data() new_var1 = np.arange(orig["var1"].size).reshape(orig["var1"].shape) with pytest.raises(ValueError, match=r"Data must be dict-like"): @@ -2705,12 +2717,15 @@ def test_copy_with_data_errors(self): with pytest.raises(ValueError, match=r"contain all variables in original"): orig.copy(data={"var1": new_var1}) - def test_rename(self): + def test_rename(self) -> None: data = create_test_data() - newnames = {"var1": "renamed_var1", "dim2": "renamed_dim2"} + newnames: dict[Hashable, Hashable] = { + "var1": "renamed_var1", + "dim2": "renamed_dim2", + } renamed = data.rename(newnames) - variables = dict(data.variables) + variables: dict[Hashable, Variable] = dict(data.variables) for k, v in newnames.items(): variables[v] = variables.pop(k) @@ -2746,7 +2761,7 @@ def test_rename(self): renamed_kwargs = data.rename(**newnames) assert_identical(renamed, renamed_kwargs) - def test_rename_old_name(self): + def test_rename_old_name(self) -> None: # regtest for GH1477 data = create_test_data() @@ -2756,13 +2771,13 @@ def test_rename_old_name(self): # This shouldn't cause any problems. data.rename({"var1": "var2", "var2": "var1"}) - def test_rename_same_name(self): + def test_rename_same_name(self) -> None: data = create_test_data() newnames = {"var1": "var1", "dim2": "dim2"} renamed = data.rename(newnames) assert_identical(renamed, data) - def test_rename_dims(self): + def test_rename_dims(self) -> None: original = Dataset({"x": ("x", [0, 1, 2]), "y": ("x", [10, 11, 12]), "z": 42}) expected = Dataset( {"x": ("x_new", [0, 1, 2]), "y": ("x_new", [10, 11, 12]), "z": 42} @@ -2770,10 +2785,9 @@ def test_rename_dims(self): # TODO: (benbovy - explicit indexes) update when set_index supports # seeting index for non-dimension variables expected = expected.set_coords("x") - dims_dict = {"x": "x_new"} - actual = original.rename_dims(dims_dict) + actual = original.rename_dims({"x": "x_new"}) assert_identical(expected, actual, check_default_indexes=False) - actual_2 = original.rename_dims(**dims_dict) + actual_2 = original.rename_dims(x="x_new") assert_identical(expected, actual_2, check_default_indexes=False) # Test to raise ValueError @@ -2784,7 +2798,7 @@ def test_rename_dims(self): with pytest.raises(ValueError): original.rename_dims({"x": "z"}) - def test_rename_vars(self): + def test_rename_vars(self) -> None: original = Dataset({"x": ("x", [0, 1, 2]), "y": ("x", [10, 11, 12]), "z": 42}) expected = Dataset( {"x_new": ("x", [0, 1, 2]), "y": ("x", [10, 11, 12]), "z": 42} @@ -2792,10 +2806,9 @@ def test_rename_vars(self): # TODO: (benbovy - explicit indexes) update when set_index supports # seeting index for non-dimension variables expected = expected.set_coords("x_new") - name_dict = {"x": "x_new"} - actual = original.rename_vars(name_dict) + actual = original.rename_vars({"x": "x_new"}) assert_identical(expected, actual, check_default_indexes=False) - actual_2 = original.rename_vars(**name_dict) + actual_2 = original.rename_vars(x="x_new") assert_identical(expected, actual_2, check_default_indexes=False) # Test to raise ValueError @@ -2841,7 +2854,7 @@ def test_rename_perserve_attrs_encoding(self) -> None: assert_identical(actual, expected) @requires_cftime - def test_rename_does_not_change_CFTimeIndex_type(self): + def test_rename_does_not_change_CFTimeIndex_type(self) -> None: # make sure CFTimeIndex is not converted to DatetimeIndex #3522 time = xr.cftime_range(start="2000", periods=6, freq="2MS", calendar="noleap") @@ -2866,7 +2879,7 @@ def test_rename_does_not_change_CFTimeIndex_type(self): renamed = orig.rename_vars() assert isinstance(renamed.xindexes["time"].to_pandas_index(), CFTimeIndex) - def test_rename_does_not_change_DatetimeIndex_type(self): + def test_rename_does_not_change_DatetimeIndex_type(self) -> None: # make sure DatetimeIndex is conderved on rename time = pd.date_range(start="2000", periods=6, freq="2MS") @@ -2891,7 +2904,7 @@ def test_rename_does_not_change_DatetimeIndex_type(self): renamed = orig.rename_vars() assert isinstance(renamed.xindexes["time"].to_pandas_index(), DatetimeIndex) - def test_swap_dims(self): + def test_swap_dims(self) -> None: original = Dataset({"x": [1, 2, 3], "y": ("x", list("abc")), "z": 42}) expected = Dataset({"z": 42}, {"x": ("y", [1, 2, 3]), "y": list("abc")}) actual = original.swap_dims({"x": "y"}) @@ -2931,7 +2944,7 @@ def test_swap_dims(self): assert isinstance(actual.variables["x"], Variable) assert actual.xindexes["y"].equals(expected.xindexes["y"]) - def test_expand_dims_error(self): + def test_expand_dims_error(self) -> None: original = Dataset( { "x": ("a", np.random.randn(3)), @@ -2973,7 +2986,7 @@ def test_expand_dims_error(self): with pytest.raises(ValueError, match=r"both keyword and positional"): original.expand_dims({"d": 4}, e=4) - def test_expand_dims_int(self): + def test_expand_dims_int(self) -> None: original = Dataset( {"x": ("a", np.random.randn(3)), "y": (["b", "a"], np.random.randn(4, 3))}, coords={ @@ -3021,7 +3034,7 @@ def test_expand_dims_int(self): roundtripped = actual.squeeze("z") assert_identical(original, roundtripped) - def test_expand_dims_coords(self): + def test_expand_dims_coords(self) -> None: original = Dataset({"x": ("a", np.array([1, 2, 3]))}) expected = Dataset( {"x": (("b", "a"), np.array([[1, 2, 3], [1, 2, 3]]))}, coords={"b": [1, 2]} @@ -3030,18 +3043,18 @@ def test_expand_dims_coords(self): assert_identical(expected, actual) assert "b" not in original._coord_names - def test_expand_dims_existing_scalar_coord(self): + def test_expand_dims_existing_scalar_coord(self) -> None: original = Dataset({"x": 1}, {"a": 2}) expected = Dataset({"x": (("a",), [1])}, {"a": [2]}) actual = original.expand_dims("a") assert_identical(expected, actual) - def test_isel_expand_dims_roundtrip(self): + def test_isel_expand_dims_roundtrip(self) -> None: original = Dataset({"x": (("a",), [1])}, {"a": [2]}) actual = original.isel(a=0).expand_dims("a") assert_identical(actual, original) - def test_expand_dims_mixed_int_and_coords(self): + def test_expand_dims_mixed_int_and_coords(self) -> None: # Test expanding one dimension to have size > 1 that doesn't have # coordinates, and also expanding another dimension to have size > 1 # that DOES have coordinates. @@ -3078,7 +3091,7 @@ def test_expand_dims_mixed_int_and_coords(self): ) assert_identical(actual, expected) - def test_expand_dims_kwargs_python36plus(self): + def test_expand_dims_kwargs_python36plus(self) -> None: original = Dataset( {"x": ("a", np.random.randn(3)), "y": (["b", "a"], np.random.randn(4, 3))}, coords={ @@ -3111,7 +3124,7 @@ def test_expand_dims_kwargs_python36plus(self): ) assert_identical(other_way_expected, other_way) - def test_set_index(self): + def test_set_index(self) -> None: expected = create_test_multiindex() mindex = expected["x"].to_index() indexes = [mindex.get_level_values(n) for n in mindex.names] @@ -3142,7 +3155,7 @@ def test_set_index(self): with pytest.raises(ValueError, match=r"dimension mismatch.*"): ds.set_index(y="x_var") - def test_reset_index(self): + def test_reset_index(self) -> None: ds = create_test_multiindex() mindex = ds["x"].to_index() indexes = [mindex.get_level_values(n) for n in mindex.names] @@ -3158,14 +3171,14 @@ def test_reset_index(self): with pytest.raises(ValueError, match=r".*not coordinates with an index"): ds.reset_index("y") - def test_reset_index_keep_attrs(self): + def test_reset_index_keep_attrs(self) -> None: coord_1 = DataArray([1, 2], dims=["coord_1"], attrs={"attrs": True}) ds = Dataset({}, {"coord_1": coord_1}) obj = ds.reset_index("coord_1") assert_identical(obj, ds, check_default_indexes=False) assert len(obj.xindexes) == 0 - def test_reorder_levels(self): + def test_reorder_levels(self) -> None: ds = create_test_multiindex() mindex = ds["x"].to_index() midx = mindex.reorder_levels(["level_2", "level_1"]) @@ -3182,7 +3195,7 @@ def test_reorder_levels(self): with pytest.raises(ValueError, match=r"has no MultiIndex"): ds.reorder_levels(x=["level_1", "level_2"]) - def test_stack(self): + def test_stack(self) -> None: ds = Dataset( data_vars={"b": (("x", "y"), [[0, 1], [2, 3]])}, coords={"x": ("x", [0, 1]), "y": ["a", "b"]}, @@ -3266,7 +3279,7 @@ def test_stack_multi_index(self) -> None: with pytest.raises(ValueError, match=r"cannot create.*wraps a multi-index"): ds.stack(z=["x", "y"], create_index=True) - def test_stack_non_dim_coords(self): + def test_stack_non_dim_coords(self) -> None: ds = Dataset( data_vars={"b": (("x", "y"), [[0, 1], [2, 3]])}, coords={"x": ("x", [0, 1]), "y": ["a", "b"]}, @@ -3282,7 +3295,7 @@ def test_stack_non_dim_coords(self): assert_identical(expected, actual) assert list(actual.xindexes) == ["z", "xx", "y"] - def test_unstack(self): + def test_unstack(self) -> None: index = pd.MultiIndex.from_product([[0, 1], ["a", "b"]], names=["x", "y"]) ds = Dataset(data_vars={"b": ("z", [0, 1, 2, 3])}, coords={"z": index}) expected = Dataset( @@ -3297,14 +3310,14 @@ def test_unstack(self): actual = ds.unstack(dim) assert_identical(actual, expected) - def test_unstack_errors(self): + def test_unstack_errors(self) -> None: ds = Dataset({"x": [1, 2, 3]}) with pytest.raises(ValueError, match=r"does not contain the dimensions"): ds.unstack("foo") with pytest.raises(ValueError, match=r".*do not have exactly one multi-index"): ds.unstack("x") - def test_unstack_fill_value(self): + def test_unstack_fill_value(self) -> None: ds = xr.Dataset( {"var": (("x",), np.arange(6)), "other_var": (("x",), np.arange(3, 9))}, coords={"x": [0, 1, 2] * 2, "y": (("x",), ["a"] * 3 + ["b"] * 3)}, @@ -3312,21 +3325,21 @@ def test_unstack_fill_value(self): # make ds incomplete ds = ds.isel(x=[0, 2, 3, 4]).set_index(index=["x", "y"]) # test fill_value - actual = ds.unstack("index", fill_value=-1) - expected = ds.unstack("index").fillna(-1).astype(int) - assert actual["var"].dtype == int - assert_equal(actual, expected) + actual1 = ds.unstack("index", fill_value=-1) + expected1 = ds.unstack("index").fillna(-1).astype(int) + assert actual1["var"].dtype == int + assert_equal(actual1, expected1) - actual = ds["var"].unstack("index", fill_value=-1) - expected = ds["var"].unstack("index").fillna(-1).astype(int) - assert_equal(actual, expected) + actual2 = ds["var"].unstack("index", fill_value=-1) + expected2 = ds["var"].unstack("index").fillna(-1).astype(int) + assert_equal(actual2, expected2) - actual = ds.unstack("index", fill_value={"var": -1, "other_var": 1}) - expected = ds.unstack("index").fillna({"var": -1, "other_var": 1}).astype(int) - assert_equal(actual, expected) + actual3 = ds.unstack("index", fill_value={"var": -1, "other_var": 1}) + expected3 = ds.unstack("index").fillna({"var": -1, "other_var": 1}).astype(int) + assert_equal(actual3, expected3) @requires_sparse - def test_unstack_sparse(self): + def test_unstack_sparse(self) -> None: ds = xr.Dataset( {"var": (("x",), np.arange(6))}, coords={"x": [0, 1, 2] * 2, "y": (("x",), ["a"] * 3 + ["b"] * 3)}, @@ -3334,17 +3347,17 @@ def test_unstack_sparse(self): # make ds incomplete ds = ds.isel(x=[0, 2, 3, 4]).set_index(index=["x", "y"]) # test fill_value - actual = ds.unstack("index", sparse=True) - expected = ds.unstack("index") - assert isinstance(actual["var"].data, sparse_array_type) - assert actual["var"].variable._to_dense().equals(expected["var"].variable) - assert actual["var"].data.density < 1.0 - - actual = ds["var"].unstack("index", sparse=True) - expected = ds["var"].unstack("index") - assert isinstance(actual.data, sparse_array_type) - assert actual.variable._to_dense().equals(expected.variable) - assert actual.data.density < 1.0 + actual1 = ds.unstack("index", sparse=True) + expected1 = ds.unstack("index") + assert isinstance(actual1["var"].data, sparse_array_type) + assert actual1["var"].variable._to_dense().equals(expected1["var"].variable) + assert actual1["var"].data.density < 1.0 + + actual2 = ds["var"].unstack("index", sparse=True) + expected2 = ds["var"].unstack("index") + assert isinstance(actual2.data, sparse_array_type) + assert actual2.variable._to_dense().equals(expected2.variable) + assert actual2.data.density < 1.0 mindex = pd.MultiIndex.from_arrays( [np.arange(3), np.arange(3)], names=["a", "b"] @@ -3353,9 +3366,9 @@ def test_unstack_sparse(self): {"var": (("z", "foo", "bar"), np.ones((3, 4, 5)))}, coords={"z": mindex, "foo": np.arange(4), "bar": np.arange(5)}, ) - actual = ds_eye.unstack(sparse=True, fill_value=0) - assert isinstance(actual["var"].data, sparse_array_type) - expected = xr.Dataset( + actual3 = ds_eye.unstack(sparse=True, fill_value=0) + assert isinstance(actual3["var"].data, sparse_array_type) + expected3 = xr.Dataset( { "var": ( ("foo", "bar", "a", "b"), @@ -3369,10 +3382,10 @@ def test_unstack_sparse(self): "b": np.arange(3), }, ) - actual["var"].data = actual["var"].data.todense() - assert_equal(expected, actual) + actual3["var"].data = actual3["var"].data.todense() + assert_equal(expected3, actual3) - def test_stack_unstack_fast(self): + def test_stack_unstack_fast(self) -> None: ds = Dataset( { "a": ("x", [0, 1]), @@ -3387,7 +3400,7 @@ def test_stack_unstack_fast(self): actual = ds[["b"]].stack(z=["x", "y"]).unstack("z") assert actual.identical(ds[["b"]]) - def test_stack_unstack_slow(self): + def test_stack_unstack_slow(self) -> None: ds = Dataset( data_vars={ "a": ("x", [0, 1]), @@ -3403,7 +3416,7 @@ def test_stack_unstack_slow(self): actual = stacked.isel(z=slice(None, None, -1)).unstack("z") assert actual.identical(ds[["b"]]) - def test_to_stacked_array_invalid_sample_dims(self): + def test_to_stacked_array_invalid_sample_dims(self) -> None: data = xr.Dataset( data_vars={"a": (("x", "y"), [[0, 1, 2], [3, 4, 5]]), "b": ("x", [6, 7])}, coords={"y": ["u", "v", "w"]}, @@ -3411,7 +3424,7 @@ def test_to_stacked_array_invalid_sample_dims(self): with pytest.raises(ValueError): data.to_stacked_array("features", sample_dims=["y"]) - def test_to_stacked_array_name(self): + def test_to_stacked_array_name(self) -> None: name = "adf9d" # make a two dimensional dataset @@ -3422,7 +3435,7 @@ def test_to_stacked_array_name(self): y = D.to_stacked_array("features", sample_dims, name=name) assert y.name == name - def test_to_stacked_array_dtype_dims(self): + def test_to_stacked_array_dtype_dims(self) -> None: # make a two dimensional dataset a, b = create_test_stacked_array() D = xr.Dataset({"a": a, "b": b}) @@ -3431,7 +3444,7 @@ def test_to_stacked_array_dtype_dims(self): assert y.xindexes["features"].to_pandas_index().levels[1].dtype == D.y.dtype assert y.dims == ("x", "features") - def test_to_stacked_array_to_unstacked_dataset(self): + def test_to_stacked_array_to_unstacked_dataset(self) -> None: # single dimension: regression test for GH4049 arr = xr.DataArray(np.arange(3), coords=[("x", [0, 1, 2])]) @@ -3454,7 +3467,7 @@ def test_to_stacked_array_to_unstacked_dataset(self): d0 = D.isel(x=0) assert_identical(d0, x0) - def test_to_stacked_array_to_unstacked_dataset_different_dimension(self): + def test_to_stacked_array_to_unstacked_dataset_different_dimension(self) -> None: # test when variables have different dimensionality a, b = create_test_stacked_array() sample_dims = ["x"] @@ -3464,7 +3477,7 @@ def test_to_stacked_array_to_unstacked_dataset_different_dimension(self): x = y.to_unstacked_dataset("features") assert_identical(D, x) - def test_update(self): + def test_update(self) -> None: data = create_test_data(seed=0) expected = data.copy() var2 = Variable("dim1", np.arange(8)) @@ -3482,7 +3495,7 @@ def test_update(self): actual.update(other) assert_identical(expected, actual) - def test_update_overwrite_coords(self): + def test_update_overwrite_coords(self) -> None: data = Dataset({"a": ("x", [1, 2])}, {"b": 3}) data.update(Dataset(coords={"b": 4})) expected = Dataset({"a": ("x", [1, 2])}, {"b": 4}) @@ -3498,7 +3511,7 @@ def test_update_overwrite_coords(self): expected = Dataset({"a": ("x", [1, 2]), "c": 5}, {"b": 3}) assert_identical(data, expected) - def test_update_multiindex_level(self): + def test_update_multiindex_level(self) -> None: data = create_test_multiindex() with pytest.raises( @@ -3506,26 +3519,28 @@ def test_update_multiindex_level(self): ): data.update({"level_1": range(4)}) - def test_update_auto_align(self): + def test_update_auto_align(self) -> None: ds = Dataset({"x": ("t", [3, 4])}, {"t": [0, 1]}) - expected = Dataset({"x": ("t", [3, 4]), "y": ("t", [np.nan, 5])}, {"t": [0, 1]}) - actual = ds.copy() - other = {"y": ("t", [5]), "t": [1]} + expected1 = Dataset( + {"x": ("t", [3, 4]), "y": ("t", [np.nan, 5])}, {"t": [0, 1]} + ) + actual1 = ds.copy() + other1 = {"y": ("t", [5]), "t": [1]} with pytest.raises(ValueError, match=r"conflicting sizes"): - actual.update(other) - actual.update(Dataset(other)) - assert_identical(expected, actual) - - actual = ds.copy() - other = Dataset({"y": ("t", [5]), "t": [100]}) - actual.update(other) - expected = Dataset( + actual1.update(other1) + actual1.update(Dataset(other1)) + assert_identical(expected1, actual1) + + actual2 = ds.copy() + other2 = Dataset({"y": ("t", [5]), "t": [100]}) + actual2.update(other2) + expected2 = Dataset( {"x": ("t", [3, 4]), "y": ("t", [np.nan] * 2)}, {"t": [0, 1]} ) - assert_identical(expected, actual) + assert_identical(expected2, actual2) - def test_getitem(self): + def test_getitem(self) -> None: data = create_test_data() assert isinstance(data["var1"], DataArray) assert_equal(data["var1"].variable, data.variables["var1"]) @@ -3534,24 +3549,24 @@ def test_getitem(self): with pytest.raises(KeyError): data[["var1", "notfound"]] - actual = data[["var1", "var2"]] - expected = Dataset({"var1": data["var1"], "var2": data["var2"]}) - assert_equal(expected, actual) + actual1 = data[["var1", "var2"]] + expected1 = Dataset({"var1": data["var1"], "var2": data["var2"]}) + assert_equal(expected1, actual1) - actual = data["numbers"] - expected = DataArray( + actual2 = data["numbers"] + expected2 = DataArray( data["numbers"].variable, {"dim3": data["dim3"], "numbers": data["numbers"]}, dims="dim3", name="numbers", ) - assert_identical(expected, actual) + assert_identical(expected2, actual2) - actual = data[dict(dim1=0)] - expected = data.isel(dim1=0) - assert_identical(expected, actual) + actual3 = data[dict(dim1=0)] + expected3 = data.isel(dim1=0) + assert_identical(expected3, actual3) - def test_getitem_hashable(self): + def test_getitem_hashable(self) -> None: data = create_test_data() data[(3, 4)] = data["var1"] + 1 expected = data["var1"] + 1 @@ -3560,29 +3575,25 @@ def test_getitem_hashable(self): with pytest.raises(KeyError, match=r"('var1', 'var2')"): data[("var1", "var2")] - def test_getitem_multiple_dtype(self): + def test_getitem_multiple_dtype(self) -> None: keys = ["foo", 1] dataset = Dataset({key: ("dim0", range(1)) for key in keys}) assert_identical(dataset, dataset[keys]) - def test_virtual_variables_default_coords(self): + def test_virtual_variables_default_coords(self) -> None: dataset = Dataset({"foo": ("x", range(10))}) - expected = DataArray(range(10), dims="x", name="x") - actual = dataset["x"] - assert_identical(expected, actual) - assert isinstance(actual.variable, IndexVariable) + expected1 = DataArray(range(10), dims="x", name="x") + actual1 = dataset["x"] + assert_identical(expected1, actual1) + assert isinstance(actual1.variable, IndexVariable) - actual = dataset[["x", "foo"]] - expected = dataset.assign_coords(x=range(10)) - assert_identical(expected, actual) + actual2 = dataset[["x", "foo"]] + expected2 = dataset.assign_coords(x=range(10)) + assert_identical(expected2, actual2) - def test_virtual_variables_time(self): + def test_virtual_variables_time(self) -> None: # access virtual variables data = create_test_data() - expected = DataArray( - 1 + np.arange(20), coords=[data["time"]], dims="time", name="dayofyear" - ) - assert_array_equal( data["time.month"].values, data.variables["time"].to_index().month ) @@ -3598,7 +3609,7 @@ def test_virtual_variables_time(self): ds = Dataset({"t": ("x", pd.date_range("2000-01-01", periods=3))}) assert (ds["t.year"] == 2000).all() - def test_virtual_variable_same_name(self): + def test_virtual_variable_same_name(self) -> None: # regression test for GH367 times = pd.date_range("2000-01-01", freq="H", periods=5) data = Dataset({"time": times}) @@ -3606,19 +3617,19 @@ def test_virtual_variable_same_name(self): expected = DataArray(times.time, [("time", times)], name="time") assert_identical(actual, expected) - def test_time_season(self): + def test_time_season(self) -> None: ds = Dataset({"t": pd.date_range("2000-01-01", periods=12, freq="M")}) seas = ["DJF"] * 2 + ["MAM"] * 3 + ["JJA"] * 3 + ["SON"] * 3 + ["DJF"] assert_array_equal(seas, ds["t.season"]) - def test_slice_virtual_variable(self): + def test_slice_virtual_variable(self) -> None: data = create_test_data() assert_equal( data["time.dayofyear"][:10].variable, Variable(["time"], 1 + np.arange(10)) ) assert_equal(data["time.dayofyear"][0].variable, Variable([], 1)) - def test_setitem(self): + def test_setitem(self) -> None: # assign a variable var = Variable(["dim1"], np.random.randn(8)) data1 = create_test_data() @@ -3710,7 +3721,7 @@ def test_setitem(self): dat4.loc[{"dim2": unchanged}], dat3.loc[{"dim2": unchanged}] ) - def test_setitem_pandas(self): + def test_setitem_pandas(self) -> None: ds = self.make_example_math_dataset() ds["x"] = np.arange(3) @@ -3719,7 +3730,7 @@ def test_setitem_pandas(self): assert_equal(ds, ds_copy) - def test_setitem_auto_align(self): + def test_setitem_auto_align(self) -> None: ds = Dataset() ds["x"] = ("y", range(3)) ds["y"] = 1 + np.arange(3) @@ -3742,7 +3753,7 @@ def test_setitem_auto_align(self): expected = Dataset({"x": ("y", [4, 5, 6])}, {"y": range(3)}) assert_identical(ds, expected) - def test_setitem_dimension_override(self): + def test_setitem_dimension_override(self) -> None: # regression test for GH-3377 ds = xr.Dataset({"x": [0, 1, 2]}) ds["x"] = ds["x"][:2] @@ -3757,7 +3768,7 @@ def test_setitem_dimension_override(self): ds.coords["x"] = [0, 1] assert_identical(ds, expected) - def test_setitem_with_coords(self): + def test_setitem_with_coords(self) -> None: # Regression test for GH:2068 ds = create_test_data() @@ -3805,7 +3816,7 @@ def test_setitem_with_coords(self): ds["var"] = ds["var"] * 2 assert np.allclose(ds["var"], [2, 4, 6]) - def test_setitem_align_new_indexes(self): + def test_setitem_align_new_indexes(self) -> None: ds = Dataset({"foo": ("x", [1, 2, 3])}, {"x": [0, 1, 2]}) ds["bar"] = DataArray([2, 3, 4], [("x", [1, 2, 3])]) expected = Dataset( @@ -3814,7 +3825,7 @@ def test_setitem_align_new_indexes(self): assert_identical(ds, expected) @pytest.mark.parametrize("dtype", [str, bytes]) - def test_setitem_str_dtype(self, dtype): + def test_setitem_str_dtype(self, dtype) -> None: ds = xr.Dataset(coords={"x": np.array(["x", "y"], dtype=dtype)}) # test Dataset update @@ -3822,7 +3833,7 @@ def test_setitem_str_dtype(self, dtype): assert np.issubdtype(ds.x.dtype, dtype) - def test_setitem_using_list(self): + def test_setitem_using_list(self) -> None: # assign a list of variables var1 = Variable(["dim1"], np.random.randn(8)) @@ -3851,12 +3862,12 @@ def test_setitem_using_list(self): (["A", "B"], xr.DataArray([1, 2]), r"assign single DataArray"), ], ) - def test_setitem_using_list_errors(self, var_list, data, error_regex): + def test_setitem_using_list_errors(self, var_list, data, error_regex) -> None: actual = create_test_data() with pytest.raises(ValueError, match=error_regex): actual[var_list] = data - def test_assign(self): + def test_assign(self) -> None: ds = Dataset() actual = ds.assign(x=[0, 1, 2], y=2) expected = Dataset({"x": [0, 1, 2], "y": 2}) @@ -3872,7 +3883,7 @@ def test_assign(self): expected = Dataset({"y": ("x", [0, 1, 4])}, {"z": 2, "x": [0, 1, 2]}) assert_identical(actual, expected) - def test_assign_coords(self): + def test_assign_coords(self) -> None: ds = Dataset() actual = ds.assign(x=[0, 1, 2], y=2) @@ -3885,7 +3896,7 @@ def test_assign_coords(self): expected = ds.assign(x=[0, 1, 2], y=[2.0, 3.0]) assert_identical(actual, expected) - def test_assign_attrs(self): + def test_assign_attrs(self) -> None: expected = Dataset(attrs=dict(a=1, b=2)) new = Dataset() actual = new.assign_attrs(a=1, b=2) @@ -3897,7 +3908,7 @@ def test_assign_attrs(self): assert_identical(new_actual, expected) assert actual.attrs == dict(a=1, b=2) - def test_assign_multiindex_level(self): + def test_assign_multiindex_level(self) -> None: data = create_test_multiindex() with pytest.raises( ValueError, match=r"cannot set or update variable.*corrupt.*index " @@ -3905,7 +3916,7 @@ def test_assign_multiindex_level(self): data.assign(level_1=range(4)) data.assign_coords(level_1=range(4)) - def test_assign_all_multiindex_coords(self): + def test_assign_all_multiindex_coords(self) -> None: data = create_test_multiindex() actual = data.assign(x=range(4), level_1=range(4), level_2=range(4)) # no error but multi-index dropped in favor of single indexes for each level @@ -3915,7 +3926,7 @@ def test_assign_all_multiindex_coords(self): is not actual.xindexes["level_2"] ) - def test_merge_multiindex_level(self): + def test_merge_multiindex_level(self) -> None: data = create_test_multiindex() other = Dataset({"level_1": ("x", [0, 1])}) @@ -3932,7 +3943,7 @@ def test_merge_multiindex_level(self): other = Dataset(coords={"level_1": ("x", range(4))}) assert_identical(data.merge(other), data) - def test_setitem_original_non_unique_index(self): + def test_setitem_original_non_unique_index(self) -> None: # regression test for GH943 original = Dataset({"data": ("x", np.arange(5))}, coords={"x": [0, 1, 2, 0, 1]}) expected = Dataset({"data": ("x", np.arange(5))}, {"x": range(5)}) @@ -3949,7 +3960,7 @@ def test_setitem_original_non_unique_index(self): actual.coords["x"] = list(range(5)) assert_identical(actual, expected) - def test_setitem_both_non_unique_index(self): + def test_setitem_both_non_unique_index(self) -> None: # regression test for GH956 names = ["joaquin", "manolo", "joaquin"] values = np.random.randint(0, 256, (3, 4, 4)) @@ -3961,14 +3972,14 @@ def test_setitem_both_non_unique_index(self): actual["second"] = array assert_identical(expected, actual) - def test_setitem_multiindex_level(self): + def test_setitem_multiindex_level(self) -> None: data = create_test_multiindex() with pytest.raises( ValueError, match=r"cannot set or update variable.*corrupt.*index " ): data["level_1"] = range(4) - def test_delitem(self): + def test_delitem(self) -> None: data = create_test_data() all_items = set(data.variables) assert set(data.variables) == all_items @@ -3983,16 +3994,17 @@ def test_delitem(self): del actual["y"] assert_identical(expected, actual) - def test_delitem_multiindex_level(self): + def test_delitem_multiindex_level(self) -> None: data = create_test_multiindex() with pytest.raises( ValueError, match=r"cannot remove coordinate.*corrupt.*index " ): del data["level_1"] - def test_squeeze(self): + def test_squeeze(self) -> None: data = Dataset({"foo": (["x", "y", "z"], [[[1], [2]]])}) - for args in [[], [["x"]], [["x", "z"]]]: + test_args: list[list] = [[], [["x"]], [["x", "z"]]] + for args in test_args: def get_args(v): return [set(args[0]) & set(v.dims)] if args else [] @@ -4006,7 +4018,7 @@ def get_args(v): with pytest.raises(ValueError, match=r"cannot select a dimension"): data.squeeze("y") - def test_squeeze_drop(self): + def test_squeeze_drop(self) -> None: data = Dataset({"foo": ("x", [1])}, {"x": [0]}) expected = Dataset({"foo": 1}) selected = data.squeeze(drop=True) @@ -4029,7 +4041,7 @@ def test_squeeze_drop(self): selected = data.squeeze(drop=True) assert_identical(data, selected) - def test_to_array(self): + def test_to_array(self) -> None: ds = Dataset( {"a": 1, "b": ("x", [1, 2, 3])}, coords={"c": 42}, @@ -4046,7 +4058,7 @@ def test_to_array(self): expected = expected.rename({"variable": "abc"}).rename("foo") assert_identical(expected, actual) - def test_to_and_from_dataframe(self): + def test_to_and_from_dataframe(self) -> None: x = np.random.randn(10) y = np.random.randn(10) t = list("abcdefghij") @@ -4142,7 +4154,7 @@ def test_to_and_from_dataframe(self): expected = pd.DataFrame([[]], index=idx) assert expected.equals(actual), (expected, actual) - def test_from_dataframe_categorical(self): + def test_from_dataframe_categorical(self) -> None: cat = pd.CategoricalDtype( categories=["foo", "bar", "baz", "qux", "quux", "corge"] ) @@ -4158,7 +4170,7 @@ def test_from_dataframe_categorical(self): assert len(ds["i2"]) == 2 @requires_sparse - def test_from_dataframe_sparse(self): + def test_from_dataframe_sparse(self) -> None: import sparse df_base = pd.DataFrame( @@ -4179,7 +4191,7 @@ def test_from_dataframe_sparse(self): ds_sparse["z"].data = ds_sparse["z"].data.todense() assert_identical(ds_dense, ds_sparse) - def test_to_and_from_empty_dataframe(self): + def test_to_and_from_empty_dataframe(self) -> None: # GH697 expected = pd.DataFrame({"foo": []}) ds = Dataset.from_dataframe(expected) @@ -4188,7 +4200,7 @@ def test_to_and_from_empty_dataframe(self): assert len(actual) == 0 assert expected.equals(actual) - def test_from_dataframe_multiindex(self): + def test_from_dataframe_multiindex(self) -> None: index = pd.MultiIndex.from_product([["a", "b"], [1, 2, 3]], names=["x", "y"]) df = pd.DataFrame({"z": np.arange(6)}, index=index) @@ -4215,7 +4227,7 @@ def test_from_dataframe_multiindex(self): with pytest.raises(ValueError, match=r"non-unique MultiIndex"): Dataset.from_dataframe(df_nonunique) - def test_from_dataframe_unsorted_levels(self): + def test_from_dataframe_unsorted_levels(self) -> None: # regression test for GH-4186 index = pd.MultiIndex( levels=[["b", "a"], ["foo"]], codes=[[0, 1], [0, 0]], names=["lev1", "lev2"] @@ -4231,14 +4243,14 @@ def test_from_dataframe_unsorted_levels(self): actual = Dataset.from_dataframe(df) assert_identical(actual, expected) - def test_from_dataframe_non_unique_columns(self): + def test_from_dataframe_non_unique_columns(self) -> None: # regression test for GH449 df = pd.DataFrame(np.zeros((2, 2))) df.columns = ["foo", "foo"] with pytest.raises(ValueError, match=r"non-unique columns"): Dataset.from_dataframe(df) - def test_convert_dataframe_with_many_types_and_multiindex(self): + def test_convert_dataframe_with_many_types_and_multiindex(self) -> None: # regression test for GH737 df = pd.DataFrame( { @@ -4259,7 +4271,7 @@ def test_convert_dataframe_with_many_types_and_multiindex(self): expected = df.apply(np.asarray) assert roundtripped.equals(expected) - def test_to_and_from_dict(self): + def test_to_and_from_dict(self) -> None: # # Dimensions: (t: 10) # Coordinates: @@ -4271,7 +4283,7 @@ def test_to_and_from_dict(self): y = np.random.randn(10) t = list("abcdefghij") ds = Dataset({"a": ("t", x), "b": ("t", y), "t": ("t", t)}) - expected = { + expected: dict[str, dict[str, Any]] = { "coords": {"t": {"dims": ("t",), "data": t, "attrs": {}}}, "attrs": {}, "dims": {"t": 10}, @@ -4303,9 +4315,9 @@ def test_to_and_from_dict(self): # verify coords are included roundtrip expected_ds = ds.set_coords("b") - actual = Dataset.from_dict(expected_ds.to_dict()) + actual2 = Dataset.from_dict(expected_ds.to_dict()) - assert_identical(expected_ds, actual) + assert_identical(expected_ds, actual2) # test some incomplete dicts: # this one has no attrs field, the dims are strings, and x, y are @@ -4337,7 +4349,7 @@ def test_to_and_from_dict(self): ): Dataset.from_dict(d) - def test_to_and_from_dict_with_time_dim(self): + def test_to_and_from_dict_with_time_dim(self) -> None: x = np.random.randn(10, 3) y = np.random.randn(10, 3) t = pd.date_range("20130101", periods=10) @@ -4353,7 +4365,7 @@ def test_to_and_from_dict_with_time_dim(self): roundtripped = Dataset.from_dict(ds.to_dict()) assert_identical(ds, roundtripped) - def test_to_and_from_dict_with_nan_nat(self): + def test_to_and_from_dict_with_nan_nat(self) -> None: x = np.random.randn(10, 3) y = np.random.randn(10, 3) y[2] = np.nan @@ -4372,7 +4384,7 @@ def test_to_and_from_dict_with_nan_nat(self): roundtripped = Dataset.from_dict(ds.to_dict()) assert_identical(ds, roundtripped) - def test_to_dict_with_numpy_attrs(self): + def test_to_dict_with_numpy_attrs(self) -> None: # this doesn't need to roundtrip x = np.random.randn(10) y = np.random.randn(10) @@ -4384,8 +4396,8 @@ def test_to_dict_with_numpy_attrs(self): } ds = Dataset({"a": ("t", x, attrs), "b": ("t", y, attrs), "t": ("t", t)}) expected_attrs = { - "created": attrs["created"].item(), - "coords": attrs["coords"].tolist(), + "created": attrs["created"].item(), # type: ignore[attr-defined] + "coords": attrs["coords"].tolist(), # type: ignore[attr-defined] "maintainer": "bar", } actual = ds.to_dict() @@ -4393,14 +4405,14 @@ def test_to_dict_with_numpy_attrs(self): # check that they are identical assert expected_attrs == actual["data_vars"]["a"]["attrs"] - def test_pickle(self): + def test_pickle(self) -> None: data = create_test_data() roundtripped = pickle.loads(pickle.dumps(data)) assert_identical(data, roundtripped) # regression test for #167: assert data.dims == roundtripped.dims - def test_lazy_load(self): + def test_lazy_load(self) -> None: store = InaccessibleVariableDataStore() create_test_data().dump_to_store(store) @@ -4415,7 +4427,7 @@ def test_lazy_load(self): ds.isel(time=10) ds.isel(time=slice(10), dim1=[0]).isel(dim1=0, dim2=-1) - def test_dropna(self): + def test_dropna(self) -> None: x = np.random.randn(4, 4) x[::2, 0] = np.nan y = np.random.randn(4) @@ -4471,78 +4483,78 @@ def test_dropna(self): with pytest.raises(ValueError, match=r"a single dataset dimension"): ds.dropna("foo") with pytest.raises(ValueError, match=r"invalid how"): - ds.dropna("a", how="somehow") + ds.dropna("a", how="somehow") # type: ignore with pytest.raises(TypeError, match=r"must specify how or thresh"): - ds.dropna("a", how=None) + ds.dropna("a", how=None) # type: ignore - def test_fillna(self): + def test_fillna(self) -> None: ds = Dataset({"a": ("x", [np.nan, 1, np.nan, 3])}, {"x": [0, 1, 2, 3]}) # fill with -1 - actual = ds.fillna(-1) + actual1 = ds.fillna(-1) expected = Dataset({"a": ("x", [-1, 1, -1, 3])}, {"x": [0, 1, 2, 3]}) - assert_identical(expected, actual) + assert_identical(expected, actual1) - actual = ds.fillna({"a": -1}) - assert_identical(expected, actual) + actual2 = ds.fillna({"a": -1}) + assert_identical(expected, actual2) other = Dataset({"a": -1}) - actual = ds.fillna(other) - assert_identical(expected, actual) + actual3 = ds.fillna(other) + assert_identical(expected, actual3) - actual = ds.fillna({"a": other.a}) - assert_identical(expected, actual) + actual4 = ds.fillna({"a": other.a}) + assert_identical(expected, actual4) # fill with range(4) b = DataArray(range(4), coords=[("x", range(4))]) - actual = ds.fillna(b) + actual5 = ds.fillna(b) expected = b.rename("a").to_dataset() - assert_identical(expected, actual) + assert_identical(expected, actual5) - actual = ds.fillna(expected) - assert_identical(expected, actual) + actual6 = ds.fillna(expected) + assert_identical(expected, actual6) - actual = ds.fillna(range(4)) - assert_identical(expected, actual) + actual7 = ds.fillna(range(4)) + assert_identical(expected, actual7) - actual = ds.fillna(b[:3]) - assert_identical(expected, actual) + actual8 = ds.fillna(b[:3]) + assert_identical(expected, actual8) # okay to only include some data variables ds["b"] = np.nan - actual = ds.fillna({"a": -1}) + actual9 = ds.fillna({"a": -1}) expected = Dataset( {"a": ("x", [-1, 1, -1, 3]), "b": np.nan}, {"x": [0, 1, 2, 3]} ) - assert_identical(expected, actual) + assert_identical(expected, actual9) # but new data variables is not okay with pytest.raises(ValueError, match=r"must be contained"): ds.fillna({"x": 0}) # empty argument should be OK - result = ds.fillna({}) - assert_identical(ds, result) + result1 = ds.fillna({}) + assert_identical(ds, result1) - result = ds.fillna(Dataset(coords={"c": 42})) + result2 = ds.fillna(Dataset(coords={"c": 42})) expected = ds.assign_coords(c=42) - assert_identical(expected, result) + assert_identical(expected, result2) da = DataArray(range(5), name="a", attrs={"attr": "da"}) - actual = da.fillna(1) - assert actual.name == "a" - assert actual.attrs == da.attrs + actual10 = da.fillna(1) + assert actual10.name == "a" + assert actual10.attrs == da.attrs ds = Dataset({"a": da}, attrs={"attr": "ds"}) - actual = ds.fillna({"a": 1}) - assert actual.attrs == ds.attrs - assert actual.a.name == "a" - assert actual.a.attrs == ds.a.attrs + actual11 = ds.fillna({"a": 1}) + assert actual11.attrs == ds.attrs + assert actual11.a.name == "a" + assert actual11.a.attrs == ds.a.attrs @pytest.mark.parametrize( "func", [lambda x: x.clip(0, 1), lambda x: np.float64(1.0) * x, np.abs, abs] ) - def test_propagate_attrs(self, func): + def test_propagate_attrs(self, func) -> None: da = DataArray(range(5), name="a", attrs={"attr": "da"}) ds = Dataset({"a": da}, attrs={"attr": "ds"}) @@ -4561,51 +4573,51 @@ def test_propagate_attrs(self, func): assert func(ds).attrs == ds.attrs assert func(ds).a.attrs == ds.a.attrs - def test_where(self): + def test_where(self) -> None: ds = Dataset({"a": ("x", range(5))}) - expected = Dataset({"a": ("x", [np.nan, np.nan, 2, 3, 4])}) - actual = ds.where(ds > 1) - assert_identical(expected, actual) + expected1 = Dataset({"a": ("x", [np.nan, np.nan, 2, 3, 4])}) + actual1 = ds.where(ds > 1) + assert_identical(expected1, actual1) - actual = ds.where(ds.a > 1) - assert_identical(expected, actual) + actual2 = ds.where(ds.a > 1) + assert_identical(expected1, actual2) - actual = ds.where(ds.a.values > 1) - assert_identical(expected, actual) + actual3 = ds.where(ds.a.values > 1) + assert_identical(expected1, actual3) - actual = ds.where(True) - assert_identical(ds, actual) + actual4 = ds.where(True) + assert_identical(ds, actual4) - expected = ds.copy(deep=True) - expected["a"].values = [np.nan] * 5 - actual = ds.where(False) - assert_identical(expected, actual) + expected5 = ds.copy(deep=True) + expected5["a"].values = np.array([np.nan] * 5) + actual5 = ds.where(False) + assert_identical(expected5, actual5) # 2d ds = Dataset({"a": (("x", "y"), [[0, 1], [2, 3]])}) - expected = Dataset({"a": (("x", "y"), [[np.nan, 1], [2, 3]])}) - actual = ds.where(ds > 0) - assert_identical(expected, actual) + expected6 = Dataset({"a": (("x", "y"), [[np.nan, 1], [2, 3]])}) + actual6 = ds.where(ds > 0) + assert_identical(expected6, actual6) # attrs da = DataArray(range(5), name="a", attrs={"attr": "da"}) - actual = da.where(da.values > 1) - assert actual.name == "a" - assert actual.attrs == da.attrs + actual7 = da.where(da.values > 1) + assert actual7.name == "a" + assert actual7.attrs == da.attrs ds = Dataset({"a": da}, attrs={"attr": "ds"}) - actual = ds.where(ds > 0) - assert actual.attrs == ds.attrs - assert actual.a.name == "a" - assert actual.a.attrs == ds.a.attrs + actual8 = ds.where(ds > 0) + assert actual8.attrs == ds.attrs + assert actual8.a.name == "a" + assert actual8.a.attrs == ds.a.attrs # lambda ds = Dataset({"a": ("x", range(5))}) - expected = Dataset({"a": ("x", [np.nan, np.nan, 2, 3, 4])}) - actual = ds.where(lambda x: x > 1) - assert_identical(expected, actual) + expected9 = Dataset({"a": ("x", [np.nan, np.nan, 2, 3, 4])}) + actual9 = ds.where(lambda x: x > 1) + assert_identical(expected9, actual9) - def test_where_other(self): + def test_where_other(self) -> None: ds = Dataset({"a": ("x", range(5))}, {"x": range(5)}) expected = Dataset({"a": ("x", [-1, -1, 2, 3, 4])}, {"x": range(5)}) actual = ds.where(ds > 1, -1) @@ -4627,25 +4639,25 @@ def test_where_other(self): with pytest.raises(ValueError, match=r"exact match required"): ds.where(ds > 1, ds.assign(b=2)) - def test_where_drop(self): + def test_where_drop(self) -> None: # if drop=True # 1d # data array case array = DataArray(range(5), coords=[range(5)], dims=["x"]) - expected = DataArray(range(5)[2:], coords=[range(5)[2:]], dims=["x"]) - actual = array.where(array > 1, drop=True) - assert_identical(expected, actual) + expected1 = DataArray(range(5)[2:], coords=[range(5)[2:]], dims=["x"]) + actual1 = array.where(array > 1, drop=True) + assert_identical(expected1, actual1) # dataset case ds = Dataset({"a": array}) - expected = Dataset({"a": expected}) + expected2 = Dataset({"a": expected1}) - actual = ds.where(ds > 1, drop=True) - assert_identical(expected, actual) + actual2 = ds.where(ds > 1, drop=True) + assert_identical(expected2, actual2) - actual = ds.where(ds.a > 1, drop=True) - assert_identical(expected, actual) + actual3 = ds.where(ds.a > 1, drop=True) + assert_identical(expected2, actual3) with pytest.raises(TypeError, match=r"must be a"): ds.where(np.arange(5) > 1, drop=True) @@ -4654,25 +4666,25 @@ def test_where_drop(self): array = DataArray( np.array([2, 7, 1, 8, 3]), coords=[np.array([3, 1, 4, 5, 9])], dims=["x"] ) - expected = DataArray( + expected4 = DataArray( np.array([7, 8, 3]), coords=[np.array([1, 5, 9])], dims=["x"] ) - actual = array.where(array > 2, drop=True) - assert_identical(expected, actual) + actual4 = array.where(array > 2, drop=True) + assert_identical(expected4, actual4) # 1d multiple variables ds = Dataset({"a": (("x"), [0, 1, 2, 3]), "b": (("x"), [4, 5, 6, 7])}) - expected = Dataset( + expected5 = Dataset( {"a": (("x"), [np.nan, 1, 2, 3]), "b": (("x"), [4, 5, 6, np.nan])} ) - actual = ds.where((ds > 0) & (ds < 7), drop=True) - assert_identical(expected, actual) + actual5 = ds.where((ds > 0) & (ds < 7), drop=True) + assert_identical(expected5, actual5) # 2d ds = Dataset({"a": (("x", "y"), [[0, 1], [2, 3]])}) - expected = Dataset({"a": (("x", "y"), [[np.nan, 1], [2, 3]])}) - actual = ds.where(ds > 0, drop=True) - assert_identical(expected, actual) + expected6 = Dataset({"a": (("x", "y"), [[np.nan, 1], [2, 3]])}) + actual6 = ds.where(ds > 0, drop=True) + assert_identical(expected6, actual6) # 2d with odd coordinates ds = Dataset( @@ -4683,27 +4695,27 @@ def test_where_drop(self): "z": (["x", "y"], [[np.e, np.pi], [np.pi * np.e, np.pi * 3]]), }, ) - expected = Dataset( + expected7 = Dataset( {"a": (("x", "y"), [[3]])}, coords={"x": [3], "y": [2], "z": (["x", "y"], [[np.pi * 3]])}, ) - actual = ds.where(ds > 2, drop=True) - assert_identical(expected, actual) + actual7 = ds.where(ds > 2, drop=True) + assert_identical(expected7, actual7) # 2d multiple variables ds = Dataset( {"a": (("x", "y"), [[0, 1], [2, 3]]), "b": (("x", "y"), [[4, 5], [6, 7]])} ) - expected = Dataset( + expected8 = Dataset( { "a": (("x", "y"), [[np.nan, 1], [2, 3]]), "b": (("x", "y"), [[4, 5], [6, 7]]), } ) - actual = ds.where(ds > 0, drop=True) - assert_identical(expected, actual) + actual8 = ds.where(ds > 0, drop=True) + assert_identical(expected8, actual8) - def test_where_drop_empty(self): + def test_where_drop_empty(self) -> None: # regression test for GH1341 array = DataArray(np.random.rand(100, 10), dims=["nCells", "nVertLevels"]) mask = DataArray(np.zeros((100,), dtype="bool"), dims="nCells") @@ -4711,7 +4723,7 @@ def test_where_drop_empty(self): expected = DataArray(np.zeros((0, 10)), dims=["nCells", "nVertLevels"]) assert_identical(expected, actual) - def test_where_drop_no_indexes(self): + def test_where_drop_no_indexes(self) -> None: ds = Dataset({"foo": ("x", [0.0, 1.0])}) expected = Dataset({"foo": ("x", [1.0])}) actual = ds.where(ds == 1, drop=True) @@ -4753,7 +4765,7 @@ def test_reduce_coords(self) -> None: actual = data["a"].mean("x").to_dataset() assert_identical(actual, expected) - def test_mean_uint_dtype(self): + def test_mean_uint_dtype(self) -> None: data = xr.Dataset( { "a": (("x", "y"), np.arange(6).reshape(3, 2).astype("uint")), @@ -4771,7 +4783,7 @@ def test_reduce_bad_dim(self) -> None: with pytest.raises(ValueError, match=r"Dataset does not contain"): data.mean(dim="bad_dim") - def test_reduce_cumsum(self): + def test_reduce_cumsum(self) -> None: data = xr.Dataset( {"a": 1, "b": ("x", [1, 2]), "c": (("x", "y"), [[np.nan, 3], [0, 4]])} ) @@ -4792,7 +4804,7 @@ def test_reduce_cumsum(self): ], ) @pytest.mark.parametrize("func", ["cumsum", "cumprod"]) - def test_reduce_cumsum_test_dims(self, reduct, expected, func): + def test_reduce_cumsum_test_dims(self, reduct, expected, func) -> None: data = create_test_data() with pytest.raises(ValueError, match=r"Dataset does not contain"): getattr(data, func)(dim="bad_dim") @@ -4892,7 +4904,7 @@ def test_reduce_keep_attrs(self) -> None: @pytest.mark.filterwarnings( "ignore:Once the behaviour of DataArray:DeprecationWarning" ) - def test_reduce_argmin(self): + def test_reduce_argmin(self) -> None: # regression test for #205 ds = Dataset({"a": ("x", [0, 1])}) expected = Dataset({"a": ([], 0)}) @@ -4902,7 +4914,7 @@ def test_reduce_argmin(self): actual = ds.argmin("x") assert_identical(expected, actual) - def test_reduce_scalars(self): + def test_reduce_scalars(self) -> None: ds = Dataset({"x": ("a", [2, 2]), "y": 2, "z": ("b", [2])}) expected = Dataset({"x": 0, "y": 0, "z": 0}) actual = ds.var() @@ -5031,7 +5043,7 @@ def test_quantile_interpolation_deprecated(self, method) -> None: ds.quantile(q, method=method, interpolation=method) @requires_bottleneck - def test_rank(self): + def test_rank(self) -> None: ds = create_test_data(seed=1234) # only ds.var3 depends on dim3 z = ds.rank("dim3") @@ -5047,19 +5059,19 @@ def test_rank(self): with pytest.raises(ValueError, match=r"does not contain"): x.rank("invalid_dim") - def test_rank_use_bottleneck(self): + def test_rank_use_bottleneck(self) -> None: ds = Dataset({"a": ("x", [0, np.nan, 2]), "b": ("y", [4, 6, 3, 4])}) with xr.set_options(use_bottleneck=False): with pytest.raises(RuntimeError): ds.rank("x") - def test_count(self): + def test_count(self) -> None: ds = Dataset({"x": ("a", [np.nan, 1]), "y": 0, "z": np.nan}) expected = Dataset({"x": 1, "y": 1, "z": 0}) actual = ds.count() assert_identical(expected, actual) - def test_map(self): + def test_map(self) -> None: data = create_test_data() data.attrs["foo"] = "bar" @@ -5082,7 +5094,7 @@ def scale(x, multiple=1): expected = data.drop_vars("time") # time is not used on a data var assert_equal(expected, actual) - def test_apply_pending_deprecated_map(self): + def test_apply_pending_deprecated_map(self) -> None: data = create_test_data() data.attrs["foo"] = "bar" @@ -5099,7 +5111,7 @@ def make_example_math_dataset(self): ds["foo"][0, 0] = np.nan return ds - def test_dataset_number_math(self): + def test_dataset_number_math(self) -> None: ds = self.make_example_math_dataset() assert_identical(ds, +ds) @@ -5112,7 +5124,7 @@ def test_dataset_number_math(self): actual += 0 assert_identical(ds, actual) - def test_unary_ops(self): + def test_unary_ops(self) -> None: ds = self.make_example_math_dataset() assert_identical(ds.map(abs), abs(ds)) @@ -5133,7 +5145,7 @@ def test_unary_ops(self): with pytest.raises(AttributeError): ds.searchsorted - def test_dataset_array_math(self): + def test_dataset_array_math(self) -> None: ds = self.make_example_math_dataset() expected = ds.map(lambda x: x - ds["foo"]) @@ -5155,7 +5167,7 @@ def test_dataset_array_math(self): assert_identical(expected, ds[["bar"]] + np.arange(3)) assert_identical(expected, np.arange(3) + ds[["bar"]]) - def test_dataset_dataset_math(self): + def test_dataset_dataset_math(self) -> None: ds = self.make_example_math_dataset() assert_identical(ds, ds + 0 * ds) @@ -5180,7 +5192,7 @@ def test_dataset_dataset_math(self): assert_identical(expected, subsampled + ds) assert_identical(expected, ds + subsampled) - def test_dataset_math_auto_align(self): + def test_dataset_math_auto_align(self) -> None: ds = self.make_example_math_dataset() subset = ds.isel(y=[1, 3]) expected = 2 * subset @@ -5210,7 +5222,7 @@ def test_dataset_math_auto_align(self): expected = ds + other.reindex_like(ds) assert_identical(expected, actual) - def test_dataset_math_errors(self): + def test_dataset_math_errors(self) -> None: ds = self.make_example_math_dataset() with pytest.raises(TypeError): @@ -5229,7 +5241,7 @@ def test_dataset_math_errors(self): actual += other assert_identical(actual, ds) - def test_dataset_transpose(self): + def test_dataset_transpose(self) -> None: ds = Dataset( { "a": (("x", "y"), np.random.randn(3, 4)), @@ -5295,7 +5307,7 @@ def test_dataset_transpose(self): assert "T" not in dir(ds) - def test_dataset_ellipsis_transpose_different_ordered_vars(self): + def test_dataset_ellipsis_transpose_different_ordered_vars(self) -> None: # https://github.com/pydata/xarray/issues/1081#issuecomment-544350457 ds = Dataset( dict( @@ -5307,7 +5319,7 @@ def test_dataset_ellipsis_transpose_different_ordered_vars(self): assert list(result["a"].dims) == list("wxzy") assert list(result["b"].dims) == list("xwzy") - def test_dataset_retains_period_index_on_transpose(self): + def test_dataset_retains_period_index_on_transpose(self) -> None: ds = create_test_data() ds["time"] = pd.period_range("2000-01-01", periods=20) @@ -5316,13 +5328,13 @@ def test_dataset_retains_period_index_on_transpose(self): assert isinstance(transposed.time.to_index(), pd.PeriodIndex) - def test_dataset_diff_n1_simple(self): + def test_dataset_diff_n1_simple(self) -> None: ds = Dataset({"foo": ("x", [5, 5, 6, 6])}) actual = ds.diff("x") expected = Dataset({"foo": ("x", [0, 1, 0])}) assert_equal(expected, actual) - def test_dataset_diff_n1_label(self): + def test_dataset_diff_n1_label(self) -> None: ds = Dataset({"foo": ("x", [5, 5, 6, 6])}, {"x": [0, 1, 2, 3]}) actual = ds.diff("x", label="lower") expected = Dataset({"foo": ("x", [0, 1, 0])}, {"x": [0, 1, 2]}) @@ -5332,56 +5344,56 @@ def test_dataset_diff_n1_label(self): expected = Dataset({"foo": ("x", [0, 1, 0])}, {"x": [1, 2, 3]}) assert_equal(expected, actual) - def test_dataset_diff_n1(self): + def test_dataset_diff_n1(self) -> None: ds = create_test_data(seed=1) actual = ds.diff("dim2") - expected = {} - expected["var1"] = DataArray( + expected_dict = {} + expected_dict["var1"] = DataArray( np.diff(ds["var1"].values, axis=1), {"dim2": ds["dim2"].values[1:]}, ["dim1", "dim2"], ) - expected["var2"] = DataArray( + expected_dict["var2"] = DataArray( np.diff(ds["var2"].values, axis=1), {"dim2": ds["dim2"].values[1:]}, ["dim1", "dim2"], ) - expected["var3"] = ds["var3"] - expected = Dataset(expected, coords={"time": ds["time"].values}) + expected_dict["var3"] = ds["var3"] + expected = Dataset(expected_dict, coords={"time": ds["time"].values}) expected.coords["numbers"] = ("dim3", ds["numbers"].values) assert_equal(expected, actual) - def test_dataset_diff_n2(self): + def test_dataset_diff_n2(self) -> None: ds = create_test_data(seed=1) actual = ds.diff("dim2", n=2) - expected = {} - expected["var1"] = DataArray( + expected_dict = {} + expected_dict["var1"] = DataArray( np.diff(ds["var1"].values, axis=1, n=2), {"dim2": ds["dim2"].values[2:]}, ["dim1", "dim2"], ) - expected["var2"] = DataArray( + expected_dict["var2"] = DataArray( np.diff(ds["var2"].values, axis=1, n=2), {"dim2": ds["dim2"].values[2:]}, ["dim1", "dim2"], ) - expected["var3"] = ds["var3"] - expected = Dataset(expected, coords={"time": ds["time"].values}) + expected_dict["var3"] = ds["var3"] + expected = Dataset(expected_dict, coords={"time": ds["time"].values}) expected.coords["numbers"] = ("dim3", ds["numbers"].values) assert_equal(expected, actual) - def test_dataset_diff_exception_n_neg(self): + def test_dataset_diff_exception_n_neg(self) -> None: ds = create_test_data(seed=1) with pytest.raises(ValueError, match=r"must be non-negative"): ds.diff("dim2", n=-1) - def test_dataset_diff_exception_label_str(self): + def test_dataset_diff_exception_label_str(self) -> None: ds = create_test_data(seed=1) with pytest.raises(ValueError, match=r"'label' argument has to"): ds.diff("dim2", label="raise_me") @pytest.mark.parametrize("fill_value", [dtypes.NA, 2, 2.0, {"foo": -10}]) - def test_shift(self, fill_value): + def test_shift(self, fill_value) -> None: coords = {"bar": ("x", list("abc")), "x": [-4, 3, 2]} attrs = {"meta": "data"} ds = Dataset({"foo": ("x", [1, 2, 3])}, coords, attrs) @@ -5398,7 +5410,7 @@ def test_shift(self, fill_value): with pytest.raises(ValueError, match=r"dimensions"): ds.shift(foo=123) - def test_roll_coords(self): + def test_roll_coords(self) -> None: coords = {"bar": ("x", list("abc")), "x": [-4, 3, 2]} attrs = {"meta": "data"} ds = Dataset({"foo": ("x", [1, 2, 3])}, coords, attrs) @@ -5411,7 +5423,7 @@ def test_roll_coords(self): with pytest.raises(ValueError, match=r"dimensions"): ds.roll(foo=123, roll_coords=True) - def test_roll_no_coords(self): + def test_roll_no_coords(self) -> None: coords = {"bar": ("x", list("abc")), "x": [-4, 3, 2]} attrs = {"meta": "data"} ds = Dataset({"foo": ("x", [1, 2, 3])}, coords, attrs) @@ -5423,7 +5435,7 @@ def test_roll_no_coords(self): with pytest.raises(ValueError, match=r"dimensions"): ds.roll(abc=321) - def test_roll_multidim(self): + def test_roll_multidim(self) -> None: # regression test for 2445 arr = xr.DataArray( [[1, 2, 3], [4, 5, 6]], @@ -5436,7 +5448,7 @@ def test_roll_multidim(self): ) assert_identical(expected, actual) - def test_real_and_imag(self): + def test_real_and_imag(self) -> None: attrs = {"foo": "bar"} ds = Dataset({"x": ((), 1 + 2j, attrs)}, attrs=attrs) @@ -5446,7 +5458,7 @@ def test_real_and_imag(self): expected_im = Dataset({"x": ((), 2, attrs)}, attrs=attrs) assert_identical(ds.imag, expected_im) - def test_setattr_raises(self): + def test_setattr_raises(self) -> None: ds = Dataset({}, coords={"scalar": 1}, attrs={"foo": "bar"}) with pytest.raises(AttributeError, match=r"cannot set attr"): ds.scalar = 2 @@ -5455,7 +5467,7 @@ def test_setattr_raises(self): with pytest.raises(AttributeError, match=r"cannot set attr"): ds.other = 2 - def test_filter_by_attrs(self): + def test_filter_by_attrs(self) -> None: precip = dict(standard_name="convective_precipitation_flux") temp0 = dict(standard_name="air_potential_temperature", height="0 m") temp10 = dict(standard_name="air_potential_temperature", height="10 m") @@ -5522,7 +5534,7 @@ def test_filter_by_attrs(self): ) assert not bool(new_ds.data_vars) - def test_binary_op_propagate_indexes(self): + def test_binary_op_propagate_indexes(self) -> None: ds = Dataset( {"d1": DataArray([1, 2, 3], dims=["x"], coords={"x": [10, 20, 30]})} ) @@ -5530,7 +5542,7 @@ def test_binary_op_propagate_indexes(self): actual = (ds * 2).xindexes["x"] assert expected is actual - def test_binary_op_join_setting(self): + def test_binary_op_join_setting(self) -> None: # arithmetic_join applies to data array coordinates missing_2 = xr.Dataset({"x": [0, 1]}) missing_0 = xr.Dataset({"x": [1, 2]}) @@ -5604,7 +5616,7 @@ def test_full_like(self) -> None: assert expected["d2"].dtype == float assert_identical(expected, actual) - def test_combine_first(self): + def test_combine_first(self) -> None: dsx0 = DataArray([0, 0], [("x", ["a", "b"])]).to_dataset(name="dsx0") dsx1 = DataArray([1, 1], [("x", ["b", "c"])]).to_dataset(name="dsx1") @@ -5622,7 +5634,7 @@ def test_combine_first(self): expected = xr.merge([dsy2, dsx0]) assert_equal(actual, expected) - def test_sortby(self): + def test_sortby(self) -> None: ds = Dataset( { "A": DataArray( @@ -5679,7 +5691,7 @@ def test_sortby(self): assert_equal(actual, expected) # test exception-raising - with pytest.raises(KeyError) as excinfo: + with pytest.raises(KeyError): actual = ds.sortby("z") with pytest.raises(ValueError) as excinfo: @@ -5725,7 +5737,7 @@ def test_sortby(self): actual = ds.sortby(["x", "y"], ascending=False) assert_equal(actual, ds) - def test_attribute_access(self): + def test_attribute_access(self) -> None: ds = create_test_data(seed=1) for key in ["var1", "var2", "var3", "time", "dim1", "dim2", "dim3", "numbers"]: assert_equal(ds[key], getattr(ds, key)) @@ -5738,7 +5750,7 @@ def test_attribute_access(self): assert ds["var3"].attrs["foo"] == ds.var3.foo assert "foo" in dir(ds["var3"]) - def test_ipython_key_completion(self): + def test_ipython_key_completion(self) -> None: ds = create_test_data(seed=1) actual = ds._ipython_key_completions_() expected = ["var1", "var2", "var3", "time", "dim1", "dim2", "dim3", "numbers"] @@ -5814,7 +5826,7 @@ def test_polyfit_warnings(self) -> None: ds.var1.polyfit("dim2", 10, full=True) assert len(ws) == 1 - def test_pad(self): + def test_pad(self) -> None: ds = create_test_data(seed=1) padded = ds.pad(dim2=(1, 1), constant_values=42) @@ -5827,7 +5839,7 @@ def test_pad(self): np.testing.assert_equal(padded["var1"].isel(dim2=[0, -1]).data, 42) np.testing.assert_equal(padded["dim2"][[0, -1]].data, np.nan) - def test_astype_attrs(self): + def test_astype_attrs(self) -> None: data = create_test_data(seed=123) data.attrs["foo"] = "bar" @@ -5843,7 +5855,7 @@ def test_astype_attrs(self): @pytest.mark.parametrize( "backend", ["numpy", pytest.param("dask", marks=[requires_dask])] ) - def test_query(self, backend, engine, parser): + def test_query(self, backend, engine, parser) -> None: """Test querying a dataset.""" # setup test data @@ -5953,9 +5965,9 @@ def test_query(self, backend, engine, parser): # test error handling with pytest.raises(ValueError): - ds.query("a > 5") # must be dict or kwargs + ds.query("a > 5") # type: ignore # must be dict or kwargs with pytest.raises(ValueError): - ds.query(x=(a > 5)) # must be query string + ds.query(x=(a > 5)) # type: ignore # must be query string with pytest.raises(IndexError): ds.query(y="a > 5") # wrong length dimension with pytest.raises(IndexError): @@ -5970,7 +5982,7 @@ def test_query(self, backend, engine, parser): @pytest.mark.parametrize("test_elements", ([1, 2], np.array([1, 2]), DataArray([1, 2]))) -def test_isin(test_elements, backend): +def test_isin(test_elements, backend) -> None: expected = Dataset( data_vars={ "var1": (("dim1",), [0, 1]), @@ -5993,7 +6005,7 @@ def test_isin(test_elements, backend): assert_equal(result, expected) -def test_isin_dataset(): +def test_isin_dataset() -> None: ds = Dataset({"x": [1, 2]}) with pytest.raises(TypeError): ds.isin(ds) @@ -6015,7 +6027,9 @@ def test_isin_dataset(): ), ) @pytest.mark.parametrize("coords", ({"x": ("x", [0, 1, 2])}, {"x": [0, 1, 2]})) -def test_dataset_constructor_aligns_to_explicit_coords(unaligned_coords, coords): +def test_dataset_constructor_aligns_to_explicit_coords( + unaligned_coords, coords +) -> None: a = xr.DataArray([1, 2, 3], dims=["x"], coords=unaligned_coords) @@ -6027,27 +6041,27 @@ def test_dataset_constructor_aligns_to_explicit_coords(unaligned_coords, coords) assert_equal(expected, result) -def test_error_message_on_set_supplied(): +def test_error_message_on_set_supplied() -> None: with pytest.raises(TypeError, match="has invalid type "): xr.Dataset(dict(date=[1, 2, 3], sec={4})) @pytest.mark.parametrize("unaligned_coords", ({"y": ("b", np.asarray([2, 1, 0]))},)) -def test_constructor_raises_with_invalid_coords(unaligned_coords): +def test_constructor_raises_with_invalid_coords(unaligned_coords) -> None: with pytest.raises(ValueError, match="not a subset of the DataArray dimensions"): xr.DataArray([1, 2, 3], dims=["x"], coords=unaligned_coords) @pytest.mark.parametrize("ds", [3], indirect=True) -def test_dir_expected_attrs(ds): +def test_dir_expected_attrs(ds) -> None: some_expected_attrs = {"pipe", "mean", "isnull", "var1", "dim2", "numbers"} result = dir(ds) assert set(result) >= some_expected_attrs -def test_dir_non_string(ds): +def test_dir_non_string(ds) -> None: # add a numbered key to ensure this doesn't break dir ds[5] = "foo" result = dir(ds) @@ -6060,7 +6074,7 @@ def test_dir_non_string(ds): dir(x2) -def test_dir_unicode(ds): +def test_dir_unicode(ds) -> None: ds["unicode"] = "uni" result = dir(ds) assert "unicode" in result @@ -6115,7 +6129,7 @@ def ds(request, backend): ("count", ()), ], ) -def test_rolling_keep_attrs(funcname, argument): +def test_rolling_keep_attrs(funcname, argument) -> None: global_attrs = {"units": "test", "long_name": "testing"} da_attrs = {"da_attr": "test"} da_not_rolled_attrs = {"da_not_rolled_attr": "test"} @@ -6182,7 +6196,7 @@ def test_rolling_keep_attrs(funcname, argument): assert result.da_not_rolled.name == "da_not_rolled" -def test_rolling_properties(ds): +def test_rolling_properties(ds) -> None: # catching invalid args with pytest.raises(ValueError, match="window must be > 0"): ds.rolling(time=-2) @@ -6197,7 +6211,7 @@ def test_rolling_properties(ds): @pytest.mark.parametrize("min_periods", (1, None)) @pytest.mark.parametrize("key", ("z1", "z2")) @pytest.mark.parametrize("backend", ["numpy"], indirect=True) -def test_rolling_wrapped_bottleneck(ds, name, center, min_periods, key): +def test_rolling_wrapped_bottleneck(ds, name, center, min_periods, key) -> None: bn = pytest.importorskip("bottleneck", minversion="1.1") # Test all bottleneck functions @@ -6223,7 +6237,7 @@ def test_rolling_wrapped_bottleneck(ds, name, center, min_periods, key): @requires_numbagg @pytest.mark.parametrize("backend", ["numpy"], indirect=True) -def test_rolling_exp(ds): +def test_rolling_exp(ds) -> None: result = ds.rolling_exp(time=10, window_type="span").mean() assert isinstance(result, Dataset) @@ -6231,7 +6245,7 @@ def test_rolling_exp(ds): @requires_numbagg @pytest.mark.parametrize("backend", ["numpy"], indirect=True) -def test_rolling_exp_keep_attrs(ds): +def test_rolling_exp_keep_attrs(ds) -> None: attrs_global = {"attrs": "global"} attrs_z1 = {"attr": "z1"} @@ -6275,7 +6289,7 @@ def test_rolling_exp_keep_attrs(ds): @pytest.mark.parametrize("center", (True, False)) @pytest.mark.parametrize("min_periods", (None, 1, 2, 3)) @pytest.mark.parametrize("window", (1, 2, 3, 4)) -def test_rolling_pandas_compat(center, window, min_periods): +def test_rolling_pandas_compat(center, window, min_periods) -> None: df = pd.DataFrame( { "x": np.random.randn(20), @@ -6297,7 +6311,7 @@ def test_rolling_pandas_compat(center, window, min_periods): @pytest.mark.parametrize("center", (True, False)) @pytest.mark.parametrize("window", (1, 2, 3, 4)) -def test_rolling_construct(center, window): +def test_rolling_construct(center, window) -> None: df = pd.DataFrame( { "x": np.random.randn(20), @@ -6332,7 +6346,7 @@ def test_rolling_construct(center, window): @pytest.mark.parametrize("min_periods", (None, 1, 2, 3)) @pytest.mark.parametrize("window", (1, 2, 3, 4)) @pytest.mark.parametrize("name", ("sum", "mean", "std", "var", "min", "max", "median")) -def test_rolling_reduce(ds, center, min_periods, window, name): +def test_rolling_reduce(ds, center, min_periods, window, name) -> None: if min_periods is not None and window < min_periods: min_periods = window @@ -6360,7 +6374,7 @@ def test_rolling_reduce(ds, center, min_periods, window, name): @pytest.mark.parametrize("min_periods", (None, 1)) @pytest.mark.parametrize("name", ("sum", "max")) @pytest.mark.parametrize("dask", (True, False)) -def test_ndrolling_reduce(ds, center, min_periods, name, dask): +def test_ndrolling_reduce(ds, center, min_periods, name, dask) -> None: if dask and has_dask: ds = ds.chunk({"x": 4}) @@ -6391,7 +6405,7 @@ def test_ndrolling_reduce(ds, center, min_periods, name, dask): @pytest.mark.parametrize("center", (True, False, (True, False))) @pytest.mark.parametrize("fill_value", (np.nan, 0.0)) @pytest.mark.parametrize("dask", (True, False)) -def test_ndrolling_construct(center, fill_value, dask): +def test_ndrolling_construct(center, fill_value, dask) -> None: da = DataArray( np.arange(5 * 6 * 7).reshape(5, 6, 7).astype(float), dims=["x", "y", "z"], @@ -6415,14 +6429,14 @@ def test_ndrolling_construct(center, fill_value, dask): assert_allclose(actual, expected) -def test_raise_no_warning_for_nan_in_binary_ops(): +def test_raise_no_warning_for_nan_in_binary_ops() -> None: with assert_no_warnings(): Dataset(data_vars={"x": ("y", [1, 2, np.NaN])}) > 0 @pytest.mark.filterwarnings("error") @pytest.mark.parametrize("ds", (2,), indirect=True) -def test_raise_no_warning_assert_close(ds): +def test_raise_no_warning_assert_close(ds) -> None: assert_allclose(ds, ds) @@ -6430,7 +6444,7 @@ def test_raise_no_warning_assert_close(ds): @pytest.mark.filterwarnings("error") @pytest.mark.parametrize("ds", (2,), indirect=True) @pytest.mark.parametrize("name", ("mean", "max")) -def test_raise_no_warning_dask_rolling_assert_close(ds, name): +def test_raise_no_warning_dask_rolling_assert_close(ds, name) -> None: """ This is a puzzle — I can't easily find the source of the warning. It requires `assert_allclose` to be run, for the `ds` param to be 2, and is @@ -6448,7 +6462,7 @@ def test_raise_no_warning_dask_rolling_assert_close(ds, name): @pytest.mark.parametrize("dask", [True, False]) @pytest.mark.parametrize("edge_order", [1, 2]) -def test_differentiate(dask, edge_order): +def test_differentiate(dask, edge_order) -> None: rs = np.random.RandomState(42) coord = [0.2, 0.35, 0.4, 0.6, 0.7, 0.75, 0.76, 0.8] @@ -6496,7 +6510,7 @@ def test_differentiate(dask, edge_order): @pytest.mark.parametrize("dask", [True, False]) -def test_differentiate_datetime(dask): +def test_differentiate_datetime(dask) -> None: rs = np.random.RandomState(42) coord = np.array( [ @@ -6546,7 +6560,7 @@ def test_differentiate_datetime(dask): @pytest.mark.skipif(not has_cftime, reason="Test requires cftime.") @pytest.mark.parametrize("dask", [True, False]) -def test_differentiate_cftime(dask): +def test_differentiate_cftime(dask) -> None: rs = np.random.RandomState(42) coord = xr.cftime_range("2000", periods=8, freq="2M") @@ -6575,7 +6589,7 @@ def test_differentiate_cftime(dask): @pytest.mark.parametrize("dask", [True, False]) -def test_integrate(dask): +def test_integrate(dask) -> None: rs = np.random.RandomState(42) coord = [0.2, 0.35, 0.4, 0.6, 0.7, 0.75, 0.76, 0.8] @@ -6629,7 +6643,7 @@ def test_integrate(dask): @requires_scipy @pytest.mark.parametrize("dask", [True, False]) -def test_cumulative_integrate(dask): +def test_cumulative_integrate(dask) -> None: rs = np.random.RandomState(43) coord = [0.2, 0.35, 0.4, 0.6, 0.7, 0.75, 0.76, 0.8] @@ -6693,7 +6707,7 @@ def test_cumulative_integrate(dask): @pytest.mark.parametrize("dask", [True, False]) @pytest.mark.parametrize("which_datetime", ["np", "cftime"]) -def test_trapz_datetime(dask, which_datetime): +def test_trapz_datetime(dask, which_datetime) -> None: rs = np.random.RandomState(42) if which_datetime == "np": coord = np.array( @@ -6743,13 +6757,13 @@ def test_trapz_datetime(dask, which_datetime): assert_allclose(actual, actual2 / 24.0) -def test_no_dict(): +def test_no_dict() -> None: d = Dataset() with pytest.raises(AttributeError): d.__dict__ -def test_subclass_slots(): +def test_subclass_slots() -> None: """Test that Dataset subclasses must explicitly define ``__slots__``. .. note:: @@ -6764,7 +6778,7 @@ class MyDS(Dataset): assert str(e.value) == "MyDS must explicitly define __slots__" -def test_weakref(): +def test_weakref() -> None: """Classes with __slots__ are incompatible with the weakref module unless they explicitly state __weakref__ among their slots """ @@ -6775,13 +6789,13 @@ def test_weakref(): assert r() is ds -def test_deepcopy_obj_array(): +def test_deepcopy_obj_array() -> None: x0 = Dataset(dict(foo=DataArray(np.array([object()])))) x1 = deepcopy(x0) assert x0["foo"].values[0] is not x1["foo"].values[0] -def test_clip(ds): +def test_clip(ds) -> None: result = ds.clip(min=0.5) assert all((result.min(...) >= 0.5).values()) @@ -6798,7 +6812,7 @@ def test_clip(ds): class TestDropDuplicates: @pytest.mark.parametrize("keep", ["first", "last", False]) - def test_drop_duplicates_1d(self, keep): + def test_drop_duplicates_1d(self, keep) -> None: ds = xr.Dataset( {"a": ("time", [0, 5, 6, 7]), "b": ("time", [9, 3, 8, 2])}, coords={"time": [0, 0, 1, 2]}, @@ -6828,20 +6842,20 @@ def test_drop_duplicates_1d(self, keep): class TestNumpyCoercion: - def test_from_numpy(self): + def test_from_numpy(self) -> None: ds = xr.Dataset({"a": ("x", [1, 2, 3])}, coords={"lat": ("x", [4, 5, 6])}) assert_identical(ds.as_numpy(), ds) @requires_dask - def test_from_dask(self): + def test_from_dask(self) -> None: ds = xr.Dataset({"a": ("x", [1, 2, 3])}, coords={"lat": ("x", [4, 5, 6])}) ds_chunked = ds.chunk(1) assert_identical(ds_chunked.as_numpy(), ds.compute()) @requires_pint - def test_from_pint(self): + def test_from_pint(self) -> None: from pint import Quantity arr = np.array([1, 2, 3]) @@ -6854,7 +6868,7 @@ def test_from_pint(self): assert_identical(ds.as_numpy(), expected) @requires_sparse - def test_from_sparse(self): + def test_from_sparse(self) -> None: import sparse arr = np.diagflat([1, 2, 3]) @@ -6869,7 +6883,7 @@ def test_from_sparse(self): assert_identical(ds.as_numpy(), expected) @requires_cupy - def test_from_cupy(self): + def test_from_cupy(self) -> None: import cupy as cp arr = np.array([1, 2, 3]) @@ -6882,7 +6896,7 @@ def test_from_cupy(self): @requires_dask @requires_pint - def test_from_pint_wrapping_dask(self): + def test_from_pint_wrapping_dask(self) -> None: import dask from pint import Quantity From 68b4c261df15688ee97c8453fcf5fe441f1aec4a Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 17:09:56 +0200 Subject: [PATCH 15/21] fix bug in dataset setitem --- xarray/core/dataset.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index 534615e0ff0..e04b7da3588 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -1426,6 +1426,14 @@ def __setitem__(self, key: Hashable | list[Hashable] | Mapping, value) -> None: else: raise e + elif utils.hashable(key): + if isinstance(value, Dataset): + raise TypeError( + "Cannot assign a Dataset to a single key - only a DataArray or Variable " + "object can be stored under a single key." + ) + self.update({key: value}) + elif utils.iterable_of_hashable(key): keylist = list(key) if len(keylist) == 0: @@ -1446,14 +1454,6 @@ def __setitem__(self, key: Hashable | list[Hashable] | Mapping, value) -> None: else: self.update(dict(zip(keylist, value))) - elif utils.hashable(key): - if isinstance(value, Dataset): - raise TypeError( - "Cannot assign a Dataset to a single key - only a DataArray or Variable " - "object can be stored under a single key." - ) - self.update({key: value}) - else: raise ValueError(f"Unsupported key-type {type(key)}") From 618f6ccff6f7c7dd5c12ea109254eb16f4b42068 Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 17:15:18 +0200 Subject: [PATCH 16/21] fix typing of dataset setitem --- xarray/core/dataset.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index e04b7da3588..50531873a24 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -1386,7 +1386,9 @@ def __getitem__( return self._copy_listed(key) raise ValueError(f"Unsupported key-type {type(key)}") - def __setitem__(self, key: Hashable | list[Hashable] | Mapping, value) -> None: + def __setitem__( + self, key: Hashable | Iterable[Hashable] | Mapping, value: Any + ) -> None: """Add an array to this dataset. Multiple arrays can be added at the same time, in which case each of the following operations is applied to the respective value. From 223b4ddb6f1d2fc3e0cea8d26891a1a7c9a28844 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 3 Jun 2022 15:23:58 +0000 Subject: [PATCH 17/21] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/core/_reductions.py | 160 ++++++++++++++++++------------------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/xarray/core/_reductions.py b/xarray/core/_reductions.py index 72bb5748281..0c5aa354064 100644 --- a/xarray/core/_reductions.py +++ b/xarray/core/_reductions.py @@ -31,7 +31,7 @@ def reduce( keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: raise NotImplementedError() def count( @@ -40,7 +40,7 @@ def count( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``count`` along some dimension(s). @@ -101,7 +101,7 @@ def all( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``all`` along some dimension(s). @@ -162,7 +162,7 @@ def any( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``any`` along some dimension(s). @@ -224,7 +224,7 @@ def max( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``max`` along some dimension(s). @@ -296,7 +296,7 @@ def min( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``min`` along some dimension(s). @@ -368,7 +368,7 @@ def mean( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``mean`` along some dimension(s). @@ -445,7 +445,7 @@ def prod( min_count: int | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``prod`` along some dimension(s). @@ -533,7 +533,7 @@ def sum( min_count: int | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``sum`` along some dimension(s). @@ -621,7 +621,7 @@ def std( ddof: int = 0, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``std`` along some dimension(s). @@ -706,7 +706,7 @@ def var( ddof: int = 0, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``var`` along some dimension(s). @@ -790,7 +790,7 @@ def median( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``median`` along some dimension(s). @@ -872,7 +872,7 @@ def reduce( keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: raise NotImplementedError() def count( @@ -881,7 +881,7 @@ def count( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``count`` along some dimension(s). @@ -940,7 +940,7 @@ def all( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``all`` along some dimension(s). @@ -999,7 +999,7 @@ def any( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``any`` along some dimension(s). @@ -1059,7 +1059,7 @@ def max( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``max`` along some dimension(s). @@ -1129,7 +1129,7 @@ def min( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``min`` along some dimension(s). @@ -1199,7 +1199,7 @@ def mean( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``mean`` along some dimension(s). @@ -1274,7 +1274,7 @@ def prod( min_count: int | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``prod`` along some dimension(s). @@ -1360,7 +1360,7 @@ def sum( min_count: int | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``sum`` along some dimension(s). @@ -1446,7 +1446,7 @@ def std( ddof: int = 0, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``std`` along some dimension(s). @@ -1529,7 +1529,7 @@ def var( ddof: int = 0, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``var`` along some dimension(s). @@ -1611,7 +1611,7 @@ def median( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``median`` along some dimension(s). @@ -1680,7 +1680,7 @@ def median( class DatasetGroupByReductions: - _obj: "Dataset" + _obj: Dataset def reduce( self, @@ -1691,14 +1691,14 @@ def reduce( keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: raise NotImplementedError() def _flox_reduce( self, dim: None | Hashable | Sequence[Hashable], **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: raise NotImplementedError() def count( @@ -1707,7 +1707,7 @@ def count( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``count`` along some dimension(s). @@ -1778,7 +1778,7 @@ def all( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``all`` along some dimension(s). @@ -1849,7 +1849,7 @@ def any( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``any`` along some dimension(s). @@ -1921,7 +1921,7 @@ def max( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``max`` along some dimension(s). @@ -2004,7 +2004,7 @@ def min( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``min`` along some dimension(s). @@ -2087,7 +2087,7 @@ def mean( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``mean`` along some dimension(s). @@ -2175,7 +2175,7 @@ def prod( min_count: int | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``prod`` along some dimension(s). @@ -2275,7 +2275,7 @@ def sum( min_count: int | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``sum`` along some dimension(s). @@ -2375,7 +2375,7 @@ def std( ddof: int = 0, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``std`` along some dimension(s). @@ -2472,7 +2472,7 @@ def var( ddof: int = 0, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``var`` along some dimension(s). @@ -2568,7 +2568,7 @@ def median( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``median`` along some dimension(s). @@ -2639,7 +2639,7 @@ def median( class DatasetResampleReductions: - _obj: "Dataset" + _obj: Dataset def reduce( self, @@ -2650,14 +2650,14 @@ def reduce( keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: raise NotImplementedError() def _flox_reduce( self, dim: None | Hashable | Sequence[Hashable], **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: raise NotImplementedError() def count( @@ -2666,7 +2666,7 @@ def count( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``count`` along some dimension(s). @@ -2737,7 +2737,7 @@ def all( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``all`` along some dimension(s). @@ -2808,7 +2808,7 @@ def any( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``any`` along some dimension(s). @@ -2880,7 +2880,7 @@ def max( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``max`` along some dimension(s). @@ -2963,7 +2963,7 @@ def min( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``min`` along some dimension(s). @@ -3046,7 +3046,7 @@ def mean( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``mean`` along some dimension(s). @@ -3134,7 +3134,7 @@ def prod( min_count: int | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``prod`` along some dimension(s). @@ -3234,7 +3234,7 @@ def sum( min_count: int | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``sum`` along some dimension(s). @@ -3334,7 +3334,7 @@ def std( ddof: int = 0, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``std`` along some dimension(s). @@ -3431,7 +3431,7 @@ def var( ddof: int = 0, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``var`` along some dimension(s). @@ -3527,7 +3527,7 @@ def median( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "Dataset": + ) -> Dataset: """ Reduce this Dataset's data by applying ``median`` along some dimension(s). @@ -3598,7 +3598,7 @@ def median( class DataArrayGroupByReductions: - _obj: "DataArray" + _obj: DataArray def reduce( self, @@ -3609,14 +3609,14 @@ def reduce( keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: raise NotImplementedError() def _flox_reduce( self, dim: None | Hashable | Sequence[Hashable], **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: raise NotImplementedError() def count( @@ -3625,7 +3625,7 @@ def count( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``count`` along some dimension(s). @@ -3693,7 +3693,7 @@ def all( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``all`` along some dimension(s). @@ -3761,7 +3761,7 @@ def any( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``any`` along some dimension(s). @@ -3830,7 +3830,7 @@ def max( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``max`` along some dimension(s). @@ -3910,7 +3910,7 @@ def min( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``min`` along some dimension(s). @@ -3990,7 +3990,7 @@ def mean( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``mean`` along some dimension(s). @@ -4075,7 +4075,7 @@ def prod( min_count: int | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``prod`` along some dimension(s). @@ -4172,7 +4172,7 @@ def sum( min_count: int | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``sum`` along some dimension(s). @@ -4269,7 +4269,7 @@ def std( ddof: int = 0, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``std`` along some dimension(s). @@ -4363,7 +4363,7 @@ def var( ddof: int = 0, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``var`` along some dimension(s). @@ -4456,7 +4456,7 @@ def median( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``median`` along some dimension(s). @@ -4525,7 +4525,7 @@ def median( class DataArrayResampleReductions: - _obj: "DataArray" + _obj: DataArray def reduce( self, @@ -4536,14 +4536,14 @@ def reduce( keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: raise NotImplementedError() def _flox_reduce( self, dim: None | Hashable | Sequence[Hashable], **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: raise NotImplementedError() def count( @@ -4552,7 +4552,7 @@ def count( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``count`` along some dimension(s). @@ -4620,7 +4620,7 @@ def all( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``all`` along some dimension(s). @@ -4688,7 +4688,7 @@ def any( *, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``any`` along some dimension(s). @@ -4757,7 +4757,7 @@ def max( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``max`` along some dimension(s). @@ -4837,7 +4837,7 @@ def min( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``min`` along some dimension(s). @@ -4917,7 +4917,7 @@ def mean( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``mean`` along some dimension(s). @@ -5002,7 +5002,7 @@ def prod( min_count: int | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``prod`` along some dimension(s). @@ -5099,7 +5099,7 @@ def sum( min_count: int | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``sum`` along some dimension(s). @@ -5196,7 +5196,7 @@ def std( ddof: int = 0, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``std`` along some dimension(s). @@ -5290,7 +5290,7 @@ def var( ddof: int = 0, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``var`` along some dimension(s). @@ -5383,7 +5383,7 @@ def median( skipna: bool | None = None, keep_attrs: bool | None = None, **kwargs: Any, - ) -> "DataArray": + ) -> DataArray: """ Reduce this DataArray's data by applying ``median`` along some dimension(s). From a5af82b9e6e43e5d7452b20bbebb3fe70d529a4d Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 20:20:25 +0200 Subject: [PATCH 18/21] fix broken unit test --- xarray/tests/test_accessor_str.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xarray/tests/test_accessor_str.py b/xarray/tests/test_accessor_str.py index ec1d6cbdc7a..6c9705cdaa4 100644 --- a/xarray/tests/test_accessor_str.py +++ b/xarray/tests/test_accessor_str.py @@ -754,7 +754,7 @@ def test_extract_single_nocase(dtype) -> None: res_str_none = value.str.extract(pat=pat_str, dim=None, case=False) res_str_dim = value.str.extract(pat=pat_str, dim="XX", case=False) - res_re_none = value.str.extract(pat=pat_re, dim=None) + res_re_none = value.str.extract(pat=pat_compiled, dim=None) res_re_dim = value.str.extract(pat=pat_compiled, dim="XX") assert res_re_dim.dtype == targ_none.dtype From 0812415e63a59470128d8815b67565b91170ce6b Mon Sep 17 00:00:00 2001 From: Michael Niklas Date: Fri, 3 Jun 2022 20:26:54 +0200 Subject: [PATCH 19/21] fix _reductions docs --- xarray/core/_reductions.py | 994 +++++++++++++++++++++++++++++++++++++ 1 file changed, 994 insertions(+) diff --git a/xarray/core/_reductions.py b/xarray/core/_reductions.py index 0c5aa354064..dd2cf311079 100644 --- a/xarray/core/_reductions.py +++ b/xarray/core/_reductions.py @@ -84,8 +84,19 @@ def count( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.count() + + Dimensions: () + Data variables: + da int32 5 """ return self.reduce( duck_array_ops.count, @@ -145,8 +156,19 @@ def all( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.all() + + Dimensions: () + Data variables: + da bool False """ return self.reduce( duck_array_ops.array_all, @@ -206,8 +228,19 @@ def any( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.any() + + Dimensions: () + Data variables: + da bool True """ return self.reduce( duck_array_ops.array_any, @@ -273,12 +306,27 @@ def max( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.max() + + Dimensions: () + Data variables: + da float64 3.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.max(skipna=False) + + Dimensions: () + Data variables: + da float64 nan """ return self.reduce( duck_array_ops.max, @@ -345,12 +393,27 @@ def min( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.min() + + Dimensions: () + Data variables: + da float64 1.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.min(skipna=False) + + Dimensions: () + Data variables: + da float64 nan """ return self.reduce( duck_array_ops.min, @@ -421,12 +484,27 @@ def mean( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.mean() + + Dimensions: () + Data variables: + da float64 1.8 Use ``skipna`` to control whether NaNs are ignored. >>> ds.mean(skipna=False) + + Dimensions: () + Data variables: + da float64 nan """ return self.reduce( duck_array_ops.mean, @@ -504,16 +582,35 @@ def prod( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.prod() + + Dimensions: () + Data variables: + da float64 12.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.prod(skipna=False) + + Dimensions: () + Data variables: + da float64 nan Specify ``min_count`` for finer control over when NaNs are ignored. >>> ds.prod(skipna=True, min_count=2) + + Dimensions: () + Data variables: + da float64 12.0 """ return self.reduce( duck_array_ops.prod, @@ -592,16 +689,35 @@ def sum( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.sum() + + Dimensions: () + Data variables: + da float64 9.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.sum(skipna=False) + + Dimensions: () + Data variables: + da float64 nan Specify ``min_count`` for finer control over when NaNs are ignored. >>> ds.sum(skipna=True, min_count=2) + + Dimensions: () + Data variables: + da float64 9.0 """ return self.reduce( duck_array_ops.sum, @@ -677,16 +793,35 @@ def std( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.std() + + Dimensions: () + Data variables: + da float64 0.7483 Use ``skipna`` to control whether NaNs are ignored. >>> ds.std(skipna=False) + + Dimensions: () + Data variables: + da float64 nan Specify ``ddof=1`` for an unbiased estimate. >>> ds.std(skipna=True, ddof=1) + + Dimensions: () + Data variables: + da float64 0.8367 """ return self.reduce( duck_array_ops.std, @@ -762,16 +897,35 @@ def var( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.var() + + Dimensions: () + Data variables: + da float64 0.56 Use ``skipna`` to control whether NaNs are ignored. >>> ds.var(skipna=False) + + Dimensions: () + Data variables: + da float64 nan Specify ``ddof=1`` for an unbiased estimate. >>> ds.var(skipna=True, ddof=1) + + Dimensions: () + Data variables: + da float64 0.7 """ return self.reduce( duck_array_ops.var, @@ -843,12 +997,27 @@ def median( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.median() + + Dimensions: () + Data variables: + da float64 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.median(skipna=False) + + Dimensions: () + Data variables: + da float64 nan """ return self.reduce( duck_array_ops.median, @@ -924,8 +1093,15 @@ def count( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.count() + + array(5) """ return self.reduce( duck_array_ops.count, @@ -983,8 +1159,15 @@ def all( ... ), ... ) >>> da + + array([ True, True, True, True, True, False]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.all() + + array(False) """ return self.reduce( duck_array_ops.array_all, @@ -1042,8 +1225,15 @@ def any( ... ), ... ) >>> da + + array([ True, True, True, True, True, False]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.any() + + array(True) """ return self.reduce( duck_array_ops.array_any, @@ -1107,12 +1297,21 @@ def max( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.max() + + array(3.) Use ``skipna`` to control whether NaNs are ignored. >>> da.max(skipna=False) + + array(nan) """ return self.reduce( duck_array_ops.max, @@ -1177,12 +1376,21 @@ def min( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.min() + + array(1.) Use ``skipna`` to control whether NaNs are ignored. >>> da.min(skipna=False) + + array(nan) """ return self.reduce( duck_array_ops.min, @@ -1251,12 +1459,21 @@ def mean( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.mean() + + array(1.8) Use ``skipna`` to control whether NaNs are ignored. >>> da.mean(skipna=False) + + array(nan) """ return self.reduce( duck_array_ops.mean, @@ -1332,16 +1549,27 @@ def prod( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.prod() + + array(12.) Use ``skipna`` to control whether NaNs are ignored. >>> da.prod(skipna=False) + + array(nan) Specify ``min_count`` for finer control over when NaNs are ignored. >>> da.prod(skipna=True, min_count=2) + + array(12.) """ return self.reduce( duck_array_ops.prod, @@ -1418,16 +1646,27 @@ def sum( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.sum() + + array(9.) Use ``skipna`` to control whether NaNs are ignored. >>> da.sum(skipna=False) + + array(nan) Specify ``min_count`` for finer control over when NaNs are ignored. >>> da.sum(skipna=True, min_count=2) + + array(9.) """ return self.reduce( duck_array_ops.sum, @@ -1501,16 +1740,27 @@ def std( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.std() + + array(0.74833148) Use ``skipna`` to control whether NaNs are ignored. >>> da.std(skipna=False) + + array(nan) Specify ``ddof=1`` for an unbiased estimate. >>> da.std(skipna=True, ddof=1) + + array(0.83666003) """ return self.reduce( duck_array_ops.std, @@ -1584,16 +1834,27 @@ def var( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.var() + + array(0.56) Use ``skipna`` to control whether NaNs are ignored. >>> da.var(skipna=False) + + array(nan) Specify ``ddof=1`` for an unbiased estimate. >>> da.var(skipna=True, ddof=1) + + array(0.7) """ return self.reduce( duck_array_ops.var, @@ -1663,12 +1924,21 @@ def median( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.median() + + array(2.) Use ``skipna`` to control whether NaNs are ignored. >>> da.median(skipna=False) + + array(nan) """ return self.reduce( duck_array_ops.median, @@ -1751,8 +2021,21 @@ def count( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.groupby("labels").count() + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) int64 1 2 2 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -1822,8 +2105,21 @@ def all( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.groupby("labels").all() + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) bool False True True """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -1893,8 +2189,21 @@ def any( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.groupby("labels").any() + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) bool True True True """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -1970,12 +2279,31 @@ def max( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.groupby("labels").max() + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 1.0 2.0 3.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").max(skipna=False) + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 nan 2.0 3.0 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2053,12 +2381,31 @@ def min( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.groupby("labels").min() + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 1.0 2.0 1.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").min(skipna=False) + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 nan 2.0 1.0 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2140,12 +2487,31 @@ def mean( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.groupby("labels").mean() + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 1.0 2.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").mean(skipna=False) + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 nan 2.0 2.0 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2234,16 +2600,41 @@ def prod( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.groupby("labels").prod() + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 1.0 4.0 3.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").prod(skipna=False) + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 nan 4.0 3.0 Specify ``min_count`` for finer control over when NaNs are ignored. >>> ds.groupby("labels").prod(skipna=True, min_count=2) + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 nan 4.0 3.0 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2334,16 +2725,41 @@ def sum( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.groupby("labels").sum() + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 1.0 4.0 4.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").sum(skipna=False) + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 nan 4.0 4.0 Specify ``min_count`` for finer control over when NaNs are ignored. >>> ds.groupby("labels").sum(skipna=True, min_count=2) + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 nan 4.0 4.0 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2431,16 +2847,41 @@ def std( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.groupby("labels").std() + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 0.0 0.0 1.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").std(skipna=False) + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 nan 0.0 1.0 Specify ``ddof=1`` for an unbiased estimate. >>> ds.groupby("labels").std(skipna=True, ddof=1) + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 nan 0.0 1.414 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2528,16 +2969,41 @@ def var( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.groupby("labels").var() + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 0.0 0.0 1.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").var(skipna=False) + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 nan 0.0 1.0 Specify ``ddof=1`` for an unbiased estimate. >>> ds.groupby("labels").var(skipna=True, ddof=1) + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 nan 0.0 2.0 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2621,12 +3087,31 @@ def median( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.groupby("labels").median() + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 1.0 2.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.groupby("labels").median(skipna=False) + + Dimensions: (labels: 3) + Coordinates: + * labels (labels) object 'a' 'b' 'c' + Data variables: + da (labels) float64 nan 2.0 2.0 """ return self.reduce( duck_array_ops.median, @@ -2710,8 +3195,21 @@ def count( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3M").count() + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) int64 1 3 1 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2781,8 +3279,21 @@ def all( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3M").all() + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) bool True True False """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2852,8 +3363,21 @@ def any( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3M").any() + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) bool True True True """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -2929,12 +3453,31 @@ def max( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3M").max() + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 1.0 3.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").max(skipna=False) + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 1.0 3.0 nan """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3012,12 +3555,31 @@ def min( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3M").min() + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 1.0 1.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").min(skipna=False) + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 1.0 1.0 nan """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3099,12 +3661,31 @@ def mean( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3M").mean() + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 1.0 2.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").mean(skipna=False) + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 1.0 2.0 nan """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3193,16 +3774,41 @@ def prod( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3M").prod() + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 1.0 6.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").prod(skipna=False) + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 1.0 6.0 nan Specify ``min_count`` for finer control over when NaNs are ignored. >>> ds.resample(time="3M").prod(skipna=True, min_count=2) + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 nan 6.0 nan """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3293,16 +3899,41 @@ def sum( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3M").sum() + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 1.0 6.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").sum(skipna=False) + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 1.0 6.0 nan Specify ``min_count`` for finer control over when NaNs are ignored. >>> ds.resample(time="3M").sum(skipna=True, min_count=2) + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 nan 6.0 nan """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3390,16 +4021,41 @@ def std( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3M").std() + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 0.0 0.8165 0.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").std(skipna=False) + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 0.0 0.8165 nan Specify ``ddof=1`` for an unbiased estimate. >>> ds.resample(time="3M").std(skipna=True, ddof=1) + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 nan 1.0 nan """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3487,16 +4143,41 @@ def var( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3M").var() + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 0.0 0.6667 0.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").var(skipna=False) + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 0.0 0.6667 nan Specify ``ddof=1`` for an unbiased estimate. >>> ds.resample(time="3M").var(skipna=True, ddof=1) + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 nan 1.0 nan """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3580,12 +4261,31 @@ def median( ... ) >>> ds = xr.Dataset(dict(da=da)) >>> ds + + Dimensions: (time: 6) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> ds.resample(time="3M").median() + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 1.0 2.0 2.0 Use ``skipna`` to control whether NaNs are ignored. >>> ds.resample(time="3M").median(skipna=False) + + Dimensions: (time: 3) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 + Data variables: + da (time) float64 1.0 2.0 nan """ return self.reduce( duck_array_ops.median, @@ -3668,8 +4368,17 @@ def count( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.groupby("labels").count() + + array([1, 2, 2], dtype=int64) + Coordinates: + * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3736,8 +4445,17 @@ def all( ... ), ... ) >>> da + + array([ True, True, True, True, True, False]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.groupby("labels").all() + + array([False, True, True]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3804,8 +4522,17 @@ def any( ... ), ... ) >>> da + + array([ True, True, True, True, True, False]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.groupby("labels").any() + + array([ True, True, True]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3878,12 +4605,25 @@ def max( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.groupby("labels").max() + + array([1., 2., 3.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").max(skipna=False) + + array([nan, 2., 3.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -3958,12 +4698,25 @@ def min( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.groupby("labels").min() + + array([1., 2., 1.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").min(skipna=False) + + array([nan, 2., 1.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4042,12 +4795,25 @@ def mean( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.groupby("labels").mean() + + array([1., 2., 2.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").mean(skipna=False) + + array([nan, 2., 2.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4133,16 +4899,33 @@ def prod( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.groupby("labels").prod() + + array([1., 4., 3.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").prod(skipna=False) + + array([nan, 4., 3.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' Specify ``min_count`` for finer control over when NaNs are ignored. >>> da.groupby("labels").prod(skipna=True, min_count=2) + + array([nan, 4., 3.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4230,16 +5013,33 @@ def sum( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.groupby("labels").sum() + + array([1., 4., 4.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").sum(skipna=False) + + array([nan, 4., 4.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' Specify ``min_count`` for finer control over when NaNs are ignored. >>> da.groupby("labels").sum(skipna=True, min_count=2) + + array([nan, 4., 4.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4324,16 +5124,33 @@ def std( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.groupby("labels").std() + + array([0., 0., 1.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").std(skipna=False) + + array([nan, 0., 1.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' Specify ``ddof=1`` for an unbiased estimate. >>> da.groupby("labels").std(skipna=True, ddof=1) + + array([ nan, 0. , 1.41421356]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4418,16 +5235,33 @@ def var( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.groupby("labels").var() + + array([0., 0., 1.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").var(skipna=False) + + array([nan, 0., 1.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' Specify ``ddof=1`` for an unbiased estimate. >>> da.groupby("labels").var(skipna=True, ddof=1) + + array([nan, 0., 2.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4508,12 +5342,25 @@ def median( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.groupby("labels").median() + + array([1., 2., 2.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' Use ``skipna`` to control whether NaNs are ignored. >>> da.groupby("labels").median(skipna=False) + + array([nan, 2., 2.]) + Coordinates: + * labels (labels) object 'a' 'b' 'c' """ return self.reduce( duck_array_ops.median, @@ -4595,8 +5442,17 @@ def count( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.resample(time="3M").count() + + array([1, 3, 1], dtype=int64) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4663,8 +5519,17 @@ def all( ... ), ... ) >>> da + + array([ True, True, True, True, True, False]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.resample(time="3M").all() + + array([ True, True, False]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4731,8 +5596,17 @@ def any( ... ), ... ) >>> da + + array([ True, True, True, True, True, False]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.resample(time="3M").any() + + array([ True, True, True]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4805,12 +5679,25 @@ def max( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.resample(time="3M").max() + + array([1., 3., 2.]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").max(skipna=False) + + array([ 1., 3., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4885,12 +5772,25 @@ def min( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.resample(time="3M").min() + + array([1., 1., 2.]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").min(skipna=False) + + array([ 1., 1., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -4969,12 +5869,25 @@ def mean( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.resample(time="3M").mean() + + array([1., 2., 2.]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").mean(skipna=False) + + array([ 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -5060,16 +5973,33 @@ def prod( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.resample(time="3M").prod() + + array([1., 6., 2.]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").prod(skipna=False) + + array([ 1., 6., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Specify ``min_count`` for finer control over when NaNs are ignored. >>> da.resample(time="3M").prod(skipna=True, min_count=2) + + array([nan, 6., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -5157,16 +6087,33 @@ def sum( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.resample(time="3M").sum() + + array([1., 6., 2.]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").sum(skipna=False) + + array([ 1., 6., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Specify ``min_count`` for finer control over when NaNs are ignored. >>> da.resample(time="3M").sum(skipna=True, min_count=2) + + array([nan, 6., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -5251,16 +6198,33 @@ def std( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.resample(time="3M").std() + + array([0. , 0.81649658, 0. ]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").std(skipna=False) + + array([0. , 0.81649658, nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Specify ``ddof=1`` for an unbiased estimate. >>> da.resample(time="3M").std(skipna=True, ddof=1) + + array([nan, 1., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -5345,16 +6309,33 @@ def var( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.resample(time="3M").var() + + array([0. , 0.66666667, 0. ]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").var(skipna=False) + + array([0. , 0.66666667, nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Specify ``ddof=1`` for an unbiased estimate. >>> da.resample(time="3M").var(skipna=True, ddof=1) + + array([nan, 1., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ if flox and OPTIONS["use_flox"] and contains_only_dask_or_numpy(self._obj): return self._flox_reduce( @@ -5435,12 +6416,25 @@ def median( ... ), ... ) >>> da + + array([ 1., 2., 3., 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-02-28 ... 2001-06-30 + labels (time) >> da.resample(time="3M").median() + + array([1., 2., 2.]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 Use ``skipna`` to control whether NaNs are ignored. >>> da.resample(time="3M").median(skipna=False) + + array([ 1., 2., nan]) + Coordinates: + * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """ return self.reduce( duck_array_ops.median, From ea6455884b0f9c454b6426d2dab82cb8e0c14844 Mon Sep 17 00:00:00 2001 From: dcherian Date: Fri, 3 Jun 2022 13:03:55 -0600 Subject: [PATCH 20/21] generate_reductions: fix typing in templates --- xarray/util/generate_reductions.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/xarray/util/generate_reductions.py b/xarray/util/generate_reductions.py index e526832a0d5..279b7859032 100644 --- a/xarray/util/generate_reductions.py +++ b/xarray/util/generate_reductions.py @@ -51,13 +51,13 @@ def reduce( keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, - ) -> "{obj}": + ) -> {obj}: raise NotImplementedError()""" GROUPBY_PREAMBLE = """ class {obj}{cls}Reductions: - _obj: "{obj}" + _obj: {obj} def reduce( self, @@ -68,20 +68,20 @@ def reduce( keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, - ) -> "{obj}": + ) -> {obj}: raise NotImplementedError() def _flox_reduce( self, dim: None | Hashable | Sequence[Hashable], **kwargs: Any, - ) -> "{obj}": + ) -> {obj}: raise NotImplementedError()""" RESAMPLE_PREAMBLE = """ class {obj}{cls}Reductions: - _obj: "{obj}" + _obj: {obj} def reduce( self, @@ -92,14 +92,14 @@ def reduce( keep_attrs: bool | None = None, keepdims: bool = False, **kwargs: Any, - ) -> "{obj}": + ) -> {obj}: raise NotImplementedError() def _flox_reduce( self, dim: None | Hashable | Sequence[Hashable], **kwargs: Any, - ) -> "{obj}": + ) -> {obj}: raise NotImplementedError()""" TEMPLATE_REDUCTION_SIGNATURE = ''' @@ -109,7 +109,7 @@ def {method}( *,{extra_kwargs} keep_attrs: bool | None = None, **kwargs: Any, - ) -> "{obj}": + ) -> {obj}: """ Reduce this {obj}'s data by applying ``{method}`` along some dimension(s). From 6889810ce1bdb363cb184a52f213859283bf4923 Mon Sep 17 00:00:00 2001 From: dcherian Date: Fri, 3 Jun 2022 13:04:13 -0600 Subject: [PATCH 21/21] update _reductions --- xarray/core/_reductions.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xarray/core/_reductions.py b/xarray/core/_reductions.py index dd2cf311079..d2aebd3efa7 100644 --- a/xarray/core/_reductions.py +++ b/xarray/core/_reductions.py @@ -96,7 +96,7 @@ def count( Dimensions: () Data variables: - da int32 5 + da int64 5 """ return self.reduce( duck_array_ops.count, @@ -4376,7 +4376,7 @@ def count( >>> da.groupby("labels").count() - array([1, 2, 2], dtype=int64) + array([1, 2, 2]) Coordinates: * labels (labels) object 'a' 'b' 'c' """ @@ -5450,7 +5450,7 @@ def count( >>> da.resample(time="3M").count() - array([1, 3, 1], dtype=int64) + array([1, 3, 1]) Coordinates: * time (time) datetime64[ns] 2001-01-31 2001-04-30 2001-07-31 """