Overview of Pynu (Python Node Utilities)

The library offers two helper classes, GraphNode and TreeNode. TreeNode can be considered to be a special case of a GraphNode. A TreeNode may have only one parent at a time. In addition it provides functionality to find the root of the tree (find_root) and to walk through each node of the tree based on the node used as a pivot.

Node

Both GraphNode and TreeNode have been derived from Node that provides following functionality:

Node.__setattr__(name, value)

Assignment of children/parents resets previous content and creates needed links to nodes. Otherwise setting attributes works as expected.

Simple assignment

>>> node1, node2 = Node(), Node()
>>> node1.children = node2
>>>
>>> assert node1.children[0] == node2
>>> assert node2.parents[0] == node1

Tuple assignment

>>> node1, node2, node3 = Node(), Node(), Node()
>>> node1.children = (node2, node3)
>>>
>>> assert node1.children[0] == node2
>>> assert node2.parents[0] == node1
>>> assert node1.children[1] == node3
>>> assert node3.parents[0] == node1

Assign value to an attribute

>>> node = Node()
>>>
>>> node.value = 13
>>> assert node.value == 13
NodeContainer.empty()

Empties container content.

>>> node1, node2 = Node(), Node()
>>>
>>> node1.children = node2
>>> node1.children.empty()
>>>
>>> assert len(node1.children) == 0
>>> assert len(node2.parents) == 0
NodeContainer.append(*items)

Appends given items to container.

Regular case

>>> node1, node2 = Node(), Node()
>>>
>>> node1.children = node2
>>>
>>> assert node1.children[0] == node2
>>> assert node2.parents[0] == node1

Cycles are allowed by default

>>> node1.parents.append(node2)
>>>
>>> assert node2.children[0] == node1
>>> assert node1.parents[0] == node2

Append multiple times

>>> node1, node2 = Node(), Node()
>>> node1.children.append(node2)
>>> node1.children.append(node2)
>>>
>>> assert node1.children[0] == node2
>>> assert node2.parents[0] == node1
>>> assert len(node1.children) == 1
>>> assert len(node2.parents) == 1

Append multiple at once

>>> node1, node2, node3 = Node(), Node(), Node()
>>>
>>> node1.children = (node2, node3)
>>>
>>> assert len(node1.children) == 2
>>> assert node2 in node1.children
>>> assert node3 in node1.children
NodeContainer.remove(*items)

Removes given items from container.

Regular case

>>> node1, node2 = Node(), Node()
>>>
>>> node1.children = node2
>>> node1.children.remove(node2)
>>>
>>> assert len(node1.children) == 0
>>> assert len(node2.parents) == 0

Remove multiple times

>>> node1, node2 = Node(), Node()
>>>
>>> node1.parents = node2
>>> node1.parents.remove(node2)
>>> node1.parents.remove(node2)
>>> node1.parents.remove(node2)
>>>
>>> assert len(node1.parents) == 0
>>> assert len(node2.children) == 0

Remove multiple at once

>>> node1, node2, node3 = Node(), Node(), Node()
>>>
>>> node1.children = (node2, node3)
>>> node1.children.remove(node2, node3)
>>>
>>> assert len(node1.children) == 0
NodeContainer.find(**kvargs)

Finds nodes matching to given rules. The idea is that the method seeks based on the type of the container. For example in case “node.parents.find” is invoked, it goes through all parents beginning from the parents of the given node.

Default case

>>> node1, node2, node3, node4 = Node(), Node(), Node(), Node()
>>>
>>> node1.children = (node2, node3)
>>> node3.parents.append(node4)
>>>
>>> node1.name = 'joe'
>>> node1.value = 13
>>> node2.color = 'blue'
>>> node3.color = 'black'
>>> node4.value = 13

Single argument, single result

>>> assert node2.parents.find(name='joe') == node1
>>> assert node1.children.find(color='blue') == node2

Single argument, multiple results

>>> assert node3.parents.find(value=13) == [node1, node4]

Multiple arguments, single result

>>> assert node2.parents.find(name='joe', value=13) == node1

Regex argument (match anything except newline)

>>> assert node2.parents.find(name='.') == node1

Regex argument (match from beginning)

>>> assert node1.children.find(color='^bl') == [node2, node3]

No result

>>> assert node2.parents.find(color='red') == None

Cyclic case

>>> node1, node2 = Node(), Node()
>>>
>>> node1.children = node2
>>> node2.children = node1
>>>
>>> node1.name = 'joe'
>>> node2.name = 'jack'

Single argument, single result

>>> assert node1.children.find(name='joe') == node1
>>> assert node1.children.find(name='jack') == node2

GraphNode

Currently GraphNode does not provide any extra functionality.

TreeNode

TreeNode provides following utility methods:

class pynu.TreeNode
find_root()

Finds the root node.

Regular case

>>> node1, node1a = TreeNode(), TreeNode()
>>> node1b, node1a1 = TreeNode(), TreeNode()
>>> node1.children.append(node1a, node1b)
>>> node1a.children.append(node1a1)
>>>
>>> assert node1.find_root() == node1
>>> assert node1a.find_root() == node1
>>> assert node1b.find_root() == node1
>>> assert node1a1.find_root() == node1
walk()

Walks through the nodes beginning from the current one in preorder.

>>> node1, node2, node3 = TreeNode(), TreeNode(), TreeNode()
>>> node4, node5 = TreeNode(), TreeNode()
>>>
>>> node1.children = (node2, node5)
>>> node2.children = (node3, node4)
>>> result = (node1, node3, node4, node2, node5 )
>>>
>>> for i, node in enumerate(node1.walk()):
...    assert node == result[i], '%s %s %s' % (i, node, result[i])

Table Of Contents

This Page