Skip to content
This repository was archived by the owner on Oct 24, 2024. It is now read-only.

Commit 5330a3c

Browse files
Map over only data nodes, ignoring attrs (#263)
* add test from issue * test as a property of map_over_subtree directly * change behaviour * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * correct test * whatsnew --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 7ba0588 commit 5330a3c

File tree

4 files changed

+25
-3
lines changed

4 files changed

+25
-3
lines changed

datatree/mapping.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ def map_over_subtree(func: Callable) -> Callable:
109109
110110
Applies a function to every dataset in one or more subtrees, returning new trees which store the results.
111111
112-
The function will be applied to any non-empty dataset stored in any of the nodes in the trees. The returned trees
113-
will have the same structure as the supplied trees.
112+
The function will be applied to any data-containing dataset stored in any of the nodes in the trees. The returned
113+
trees will have the same structure as the supplied trees.
114114
115115
`func` needs to return one Datasets, DataArrays, or None in order to be able to rebuild the subtrees after
116116
mapping, as each result will be assigned to its respective node of a new tree via `DataTree.__setitem__`. Any
@@ -206,7 +206,7 @@ def _map_over_subtree(*args, **kwargs) -> DataTree | Tuple[DataTree, ...]:
206206
# Now we can call func on the data in this particular set of corresponding nodes
207207
results = (
208208
func(*node_args_as_datasets, **node_kwargs_as_datasets)
209-
if not node_of_first_tree.is_empty
209+
if node_of_first_tree.has_data
210210
else None
211211
)
212212

datatree/tests/test_datatree.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,13 @@ def test_ipython_key_completions(self, create_test_datatree):
603603
var_keys = list(dt.variables.keys())
604604
assert all(var_key in key_completions for var_key in var_keys)
605605

606+
def test_operation_with_attrs_but_no_data(self):
607+
# tests bug from xarray-datatree GH262
608+
xs = xr.Dataset({"testvar": xr.DataArray(np.ones((2, 3)))})
609+
dt = DataTree.from_dict({"node1": xs, "node2": xs})
610+
dt.attrs["test_key"] = 1 # sel works fine without this line
611+
dt.sel(dim_0=0)
612+
606613

607614
class TestRestructuring:
608615
def test_drop_nodes(self):

datatree/tests/test_mapping.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,18 @@ def times_ten(ds):
252252
result_tree = times_ten(subtree)
253253
assert_equal(result_tree, expected, from_root=False)
254254

255+
def test_skip_empty_nodes_with_attrs(self, create_test_datatree):
256+
# inspired by xarray-datatree GH262
257+
dt = create_test_datatree()
258+
dt["set1/set2"].attrs["foo"] = "bar"
259+
260+
def check_for_data(ds):
261+
# fails if run on a node that has no data
262+
assert len(ds.variables) != 0
263+
return ds
264+
265+
dt.map_over_subtree(check_for_data)
266+
255267

256268
class TestMutableOperations:
257269
def test_construct_using_type(self):

docs/source/whats-new.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ New Features
2626
Breaking changes
2727
~~~~~~~~~~~~~~~~
2828

29+
- Nodes containing only attributes but no data are now ignored by :py:func:`map_over_subtree` (:issue:`262`, :pull:`263`)
30+
By `Tom Nicholas <https://github.com/TomNicholas>`_.
31+
2932
Deprecations
3033
~~~~~~~~~~~~
3134

0 commit comments

Comments
 (0)