diff --git a/.github/ci/min_deps_check.py b/.github/ci/min_deps_check.py index ea23ba657f..3a353e724e 100644 --- a/.github/ci/min_deps_check.py +++ b/.github/ci/min_deps_check.py @@ -193,7 +193,7 @@ def main() -> None: print("\nErrors:") print("-------") for i, e in enumerate(errors): - print(f"{i+1}. {e}") + print(f"{i + 1}. {e}") sys.exit(1) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index db5b67a442..ee15347d81 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,7 +10,7 @@ repos: types: [text] files: \.(json|ipynb)$ - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.6 + rev: v0.12.5 hooks: - id: ruff name: ruff lint (.py) @@ -23,13 +23,13 @@ repos: - id: ruff-format types_or: [python, jupyter] - repo: https://github.com/rbubley/mirrors-prettier # Update mirror as official mirror is deprecated - rev: v3.4.2 + rev: v3.6.2 hooks: - id: prettier # Ruff doesn't have full coverage of pydoclint https://github.com/astral-sh/ruff/issues/12434 - repo: https://github.com/PyCQA/flake8 - rev: 7.1.1 + rev: 7.3.0 hooks: - id: flake8 name: pydoclint diff --git a/docs/examples/tutorial_nemo_3D.ipynb b/docs/examples/tutorial_nemo_3D.ipynb index a26ddf1678..a31cab2696 100644 --- a/docs/examples/tutorial_nemo_3D.ipynb +++ b/docs/examples/tutorial_nemo_3D.ipynb @@ -121,7 +121,7 @@ "print(\n", " f\"Level[{int(depth_level)}] depth is: \"\n", " f\"[{fieldset.W.grid.depth[depth_level]:g} \"\n", - " f\"{fieldset.W.grid.depth[depth_level+1]:g}]\"\n", + " f\"{fieldset.W.grid.depth[depth_level + 1]:g}]\"\n", ")\n", "\n", "plt.pcolormesh(\n", diff --git a/docs/examples/tutorial_peninsula_AvsCgrid.ipynb b/docs/examples/tutorial_peninsula_AvsCgrid.ipynb index e63724b15d..71a2a55e93 100644 --- a/docs/examples/tutorial_peninsula_AvsCgrid.ipynb +++ b/docs/examples/tutorial_peninsula_AvsCgrid.ipynb @@ -242,7 +242,7 @@ " # Set the same limits for all subplots\n", " ax.set_xlim([fieldset.U.lon.min(), fieldset.U.lon.max()])\n", " ax.set_ylim([0, 23e3])\n", - " m2km = lambda x, _: f\"{x/1000:.1f}\"\n", + " m2km = lambda x, _: f\"{x / 1000:.1f}\"\n", " ax.xaxis.set_major_formatter(m2km)\n", " ax.yaxis.set_major_formatter(m2km)\n", " ax.set_xlabel(\"x [km]\")\n", @@ -306,7 +306,7 @@ "ax.set_ylim([0, 23e3])\n", "ax.set_ylabel(\"y [km]\")\n", "ax.set_xlabel(\"x [km]\")\n", - "m2km = lambda x, _: f\"{x/1000:.1f}\"\n", + "m2km = lambda x, _: f\"{x / 1000:.1f}\"\n", "ax.xaxis.set_major_formatter(m2km)\n", "ax.yaxis.set_major_formatter(m2km)\n", "\n", diff --git a/docs/v4/api.md b/docs/v4/api.md index a30ed3e881..a7a9252863 100644 --- a/docs/v4/api.md +++ b/docs/v4/api.md @@ -35,7 +35,6 @@ classDiagram Here, important things to note are: - Interpolators (which would implement the `Interpolator` protocol) are responsible for the actual interpolation of the data, and performance considerations. There will be interpolation and indexing utilities that can be made available to the interpolators, allowing for code re-use. - - Interpolators of the data should handle spatial periodicity and, for the case of rectilinear structured grids, without pre-computing a halo for the FieldSet and Grid ([issue](https://github.com/OceanParcels/Parcels/issues/1898)). - In the `Field` class, not all combinations of `data`, `grid`, and `interpolator` will logically make sense (e.g., a `xr.DataArray` on a `ux.Grid`, or `ux.DataArray` on a `parcels.Grid`). It's up to the `Interpolator.assert_is_compatible(Field)` to define what is and is not compatible, and raise `ValueError` / `TypeError` on incompatible data types. The `.assert_is_compatible()` method also acts as developer documentation, defining clearly for the `.interpolate()` method what assumptions it is working on. The `.assert_is_compatible()` method should be lightweight as it will be called on `Field` initialisation. diff --git a/parcels/interaction/interactionkernel.py b/parcels/interaction/interactionkernel.py index 16d95fd8f8..fa8682f00c 100644 --- a/parcels/interaction/interactionkernel.py +++ b/parcels/interaction/interactionkernel.py @@ -74,9 +74,9 @@ def __init__( numkernelargs = self.check_kernel_signature_on_version() - assert numkernelargs[0] == 5 and numkernelargs.count(numkernelargs[0]) == len( - numkernelargs - ), "Interactionkernels take exactly 5 arguments: particle, fieldset, time, neighbors, mutator" + assert numkernelargs[0] == 5 and numkernelargs.count(numkernelargs[0]) == len(numkernelargs), ( + "Interactionkernels take exactly 5 arguments: particle, fieldset, time, neighbors, mutator" + ) def check_fieldsets_in_kernels(self, pyfunc): # Currently, the implemented interaction kernels do not impose diff --git a/parcels/particleset.py b/parcels/particleset.py index 8448a4b2d8..1776efdb06 100644 --- a/parcels/particleset.py +++ b/parcels/particleset.py @@ -133,9 +133,9 @@ def __init__( for kwvar in kwargs: if kwvar not in ["partition_function"]: kwargs[kwvar] = convert_to_flat_array(kwargs[kwvar]) - assert ( - lon.size == kwargs[kwvar].size - ), f"{kwvar} and positions (lon, lat, depth) don't have the same lengths." + assert lon.size == kwargs[kwvar].size, ( + f"{kwvar} and positions (lon, lat, depth) don't have the same lengths." + ) self._data = { "lon": lon.astype(lonlatdepth_dtype), @@ -233,9 +233,9 @@ def add(self, particles): The current ParticleSet """ - assert ( - particles is not None - ), f"Trying to add another {type(self)} to this one, but the other one is None - invalid operation." + assert particles is not None, ( + f"Trying to add another {type(self)} to this one, but the other one is None - invalid operation." + ) assert type(particles) is type(self) if len(particles) == 0: diff --git a/parcels/tools/timer.py b/parcels/tools/timer.py index cd6725fb2f..ea1181a448 100644 --- a/parcels/tools/timer.py +++ b/parcels/tools/timer.py @@ -48,7 +48,7 @@ def print_tree_sequential(self, step=0, root_time=0, parent_time=0): if step > 0: print(f"({round(time / parent_time * 100):3d}%) ", end="") t_str = f"{time:1.3e} s" if root_time < 300 else datetime.timedelta(seconds=time) - print(f"Timer {(self._name).ljust(20 - 2*step + 7*(step == 0))}: {t_str}") + print(f"Timer {(self._name).ljust(20 - 2 * step + 7 * (step == 0))}: {t_str}") for child in self._children: child.print_tree_sequential(step + 1, root_time, time) diff --git a/parcels/xgcm/grid.py b/parcels/xgcm/grid.py index 622b7c2305..8495e08773 100644 --- a/parcels/xgcm/grid.py +++ b/parcels/xgcm/grid.py @@ -516,8 +516,7 @@ def check_neighbor(link, position): neighbor_link = face_links[idx][ax][correct_position] except (KeyError, IndexError): raise KeyError( - f"Couldn't find a face link for face {idx!r}" - f"in axis {ax!r} at position {correct_position!r}" + f"Couldn't find a face link for face {idx!r}in axis {ax!r} at position {correct_position!r}" ) idx_n, ax_n, rev_n = neighbor_link if ax not in self.axes: diff --git a/pyproject.toml b/pyproject.toml index 318f5851fb..1f60175e78 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -169,6 +169,7 @@ ignore = [ "RUF015", # Use `X | Y` in `isinstance` (see https://github.com/home-assistant/core/issues/123850) "UP038", + "RUF046", # Value being cast to `int` is already an integer # TODO: ignore for now (requires more work). Remove ignore once fixed # Missing docstring in public module