From beaa3e864d6005f419ad1d0adb9069ebbdb5db93 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sun, 24 Nov 2024 18:30:43 +0100 Subject: [PATCH 1/5] Get rid of deprecated rules removed from ruff 0.8.0 https://astral.sh/blog/ruff-v0.8.0#removal-of-six-deprecated-rules --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index dab280f0eba..0051ff3f48d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -256,7 +256,6 @@ ignore = [ "E501", # line too long - let the formatter worry about that "E731", # do not assign a lambda expression, use a def "UP007", # use X | Y for type annotations - "UP027", # deprecated "C40", # unnecessary generator, comprehension, or literal "PIE790", # unnecessary pass statement "PERF203", # try-except within a loop incurs performance overhead From 70d2c7b1a7aa999beafc89c6c6180be2c195ef0c Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sun, 24 Nov 2024 18:37:25 +0100 Subject: [PATCH 2/5] Apply new ruff rule RUF021 RUF021 Parenthesize `a and b` expressions when chaining `and` and `or` together, to make the precedence clear --- xarray/coding/cftime_offsets.py | 3 +-- xarray/conventions.py | 7 ++----- xarray/core/dataset.py | 6 ++---- xarray/plot/utils.py | 3 +-- xarray/testing/assertions.py | 8 ++++---- xarray/tests/test_backends.py | 3 +-- 6 files changed, 11 insertions(+), 19 deletions(-) diff --git a/xarray/coding/cftime_offsets.py b/xarray/coding/cftime_offsets.py index 9677a406471..a994eb9661f 100644 --- a/xarray/coding/cftime_offsets.py +++ b/xarray/coding/cftime_offsets.py @@ -1451,8 +1451,7 @@ def date_range_like(source, calendar, use_cftime=None): from xarray.core.dataarray import DataArray if not isinstance(source, pd.DatetimeIndex | CFTimeIndex) and ( - isinstance(source, DataArray) - and (source.ndim != 1) + (isinstance(source, DataArray) and (source.ndim != 1)) or not _contains_datetime_like_objects(source.variable) ): raise ValueError( diff --git a/xarray/conventions.py b/xarray/conventions.py index e4e71a481e8..5b57c160850 100644 --- a/xarray/conventions.py +++ b/xarray/conventions.py @@ -726,11 +726,8 @@ def _encode_coordinates( ) # if coordinates set to None, don't write coordinates attribute - if ( - "coordinates" in attrs - and attrs.get("coordinates") is None - or "coordinates" in encoding - and encoding.get("coordinates") is None + if ("coordinates" in attrs and attrs.get("coordinates") is None) or ( + "coordinates" in encoding and encoding.get("coordinates") is None ): # make sure "coordinates" is removed from attrs/encoding attrs.pop("coordinates", None) diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index e80ce5fa64a..d521db52b6e 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -5401,11 +5401,9 @@ def _get_stack_index( and var.dims[0] == dim and ( # stack: must be a single coordinate index - not multi - and not self.xindexes.is_multi(name) + (not multi and not self.xindexes.is_multi(name)) # unstack: must be an index that implements .unstack - or multi - and type(index).unstack is not Index.unstack + or (multi and type(index).unstack is not Index.unstack) ) ): if stack_index is not None and index is not stack_index: diff --git a/xarray/plot/utils.py b/xarray/plot/utils.py index 717adc41ffd..4f079eb4ac2 100644 --- a/xarray/plot/utils.py +++ b/xarray/plot/utils.py @@ -1708,8 +1708,7 @@ def _determine_guide( if ( not add_colorbar and (hueplt_norm.data is not None and hueplt_norm.data_is_numeric is False) - or sizeplt_norm.data is not None - ): + ) or sizeplt_norm.data is not None: add_legend = True else: add_legend = False diff --git a/xarray/testing/assertions.py b/xarray/testing/assertions.py index d2b01677ce4..026fff6ffba 100644 --- a/xarray/testing/assertions.py +++ b/xarray/testing/assertions.py @@ -124,8 +124,8 @@ def assert_equal(a, b, check_dim_order: bool = True): numpy.testing.assert_array_equal """ __tracebackhide__ = True - assert ( - type(a) is type(b) or isinstance(a, Coordinates) and isinstance(b, Coordinates) + assert type(a) is type(b) or ( + isinstance(a, Coordinates) and isinstance(b, Coordinates) ) b = maybe_transpose_dims(a, b, check_dim_order) if isinstance(a, Variable | DataArray): @@ -163,8 +163,8 @@ def assert_identical(a, b): assert_equal, assert_allclose, Dataset.equals, DataArray.equals """ __tracebackhide__ = True - assert ( - type(a) is type(b) or isinstance(a, Coordinates) and isinstance(b, Coordinates) + assert type(a) is type(b) or ( + isinstance(a, Coordinates) and isinstance(b, Coordinates) ) if isinstance(a, Variable): assert a.identical(b), formatting.diff_array_repr(a, b, "identical") diff --git a/xarray/tests/test_backends.py b/xarray/tests/test_backends.py index 3ca7c08eb2f..8cb26f8482c 100644 --- a/xarray/tests/test_backends.py +++ b/xarray/tests/test_backends.py @@ -963,8 +963,7 @@ def test_roundtrip_mask_and_scale(self, decoded_fn, encoded_fn, dtype) -> None: decoded = decoded_fn(dtype) encoded = encoded_fn(dtype) if decoded["x"].encoding["dtype"] == "u1" and not ( - self.engine == "netcdf4" - and self.file_format is None + (self.engine == "netcdf4" and self.file_format is None) or self.file_format == "NETCDF4" ): pytest.skip("uint8 data can't be written to non-NetCDF4 data") From 39984fec5325a67ac32bcf8edb1d132c62d58642 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sun, 24 Nov 2024 18:39:54 +0100 Subject: [PATCH 3/5] Apply new ruff rule RUF022 RUF022 `__all__` is not sorted --- xarray/__init__.py | 6 ++-- xarray/ufuncs.py | 82 +++++++++++++++++++++++----------------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/xarray/__init__.py b/xarray/__init__.py index 634f67a61a2..622c927b468 100644 --- a/xarray/__init__.py +++ b/xarray/__init__.py @@ -64,7 +64,7 @@ # A hardcoded __all__ variable is necessary to appease # `mypy --strict` running in projects that import xarray. -__all__ = ( +__all__ = ( # noqa: RUF022 # Sub-packages "groupers", "testing", @@ -117,8 +117,8 @@ "Context", "Coordinates", "DataArray", - "Dataset", "DataTree", + "Dataset", "Index", "IndexSelResult", "IndexVariable", @@ -131,6 +131,6 @@ "SerializationWarning", "TreeIsomorphismError", # Constants - "__version__", "ALL_DIMS", + "__version__", ) diff --git a/xarray/ufuncs.py b/xarray/ufuncs.py index cedece4c68f..e25657216fd 100644 --- a/xarray/ufuncs.py +++ b/xarray/ufuncs.py @@ -247,70 +247,45 @@ def _dedent(doc): "absolute", "acos", "acosh", + "add", + "angle", "arccos", "arccosh", "arcsin", "arcsinh", "arctan", + "arctan2", "arctanh", "asin", "asinh", "atan", + "atan2", "atanh", + "bitwise_and", "bitwise_count", "bitwise_invert", + "bitwise_left_shift", "bitwise_not", + "bitwise_or", + "bitwise_right_shift", + "bitwise_xor", "cbrt", "ceil", "conj", "conjugate", + "copysign", "cos", "cosh", "deg2rad", "degrees", + "divide", + "equal", "exp", "exp2", "expm1", "fabs", - "floor", - "invert", - "isfinite", - "isinf", - "isnan", - "isnat", - "log", - "log10", - "log1p", - "log2", - "logical_not", - "negative", - "positive", - "rad2deg", - "radians", - "reciprocal", - "rint", - "sign", - "signbit", - "sin", - "sinh", - "spacing", - "sqrt", - "square", - "tan", - "tanh", - "trunc", - "add", - "arctan2", - "atan2", - "bitwise_and", - "bitwise_left_shift", - "bitwise_or", - "bitwise_right_shift", - "bitwise_xor", - "copysign", - "divide", - "equal", "float_power", + "floor", "floor_divide", "fmax", "fmin", @@ -320,29 +295,54 @@ def _dedent(doc): "greater_equal", "heaviside", "hypot", + "invert", + "iscomplex", + "isfinite", + "isinf", + "isnan", + "isnat", + "isreal", "lcm", "ldexp", "left_shift", "less", "less_equal", + "log", + "log1p", + "log2", + "log10", "logaddexp", "logaddexp2", "logical_and", + "logical_not", "logical_or", "logical_xor", "maximum", "minimum", "mod", "multiply", + "negative", "nextafter", "not_equal", + "positive", "pow", "power", + "rad2deg", + "radians", + "reciprocal", "remainder", "right_shift", + "rint", + "sign", + "signbit", + "sin", + "sinh", + "spacing", + "sqrt", + "square", "subtract", + "tan", + "tanh", "true_divide", - "angle", - "isreal", - "iscomplex", + "trunc", ] From e021453f1257ad3d1a2817c61542f12057d9b7ed Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sun, 24 Nov 2024 18:56:24 +0100 Subject: [PATCH 4/5] Apply ruff/pyupgrade rule UP031 UP031 Use format specifiers instead of percent format --- asv_bench/benchmarks/dataset_io.py | 2 +- xarray/core/dataset.py | 2 +- xarray/plot/utils.py | 4 ++-- xarray/tests/__init__.py | 3 +-- xarray/tests/test_dataset.py | 5 ++--- xarray/tests/test_formatting.py | 14 ++++++-------- 6 files changed, 13 insertions(+), 17 deletions(-) diff --git a/asv_bench/benchmarks/dataset_io.py b/asv_bench/benchmarks/dataset_io.py index 3a09288c8dc..f1296a8b44f 100644 --- a/asv_bench/benchmarks/dataset_io.py +++ b/asv_bench/benchmarks/dataset_io.py @@ -305,7 +305,7 @@ def make_ds(self, nfiles=10): ds.attrs = {"history": "created for xarray benchmarking"} self.ds_list.append(ds) - self.filenames_list.append("test_netcdf_%i.nc" % i) + self.filenames_list.append(f"test_netcdf_{i}.nc") class IOWriteMultipleNetCDF3(IOMultipleNetCDF): diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index d521db52b6e..ee6d272ad66 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -7615,7 +7615,7 @@ def from_dataframe(cls, dataframe: pd.DataFrame, sparse: bool = False) -> Self: if isinstance(idx, pd.MultiIndex): dims = tuple( - name if name is not None else "level_%i" % n # type: ignore[redundant-expr] + name if name is not None else f"level_{n}" # type: ignore[redundant-expr] for n, name in enumerate(idx.names) ) for dim, lev in zip(dims, idx.levels, strict=True): diff --git a/xarray/plot/utils.py b/xarray/plot/utils.py index 4f079eb4ac2..c1b5b29c7bf 100644 --- a/xarray/plot/utils.py +++ b/xarray/plot/utils.py @@ -869,11 +869,11 @@ def _infer_interval_breaks(coord, axis=0, scale=None, check_monotonic=False): if check_monotonic and not _is_monotonic(coord, axis=axis): raise ValueError( "The input coordinate is not sorted in increasing " - "order along axis %d. This can lead to unexpected " + f"order along axis {axis}. This can lead to unexpected " "results. Consider calling the `sortby` method on " "the input DataArray. To plot data with categorical " "axes, consider using the `heatmap` function from " - "the `seaborn` statistical plotting library." % axis + "the `seaborn` statistical plotting library." ) # If logscale, compute the intervals in the logarithmic space diff --git a/xarray/tests/__init__.py b/xarray/tests/__init__.py index 442a0e51398..3aafbfcb0c1 100644 --- a/xarray/tests/__init__.py +++ b/xarray/tests/__init__.py @@ -210,8 +210,7 @@ def __call__(self, dsk, keys, **kwargs): self.total_computes += 1 if self.total_computes > self.max_computes: raise RuntimeError( - "Too many computes. Total: %d > max: %d." - % (self.total_computes, self.max_computes) + f"Too many computes. Total: {self.total_computes} > max: {self.max_computes}." ) return dask.get(dsk, keys, **kwargs) diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index 67d38aac0fe..d9c5aac57ab 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -388,16 +388,15 @@ def test_unicode_data(self) -> None: byteorder = "<" if sys.byteorder == "little" else ">" expected = dedent( - """\ + f"""\ Size: 12B Dimensions: (foø: 1) Coordinates: - * foø (foø) %cU3 12B %r + * foø (foø) {byteorder}U3 12B {'ba®'!r} Data variables: *empty* Attributes: å: ∑""" - % (byteorder, "ba®") ) actual = str(data) assert expected == actual diff --git a/xarray/tests/test_formatting.py b/xarray/tests/test_formatting.py index c7af13415c0..946d491bd61 100644 --- a/xarray/tests/test_formatting.py +++ b/xarray/tests/test_formatting.py @@ -295,7 +295,7 @@ def test_diff_array_repr(self) -> None: byteorder = "<" if sys.byteorder == "little" else ">" expected = dedent( - """\ + f"""\ Left and right DataArray objects are not identical Differing dimensions: (x: 2, y: 3) != (x: 2) @@ -306,8 +306,8 @@ def test_diff_array_repr(self) -> None: R array([1, 2], dtype=int64) Differing coordinates: - L * x (x) %cU1 8B 'a' 'b' - R * x (x) %cU1 8B 'a' 'c' + L * x (x) {byteorder}U1 8B 'a' 'b' + R * x (x) {byteorder}U1 8B 'a' 'c' Coordinates only on the left object: * y (y) int64 24B 1 2 3 Coordinates only on the right object: @@ -317,7 +317,6 @@ def test_diff_array_repr(self) -> None: R units: kg Attributes only on the left object: description: desc""" - % (byteorder, byteorder) ) actual = formatting.diff_array_repr(da_a, da_b, "identical") @@ -496,15 +495,15 @@ def test_diff_dataset_repr(self) -> None: byteorder = "<" if sys.byteorder == "little" else ">" expected = dedent( - """\ + f"""\ Left and right Dataset objects are not identical Differing dimensions: (x: 2, y: 3) != (x: 2) Differing coordinates: - L * x (x) %cU1 8B 'a' 'b' + L * x (x) {byteorder}U1 8B 'a' 'b' Differing variable attributes: foo: bar - R * x (x) %cU1 8B 'a' 'c' + R * x (x) {byteorder}U1 8B 'a' 'c' Differing variable attributes: source: 0 foo: baz @@ -522,7 +521,6 @@ def test_diff_dataset_repr(self) -> None: R title: newtitle Attributes only on the left object: description: desc""" - % (byteorder, byteorder) ) actual = formatting.diff_dataset_repr(ds_a, ds_b, "identical") From 49972189d2a7727be2e6e8136e6942ea2471b803 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sun, 24 Nov 2024 19:14:03 +0100 Subject: [PATCH 5/5] Bump ruff version in pre-commit --- .pre-commit-config.yaml | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e2bffbfefde..d543a36edd3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: - id: text-unicode-replacement-char - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.7.2 + rev: v0.8.0 hooks: - id: ruff-format - id: ruff diff --git a/pyproject.toml b/pyproject.toml index 0051ff3f48d..3ac1a024195 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,7 @@ dev = [ "pytest-env", "pytest-xdist", "pytest-timeout", - "ruff", + "ruff>=0.8.0", "sphinx", "sphinx_autosummary_accessors", "xarray[complete]",