Skip to content

Commit

Permalink
Merge pull request #335 from kayjan/v0.23.0
Browse files Browse the repository at this point in the history
v0.23.0
  • Loading branch information
kayjan authored Dec 26, 2024
2 parents cfc1f6f + 6f9bda2 commit 35cb5d6
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 30 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.23.0] - 2024-12-26
### Changed:
- Tree Modify: Update documentation and docstring with some rephrasing.
- Tree Modify: Clean up test cases.
### Added:
- Tree Modify: Add parameter `merge_attribute` to allow from-node and to-node attributes to be merged if there are clashes.
### Fixed:
- Tree Modify: Fixed bug when `merge_children` is used with `overriding` as the `merge_children` value is changed in for-loop (bad move, literally).
- Tree Modify: Fixed bug when `merge_children` is used with `overriding` as the `merge_children` value is changed in
for-loop (bad move, literally). Modified the logic such that if there are clashes for `merge_children=True, overriding=True`,
the origin node parent and destination node children are preserved. The origin node's children are overridden.
**This might not be backwards-compatible!**

## [0.22.3] - 2024-11-14
### Added:
Expand Down
2 changes: 1 addition & 1 deletion bigtree/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "0.22.3"
__version__ = "0.23.0"

from bigtree.binarytree.construct import list_to_binarytree
from bigtree.dag.construct import dataframe_to_dag, dict_to_dag, list_to_dag
Expand Down
29 changes: 11 additions & 18 deletions bigtree/tree/modify.py
Original file line number Diff line number Diff line change
Expand Up @@ -1216,10 +1216,6 @@ def copy_or_shift_logic(

# Perform shifting/copying
for from_path, to_path in zip(from_paths, to_paths):
# Reset parameters
merge_children2 = merge_children
merge_leaves2 = merge_leaves

if with_full_path:
from_node = search.find_full_path(tree, from_path)
else:
Expand Down Expand Up @@ -1264,10 +1260,7 @@ def copy_or_shift_logic(
logging.info(
f"Path {to_path} already exists and its children be overridden by the merge"
)
parent = to_node.parent
to_node.parent = None
to_node = parent
merge_children2 = False
del to_node.children
elif merge_attribute:
logging.info(
f"Path {to_path} already exists and their attributes will be merged"
Expand All @@ -1279,10 +1272,10 @@ def copy_or_shift_logic(
merge_children=merge_children,
merge_leaves=merge_leaves,
)
parent = to_node.parent
to_node.parent = None
to_node = parent
merge_children2 = False
to_node.set_attrs(
dict(from_node.describe(exclude_prefix="_"))
)
del to_node.children
else:
logging.info(
f"Path {to_path} already exists and children are merged"
Expand All @@ -1304,10 +1297,10 @@ def copy_or_shift_logic(
merge_children=merge_children,
merge_leaves=merge_leaves,
)
parent = to_node.parent
to_node.parent = None
to_node = parent
merge_leaves2 = False
to_node.set_attrs(
dict(from_node.describe(exclude_prefix="_"))
)
del to_node.children
else:
logging.info(
f"Path {to_path} already exists and leaves are merged"
Expand Down Expand Up @@ -1353,7 +1346,7 @@ def copy_or_shift_logic(
if copy:
logging.debug(f"Copying {from_node.node_name}")
from_node = from_node.copy()
if merge_children2:
if merge_children:
# overriding / merge_attribute handled merge_children, set merge_children=False
logging.debug(
f"Reassigning children from {from_node.node_name} to {to_node.node_name}"
Expand All @@ -1363,7 +1356,7 @@ def copy_or_shift_logic(
del children.children
children.parent = to_node
from_node.parent = None
elif merge_leaves2:
elif merge_leaves:
logging.debug(
f"Reassigning leaf nodes from {from_node.node_name} to {to_node.node_name}"
)
Expand Down
22 changes: 13 additions & 9 deletions docs/bigtree/tree/modify.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,33 +94,37 @@ If you're still feeling lost over the parameters, here are some guiding question
- Do I want to retain the original node where they are?
- Yes: Set `copy=True`
- Default performs a shift instead of copy
- Am I unsure of what nodes I am going to shift, they may or may not exist and this is perfectly fine?
- Am I unsure of what nodes I am going to copy/shift, they may or may not exist and this is perfectly fine?
- Yes: Set `skippable=True`
- Default throws error if origin node is not found
- The origin node (and its descendants) may clash with the destination node(s), how do I want to handle it?
- Set `overriding=True` to overwrite origin node
- Set `merge_attribute=True` to combine both nodes' attributes
- Default throws error about the clash in node name
- I want to shift everything under the node, but not the node itself
- I want to copy/shift everything under the node, but not the node itself
- Set `merge_children=True` or `merge_leaves=True` to shift the children and leaf nodes respectively
- Default shifts the node itself, and everything under it
- I want to shift the node and only the node, and not everything under it
- I want to copy/shift the node and only the node, and not everything under it
- Yes: Set `delete_children=True`
- Default shifts the node itself, and everything under it
- I want to shift things from one tree to another tree
- I want to copy/shift things from one tree to another tree
- Specify `to_tree`
- Default shifts nodes within the same tree

What about the permutations between the parameters?

- These parameters are standalone and does not produce any interaction effect
- These parameters are standalone and do not produce any interaction effect
- `copy`, `skippable`, `delete_children`
- These parameters have some interaction:
- `overriding` and `merge_attribute` with `merge_children` and `merge_leaves`
- `overriding` + `merge_children`: Behaves like `merge_children` when there is no clash in node name, otherwise behaves like `overriding`. Note that clashes will preserve destination nodes' children only.
- `overriding` + `merge_leaves`: Behaves like `merge_leaves` when there is no clash in node name, otherwise behaves like `overriding`. Note that clashes will preserve destination nodes' leaves only.
- `merge_attribute` + `merge_children`: Behaves like `merge_children` when there is no clash in node name, otherwise behaves like `merge_attribute`. Note that attributes will be merged for node and all descendants, and will preserve origin and destination nodes' children.
- `merge_attribute` + `merge_leaves`: Behaves like `merge_leaves` when there is no clash in node name, otherwise behaves like `merge_attribute`. Note that attributes will be merged for node and all descendants, and will preserve origin nodes' children and destination nodes' leaves.
- `overriding` + `merge_children`: Behaves like `merge_children` when there is no clash in node name, otherwise behaves like `overriding`.
Note that clashes will preserve origin node parent and destination nodes' children.
- `overriding` + `merge_leaves`: Behaves like `merge_leaves` when there is no clash in node name, otherwise behaves like `overriding`.
Note that clashes will preserve origin node parent and destination nodes' leaves.
- `merge_attribute` + `merge_children`: Behaves like `merge_children` when there is no clash in node name, otherwise behaves like `merge_attribute`.
Note that attributes will be merged for node and all descendants, and will preserve origin and destination nodes' children.
- `merge_attribute` + `merge_leaves`: Behaves like `merge_leaves` when there is no clash in node name, otherwise behaves like `merge_attribute`.
Note that attributes will be merged for node and all descendants, and will preserve origin nodes' children and destination nodes' leaves.

-----

Expand Down
3 changes: 3 additions & 0 deletions docs/gettingstarted/demo/tree.md
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,9 @@ Nodes can be <mark>shifted</mark> (with or without replacement) or <mark>copied<
from one path to another, this changes the tree in-place.
Nodes can also be copied (with or without replacement) <mark>between two different trees</mark>.

There are various other configurations for performing copying/shifting, refer to [code documentation](../../bigtree/tree/modify.md)
for more examples.

=== "Shift nodes"
```python hl_lines="12-16 24-28"
from bigtree import list_to_tree, shift_nodes, shift_and_replace_nodes
Expand Down
3 changes: 2 additions & 1 deletion tests/tree/test_modify.py
Original file line number Diff line number Diff line change
Expand Up @@ -2377,7 +2377,7 @@ def test_copy_nodes_from_tree_to_tree_merge_children_overriding(self):
overriding=True,
)
assert_tree_structure_basenode_root(self.root_other_full_wrong)
assert_tree_structure_basenode_root_attr(self.root_other_full_wrong)
assert_tree_structure_basenode_root_attr(self.root_other_full_wrong, c=("c", 1))
assert_tree_structure_node_root(self.root_other_full_wrong)

# merge_children, merge_attribute
Expand Down Expand Up @@ -2454,6 +2454,7 @@ def test_copy_nodes_from_tree_to_tree_merge_leaves_merge_attribute(self):
merge_leaves=True,
merge_attribute=True,
)
self.root_other_full_wrong["b"].sort(key=lambda node: node.node_name)
assert_tree_structure_basenode_root(self.root_other_full_wrong)
assert_tree_structure_basenode_root_attr(self.root_other_full_wrong)
assert_tree_structure_node_root(self.root_other_full_wrong)
Expand Down

0 comments on commit 35cb5d6

Please sign in to comment.