Skip to content

Commit

Permalink
Allow clones inside same parent if kind differs
Browse files Browse the repository at this point in the history
  • Loading branch information
mar10 committed Oct 31, 2024
1 parent 76b34c9 commit 89d3855
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 4 deletions.
13 changes: 10 additions & 3 deletions nutree/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,15 @@ def _register(self, node: TNode) -> None:
clone_list = self._nodes_by_data_id[node._data_id] # may raise KeyError
for clone in clone_list:
if clone.parent is node.parent:
del self._node_by_id[node._node_id]
raise UniqueConstraintError("Node.data already exists in parent")
is_same_kind = getattr(clone, "kind", None) == getattr(
node, "kind", None
)
if is_same_kind:
del self._node_by_id[node._node_id]
raise UniqueConstraintError(
f"Node.data already exists in parent: {clone=}, "
f"{clone.parent=}"
)
clone_list.append(node)
except KeyError:
self._nodes_by_data_id[node._data_id] = [node]
Expand Down Expand Up @@ -494,7 +501,7 @@ def find_first(
data_id: DataIdType | None = None,
node_id: int | None = None,
) -> TNode | None:
"""Return the one matching node or `None`.
"""Return the first matching node or `None`.
Note that 'first' sometimes means 'one arbitrary' matching node, which
is not neccessarily the first of a specific iteration method.
Expand Down
2 changes: 1 addition & 1 deletion nutree/typed_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ def __init__(
node_id: int | None = None,
meta: dict | None = None,
):
self._kind = kind # tree._register() checks for this attribute
super().__init__(
data, parent=parent, data_id=data_id, node_id=node_id, meta=meta
)
assert isinstance(kind, str) and kind != ANY_KIND, f"Unsupported `kind`: {kind}"
self._kind = kind

# del self._children
# self._child_map: Dict[Node] = None
Expand Down
26 changes: 26 additions & 0 deletions tests/test_clones.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,32 @@ def test_clones(self):

assert tree._self_check()

def test_clones_typed(self):
"""
TypedTree<'fixture'>
├── function → func1
│ ├── failure → fail1
│ │ ├── cause → cause1
│ │ ├── cause → cause2
│ │ ├── effect → eff1
│ │ ╰── effect → eff2
│ ╰── failure → fail2
╰── function → func2
"""
tree = fixture.create_typed_tree()

assert tree.count == 8
assert tree.count_unique == 8

fail1 = tree["fail1"]
# Not allowed to add two clones to same parent
with pytest.raises(UniqueConstraintError):
fail1.add("cause1", kind="cause")
fail1.add("cause1")
tree.print()
assert tree.count == 9
assert tree.count_unique == 8

def test_dict(self):
""" """
tree = fixture.create_tree()
Expand Down

0 comments on commit 89d3855

Please sign in to comment.