diff --git a/xarray/tests/test_backends.py b/xarray/tests/test_backends.py index 4799b619efd..ea088b36a9a 100644 --- a/xarray/tests/test_backends.py +++ b/xarray/tests/test_backends.py @@ -1966,7 +1966,7 @@ def test_auto_chunk(self) -> None: assert v.chunks == original[k].chunks @requires_dask - @pytest.mark.filterwarnings("ignore:The specified Dask chunks separate") + @pytest.mark.filterwarnings("ignore:The specified chunks separate:UserWarning") def test_manual_chunk(self) -> None: original = create_test_data().chunk({"dim1": 3, "dim2": 4, "dim3": 3}) @@ -3086,8 +3086,9 @@ def create_store(self): def test_complex(self) -> None: expected = Dataset({"x": ("y", np.ones(5) + 1j * np.ones(5))}) save_kwargs = {"invalid_netcdf": True} - with self.roundtrip(expected, save_kwargs=save_kwargs) as actual: - assert_equal(expected, actual) + with pytest.warns(UserWarning, match="You are writing invalid netcdf features"): + with self.roundtrip(expected, save_kwargs=save_kwargs) as actual: + assert_equal(expected, actual) @pytest.mark.parametrize("invalid_netcdf", [None, False]) def test_complex_error(self, invalid_netcdf) -> None: @@ -3101,14 +3102,14 @@ def test_complex_error(self, invalid_netcdf) -> None: with self.roundtrip(expected, save_kwargs=save_kwargs) as actual: assert_equal(expected, actual) - @pytest.mark.filterwarnings("ignore:You are writing invalid netcdf features") def test_numpy_bool_(self) -> None: # h5netcdf loads booleans as numpy.bool_, this type needs to be supported # when writing invalid_netcdf datasets in order to support a roundtrip expected = Dataset({"x": ("y", np.ones(5), {"numpy_bool": np.bool_(True)})}) save_kwargs = {"invalid_netcdf": True} - with self.roundtrip(expected, save_kwargs=save_kwargs) as actual: - assert_identical(expected, actual) + with pytest.warns(UserWarning, match="You are writing invalid netcdf features"): + with self.roundtrip(expected, save_kwargs=save_kwargs) as actual: + assert_identical(expected, actual) def test_cross_engine_read_write_netcdf4(self) -> None: # Drop dim3, because its labels include strings. These appear to be @@ -5193,7 +5194,7 @@ def test_open_dataset_chunking_zarr(chunks, tmp_path: Path) -> None: @pytest.mark.parametrize( "chunks", ["auto", -1, {}, {"x": "auto"}, {"x": -1}, {"x": "auto", "y": -1}] ) -@pytest.mark.filterwarnings("ignore:The specified Dask chunks separate") +@pytest.mark.filterwarnings("ignore:The specified chunks separate") def test_chunking_consintency(chunks, tmp_path: Path) -> None: encoded_chunks: dict[str, Any] = {} dask_arr = da.from_array( diff --git a/xarray/tests/test_cftime_offsets.py b/xarray/tests/test_cftime_offsets.py index 24ffab305ad..5f13415d925 100644 --- a/xarray/tests/test_cftime_offsets.py +++ b/xarray/tests/test_cftime_offsets.py @@ -1,6 +1,7 @@ from __future__ import annotations from itertools import product +from typing import Callable, Literal import numpy as np import pandas as pd @@ -1215,7 +1216,7 @@ def test_cftime_range_name(): @pytest.mark.parametrize( - ("start", "end", "periods", "freq", "closed"), + ("start", "end", "periods", "freq", "inclusive"), [ (None, None, 5, "A", None), ("2000", None, None, "A", None), @@ -1226,9 +1227,22 @@ def test_cftime_range_name(): ("2000", "2001", 5, "A", None), ], ) -def test_invalid_cftime_range_inputs(start, end, periods, freq, closed): +def test_invalid_cftime_range_inputs( + start: str | None, + end: str | None, + periods: int | None, + freq: str | None, + inclusive: Literal["up", None], +) -> None: with pytest.raises(ValueError): - cftime_range(start, end, periods, freq, closed=closed) + cftime_range(start, end, periods, freq, inclusive=inclusive) # type: ignore[arg-type] + + +def test_invalid_cftime_arg() -> None: + with pytest.warns( + FutureWarning, match="Following pandas, the `closed` parameter is deprecated" + ): + cftime_range("2000", "2001", None, "A", closed="left") _CALENDAR_SPECIFIC_MONTH_END_TESTS = [ @@ -1246,7 +1260,9 @@ def test_invalid_cftime_range_inputs(start, end, periods, freq, closed): _CALENDAR_SPECIFIC_MONTH_END_TESTS, ids=_id_func, ) -def test_calendar_specific_month_end(freq, calendar, expected_month_day): +def test_calendar_specific_month_end( + freq: str, calendar: str, expected_month_day: list[tuple[int, int]] +) -> None: year = 2000 # Use a leap-year to highlight calendar differences result = cftime_range( start="2000-02", end="2001", freq=freq, calendar=calendar @@ -1273,26 +1289,28 @@ def test_calendar_specific_month_end(freq, calendar, expected_month_day): ("julian", "2001", "2002", 365), ], ) -def test_calendar_year_length(calendar, start, end, expected_number_of_days): - result = cftime_range(start, end, freq="D", closed="left", calendar=calendar) +def test_calendar_year_length( + calendar: str, start: str, end: str, expected_number_of_days: int +) -> None: + result = cftime_range(start, end, freq="D", inclusive="left", calendar=calendar) assert len(result) == expected_number_of_days @pytest.mark.parametrize("freq", ["A", "M", "D"]) -def test_dayofweek_after_cftime_range(freq): +def test_dayofweek_after_cftime_range(freq: str) -> None: result = cftime_range("2000-02-01", periods=3, freq=freq).dayofweek expected = pd.date_range("2000-02-01", periods=3, freq=freq).dayofweek np.testing.assert_array_equal(result, expected) @pytest.mark.parametrize("freq", ["A", "M", "D"]) -def test_dayofyear_after_cftime_range(freq): +def test_dayofyear_after_cftime_range(freq: str) -> None: result = cftime_range("2000-02-01", periods=3, freq=freq).dayofyear expected = pd.date_range("2000-02-01", periods=3, freq=freq).dayofyear np.testing.assert_array_equal(result, expected) -def test_cftime_range_standard_calendar_refers_to_gregorian(): +def test_cftime_range_standard_calendar_refers_to_gregorian() -> None: from cftime import DatetimeGregorian (result,) = cftime_range("2000", periods=1) @@ -1310,7 +1328,9 @@ def test_cftime_range_standard_calendar_refers_to_gregorian(): ("3400-01-01", "standard", None, CFTimeIndex), ], ) -def test_date_range(start, calendar, use_cftime, expected_type): +def test_date_range( + start: str, calendar: str, use_cftime: bool | None, expected_type +) -> None: dr = date_range( start, periods=14, freq="D", calendar=calendar, use_cftime=use_cftime ) @@ -1318,7 +1338,7 @@ def test_date_range(start, calendar, use_cftime, expected_type): assert isinstance(dr, expected_type) -def test_date_range_errors(): +def test_date_range_errors() -> None: with pytest.raises(ValueError, match="Date range is invalid"): date_range( "1400-01-01", periods=1, freq="D", calendar="standard", use_cftime=False @@ -1412,7 +1432,7 @@ def as_timedelta_not_implemented_error(): @pytest.mark.parametrize("function", [cftime_range, date_range]) -def test_cftime_or_date_range_closed_and_inclusive_error(function) -> None: +def test_cftime_or_date_range_closed_and_inclusive_error(function: Callable) -> None: if function == cftime_range and not has_cftime: pytest.skip("requires cftime") @@ -1421,22 +1441,29 @@ def test_cftime_or_date_range_closed_and_inclusive_error(function) -> None: @pytest.mark.parametrize("function", [cftime_range, date_range]) -def test_cftime_or_date_range_invalid_closed_value(function) -> None: +def test_cftime_or_date_range_invalid_inclusive_value(function: Callable) -> None: if function == cftime_range and not has_cftime: pytest.skip("requires cftime") - with pytest.raises(ValueError, match="Argument `closed` must be"): - function("2000", periods=3, closed="foo") + with pytest.raises(ValueError, match="nclusive"): + function("2000", periods=3, inclusive="foo") -@pytest.mark.parametrize("function", [cftime_range, date_range]) +@pytest.mark.parametrize( + "function", + [ + pytest.param(cftime_range, id="cftime", marks=requires_cftime), + pytest.param(date_range, id="date"), + ], +) @pytest.mark.parametrize( ("closed", "inclusive"), [(None, "both"), ("left", "left"), ("right", "right")] ) -def test_cftime_or_date_range_closed(function, closed, inclusive) -> None: - if function == cftime_range and not has_cftime: - pytest.skip("requires cftime") - +def test_cftime_or_date_range_closed( + function: Callable, + closed: Literal["left", "right", None], + inclusive: Literal["left", "right", "both"], +) -> None: with pytest.warns(FutureWarning, match="Following pandas"): result_closed = function("2000-01-01", "2000-01-04", freq="D", closed=closed) result_inclusive = function( diff --git a/xarray/tests/test_cftimeindex_resample.py b/xarray/tests/test_cftimeindex_resample.py index 07bc14f8983..72aaae595de 100644 --- a/xarray/tests/test_cftimeindex_resample.py +++ b/xarray/tests/test_cftimeindex_resample.py @@ -169,7 +169,7 @@ def test_closed_label_defaults(freq, expected) -> None: @pytest.mark.parametrize( "calendar", ["gregorian", "noleap", "all_leap", "360_day", "julian"] ) -def test_calendars(calendar) -> None: +def test_calendars(calendar: str) -> None: # Limited testing for non-standard calendars freq, closed, label, base = "8001T", None, None, 17 loffset = datetime.timedelta(hours=12) diff --git a/xarray/tests/test_concat.py b/xarray/tests/test_concat.py index 543b6d33cb9..e443631a148 100644 --- a/xarray/tests/test_concat.py +++ b/xarray/tests/test_concat.py @@ -9,6 +9,7 @@ from xarray import DataArray, Dataset, Variable, concat from xarray.core import dtypes, merge +from xarray.core.coordinates import Coordinates from xarray.core.indexes import PandasIndex from xarray.tests import ( InaccessibleArray, @@ -909,8 +910,9 @@ def test_concat_dim_is_dataarray(self) -> None: assert_identical(actual, expected) def test_concat_multiindex(self) -> None: - x = pd.MultiIndex.from_product([[1, 2, 3], ["a", "b"]]) - expected = Dataset(coords={"x": x}) + midx = pd.MultiIndex.from_product([[1, 2, 3], ["a", "b"]]) + midx_coords = Coordinates.from_pandas_multiindex(midx, "x") + expected = Dataset(coords=midx_coords) actual = concat( [expected.isel(x=slice(2)), expected.isel(x=slice(2, None))], "x" ) @@ -920,8 +922,9 @@ def test_concat_multiindex(self) -> None: def test_concat_along_new_dim_multiindex(self) -> None: # see https://github.com/pydata/xarray/issues/6881 level_names = ["x_level_0", "x_level_1"] - x = pd.MultiIndex.from_product([[1, 2, 3], ["a", "b"]], names=level_names) - ds = Dataset(coords={"x": x}) + midx = pd.MultiIndex.from_product([[1, 2, 3], ["a", "b"]], names=level_names) + midx_coords = Coordinates.from_pandas_multiindex(midx, "x") + ds = Dataset(coords=midx_coords) concatenated = concat([ds], "new") actual = list(concatenated.xindexes.get_all_coords("x")) expected = ["x"] + level_names diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index d794603b341..1513c6dba94 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -359,10 +359,11 @@ def test_repr_multiindex(self) -> None: assert expected == actual # verify that long level names are not truncated - mindex = pd.MultiIndex.from_product( + midx = pd.MultiIndex.from_product( [["a", "b"], [1, 2]], names=("a_quite_long_level_name", "level_2") ) - data = Dataset({}, {"x": mindex}) + midx_coords = Coordinates.from_pandas_multiindex(midx, "x") + data = Dataset({}, midx_coords) expected = dedent( """\ @@ -637,8 +638,12 @@ def test_constructor_with_coords(self) -> None: [["a", "b"], [1, 2]], names=("level_1", "level_2") ) with pytest.raises(ValueError, match=r"conflicting MultiIndex"): - Dataset({}, {"x": mindex, "y": mindex}) - Dataset({}, {"x": mindex, "level_1": range(4)}) + with pytest.warns( + FutureWarning, + match=".*`pandas.MultiIndex`.*no longer be implicitly promoted.*", + ): + Dataset({}, {"x": mindex, "y": mindex}) + Dataset({}, {"x": mindex, "level_1": range(4)}) def test_constructor_no_default_index(self) -> None: # explicitly passing a Coordinates object skips the creation of default index @@ -1615,9 +1620,11 @@ def test_sel_dataarray(self) -> None: def test_sel_dataarray_mindex(self) -> None: midx = pd.MultiIndex.from_product([list("abc"), [0, 1]], names=("one", "two")) + midx_coords = Coordinates.from_pandas_multiindex(midx, "x") + midx_coords["y"] = range(3) + mds = xr.Dataset( - {"var": (("x", "y"), np.random.rand(6, 3))}, - coords={"x": midx, "y": range(3)}, + {"var": (("x", "y"), np.random.rand(6, 3))}, coords=midx_coords ) actual_isel = mds.isel(x=xr.DataArray(np.arange(3), dims="x")) @@ -1735,7 +1742,8 @@ def test_sel_drop(self) -> None: def test_sel_drop_mindex(self) -> None: midx = pd.MultiIndex.from_arrays([["a", "a"], [1, 2]], names=("foo", "bar")) - data = Dataset(coords={"x": midx}) + midx_coords = Coordinates.from_pandas_multiindex(midx, "x") + data = Dataset(coords=midx_coords) actual = data.sel(foo="a", drop=True) assert "foo" not in actual.coords @@ -1956,10 +1964,11 @@ def test_loc(self) -> None: data.loc["a"] # type: ignore[index] def test_selection_multiindex(self) -> None: - mindex = pd.MultiIndex.from_product( + midx = 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}) + midx_coords = Coordinates.from_pandas_multiindex(midx, "x") + mdata = Dataset(data_vars={"var": ("x", range(8))}, coords=midx_coords) def test_sel( lab_indexer, pos_indexer, replaced_idx=False, renamed_dim=None @@ -2804,8 +2813,9 @@ def test_drop_indexes(self) -> None: assert_identical(actual, ds) # test index corrupted - mindex = pd.MultiIndex.from_tuples([([1, 2]), ([3, 4])], names=["a", "b"]) - ds = Dataset(coords={"x": mindex}) + midx = pd.MultiIndex.from_tuples([([1, 2]), ([3, 4])], names=["a", "b"]) + midx_coords = Coordinates.from_pandas_multiindex(midx, "x") + ds = Dataset(coords=midx_coords) with pytest.raises(ValueError, match=".*would corrupt the following index.*"): ds.drop_indexes("a") @@ -3090,9 +3100,13 @@ def test_rename_dimension_coord_warnings(self) -> None: ds.rename(x="y") def test_rename_multiindex(self) -> None: - mindex = pd.MultiIndex.from_tuples([([1, 2]), ([3, 4])], names=["a", "b"]) - original = Dataset({}, {"x": mindex}) - expected = Dataset({}, {"x": mindex.rename(["a", "c"])}) + midx = pd.MultiIndex.from_tuples([([1, 2]), ([3, 4])], names=["a", "b"]) + midx_coords = Coordinates.from_pandas_multiindex(midx, "x") + original = Dataset({}, midx_coords) + + midx_renamed = midx.rename(["a", "c"]) + midx_coords_renamed = Coordinates.from_pandas_multiindex(midx_renamed, "x") + expected = Dataset({}, midx_coords_renamed) actual = original.rename({"b": "c"}) assert_identical(expected, actual) @@ -3202,9 +3216,14 @@ def test_swap_dims(self) -> None: assert_identical(expected, actual) # handle multiindex case - idx = pd.MultiIndex.from_arrays([list("aab"), list("yzz")], names=["y1", "y2"]) - original = Dataset({"x": [1, 2, 3], "y": ("x", idx), "z": 42}) - expected = Dataset({"z": 42}, {"x": ("y", [1, 2, 3]), "y": idx}) + midx = pd.MultiIndex.from_arrays([list("aab"), list("yzz")], names=["y1", "y2"]) + + original = Dataset({"x": [1, 2, 3], "y": ("x", midx), "z": 42}) + + midx_coords = Coordinates.from_pandas_multiindex(midx, "y") + midx_coords["x"] = ("y", [1, 2, 3]) + expected = Dataset({"z": 42}, midx_coords) + actual = original.swap_dims({"x": "y"}) assert_identical(expected, actual) assert isinstance(actual.variables["y"], IndexVariable) @@ -3436,16 +3455,20 @@ def test_set_index_deindexed_coords(self) -> None: three = ["c", "c", "d", "d"] four = [3, 4, 3, 4] - mindex_12 = pd.MultiIndex.from_arrays([one, two], names=["one", "two"]) - mindex_34 = pd.MultiIndex.from_arrays([three, four], names=["three", "four"]) + midx_12 = pd.MultiIndex.from_arrays([one, two], names=["one", "two"]) + midx_34 = pd.MultiIndex.from_arrays([three, four], names=["three", "four"]) - ds = xr.Dataset( - coords={"x": mindex_12, "three": ("x", three), "four": ("x", four)} - ) + coords = Coordinates.from_pandas_multiindex(midx_12, "x") + coords["three"] = ("x", three) + coords["four"] = ("x", four) + ds = xr.Dataset(coords=coords) actual = ds.set_index(x=["three", "four"]) - expected = xr.Dataset( - coords={"x": mindex_34, "one": ("x", one), "two": ("x", two)} - ) + + coords_expected = Coordinates.from_pandas_multiindex(midx_34, "x") + coords_expected["one"] = ("x", one) + coords_expected["two"] = ("x", two) + expected = xr.Dataset(coords=coords_expected) + assert_identical(actual, expected) def test_reset_index(self) -> None: @@ -3476,7 +3499,7 @@ def test_reset_index_drop_dims(self) -> None: assert len(reset.dims) == 0 @pytest.mark.parametrize( - "arg,drop,dropped,converted,renamed", + ["arg", "drop", "dropped", "converted", "renamed"], [ ("foo", False, [], [], {"bar": "x"}), ("foo", True, ["foo"], [], {"bar": "x"}), @@ -3489,14 +3512,20 @@ def test_reset_index_drop_dims(self) -> None: ], ) def test_reset_index_drop_convert( - self, arg, drop, dropped, converted, renamed + self, + arg: str | list[str], + drop: bool, + dropped: list[str], + converted: list[str], + renamed: dict[str, str], ) -> None: # regressions https://github.com/pydata/xarray/issues/6946 and # https://github.com/pydata/xarray/issues/6989 # check that multi-index dimension or level coordinates are dropped, converted # from IndexVariable to Variable or renamed to dimension as expected midx = pd.MultiIndex.from_product([["a", "b"], [1, 2]], names=("foo", "bar")) - ds = xr.Dataset(coords={"x": midx}) + midx_coords = Coordinates.from_pandas_multiindex(midx, "x") + ds = xr.Dataset(coords=midx_coords) reset = ds.reset_index(arg, drop=drop) for name in dropped: @@ -3510,7 +3539,8 @@ def test_reorder_levels(self) -> None: ds = create_test_multiindex() mindex = ds["x"].to_index() midx = mindex.reorder_levels(["level_2", "level_1"]) - expected = Dataset({}, coords={"x": midx}) + midx_coords = Coordinates.from_pandas_multiindex(midx, "x") + expected = Dataset({}, coords=midx_coords) # check attrs propagated ds["level_1"].attrs["foo"] = "bar" @@ -3575,10 +3605,12 @@ def test_stack(self) -> None: coords={"x": ("x", [0, 1]), "y": ["a", "b"]}, ) - exp_index = pd.MultiIndex.from_product([[0, 1], ["a", "b"]], names=["x", "y"]) + midx_expected = pd.MultiIndex.from_product( + [[0, 1], ["a", "b"]], names=["x", "y"] + ) + midx_coords_expected = Coordinates.from_pandas_multiindex(midx_expected, "z") expected = Dataset( - data_vars={"b": ("z", [0, 1, 2, 3])}, - coords={"z": exp_index}, + data_vars={"b": ("z", [0, 1, 2, 3])}, coords=midx_coords_expected ) # check attrs propagated ds["x"].attrs["foo"] = "bar" @@ -3599,10 +3631,12 @@ def test_stack(self) -> None: actual = ds.stack(z=[..., "y"]) assert_identical(expected, actual) - exp_index = pd.MultiIndex.from_product([["a", "b"], [0, 1]], names=["y", "x"]) + midx_expected = pd.MultiIndex.from_product( + [["a", "b"], [0, 1]], names=["y", "x"] + ) + midx_coords_expected = Coordinates.from_pandas_multiindex(midx_expected, "z") expected = Dataset( - data_vars={"b": ("z", [0, 2, 1, 3])}, - coords={"z": exp_index}, + data_vars={"b": ("z", [0, 2, 1, 3])}, coords=midx_coords_expected ) expected["x"].attrs["foo"] = "bar" @@ -3633,9 +3667,11 @@ def test_stack_create_index(self, create_index, expected_keys) -> None: def test_stack_multi_index(self) -> None: # multi-index on a dimension to stack is discarded too midx = pd.MultiIndex.from_product([["a", "b"], [0, 1]], names=("lvl1", "lvl2")) + coords = Coordinates.from_pandas_multiindex(midx, "x") + coords["y"] = [0, 1] ds = xr.Dataset( data_vars={"b": (("x", "y"), [[0, 1], [2, 3], [4, 5], [6, 7]])}, - coords={"x": midx, "y": [0, 1]}, + coords=coords, ) expected = Dataset( data_vars={"b": ("z", [0, 1, 2, 3, 4, 5, 6, 7])}, @@ -3660,10 +3696,8 @@ def test_stack_non_dim_coords(self) -> None: ).rename_vars(x="xx") exp_index = pd.MultiIndex.from_product([[0, 1], ["a", "b"]], names=["xx", "y"]) - expected = Dataset( - data_vars={"b": ("z", [0, 1, 2, 3])}, - coords={"z": exp_index}, - ) + exp_coords = Coordinates.from_pandas_multiindex(exp_index, "z") + expected = Dataset(data_vars={"b": ("z", [0, 1, 2, 3])}, coords=exp_coords) actual = ds.stack(z=["x", "y"]) assert_identical(expected, actual) @@ -3671,7 +3705,8 @@ def test_stack_non_dim_coords(self) -> None: 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}) + coords = Coordinates.from_pandas_multiindex(index, "z") + ds = Dataset(data_vars={"b": ("z", [0, 1, 2, 3])}, coords=coords) expected = Dataset( {"b": (("x", "y"), [[0, 1], [2, 3]]), "x": [0, 1], "y": ["a", "b"]} ) @@ -3736,12 +3771,12 @@ def test_unstack_sparse(self) -> None: 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"] - ) + midx = pd.MultiIndex.from_arrays([np.arange(3), np.arange(3)], names=["a", "b"]) + coords = Coordinates.from_pandas_multiindex(midx, "z") + coords["foo"] = np.arange(4) + coords["bar"] = np.arange(5) ds_eye = Dataset( - {"var": (("z", "foo", "bar"), np.ones((3, 4, 5)))}, - coords={"z": mindex, "foo": np.arange(4), "bar": np.arange(5)}, + {"var": (("z", "foo", "bar"), np.ones((3, 4, 5)))}, coords=coords ) actual3 = ds_eye.unstack(sparse=True, fill_value=0) assert isinstance(actual3["var"].data, sparse_array_type) diff --git a/xarray/tests/test_formatting_html.py b/xarray/tests/test_formatting_html.py index 7ea5c19019b..6540406e914 100644 --- a/xarray/tests/test_formatting_html.py +++ b/xarray/tests/test_formatting_html.py @@ -6,29 +6,31 @@ import xarray as xr from xarray.core import formatting_html as fh +from xarray.core.coordinates import Coordinates @pytest.fixture -def dataarray(): +def dataarray() -> xr.DataArray: return xr.DataArray(np.random.RandomState(0).randn(4, 6)) @pytest.fixture -def dask_dataarray(dataarray): +def dask_dataarray(dataarray: xr.DataArray) -> xr.DataArray: pytest.importorskip("dask") return dataarray.chunk() @pytest.fixture -def multiindex(): - mindex = pd.MultiIndex.from_product( +def multiindex() -> xr.Dataset: + midx = pd.MultiIndex.from_product( [["a", "b"], [1, 2]], names=("level_1", "level_2") ) - return xr.Dataset({}, {"x": mindex}) + midx_coords = Coordinates.from_pandas_multiindex(midx, "x") + return xr.Dataset({}, midx_coords) @pytest.fixture -def dataset(): +def dataset() -> xr.Dataset: times = pd.date_range("2000-01-01", "2001-12-31", name="time") annual_cycle = np.sin(2 * np.pi * (times.dayofyear.values / 365.25 - 0.28)) @@ -46,17 +48,17 @@ def dataset(): ) -def test_short_data_repr_html(dataarray) -> None: +def test_short_data_repr_html(dataarray: xr.DataArray) -> None: data_repr = fh.short_data_repr_html(dataarray) assert data_repr.startswith("
array")
 
 
-def test_short_data_repr_html_non_str_keys(dataset) -> None:
+def test_short_data_repr_html_non_str_keys(dataset: xr.Dataset) -> None:
     ds = dataset.assign({2: lambda x: x["tmin"]})
     fh.dataset_repr(ds)
 
 
-def test_short_data_repr_html_dask(dask_dataarray) -> None:
+def test_short_data_repr_html_dask(dask_dataarray: xr.DataArray) -> None:
     assert hasattr(dask_dataarray.data, "_repr_html_")
     data_repr = fh.short_data_repr_html(dask_dataarray)
     assert data_repr == dask_dataarray.data._repr_html_()
@@ -97,7 +99,7 @@ def test_summarize_attrs_with_unsafe_attr_name_and_value() -> None:
     assert "
<pd.DataFrame>
" in formatted -def test_repr_of_dataarray(dataarray) -> None: +def test_repr_of_dataarray(dataarray: xr.DataArray) -> None: formatted = fh.array_repr(dataarray) assert "dim_0" in formatted # has an expanded data section @@ -119,12 +121,12 @@ def test_repr_of_dataarray(dataarray) -> None: ) -def test_repr_of_multiindex(multiindex) -> None: +def test_repr_of_multiindex(multiindex: xr.Dataset) -> None: formatted = fh.dataset_repr(multiindex) assert "(x)" in formatted -def test_repr_of_dataset(dataset) -> None: +def test_repr_of_dataset(dataset: xr.Dataset) -> None: formatted = fh.dataset_repr(dataset) # coords, attrs, and data_vars are expanded assert ( @@ -151,7 +153,7 @@ def test_repr_of_dataset(dataset) -> None: assert "<IA>" in formatted -def test_repr_text_fallback(dataset) -> None: +def test_repr_text_fallback(dataset: xr.Dataset) -> None: formatted = fh.dataset_repr(dataset) # Just test that the "pre" block used for fallback to plain text is present. @@ -170,7 +172,7 @@ def test_variable_repr_html() -> None: assert "xarray.Variable" in html -def test_repr_of_nonstr_dataset(dataset) -> None: +def test_repr_of_nonstr_dataset(dataset: xr.Dataset) -> None: ds = dataset.copy() ds.attrs[1] = "Test value" ds[2] = ds["tmin"] @@ -179,7 +181,7 @@ def test_repr_of_nonstr_dataset(dataset) -> None: assert "
2" in formatted -def test_repr_of_nonstr_dataarray(dataarray) -> None: +def test_repr_of_nonstr_dataarray(dataarray: xr.DataArray) -> None: da = dataarray.rename(dim_0=15) da.attrs[1] = "value" formatted = fh.array_repr(da)