diff --git a/lib/ncdata/utils/_rename_dim.py b/lib/ncdata/utils/_rename_dim.py index 35aa436..8043b22 100644 --- a/lib/ncdata/utils/_rename_dim.py +++ b/lib/ncdata/utils/_rename_dim.py @@ -20,6 +20,25 @@ def _rename_dims_in_vars(ncdata: NcData, name_from: str, name_to: str) -> None: _rename_dims_in_vars(grp, name_from, name_to) +def _check_name_collisions(ncdata, name_from, 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(): + if name_from in group.dimensions: + # Skip this group as its 'name_from' dim makes it a "scope hole". + continue + inner_path = group_path + "/" + group.name + _check_name_collisions( + group, name_from, name_to, group_path=inner_path + ) + + def rename_dimension(ncdata: NcData, name_from: str, name_to: str) -> None: """ Rename a dimension of an :class:`~ncdata.NcData`. @@ -47,20 +66,6 @@ def rename_dimension(ncdata: NcData, name_from: str, name_to: str) -> None: of the new name already exists, and if so raises an error. """ - - 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) + _check_name_collisions(ncdata, name_from, 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 feab000..be51cd2 100644 --- a/tests/unit/utils/test_rename_dimension.py +++ b/tests/unit/utils/test_rename_dimension.py @@ -103,6 +103,17 @@ def test_name_collision_ingroup_fail(self, innergroup): with pytest.raises(ValueError, match=msg): rename_dimension(ncdata, "x", "z") + def test_name_ingroup_masked_nofail(self): + ncdata = self.ncdata + ncdata.groups.add( + NcData( + name="inner", + dimensions=[NcDimension("x", 2), NcDimension("z", 2)], + ) + ) + # No error in this case, because the "z" is inside a group with its own "x". + rename_dimension(ncdata, "x", "z") + @pytest.fixture() def group_example(self, setup): ncdata = self.ncdata.copy()