From b9d59821339b1fc29efc1ed12eccf797ce786254 Mon Sep 17 00:00:00 2001 From: Patrick Peglar Date: Mon, 11 Aug 2025 15:38:33 +0100 Subject: [PATCH 1/9] WIP --- lib/ncdata/utils/_rename_dim.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 lib/ncdata/utils/_rename_dim.py diff --git a/lib/ncdata/utils/_rename_dim.py b/lib/ncdata/utils/_rename_dim.py new file mode 100644 index 00000000..7d92e704 --- /dev/null +++ b/lib/ncdata/utils/_rename_dim.py @@ -0,0 +1,32 @@ +"""Utility to rename dimensions.""" +from ncdata import NcData + +def rename_dimension(ncdata: ncdata, name_from: str, name_to: str): + """ + Rename a dimension of an :class:`NcData`. + + This includes replacing the name on all contained variables which reference it, including those in sub-groups. + + Parameters + ---------- + ncdata : NcData + data with a top-level dimension to rename. + + name_from: str + existing name of dimension to rename. + + name_to: str + new name of dimension. + + Notes + ----- + * operation is in-place. To produce a new :class:`NcData` with renamed dimension, use :meth:`Ncdata.copy` first. + * unlike a simple :class:`~ncdata.NameMap.rename`, this checks whether a dimension of the new name already exists, + and if so will raise an error. + """ + if name_to in ncdata.dimensions: + msg = ( + f"Cannot rename dimension {name_from!s} to {name_to!s} to, " + f"because a {name_to!s} dimension aready exists." + ) + raise ValueError(msg) From 71d8eb80ee82a8c659ae9b64c88c8f996749cf05 Mon Sep 17 00:00:00 2001 From: Patrick Peglar Date: Mon, 11 Aug 2025 16:14:25 +0100 Subject: [PATCH 2/9] Added rename_dimension utility, and tests. --- lib/ncdata/utils/__init__.py | 2 + lib/ncdata/utils/_rename_dim.py | 26 ++++++++- tests/unit/utils/test_ncdata_copy.py | 2 +- tests/unit/utils/test_rename_dimension.py | 67 +++++++++++++++++++++++ 4 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 tests/unit/utils/test_rename_dimension.py diff --git a/lib/ncdata/utils/__init__.py b/lib/ncdata/utils/__init__.py index c2e0b445..a91e9e34 100644 --- a/lib/ncdata/utils/__init__.py +++ b/lib/ncdata/utils/__init__.py @@ -2,11 +2,13 @@ from ._compare_nc_datasets import dataset_differences, variable_differences from ._copy import ncdata_copy +from ._rename_dim import rename_dimension from ._save_errors import save_errors __all__ = [ "dataset_differences", "ncdata_copy", + "rename_dimension", "save_errors", "variable_differences", ] diff --git a/lib/ncdata/utils/_rename_dim.py b/lib/ncdata/utils/_rename_dim.py index 7d92e704..829d7aeb 100644 --- a/lib/ncdata/utils/_rename_dim.py +++ b/lib/ncdata/utils/_rename_dim.py @@ -1,7 +1,25 @@ """Utility to rename dimensions.""" from ncdata import NcData -def rename_dimension(ncdata: ncdata, name_from: str, name_to: str): + +def _rename_dims_in_vars(ncdata: NcData, name_from: str, name_to: str) -> None: + """Rename a dimension in all contained variables which reference it.""" + for var in ncdata.variables.values(): + if name_from in var.dimensions: + var.dimensions = tuple( + [ + name_to if name == name_from else name + for name in var.dimensions + ] + ) + + # Also rename in all sub-groups, expect where the dimension is redefined ("scope hole"). + for grp in ncdata.groups.values(): + if name_from not in grp.dimensions: + _rename_dims_in_vars(grp, name_from, name_to) + + +def rename_dimension(ncdata: NcData, name_from: str, name_to: str) -> None: """ Rename a dimension of an :class:`NcData`. @@ -26,7 +44,9 @@ def rename_dimension(ncdata: ncdata, name_from: str, name_to: str): """ if name_to in ncdata.dimensions: msg = ( - f"Cannot rename dimension {name_from!s} to {name_to!s} to, " - f"because a {name_to!s} dimension aready exists." + f"Cannot rename dimension {name_from!r} to {name_to!r} to, " + f"because a {name_to!r} dimension already exists." ) raise ValueError(msg) + ncdata.dimensions.rename(name_from, name_to) + _rename_dims_in_vars(ncdata, name_from, name_to) diff --git a/tests/unit/utils/test_ncdata_copy.py b/tests/unit/utils/test_ncdata_copy.py index 6a49bd83..f0e534fa 100644 --- a/tests/unit/utils/test_ncdata_copy.py +++ b/tests/unit/utils/test_ncdata_copy.py @@ -1,4 +1,4 @@ -"""Tests for class :class:`ncdata.utils.ncdata_copy`. +"""Tests for :func:`ncdata.utils.ncdata_copy`. This is generic utility function version of the copy operation. """ diff --git a/tests/unit/utils/test_rename_dimension.py b/tests/unit/utils/test_rename_dimension.py new file mode 100644 index 00000000..a5f3760f --- /dev/null +++ b/tests/unit/utils/test_rename_dimension.py @@ -0,0 +1,67 @@ +"""Tests for :func:`ncdata.utils.rename_dimension`.""" +import pytest + +from ncdata import NcData, NcDimension, NcVariable +from ncdata.utils import rename_dimension + + +class TestRenameDimension: + """Tests for :func:`ncdata.utils.rename_dimension`.""" + + @pytest.fixture(autouse=True) + def setup(self): + self.ncdata = NcData( + dimensions=[ + NcDimension("y", 2), + NcDimension("x", 3), + ], + variables=[ + NcVariable("vx", ["x"]), + NcVariable("vy", ["y"]), + NcVariable("vyx", ["y", "x"]), + ], + ) + + def test_basic(self): + ncdata = self.ncdata + xdim = ncdata.dimensions["x"] + rename_dimension(ncdata, "x", "zz") + assert ncdata.dimensions["zz"] is xdim + assert ncdata.variables["vx"].dimensions == ("zz",) + assert ncdata.variables["vy"].dimensions == ("y",) + assert ncdata.variables["vyx"].dimensions == ("y", "zz") + + def test_name_collision_fail(self): + ncdata = self.ncdata + msg = "Cannot rename dimension 'x' to 'y' .* already exists." + with pytest.raises(ValueError, match=msg): + rename_dimension(ncdata, "x", "y") + + def test_groups(self): + ncdata = self.ncdata + ncdata.groups.addall( + [ + NcData( + "a", + variables=[ + NcVariable("ax", ["x"]), + NcVariable("aqxr", ["q", "x", "r"]), + ], + ), + NcData( + "b", + dimensions=[NcDimension("x", 20)], + variables=[NcVariable("bx", ["x"])], + ), + ] + ) + rename_dimension(ncdata, "x", "zz") + assert ncdata.groups["a"].variables["ax"].dimensions == ("zz",) + assert ncdata.groups["a"].variables["aqxr"].dimensions == ( + "q", + "zz", + "r", + ) + # This one doesn't get renamed: it is in a "scope hole" because the group + # defines its own "x" dimension, which takes precedence. + assert ncdata.groups["b"].variables["bx"].dimensions == ("x",) From 9fb810ce73f4f539c9be31d8ae6cd80b071983d2 Mon Sep 17 00:00:00 2001 From: Patrick Peglar Date: Mon, 11 Aug 2025 17:14:39 +0100 Subject: [PATCH 3/9] Fix links in docstring. --- lib/ncdata/utils/_rename_dim.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/ncdata/utils/_rename_dim.py b/lib/ncdata/utils/_rename_dim.py index 829d7aeb..76b9e90c 100644 --- a/lib/ncdata/utils/_rename_dim.py +++ b/lib/ncdata/utils/_rename_dim.py @@ -21,7 +21,7 @@ def _rename_dims_in_vars(ncdata: NcData, name_from: str, name_to: str) -> None: def rename_dimension(ncdata: NcData, name_from: str, name_to: str) -> None: """ - Rename a dimension of an :class:`NcData`. + Rename a dimension of an :class:`~ncdata.NcData`. This includes replacing the name on all contained variables which reference it, including those in sub-groups. @@ -38,9 +38,10 @@ def rename_dimension(ncdata: NcData, name_from: str, name_to: str) -> None: Notes ----- - * operation is in-place. To produce a new :class:`NcData` with renamed dimension, use :meth:`Ncdata.copy` first. - * unlike a simple :class:`~ncdata.NameMap.rename`, this checks whether a dimension of the new name already exists, - and if so will raise an error. + * operation is in-place. To produce a new :class:`~ncdata.NcData` with + renamed dimension, use :meth:`~ncdata.NcData.copy` first. + * unlike a simple :class:`~ncdata.NameMap.rename`, this checks whether a dimension + of the new name already exists, and if so will raise an error. """ if name_to in ncdata.dimensions: msg = ( From 1ce93dac273cf63075d5d2381e25acad76a1b34d Mon Sep 17 00:00:00 2001 From: Patrick Peglar Date: Mon, 11 Aug 2025 17:32:30 +0100 Subject: [PATCH 4/9] Improve docstring. --- lib/ncdata/utils/_rename_dim.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/ncdata/utils/_rename_dim.py b/lib/ncdata/utils/_rename_dim.py index 76b9e90c..149676ea 100644 --- a/lib/ncdata/utils/_rename_dim.py +++ b/lib/ncdata/utils/_rename_dim.py @@ -23,7 +23,8 @@ def rename_dimension(ncdata: NcData, name_from: str, name_to: str) -> None: """ Rename a dimension of an :class:`~ncdata.NcData`. - This includes replacing the name on all contained variables which reference it, including those in sub-groups. + This function calls ``ncdata.dimensions.rename``, but then it *also* renames the + dimension in all the variables which reference it, including those in sub-groups. Parameters ---------- @@ -38,10 +39,12 @@ def rename_dimension(ncdata: NcData, name_from: str, name_to: str) -> None: Notes ----- - * operation is in-place. To produce a new :class:`~ncdata.NcData` with - renamed dimension, use :meth:`~ncdata.NcData.copy` first. - * unlike a simple :class:`~ncdata.NameMap.rename`, this checks whether a dimension - of the new name already exists, and if so will raise an error. + * The operation is in-place. To produce a *new* :class:`~ncdata.NcData` with the + renamed dimension, create a copy first with :meth:`~ncdata.NcData.copy`. + + * Unlike a simple :meth:`~ncdata.NameMap.rename`, this checks whether a dimension + of the new name already exists, and if so raises an error. + """ if name_to in ncdata.dimensions: msg = ( From 0ea06dd2a6b741f2f04ac5066c742b6c0eea1f02 Mon Sep 17 00:00:00 2001 From: Patrick Peglar Date: Mon, 11 Aug 2025 18:23:25 +0100 Subject: [PATCH 5/9] Update all docs for 'rename_dimension'. --- README.md | 6 +-- .../userdocs/getting_started/introduction.rst | 2 + .../userdocs/user_guide/common_operations.rst | 3 +- docs/userdocs/user_guide/howtos.rst | 48 +++++++++++++++---- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 8faa2736..fd8c8598 100644 --- a/README.md +++ b/README.md @@ -79,10 +79,8 @@ cubes = to_iris(ncdata) enable_lockshare(xarray=True) dataset = xr.open_dataset("file1.nc") xr_ncdata = from_xarray(dataset) -xr_ncdata.dimensions.rename("dim0", "newdim") -# N.B. must also replace the name in dimension-lists of variables -for var in xr_ncdata.variables.values(): - var.dimensions = ["newdim" if dim == "dim0" else dim for dim in var.dimensions] +from ncdata.utils import rename_dimension +rename_dimension(xr_ncdata, "dim0", "newdim") to_nc4(ncdata, "file_2a.nc") ``` diff --git a/docs/userdocs/getting_started/introduction.rst b/docs/userdocs/getting_started/introduction.rst index 24aa5bd3..0a4a51d8 100644 --- a/docs/userdocs/getting_started/introduction.rst +++ b/docs/userdocs/getting_started/introduction.rst @@ -185,6 +185,8 @@ There is also a 'rename' method of variables/attributes/groups: Renaming a :class:`~ncdata.NcDimension` within a :class:`~ncdata.NcData` does *not* adjust the variables which reference it, since a variable's :attr:`~ncdata.NcVariable.dimensions` is a simple list of names. + But there is a :func:`~ncdata.utils.rename_dimension` utility which does this + "right". See : :ref:`howto_rename_dimension` , also :func:`ncdata.utils.save_errors`. diff --git a/docs/userdocs/user_guide/common_operations.rst b/docs/userdocs/user_guide/common_operations.rst index e128e753..3e484c35 100644 --- a/docs/userdocs/user_guide/common_operations.rst +++ b/docs/userdocs/user_guide/common_operations.rst @@ -70,7 +70,8 @@ Example : .. warning:: Renaming a dimension will not rename references to it (i.e. in variables), which obviously may cause problems. - We may add a utility to do this safely in future. + The utility function :func:`~ncdata.utils.rename_dimension` is provided for this. + See : :ref:`howto_rename_dimension`. Copying ------- diff --git a/docs/userdocs/user_guide/howtos.rst b/docs/userdocs/user_guide/howtos.rst index 75f8000f..d22fb8bf 100644 --- a/docs/userdocs/user_guide/howtos.rst +++ b/docs/userdocs/user_guide/howtos.rst @@ -126,17 +126,17 @@ Note that this affects both the element's container key *and* its ``.name``. .. Warning:: - Renaming a **dimension** can cause problems, so must be done with care. - See :ref:`howto_rename_dimension`. - -.. Warning:: - - **Why Not Just...** ``dim = data.dimensions['x']; dim.name = "q"`` ? + **Why Not Just...** ``var = data.variables['x']; var.name = "q"`` ? This would break the expected ``key == elements[key].name`` rule. We don't prevent this, but it is usually a mistake. :func:`~ncdata.utils.save_errors` detects this type of problem. +.. Warning:: + + Renaming a **dimension** can cause particular problems, so must be done with care. + See :ref:`howto_rename_dimension`. + .. _howto_rename_dimension: @@ -145,10 +145,40 @@ Rename a dimension Simply using ``ncdata.dimensions.rename()`` can cause problems, because you must then **also** replace the name where it occurs in the dimensions of any variables. -.. Note:: +Instead, you should use the :func:`~ncdata.utils.rename_dimension` function, which does +this correctly. - **To-Do** : there should be a utility for this, but as yet it does not exist. - See `Issue#87 `_. +For example: + +.. doctest:: python + + >>> from ncdata.utils import rename_dimension + >>> ncdata = NcData( + ... dimensions=[NcDimension("x", 3), NcDimension("y", 4)], + ... variables=[NcVariable("vy", ["y"]), NcVariable("vzyx", ["z", "y", "x"])] + ... ) + >>> print(ncdata) + + dimensions: + x = 3 + y = 4 + + variables: + ): vy(y)> + ): vzyx(z, y, x)> + > + + >>> rename_dimension(ncdata, "y", "qqq") + >>> print(ncdata) + + dimensions: + x = 3 + qqq = 4 + + variables: + ): vy(qqq)> + ): vzyx(z, qqq, x)> + > .. _howto_read_attr: From aca0f8acaf39d74ac3b9dd34a62c387ae4429ed4 Mon Sep 17 00:00:00 2001 From: Patrick Peglar Date: Mon, 11 Aug 2025 18:29:38 +0100 Subject: [PATCH 6/9] Added whatsnew. --- docs/changelog_fragments/87.feat.rst | 3 +++ docs/userdocs/user_guide/howtos.rst | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 docs/changelog_fragments/87.feat.rst diff --git a/docs/changelog_fragments/87.feat.rst b/docs/changelog_fragments/87.feat.rst new file mode 100644 index 00000000..2d6149cd --- /dev/null +++ b/docs/changelog_fragments/87.feat.rst @@ -0,0 +1,3 @@ +Added the :func:`~ncdata.utils.rename_dimension` utility. +This provides a "safe" dimension rename, which also replaces +the name in all variables which use it. diff --git a/docs/userdocs/user_guide/howtos.rst b/docs/userdocs/user_guide/howtos.rst index d22fb8bf..48e967c0 100644 --- a/docs/userdocs/user_guide/howtos.rst +++ b/docs/userdocs/user_guide/howtos.rst @@ -167,7 +167,7 @@ For example: ): vy(y)> ): vzyx(z, y, x)> > - + >>> rename_dimension(ncdata, "y", "qqq") >>> print(ncdata) From eba5663bfaec011b165545f57786610131b46b9c Mon Sep 17 00:00:00 2001 From: Patrick Peglar Date: Mon, 11 Aug 2025 19:22:23 +0100 Subject: [PATCH 7/9] Relabel the 'adopt linkchecks' change as 'dev(eloper)' not 'feat(ure)'. --- docs/changelog_fragments/{123.feat.rst => 123.dev.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/changelog_fragments/{123.feat.rst => 123.dev.rst} (100%) diff --git a/docs/changelog_fragments/123.feat.rst b/docs/changelog_fragments/123.dev.rst similarity index 100% rename from docs/changelog_fragments/123.feat.rst rename to docs/changelog_fragments/123.dev.rst From eefdf515e39ea8a586bec69e3b8e000276bfeccd Mon Sep 17 00:00:00 2001 From: Patrick Peglar Date: Wed, 3 Sep 2025 19:46:48 +0100 Subject: [PATCH 8/9] Fix scope of collision checks; add saveability testing. --- lib/ncdata/utils/_rename_dim.py | 23 ++++-- tests/unit/utils/test_rename_dimension.py | 95 +++++++++++++++++++++-- 2 files changed, 105 insertions(+), 13 deletions(-) diff --git a/lib/ncdata/utils/_rename_dim.py b/lib/ncdata/utils/_rename_dim.py index 149676ea..2ef1e98c 100644 --- a/lib/ncdata/utils/_rename_dim.py +++ b/lib/ncdata/utils/_rename_dim.py @@ -13,7 +13,7 @@ def _rename_dims_in_vars(ncdata: NcData, name_from: str, name_to: str) -> None: ] ) - # Also rename in all sub-groups, expect where the dimension is redefined ("scope hole"). + # Also rename in all sub-groups, except where the dimension is redefined ("scope hole"). for grp in ncdata.groups.values(): if name_from not in grp.dimensions: _rename_dims_in_vars(grp, name_from, name_to) @@ -46,11 +46,20 @@ def rename_dimension(ncdata: NcData, name_from: str, name_to: str) -> None: of the new name already exists, and if so raises an error. """ - if name_to in ncdata.dimensions: - msg = ( - f"Cannot rename dimension {name_from!r} to {name_to!r} to, " - f"because a {name_to!r} dimension already exists." - ) - raise ValueError(msg) + + def check_name_collides(ncdata, name_to, group_path=""): + if name_to in ncdata.dimensions: + inner = f' in group "{group_path}"' if group_path else "" + msg = ( + f"Cannot rename dimension {name_from!r} to {name_to!r}, " + f"because a {name_to!r} dimension already exists{inner}." + ) + raise ValueError(msg) + + for group in ncdata.groups.values(): + inner_path = group_path + "/" + group.name + check_name_collides(group, name_to, group_path=inner_path) + + check_name_collides(ncdata, name_to) ncdata.dimensions.rename(name_from, name_to) _rename_dims_in_vars(ncdata, name_from, name_to) diff --git a/tests/unit/utils/test_rename_dimension.py b/tests/unit/utils/test_rename_dimension.py index a5f3760f..a5adf8c2 100644 --- a/tests/unit/utils/test_rename_dimension.py +++ b/tests/unit/utils/test_rename_dimension.py @@ -1,8 +1,56 @@ """Tests for :func:`ncdata.utils.rename_dimension`.""" +import numpy as np import pytest from ncdata import NcData, NcDimension, NcVariable -from ncdata.utils import rename_dimension +from ncdata.utils import rename_dimension, save_errors + + +def make_saveable( + ncdata: NcData, _outer_dims: dict[str, NcDimension] | None = None +): + """Add missing dimensions + data, to make a sample NcData save-able. + + Create any missing variable dimensions (length==2). + Add any missing variable data arrays. + + N.B. this might actually be a useful utility one day?? + """ + if _outer_dims is None: + _outer_dims = {} + + outer_dim_names = [dim.name for dim in _outer_dims.values()] + + def getdim(dimname): + """Fetch a known dimension by name. + + Check own, then "outer" ones, to correctly implement *scope masking*. + """ + if dimname in ncdata.dimensions: + # These ones must take precedence! + result = ncdata.dimensions[dimname] + else: + # If not here, it should be in the 'outer' dims (else error). + result = _outer_dims[dimname] + return result + + for var in ncdata.variables.values(): + # Where variables reference dims which don't exist, create them (length=2). + for dimname in var.dimensions: + # Note: list of dims we check is *dynamic* (since we may add them) + if dimname not in outer_dim_names + list(ncdata.dimensions.keys()): + ncdata.dimensions.add(NcDimension(dimname, 2)) + + # Where variables have no data, add some. + if var.data is None: + shape = tuple([getdim(dimname).size for dimname in var.dimensions]) + var.data = np.zeros(shape) + + # recurse through groups. + all_dims = _outer_dims.copy() + all_dims.update(ncdata.dimensions) + for grp in ncdata.groups.values(): + make_saveable(grp, _outer_dims=all_dims) class TestRenameDimension: @@ -16,9 +64,9 @@ def setup(self): NcDimension("x", 3), ], variables=[ - NcVariable("vx", ["x"]), - NcVariable("vy", ["y"]), - NcVariable("vyx", ["y", "x"]), + NcVariable("vx", ["x"], data=[0, 1, 2]), + NcVariable("vy", ["y"], data=[11, 12]), + NcVariable("vyx", ["y", "x"], data=np.zeros((2, 3))), ], ) @@ -30,15 +78,34 @@ def test_basic(self): assert ncdata.variables["vx"].dimensions == ("zz",) assert ncdata.variables["vy"].dimensions == ("y",) assert ncdata.variables["vyx"].dimensions == ("y", "zz") + # Check that the result is still save-able. + assert save_errors(ncdata) == [] def test_name_collision_fail(self): ncdata = self.ncdata - msg = "Cannot rename dimension 'x' to 'y' .* already exists." + msg = "Cannot rename dimension 'x' to 'y', because a 'y' dimension already exists." with pytest.raises(ValueError, match=msg): rename_dimension(ncdata, "x", "y") - def test_groups(self): + @pytest.mark.parametrize( + "innergroup", [False, True], ids=["maingroup", "innergroup"] + ) + def test_name_collision_ingroup_fail(self, innergroup): ncdata = self.ncdata + grp = NcData(name="inner", dimensions=[NcDimension("z", 2)]) + msg = "Cannot rename dimension 'x' to 'z', because a 'z' dimension already exists" + if innergroup: + grp = NcData(name="main", groups=[grp]) + msg += ' in group "/main/inner".' + else: + msg += ' in group "/inner".' + ncdata.groups.add(grp) + with pytest.raises(ValueError, match=msg): + rename_dimension(ncdata, "x", "z") + + @pytest.fixture() + def group_example(self, setup): + ncdata = self.ncdata.copy() ncdata.groups.addall( [ NcData( @@ -55,6 +122,10 @@ def test_groups(self): ), ] ) + yield ncdata + + def test_groups(self, group_example): + ncdata = group_example rename_dimension(ncdata, "x", "zz") assert ncdata.groups["a"].variables["ax"].dimensions == ("zz",) assert ncdata.groups["a"].variables["aqxr"].dimensions == ( @@ -65,3 +136,15 @@ def test_groups(self): # This one doesn't get renamed: it is in a "scope hole" because the group # defines its own "x" dimension, which takes precedence. assert ncdata.groups["b"].variables["bx"].dimensions == ("x",) + + def test_saveable(self, group_example): + # Construct a complex example, make it saveable, and check that a renamed + # version is still saveable. + ncdata = group_example.copy() + + make_saveable(ncdata) + assert save_errors(ncdata) == [] + + # now rename and try again. + rename_dimension(ncdata, "x", "zz") + assert save_errors(ncdata) == [] From e24961034b85a8a9091b6a9b9b9680120f6967b6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 3 Sep 2025 18:52:44 +0000 Subject: [PATCH 9/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- lib/ncdata/utils/_rename_dim.py | 1 + tests/unit/utils/test_rename_dimension.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ncdata/utils/_rename_dim.py b/lib/ncdata/utils/_rename_dim.py index 2ef1e98c..35aa4366 100644 --- a/lib/ncdata/utils/_rename_dim.py +++ b/lib/ncdata/utils/_rename_dim.py @@ -1,4 +1,5 @@ """Utility to rename dimensions.""" + from ncdata import NcData diff --git a/tests/unit/utils/test_rename_dimension.py b/tests/unit/utils/test_rename_dimension.py index a5adf8c2..feab000e 100644 --- a/tests/unit/utils/test_rename_dimension.py +++ b/tests/unit/utils/test_rename_dimension.py @@ -1,7 +1,7 @@ """Tests for :func:`ncdata.utils.rename_dimension`.""" + import numpy as np import pytest - from ncdata import NcData, NcDimension, NcVariable from ncdata.utils import rename_dimension, save_errors