Defines a generator used to walk into Nodes hierarchy.

    Usage::

        >>> node_a = AbstractCompositeNode("MyNodeA")
        >>> node_b = AbstractCompositeNode("MyNodeB", node_a)
        >>> node_c = AbstractCompositeNode("MyNodeC", node_a)
        >>> node_d = AbstractCompositeNode("MyNodeD", node_b)
        >>> node_e = AbstractCompositeNode("MyNodeE", node_b)
        >>> node_f = AbstractCompositeNode("MyNodeF", node_d)
        >>> node_g = AbstractCompositeNode("MyNodeG", node_f)
        >>> node_h = AbstractCompositeNode("MyNodeH", node_g)
        >>> for node in nodes_walker(node_a):
        ...	print node.name
        MyNodeB
        MyNodeD
        MyNodeF
        MyNodeG
        MyNodeH
        MyNodeE
        MyNodeC

    :param node: Node to walk.
    :type node: AbstractCompositeNode
    :param ascendants: Ascendants instead of descendants will be yielded.
    :type ascendants: bool
    :return: Node.
    :rtype: AbstractNode or AbstractCompositeNode

def nodes_walker(node, ascendants=False):
    """
    Defines a generator used to walk into Nodes hierarchy.

    Usage::

        >>> node_a = AbstractCompositeNode("MyNodeA")
        >>> node_b = AbstractCompositeNode("MyNodeB", node_a)
        >>> node_c = AbstractCompositeNode("MyNodeC", node_a)
        >>> node_d = AbstractCompositeNode("MyNodeD", node_b)
        >>> node_e = AbstractCompositeNode("MyNodeE", node_b)
        >>> node_f = AbstractCompositeNode("MyNodeF", node_d)
        >>> node_g = AbstractCompositeNode("MyNodeG", node_f)
        >>> node_h = AbstractCompositeNode("MyNodeH", node_g)
        >>> for node in nodes_walker(node_a):
        ...	print node.name
        MyNodeB
        MyNodeD
        MyNodeF
        MyNodeG
        MyNodeH
        MyNodeE
        MyNodeC

    :param node: Node to walk.
    :type node: AbstractCompositeNode
    :param ascendants: Ascendants instead of descendants will be yielded.
    :type ascendants: bool
    :return: Node.
    :rtype: AbstractNode or AbstractCompositeNode
    """

    attribute = "children" if not ascendants else "parent"
    if not hasattr(node, attribute):
        return

    elements = getattr(node, attribute)
    elements = elements if isinstance(elements, list) else [elements]

    for element in elements:
        yield element

        if not hasattr(element, attribute):
            continue

        if not getattr(element, attribute):
            continue

        for sub_element in nodes_walker(element, ascendants=ascendants):
            yield sub_element