bigtree

πŸ“ ModifyΒΆ

There are two types of modification available,

  1. Non-replacing scenario: Shift or copy nodes within same tree or between two trees using from_paths (list of paths) and to_paths (list of paths).

  2. Replacing scenario: Shift or copy nodes within same tree or between two trees while replacing the to-node using from_paths (list of paths) and to_paths (list of paths).

In non-replacing scenario, there are several configurations available for customization.

Available Configurations for CustomizationΒΆ

Configuration

Description

Default Value

copy

Indicates whether it is to shift the nodes, or copy the nodes

False (nodes are shifted, not copied)

to_tree

Indicates whether shifting/copying is within the same tree, or between different trees

None (nodes are shifted/copied within the same tree)

skippable

Skip shifting/copying of nodes if from_path cannot be found

False (from-node must be found)

overriding

Override existing node if it exists

False (to-node must not exist)

merge_children

Shift/copy children of from-node and remove intermediate parent node

False (children are not merged)

merge_leaves

Shift/copy leaves of from-node and remove all intermediate nodes

False (leaves are not merged)

delete_children

Shift/copy node only and delete its children

False (nodes are shifted/copied together with children)

In replacing scenario, all the configurations are also available except overriding, merge_children, and merge_leaves as it is doing a one-to-one replacement. It is by default overriding, and there is nothing to merge.

Note

merge_children and merge_leaves cannot be simultaneously set to True.

Note

Error will always be thrown if multiple from-nodes are found, paths in from_paths must be unique.

Tree Modification PermutationsΒΆ

There are several ways you can mix and match the tree modification methods. If you know all the parameters to choose, feel free to use copy_or_shift_logic or replace_logic methods as they are the most customizable. All other methods calls these 2 methods directly.

Tree Modification MethodsΒΆ

Shift / Copy?

Same tree / Between two trees?

Replace destination node?

Method to use

Shift

Same tree

No

shift_nodes

Copy

Same tree

No

copy_nodes

Copy

Between two trees

No

copy_nodes_from_tree_to_tree

Any

Any

No

copy_or_shift_logic

Shift

Same tree

Yes

shift_and_replace_nodes

Copy

Between two trees

Yes

copy_and_replace_nodes_from_tree_to_tree

Any

Any

Yes

replace_logic

Tree Modification IllustrationΒΆ

Shift and Copy Example
Sample Tree Modification (Shift, Copy, Delete)ΒΆ

Setting

Sample path in from_paths

Sample path in to_paths

Description

Default

β€œ/a/c”

β€œ/a/b/c”

Shift/copy node c

Default

β€œ/c”

β€œ/a/b/c”

Shift/copy node c

Default

β€œc”

β€œ/a/b/c”

Shift/copy node c

Default

β€œ/a/e”

None

Delete node e

skippable

β€œ/a/c”

β€œ/a/b/c”

Shift/copy node c, skip if β€œ/a/c” cannot be found

Advanced Shift Example
Sample Tree Modification (Advanced)ΒΆ

Setting

Sample path in from_paths

Sample path in to_paths

Description

overriding

β€œa/b/c”

β€œa/d/c”

Shift/copy node c, override if β€œa/d/c” exists

merge_children

β€œa/b/c”

β€œa/d/c”

If path not present: Shift/copy children of node c to be children of node d, removing node c
If path present: Shift/copy children of node c to be merged with existing β€œa/d/c” children

merge_children + overriding

β€œa/b/c”

β€œa/d/c”

If path not present: Behaves like merge_children
If path present: Behaves like overriding

merge_leaves

β€œa/b/c”

β€œa/d/c”

If path not present: Shift/copy leaves of node c to be children of node d
If path present: Shift/copy leaves of node c to be merged with existing β€œa/d/c” children

merge_leaves + overriding

β€œa/b/c”

β€œa/d/c”

If path not present: Behaves like merge_leaves
If path present: Behaves like overriding, but original node c remains

delete_children

β€œa/b”

β€œa/d/b”

Shift/copy node b only without any node b children

Functions:

copy_and_replace_nodes_from_tree_to_tree(...)

Copy nodes from from_paths to replace to_paths in-place.

copy_nodes(tree,Β from_paths,Β to_paths[,Β ...])

Copy nodes from from_paths to to_paths in-place.

copy_nodes_from_tree_to_tree(from_tree,Β ...)

Copy nodes from from_paths to to_paths in-place.

copy_or_shift_logic(tree,Β from_paths,Β to_paths)

Shift or copy nodes from from_paths to to_paths in-place.

replace_logic(tree,Β from_paths,Β to_paths[,Β ...])

Shift or copy nodes from from_paths to replace to_paths in-place.

shift_and_replace_nodes(tree,Β from_paths,Β ...)

Shift nodes from from_paths to replace to_paths in-place.

shift_nodes(tree,Β from_paths,Β to_paths[,Β ...])

Shift nodes from from_paths to to_paths in-place.

bigtree.tree.modify.copy_and_replace_nodes_from_tree_to_tree(from_tree: Node, to_tree: Node, from_paths: List[str], to_paths: List[str], sep: str = '/', skippable: bool = False, delete_children: bool = False, with_full_path: bool = False) NoneΒΆ

Copy nodes from from_paths to replace to_paths in-place.

  • Creates intermediate nodes if to path is not present

  • Able to skip nodes if from path is not found, defaults to False (from-nodes must be found; not skippable).

  • Able to copy node only and delete children, defaults to False (nodes are copied together with children).

For paths in from_paths and to_paths,
  • Path name can be with or without leading tree path separator symbol.

For paths in from_paths,
  • Path name can be partial path (trailing part of path) or node name.

  • If with_full_path=True, path name must be full path.

  • Path name must be unique to one node.

For paths in to_paths,
  • Path name must be full path.

  • Path must exist, node-to-be-replaced must be present.

>>> from bigtree import Node, copy_and_replace_nodes_from_tree_to_tree
>>> root = Node("Downloads")
>>> file1 = Node("file1.doc", parent=root)
>>> picture_folder = Node("Pictures", parent=root)
>>> photo1 = Node("photo1.jpg", parent=picture_folder)
>>> misc_folder = Node("Misc", parent=root)
>>> dummy_folder = Node("dummy", parent=misc_folder)
>>> photo2 = Node("photo2.jpg", parent=dummy_folder)
>>> root.show()
Downloads
β”œβ”€β”€ file1.doc
β”œβ”€β”€ Pictures
β”‚   └── photo1.jpg
└── Misc
    └── dummy
        └── photo2.jpg
>>> root_other = Node("Documents")
>>> picture_folder = Node("Pictures2", parent=root_other)
>>> photo2 = Node("photo2.jpg", parent=picture_folder)
>>> misc_folder = Node("Misc2", parent=root_other)
>>> root_other.show()
Documents
β”œβ”€β”€ Pictures2
β”‚   └── photo2.jpg
└── Misc2
>>> copy_and_replace_nodes_from_tree_to_tree(
...     from_tree=root,
...     to_tree=root_other,
...     from_paths=["Downloads/Pictures", "Downloads/Misc"],
...     to_paths=["Documents/Pictures2/photo2.jpg", "Documents/Misc2"],
... )
>>> root_other.show()
Documents
β”œβ”€β”€ Pictures2
β”‚   └── Pictures
β”‚       └── photo1.jpg
└── Misc
    └── dummy
        └── photo2.jpg

In delete_children=True case, only the node is copied without its accompanying children/descendants.

>>> root_other = Node("Documents")
>>> picture_folder = Node("Pictures2", parent=root_other)
>>> photo2 = Node("photo2.jpg", parent=picture_folder)
>>> misc_folder = Node("Misc2", parent=root_other)
>>> root_other.show()
Documents
β”œβ”€β”€ Pictures2
β”‚   └── photo2.jpg
└── Misc2
>>> copy_and_replace_nodes_from_tree_to_tree(
...     from_tree=root,
...     to_tree=root_other,
...     from_paths=["Downloads/Pictures", "Downloads/Misc"],
...     to_paths=["Documents/Pictures2/photo2.jpg", "Documents/Misc2"],
...     delete_children=True,
... )
>>> root_other.show()
Documents
β”œβ”€β”€ Pictures2
β”‚   └── Pictures
└── Misc
Parameters:
  • from_tree (Node) – tree to copy nodes from

  • to_tree (Node) – tree to copy nodes to

  • from_paths (List[str]) – original paths to shift nodes from

  • to_paths (List[str]) – new paths to shift nodes to

  • sep (str) – path separator for input paths, applies to from_path and to_path

  • skippable (bool) – indicator to skip if from path is not found, defaults to False

  • delete_children (bool) – indicator to copy node only without children, defaults to False

  • with_full_path (bool) – indicator to shift/copy node with full path in from_paths, results in faster search, defaults to False

bigtree.tree.modify.copy_nodes(tree: Node, from_paths: List[str], to_paths: List[str], sep: str = '/', skippable: bool = False, overriding: bool = False, merge_children: bool = False, merge_leaves: bool = False, delete_children: bool = False, with_full_path: bool = False) NoneΒΆ

Copy nodes from from_paths to to_paths in-place.

  • Creates intermediate nodes if to path is not present

  • Able to skip nodes if from path is not found, defaults to False (from-nodes must be found; not skippable).

  • Able to override existing node if it exists, defaults to False (to-nodes must not exist; not overridden).

  • Able to merge children and remove intermediate parent node, defaults to False (nodes are shifted; not merged).

  • Able to merge only leaf nodes and remove all intermediate nodes, defaults to False (nodes are shifted; not merged)

  • Able to copy node only and delete children, defaults to False (nodes are copied together with children).

For paths in from_paths and to_paths,
  • Path name can be with or without leading tree path separator symbol.

For paths in from_paths,
  • Path name can be partial path (trailing part of path) or node name.

  • If with_full_path=True, path name must be full path.

  • Path name must be unique to one node.

For paths in to_paths,
  • Path name must be full path.

If merge_children=True,
  • If to_path is not present, it copies children of from_path.

  • If to_path is present, and overriding=False, original and new children are merged.

  • If to_path is present and overriding=True, it behaves like overriding and only new children are retained.

If merge_leaves=True,
  • If to_path is not present, it copies leaves of from_path.

  • If to_path is present, and overriding=False, original children and leaves are merged.

  • If to_path is present and overriding=True, it behaves like overriding and only new leaves are retained.

>>> from bigtree import Node, list_to_tree, copy_nodes
>>> root = list_to_tree(["Downloads/Pictures", "Downloads/photo1.jpg", "Downloads/file1.doc"])
>>> root.show()
Downloads
β”œβ”€β”€ Pictures
β”œβ”€β”€ photo1.jpg
└── file1.doc
>>> copy_nodes(
...     tree=root,
...     from_paths=["Downloads/photo1.jpg", "Downloads/file1.doc"],
...     to_paths=["Downloads/Pictures/photo1.jpg", "Downloads/Files/file1.doc"],
... )
>>> root.show()
Downloads
β”œβ”€β”€ Pictures
β”‚   └── photo1.jpg
β”œβ”€β”€ photo1.jpg
β”œβ”€β”€ file1.doc
└── Files
    └── file1.doc

In overriding case,

>>> root = Node("Downloads")
>>> misc_folder = Node("Misc", parent=root)
>>> picture_folder = Node("Pictures", parent=misc_folder)
>>> photo1 = Node("photo1.jpg", parent=picture_folder)
>>> picture_folder2 = Node("Pictures", parent=root)
>>> photo2 = Node("photo2.jpg", parent=picture_folder2)
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”‚   └── Pictures
β”‚       └── photo1.jpg
└── Pictures
    └── photo2.jpg
>>> copy_nodes(root, ["Downloads/Misc/Pictures"], ["Downloads/Pictures"], overriding=True)
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”‚   └── Pictures
β”‚       └── photo1.jpg
└── Pictures
    └── photo1.jpg
In merge_children=True case, child nodes are copied instead of the parent node.
  • If the path already exists, child nodes are merged with existing children.

  • If same node is copied, the child nodes of the node are merged with the node’s parent.

>>> root = Node("Downloads")
>>> misc_folder = Node("Misc", parent=root)
>>> picture_folder = Node("Pictures", parent=misc_folder)
>>> photo2 = Node("photo2.jpg", parent=picture_folder)
>>> application_folder = Node("Applications", parent=misc_folder)
>>> chrome = Node("Chrome.exe", parent=application_folder)
>>> picture_folder2 = Node("Pictures", parent=root)
>>> photo1 = Node("photo1.jpg", parent=picture_folder2)
>>> dummy_folder = Node("dummy", parent=root)
>>> file_folder = Node("Files", parent=dummy_folder)
>>> file1 = Node("file1.doc", parent=file_folder)
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”‚   β”œβ”€β”€ Pictures
β”‚   β”‚   └── photo2.jpg
β”‚   └── Applications
β”‚       └── Chrome.exe
β”œβ”€β”€ Pictures
β”‚   └── photo1.jpg
└── dummy
    └── Files
        └── file1.doc
>>> copy_nodes(
...     root,
...     ["Downloads/Misc/Pictures", "Applications", "Downloads/dummy"],
...     ["Downloads/Pictures", "Downloads/Applications", "Downloads/dummy"],
...     merge_children=True,
... )
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”‚   β”œβ”€β”€ Pictures
β”‚   β”‚   └── photo2.jpg
β”‚   └── Applications
β”‚       └── Chrome.exe
β”œβ”€β”€ Pictures
β”‚   β”œβ”€β”€ photo1.jpg
β”‚   └── photo2.jpg
β”œβ”€β”€ Chrome.exe
└── Files
    └── file1.doc
In merge_leaves=True case, leaf nodes are copied instead of the parent node.
  • If the path already exists, leaf nodes are merged with existing children.

  • If same node is copied, the leaf nodes of the node are merged with the node’s parent.

>>> root = Node("Downloads")
>>> misc_folder = Node("Misc", parent=root)
>>> picture_folder = Node("Pictures", parent=misc_folder)
>>> photo2 = Node("photo2.jpg", parent=picture_folder)
>>> application_folder = Node("Applications", parent=misc_folder)
>>> chrome = Node("Chrome.exe", parent=application_folder)
>>> picture_folder2 = Node("Pictures", parent=root)
>>> photo1 = Node("photo1.jpg", parent=picture_folder2)
>>> dummy_folder = Node("dummy", parent=root)
>>> file_folder = Node("Files", parent=dummy_folder)
>>> file1 = Node("file1.doc", parent=file_folder)
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”‚   β”œβ”€β”€ Pictures
β”‚   β”‚   └── photo2.jpg
β”‚   └── Applications
β”‚       └── Chrome.exe
β”œβ”€β”€ Pictures
β”‚   └── photo1.jpg
└── dummy
    └── Files
        └── file1.doc
>>> copy_nodes(
...     root,
...     ["Downloads/Misc/Pictures", "Applications", "Downloads/dummy"],
...     ["Downloads/Pictures", "Downloads/Applications", "Downloads/dummy"],
...     merge_leaves=True,
... )
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”‚   β”œβ”€β”€ Pictures
β”‚   β”‚   └── photo2.jpg
β”‚   └── Applications
β”‚       └── Chrome.exe
β”œβ”€β”€ Pictures
β”‚   β”œβ”€β”€ photo1.jpg
β”‚   └── photo2.jpg
β”œβ”€β”€ dummy
β”‚   └── Files
β”‚       └── file1.doc
β”œβ”€β”€ Chrome.exe
└── file1.doc

In delete_children=True case, only the node is copied without its accompanying children/descendants.

>>> root = Node("Downloads")
>>> misc_folder = Node("Misc", parent=root)
>>> application_folder = Node("Applications", parent=misc_folder)
>>> chrome = Node("Chrome.exe", parent=application_folder)
>>> picture_folder = Node("Pictures", parent=root)
>>> photo1 = Node("photo1.jpg", parent=picture_folder)
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”‚   └── Applications
β”‚       └── Chrome.exe
└── Pictures
    └── photo1.jpg
>>> copy_nodes(root, ["Applications"], ["Downloads/Applications"], delete_children=True)
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”‚   └── Applications
β”‚       └── Chrome.exe
β”œβ”€β”€ Pictures
β”‚   └── photo1.jpg
└── Applications
Parameters:
  • tree (Node) – tree to modify

  • from_paths (List[str]) – original paths to shift nodes from

  • to_paths (List[str]) – new paths to shift nodes to

  • sep (str) – path separator for input paths, applies to from_path and to_path

  • skippable (bool) – indicator to skip if from path is not found, defaults to False

  • overriding (bool) – indicator to override existing to path if there is clashes, defaults to False

  • merge_children (bool) – indicator to merge children and remove intermediate parent node, defaults to False

  • merge_leaves (bool) – indicator to merge leaf nodes and remove intermediate parent node(s), defaults to False

  • delete_children (bool) – indicator to copy node only without children, defaults to False

  • with_full_path (bool) – indicator to shift/copy node with full path in from_paths, results in faster search, defaults to False

bigtree.tree.modify.copy_nodes_from_tree_to_tree(from_tree: Node, to_tree: Node, from_paths: List[str], to_paths: List[str], sep: str = '/', skippable: bool = False, overriding: bool = False, merge_children: bool = False, merge_leaves: bool = False, delete_children: bool = False, with_full_path: bool = False) NoneΒΆ

Copy nodes from from_paths to to_paths in-place.

  • Creates intermediate nodes if to path is not present

  • Able to skip nodes if from path is not found, defaults to False (from-nodes must be found; not skippable).

  • Able to override existing node if it exists, defaults to False (to-nodes must not exist; not overridden).

  • Able to merge children and remove intermediate parent node, defaults to False (nodes are shifted; not merged).

  • Able to merge only leaf nodes and remove all intermediate nodes, defaults to False (nodes are shifted; not merged)

  • Able to copy node only and delete children, defaults to False (nodes are copied together with children).

For paths in from_paths and to_paths,
  • Path name can be with or without leading tree path separator symbol.

For paths in from_paths,
  • Path name can be partial path (trailing part of path) or node name.

  • If with_full_path=True, path name must be full path.

  • Path name must be unique to one node.

For paths in to_paths,
  • Path name must be full path.

If merge_children=True,
  • If to_path is not present, it copies children of from_path

  • If to_path is present, and overriding=False, original and new children are merged

  • If to_path is present and overriding=True, it behaves like overriding and only new leaves are retained.

If merge_leaves=True,
  • If to_path is not present, it copies leaves of from_path.

  • If to_path is present, and overriding=False, original children and leaves are merged.

  • If to_path is present and overriding=True, it behaves like overriding and only new leaves are retained.

>>> from bigtree import Node, copy_nodes_from_tree_to_tree
>>> root = Node("Downloads")
>>> file1 = Node("file1.doc", parent=root)
>>> picture_folder = Node("Pictures", parent=root)
>>> photo1 = Node("photo1.jpg", parent=picture_folder)
>>> misc_folder = Node("Misc", parent=root)
>>> dummy_folder = Node("dummy", parent=misc_folder)
>>> photo2 = Node("photo2.jpg", parent=dummy_folder)
>>> root.show()
Downloads
β”œβ”€β”€ file1.doc
β”œβ”€β”€ Pictures
β”‚   └── photo1.jpg
└── Misc
    └── dummy
        └── photo2.jpg
>>> root_other = Node("Documents")
>>> copy_nodes_from_tree_to_tree(
...     from_tree=root,
...     to_tree=root_other,
...     from_paths=["Downloads/Pictures", "Downloads/Misc"],
...     to_paths=["Documents/Pictures", "Documents/New Misc/Misc"],
... )
>>> root_other.show()
Documents
β”œβ”€β”€ Pictures
β”‚   └── photo1.jpg
└── New Misc
    └── Misc
        └── dummy
            └── photo2.jpg

In overriding case,

>>> root_other = Node("Documents")
>>> picture_folder = Node("Pictures", parent=root_other)
>>> photo3 = Node("photo3.jpg", parent=picture_folder)
>>> root_other.show()
Documents
└── Pictures
    └── photo3.jpg
>>> copy_nodes_from_tree_to_tree(
...     root,
...     root_other,
...     ["Downloads/Pictures", "Downloads/Misc"],
...     ["Documents/Pictures", "Documents/Misc"],
...     overriding=True,
... )
>>> root_other.show()
Documents
β”œβ”€β”€ Pictures
β”‚   └── photo1.jpg
└── Misc
    └── dummy
        └── photo2.jpg
In merge_children=True case, child nodes are copied instead of the parent node.
  • If the path already exists, child nodes are merged with existing children.

>>> root_other = Node("Documents")
>>> picture_folder = Node("Pictures", parent=root_other)
>>> photo3 = Node("photo3.jpg", parent=picture_folder)
>>> root_other.show()
Documents
└── Pictures
    └── photo3.jpg
>>> copy_nodes_from_tree_to_tree(
...     root,
...     root_other,
...     ["Downloads/Pictures", "Downloads/Misc"],
...     ["Documents/Pictures", "Documents/Misc"],
...     merge_children=True,
... )
>>> root_other.show()
Documents
β”œβ”€β”€ Pictures
β”‚   β”œβ”€β”€ photo3.jpg
β”‚   └── photo1.jpg
└── dummy
    └── photo2.jpg
In merge_leaves=True case, leaf nodes are copied instead of the parent node.
  • If the path already exists, leaf nodes are merged with existing children.

>>> root_other = Node("Documents")
>>> picture_folder = Node("Pictures", parent=root_other)
>>> photo3 = Node("photo3.jpg", parent=picture_folder)
>>> root_other.show()
Documents
└── Pictures
    └── photo3.jpg
>>> copy_nodes_from_tree_to_tree(
...     root,
...     root_other,
...     ["Downloads/Pictures", "Downloads/Misc"],
...     ["Documents/Pictures", "Documents/Misc"],
...     merge_leaves=True,
... )
>>> root_other.show()
Documents
β”œβ”€β”€ Pictures
β”‚   β”œβ”€β”€ photo3.jpg
β”‚   └── photo1.jpg
└── photo2.jpg

In delete_children=True case, only the node is copied without its accompanying children/descendants.

>>> root_other = Node("Documents")
>>> root_other.show()
Documents
>>> copy_nodes_from_tree_to_tree(
...     root,
...     root_other,
...     ["Downloads/Pictures", "Downloads/Misc"],
...     ["Documents/Pictures", "Documents/Misc"],
...     delete_children=True,
... )
>>> root_other.show()
Documents
β”œβ”€β”€ Pictures
└── Misc
Parameters:
  • from_tree (Node) – tree to copy nodes from

  • to_tree (Node) – tree to copy nodes to

  • from_paths (List[str]) – original paths to shift nodes from

  • to_paths (List[str]) – new paths to shift nodes to

  • sep (str) – path separator for input paths, applies to from_path and to_path

  • skippable (bool) – indicator to skip if from path is not found, defaults to False

  • overriding (bool) – indicator to override existing to path if there is clashes, defaults to False

  • merge_children (bool) – indicator to merge children and remove intermediate parent node, defaults to False

  • merge_leaves (bool) – indicator to merge leaf nodes and remove intermediate parent node(s), defaults to False

  • delete_children (bool) – indicator to copy node only without children, defaults to False

  • with_full_path (bool) – indicator to shift/copy node with full path in from_paths, results in faster search, defaults to False

bigtree.tree.modify.copy_or_shift_logic(tree: Node, from_paths: List[str], to_paths: List[str], sep: str = '/', copy: bool = False, skippable: bool = False, overriding: bool = False, merge_children: bool = False, merge_leaves: bool = False, delete_children: bool = False, to_tree: Node | None = None, with_full_path: bool = False) NoneΒΆ

Shift or copy nodes from from_paths to to_paths in-place.

  • Creates intermediate nodes if to path is not present

  • Able to copy node, defaults to False (nodes are shifted; not copied).

  • Able to skip nodes if from path is not found, defaults to False (from-nodes must be found; not skippable)

  • Able to override existing node if it exists, defaults to False (to-nodes must not exist; not overridden)

  • Able to merge children and remove intermediate parent node, defaults to False (nodes are shifted; not merged)

  • Able to merge only leaf nodes and remove all intermediate nodes, defaults to False (nodes are shifted; not merged)

  • Able to shift/copy node only and delete children, defaults to False (nodes are shifted/copied together with children).

  • Able to shift/copy nodes from one tree to another tree, defaults to None (shifting/copying happens within same tree)

For paths in from_paths and to_paths,
  • Path name can be with or without leading tree path separator symbol.

For paths in from_paths,
  • Path name can be partial path (trailing part of path) or node name.

  • If with_full_path=True, path name must be full path.

  • Path name must be unique to one node.

For paths in to_paths,
  • Path name must be full path.

  • Can set to empty string or None to delete the path in from_paths, note that copy must be set to False.

If merge_children=True,
  • If to_path is not present, it shifts/copies children of from_path.

  • If to_path is present, and overriding=False, original and new children are merged.

  • If to_path is present and overriding=True, it behaves like overriding and only new children are retained.

If merge_leaves=True,
  • If to_path is not present, it shifts/copies leaves of from_path.

  • If to_path is present, and overriding=False, original children and leaves are merged.

  • If to_path is present and overriding=True, it behaves like overriding and only new leaves are retained, original non-leaf nodes in from_path are retained.

Parameters:
  • tree (Node) – tree to modify

  • from_paths (List[str]) – original paths to shift nodes from

  • to_paths (List[str]) – new paths to shift nodes to

  • sep (str) – path separator for input paths, applies to from_path and to_path

  • copy (bool) – indicator to copy node, defaults to False

  • skippable (bool) – indicator to skip if from path is not found, defaults to False

  • overriding (bool) – indicator to override existing to path if there is clashes, defaults to False

  • merge_children (bool) – indicator to merge children and remove intermediate parent node, defaults to False

  • merge_leaves (bool) – indicator to merge leaf nodes and remove intermediate parent node(s), defaults to False

  • delete_children (bool) – indicator to shift/copy node only without children, defaults to False

  • to_tree (Node) – tree to copy to, defaults to None

  • with_full_path (bool) – indicator to shift/copy node with full path in from_paths, results in faster search, defaults to False

bigtree.tree.modify.replace_logic(tree: Node, from_paths: List[str], to_paths: List[str], sep: str = '/', copy: bool = False, skippable: bool = False, delete_children: bool = False, to_tree: Node | None = None, with_full_path: bool = False) NoneΒΆ

Shift or copy nodes from from_paths to replace to_paths in-place.

  • Creates intermediate nodes if to path is not present

  • Able to copy node, defaults to False (nodes are shifted; not copied).

  • Able to skip nodes if from path is not found, defaults to False (from-nodes must be found; not skippable)

  • Able to replace node only and delete children, defaults to False (nodes are shifted/copied together with children).

  • Able to shift/copy nodes from one tree to another tree, defaults to None (shifting/copying happens within same tree)

For paths in from_paths and to_paths,
  • Path name can be with or without leading tree path separator symbol.

For paths in from_paths,
  • Path name can be partial path (trailing part of path) or node name.

  • If with_full_path=True, path name must be full path.

  • Path name must be unique to one node.

For paths in to_paths,
  • Path name must be full path.

  • Path must exist, node-to-be-replaced must be present.

Parameters:
  • tree (Node) – tree to modify

  • from_paths (List[str]) – original paths to shift nodes from

  • to_paths (List[str]) – new paths to shift nodes to

  • sep (str) – path separator for input paths, applies to from_path and to_path

  • copy (bool) – indicator to copy node, defaults to False

  • skippable (bool) – indicator to skip if from path is not found, defaults to False

  • delete_children (bool) – indicator to shift/copy node only without children, defaults to False

  • to_tree (Node) – tree to copy to, defaults to None

  • with_full_path (bool) – indicator to shift/copy node with full path in from_paths, results in faster search, defaults to False

bigtree.tree.modify.shift_and_replace_nodes(tree: Node, from_paths: List[str], to_paths: List[str], sep: str = '/', skippable: bool = False, delete_children: bool = False, with_full_path: bool = False) NoneΒΆ

Shift nodes from from_paths to replace to_paths in-place.

  • Creates intermediate nodes if to path is not present

  • Able to skip nodes if from path is not found, defaults to False (from-nodes must be found; not skippable).

  • Able to shift node only and delete children, defaults to False (nodes are shifted together with children).

For paths in from_paths and to_paths,
  • Path name can be with or without leading tree path separator symbol.

For paths in from_paths,
  • Path name can be partial path (trailing part of path) or node name.

  • If with_full_path=True, path name must be full path.

  • Path name must be unique to one node.

For paths in to_paths,
  • Path name must be full path.

  • Path must exist, node-to-be-replaced must be present.

>>> from bigtree import Node, shift_and_replace_nodes
>>> root = Node("Downloads")
>>> picture_folder = Node("Pictures", parent=root)
>>> photo1 = Node("photo1.jpg", parent=picture_folder)
>>> misc_folder = Node("Misc", parent=root)
>>> dummy_folder = Node("dummy", parent=misc_folder)
>>> root.show()
Downloads
β”œβ”€β”€ Pictures
β”‚   └── photo1.jpg
└── Misc
    └── dummy
>>> shift_and_replace_nodes(root, ["Downloads/Pictures"], ["Downloads/Misc/dummy"])
>>> root.show()
Downloads
└── Misc
    └── Pictures
        └── photo1.jpg

In delete_children=True case, only the node is shifted without its accompanying children/descendants.

>>> root = Node("Downloads")
>>> picture_folder = Node("Pictures", parent=root)
>>> photo1 = Node("photo1.jpg", parent=picture_folder)
>>> misc_folder = Node("Misc", parent=root)
>>> dummy_folder = Node("dummy", parent=misc_folder)
>>> root.show()
Downloads
β”œβ”€β”€ Pictures
β”‚   └── photo1.jpg
└── Misc
    └── dummy
>>> shift_and_replace_nodes(root, ["Downloads/Pictures"], ["Downloads/Misc/dummy"], delete_children=True)
>>> root.show()
Downloads
└── Misc
    └── Pictures
Parameters:
  • tree (Node) – tree to modify

  • from_paths (List[str]) – original paths to shift nodes from

  • to_paths (List[str]) – new paths to shift nodes to

  • sep (str) – path separator for input paths, applies to from_path and to_path

  • skippable (bool) – indicator to skip if from path is not found, defaults to False

  • delete_children (bool) – indicator to shift node only without children, defaults to False

  • with_full_path (bool) – indicator to shift/copy node with full path in from_paths, results in faster search, defaults to False

bigtree.tree.modify.shift_nodes(tree: Node, from_paths: List[str], to_paths: List[str], sep: str = '/', skippable: bool = False, overriding: bool = False, merge_children: bool = False, merge_leaves: bool = False, delete_children: bool = False, with_full_path: bool = False) NoneΒΆ

Shift nodes from from_paths to to_paths in-place.

  • Creates intermediate nodes if to path is not present

  • Able to skip nodes if from path is not found, defaults to False (from-nodes must be found; not skippable).

  • Able to override existing node if it exists, defaults to False (to-nodes must not exist; not overridden).

  • Able to merge children and remove intermediate parent node, defaults to False (nodes are shifted; not merged).

  • Able to merge only leaf nodes and remove all intermediate nodes, defaults to False (nodes are shifted; not merged)

  • Able to shift node only and delete children, defaults to False (nodes are shifted together with children).

For paths in from_paths and to_paths,
  • Path name can be with or without leading tree path separator symbol.

For paths in from_paths,
  • Path name can be partial path (trailing part of path) or node name.

  • If with_full_path=True, path name must be full path.

  • Path name must be unique to one node.

For paths in to_paths,
  • Path name must be full path.

  • Can set to empty string or None to delete the path in from_paths, note that copy must be set to False.

If merge_children=True,
  • If to_path is not present, it shifts children of from_path.

  • If to_path is present, and overriding=False, original and new children are merged.

  • If to_path is present and overriding=True, it behaves like overriding and only new children are retained.

If merge_leaves=True,
  • If to_path is not present, it shifts leaves of from_path.

  • If to_path is present, and overriding=False, original children and leaves are merged.

  • If to_path is present and overriding=True, it behaves like overriding and only new leaves are retained, original node in from_path is retained.

>>> from bigtree import Node, list_to_tree, shift_nodes
>>> root = list_to_tree(["Downloads/photo1.jpg", "Downloads/file1.doc"])
>>> root.show()
Downloads
β”œβ”€β”€ photo1.jpg
└── file1.doc
>>> shift_nodes(
...     tree=root,
...     from_paths=["Downloads/photo1.jpg", "Downloads/file1.doc"],
...     to_paths=["Downloads/Pictures/photo1.jpg", "Downloads/Files/file1.doc"],
... )
>>> root.show()
Downloads
β”œβ”€β”€ Pictures
β”‚   └── photo1.jpg
└── Files
    └── file1.doc

To delete node,

>>> root = list_to_tree(["Downloads/photo1.jpg", "Downloads/file1.doc"])
>>> root.show()
Downloads
β”œβ”€β”€ photo1.jpg
└── file1.doc
>>> shift_nodes(root, ["Downloads/photo1.jpg"], [None])
>>> root.show()
Downloads
└── file1.doc

In overriding case,

>>> root = Node("Downloads")
>>> misc_folder = Node("Misc", parent=root)
>>> picture_folder = Node("Pictures", parent=misc_folder)
>>> photo1 = Node("photo1.jpg", parent=picture_folder)
>>> picture_folder2 = Node("Pictures", parent=root)
>>> photo2 = Node("photo2.jpg", parent=picture_folder2)
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”‚   └── Pictures
β”‚       └── photo1.jpg
└── Pictures
    └── photo2.jpg
>>> shift_nodes(root, ["Downloads/Misc/Pictures"], ["Downloads/Pictures"], overriding=True)
>>> root.show()
Downloads
β”œβ”€β”€ Misc
└── Pictures
    └── photo1.jpg
In merge_children=True case, child nodes are shifted instead of the parent node.
  • If the path already exists, child nodes are merged with existing children.

  • If same node is shifted, the child nodes of the node are merged with the node’s parent.

>>> root = Node("Downloads")
>>> misc_folder = Node("Misc", parent=root)
>>> picture_folder = Node("Pictures", parent=misc_folder)
>>> photo2 = Node("photo2.jpg", parent=picture_folder)
>>> application_folder = Node("Applications", parent=misc_folder)
>>> chrome = Node("Chrome.exe", parent=application_folder)
>>> picture_folder2 = Node("Pictures", parent=root)
>>> photo1 = Node("photo1.jpg", parent=picture_folder2)
>>> dummy_folder = Node("dummy", parent=root)
>>> file_folder = Node("Files", parent=dummy_folder)
>>> file1 = Node("file1.doc", parent=file_folder)
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”‚   β”œβ”€β”€ Pictures
β”‚   β”‚   └── photo2.jpg
β”‚   └── Applications
β”‚       └── Chrome.exe
β”œβ”€β”€ Pictures
β”‚   └── photo1.jpg
└── dummy
    └── Files
        └── file1.doc
>>> shift_nodes(
...     root,
...     ["Downloads/Misc/Pictures", "Applications", "Downloads/dummy"],
...     ["Downloads/Pictures", "Downloads/Applications", "Downloads/dummy"],
...     merge_children=True,
... )
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”œβ”€β”€ Pictures
β”‚   β”œβ”€β”€ photo1.jpg
β”‚   └── photo2.jpg
β”œβ”€β”€ Chrome.exe
└── Files
    └── file1.doc
In merge_leaves=True case, leaf nodes are copied instead of the parent node.
  • If the path already exists, leaf nodes are merged with existing children.

  • If same node is copied, the leaf nodes of the node are merged with the node’s parent.

>>> root = Node("Downloads")
>>> misc_folder = Node("Misc", parent=root)
>>> picture_folder = Node("Pictures", parent=misc_folder)
>>> photo2 = Node("photo2.jpg", parent=picture_folder)
>>> application_folder = Node("Applications", parent=misc_folder)
>>> chrome = Node("Chrome.exe", parent=application_folder)
>>> picture_folder2 = Node("Pictures", parent=root)
>>> photo1 = Node("photo1.jpg", parent=picture_folder2)
>>> dummy_folder = Node("dummy", parent=root)
>>> file_folder = Node("Files", parent=dummy_folder)
>>> file1 = Node("file1.doc", parent=file_folder)
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”‚   β”œβ”€β”€ Pictures
β”‚   β”‚   └── photo2.jpg
β”‚   └── Applications
β”‚       └── Chrome.exe
β”œβ”€β”€ Pictures
β”‚   └── photo1.jpg
└── dummy
    └── Files
        └── file1.doc
>>> shift_nodes(
...     root,
...     ["Downloads/Misc/Pictures", "Applications", "Downloads/dummy"],
...     ["Downloads/Pictures", "Downloads/Applications", "Downloads/dummy"],
...     merge_leaves=True,
... )
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”‚   β”œβ”€β”€ Pictures
β”‚   └── Applications
β”œβ”€β”€ Pictures
β”‚   β”œβ”€β”€ photo1.jpg
β”‚   └── photo2.jpg
β”œβ”€β”€ dummy
β”‚   └── Files
β”œβ”€β”€ Chrome.exe
└── file1.doc

In delete_children=True case, only the node is shifted without its accompanying children/descendants.

>>> root = Node("Downloads")
>>> misc_folder = Node("Misc", parent=root)
>>> application_folder = Node("Applications", parent=misc_folder)
>>> chrome = Node("Chrome.exe", parent=application_folder)
>>> picture_folder = Node("Pictures", parent=root)
>>> photo1 = Node("photo1.jpg", parent=picture_folder)
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”‚   └── Applications
β”‚       └── Chrome.exe
└── Pictures
    └── photo1.jpg
>>> shift_nodes(root, ["Applications"], ["Downloads/Applications"], delete_children=True)
>>> root.show()
Downloads
β”œβ”€β”€ Misc
β”œβ”€β”€ Pictures
β”‚   └── photo1.jpg
└── Applications
Parameters:
  • tree (Node) – tree to modify

  • from_paths (List[str]) – original paths to shift nodes from

  • to_paths (List[str]) – new paths to shift nodes to

  • sep (str) – path separator for input paths, applies to from_path and to_path

  • skippable (bool) – indicator to skip if from path is not found, defaults to False

  • overriding (bool) – indicator to override existing to path if there is clashes, defaults to False

  • merge_children (bool) – indicator to merge children and remove intermediate parent node, defaults to False

  • merge_leaves (bool) – indicator to merge leaf nodes and remove intermediate parent node(s), defaults to False

  • delete_children (bool) – indicator to shift node only without children, defaults to False

  • with_full_path (bool) – indicator to shift/copy node with full path in from_paths, results in faster search, defaults to False