How to Paste a Subtree to a Parent Node in treelib: Complete Guide with Examples
To paste a subtree to a parent node in treelib, use Tree.paste(nid, new_tree, deep=False) after extracting the branch with Tree.subtree(nid), where deep=True creates independent copies of all nodes.
The treelib library manages tree structures through the Tree class in treelib/tree.py, which maintains a dictionary of Node instances and their hierarchical relationships. Combining the subtree() and paste() methods enables you to move or duplicate entire branches between different trees or within the same tree. This guide explains the internal mechanics of these operations and provides production-ready code examples.
How paste() Attaches a Subtree to a Parent Node
The paste() method, implemented in treelib/tree.py (lines 1534–1564), inserts an entire tree structure under an existing node by manipulating internal pointers and node registries. The implementation follows a strict four-phase process to ensure data integrity.
Input Validation and Identifier Collision Checks
First, the method validates that the source new_tree contains a root node and that the target nid exists in the destination tree. It then iterates through new_tree._nodes to verify that no identifier collisions exist with the destination tree's existing nodes. If conflicts are detected, the method raises a NodeIDAbsentError defined in treelib/exceptions.py.
Node Copying and Pointer Rewiring
The method processes each node in the source subtree. When deep=True, it creates a deep-copied Node object using Python's deepcopy module. Each node is registered in the destination tree's _nodes dictionary. The node.clone_pointers() method (from treelib/node.py) rewires the node's internal parent and child references from the source tree's identifier system to the destination tree's identifier system.
Root Re-linking to the Parent Node
Finally, the method attaches the subtree root to the target parent using two private helper methods: self.__update_bpointer(new_tree.root, nid) sets the pasted root's backward pointer to the new parent, and self.__update_fpointer(nid, new_tree.root, self.node_class.ADD) updates the forward pointer of the parent node to include the new child in its successor list.
Extracting a Subtree with subtree()
Before pasting, isolate the target branch using Tree.subtree(nid), implemented in treelib/tree.py (lines 1883–1895). This method creates a shallow copy of the requested branch where the node objects are shared between the original and extracted tree, but the root pointer changes to the specified nid. The shallow copy approach minimizes memory overhead, but modifications to shared nodes will affect both trees unless you use the deep=True parameter during the paste operation.
Practical Example: Moving a Branch Between Trees
The following example demonstrates building a source tree, extracting a subtree rooted at node "A", and pasting it under a new parent in a destination tree using both shallow and deep copy modes.
from treelib import Tree
# Build source tree
src = Tree()
src.create_node("root", "root")
src.create_node("A", "A", parent="root")
src.create_node("B", "B", parent="root")
src.create_node("C", "C", parent="A")
src.create_node("D", "D", parent="A")
src.show()
# └── root
# ├── A
# │ ├── C
# │ └── D
# └── B
# Extract subtree rooted at "A"
sub = src.subtree("A") # Shallow copy of A-branch
# Build destination tree
dst = Tree()
dst.create_node("new_root", "new_root")
dst.create_node("X", "X", parent="new_root")
dst.show()
# └── new_root
# └── X
# Paste subtree under node "X" (shallow paste)
dst.paste(nid="X", new_tree=sub)
dst.show()
# └── new_root
# └── X
# └── A
# ├── C
# └── D
# For independent copies, use deep=True
dst2 = Tree()
dst2.create_node("new_root2", "new_root2")
dst2.create_node("Y", "Y", parent="new_root2")
dst2.paste(nid="Y", new_tree=sub, deep=True)
Shallow vs. Deep Paste Operations
Understanding the copy semantics is critical when you paste a subtree to a parent node in treelib:
- Shallow paste (
deep=False): Reuses the originalNodeobjects from the source subtree. This is memory-efficient but means modifications to node attributes (such as tags or data) will affect both the source and destination trees because they reference the same object instances. - Deep paste (
deep=True): Creates independent copies of all nodes using Python'sdeepcopy. Mutations in the pasted branch do not affect the original tree, but this consumes additional memory and processing time during the paste operation.
Summary
- Use
Tree.subtree(nid)to isolate a branch from an existing tree before pasting; this creates a shallow copy of the branch structure. - Call
Tree.paste(nid, new_tree, deep=False)to attach the subtree under the specified parent node in the destination tree. - The implementation in
treelib/tree.pyvalidates inputs, checks for identifier collisions, and rewires internal pointers usingclone_pointers(). - Choose
deep=Truewhen you need independent node copies to prevent side effects on the source tree; use the default shallow paste for memory-efficient operations when shared references are safe.
Frequently Asked Questions
What happens if node identifiers collide when pasting a subtree?
The paste() method raises a NodeIDAbsentError (defined in treelib/exceptions.py) if any identifier in the source subtree already exists in the destination tree's _nodes dictionary. You must ensure all node IDs are unique across both trees before pasting, or remap the identifiers in the source subtree first.
Can I paste a subtree to the root node of another tree?
Yes. Pass the root node's identifier as the nid parameter to paste(). The method uses __update_bpointer() and __update_fpointer() to attach the subtree root as a child of the specified node, which can be any existing node including the tree root.
Does subtree() modify the original tree?
No. The subtree() method in treelib/tree.py (lines 1883–1895) creates a shallow copy of the branch without altering the original tree's structure or nodes. However, because it performs a shallow copy, modifications to the extracted nodes will affect the original tree unless you use deep=True during the paste operation or manually deep-copy the subtree before pasting.
How do I move a node and all its descendants to a new parent without keeping them in the original location?
First extract the branch with subtree(nid), then remove it from the source tree using remove_node(nid), and finally paste it to the new parent with paste(). Note that subtree() alone does not remove the branch from the source; it only creates a copy suitable for attachment elsewhere.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →