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

Name permanence via shallow copy #172

Merged
Merged
5 changes: 2 additions & 3 deletions datatree/datatree.py
Original file line number Diff line number Diff line change
Expand Up @@ -754,9 +754,8 @@ def _set(self, key: str, val: DataTree | CoercibleValue) -> None:
Counterpart to the public .get method, and also only works on the immediate node, not other nodes in the tree.
"""
if isinstance(val, DataTree):
# TODO shallow copy here so as not to alter name of node in original tree?
# new_node = copy.copy(val, deep=False)
new_node = val
# create and assign a shallow copy here so as not to alter original name of node in grafted tree
new_node = val.copy(deep=False)
new_node.name = key
new_node.parent = self
else:
Expand Down
28 changes: 17 additions & 11 deletions datatree/tests/test_datatree.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,6 @@ def test_child_gets_named_on_attach(self):
mary = DataTree(children={"Sue": sue}) # noqa
assert sue.name == "Sue"

@pytest.mark.xfail(reason="requires refactoring to retain name")
def test_grafted_subtree_retains_name(self):
subtree = DataTree("original")
root = DataTree(children={"new_name": subtree}) # noqa
assert subtree.name == "original"


class TestPaths:
def test_path_property(self):
Expand Down Expand Up @@ -294,8 +288,11 @@ class TestSetItem:
def test_setitem_new_child_node(self):
john = DataTree(name="john")
mary = DataTree(name="mary")
john["Mary"] = mary
assert john["Mary"] is mary
john["mary"] = mary

grafted_mary = john["mary"]
assert grafted_mary.parent is john
assert grafted_mary.name == "mary"

def test_setitem_unnamed_child_node_becomes_named(self):
john2 = DataTree(name="john2")
Expand All @@ -304,10 +301,19 @@ def test_setitem_unnamed_child_node_becomes_named(self):

def test_setitem_new_grandchild_node(self):
john = DataTree(name="john")
DataTree(name="mary", parent=john)
mary = DataTree(name="mary", parent=john)
rose = DataTree(name="rose")
john["Mary/Rose"] = rose
assert john["Mary/Rose"] is rose
john["mary/rose"] = rose

grafted_rose = john["mary/rose"]
assert grafted_rose.parent is mary
assert grafted_rose.name == "rose"

def test_grafted_subtree_retains_name(self):
subtree = DataTree(name="original_subtree_name")
root = DataTree(name="root")
root["new_subtree_name"] = subtree # noqa
assert subtree.name == "original_subtree_name"

def test_setitem_new_empty_node(self):
john = DataTree(name="john")
Expand Down
5 changes: 3 additions & 2 deletions datatree/tests/test_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ def test_not_isomorphic_complex_tree(self, create_test_datatree):
def test_checking_from_root(self, create_test_datatree):
dt1 = create_test_datatree()
dt2 = create_test_datatree()
real_root = DataTree()
real_root["fake_root"] = dt2
real_root = DataTree(name="real root")
dt2.name = "not_real_root"
dt2.parent = real_root
with pytest.raises(TreeIsomorphismError):
check_isomorphic(dt1, dt2, check_from_root=True)

Expand Down
2 changes: 2 additions & 0 deletions docs/source/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Breaking changes

- :py:meth:`DataTree.copy` copy method now only copies the subtree, not the parent nodes (:pull:`171`).
By `Tom Nicholas <https://github.com/TomNicholas>`_.
- Grafting a subtree onto another tree now leaves name of original subtree object unchanged (:issue:`116`, :pull:`172`).
By `Tom Nicholas <https://github.com/TomNicholas>`_.

Deprecations
~~~~~~~~~~~~
Expand Down