def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited={}):

    rname = str(root)

    if showtags:

        if showtags == 2:
            legend = (' E         = exists\n' +
                      '  R        = exists in repository only\n' +
                      '   b       = implicit builder\n' +
                      '   B       = explicit builder\n' +
                      '    S      = side effect\n' +
                      '     P     = precious\n' +
                      '      A    = always build\n' +
                      '       C   = current\n' +
                      '        N  = no clean\n' +
                      '         H = no cache\n' +
                      '\n')
            sys.stdout.write(unicode(legend))

        tags = ['[']
        tags.append(' E'[IDX(root.exists())])
        tags.append(' R'[IDX(root.rexists() and not root.exists())])
        tags.append(' BbB'[[0,1][IDX(root.has_explicit_builder())] +
                           [0,2][IDX(root.has_builder())]])
        tags.append(' S'[IDX(root.side_effect)])
        tags.append(' P'[IDX(root.precious)])
        tags.append(' A'[IDX(root.always_build)])
        tags.append(' C'[IDX(root.is_up_to_date())])
        tags.append(' N'[IDX(root.noclean)])
        tags.append(' H'[IDX(root.nocache)])
        tags.append(']')

    else:
        tags = []

    def MMM(m):
        return ["  ","| "][m]
    margins = list(map(MMM, margin[:-1]))

    children = child_func(root)

    if prune and rname in visited and children:
        sys.stdout.write(''.join(tags + margins + ['+-[', rname, ']']) + u'\n')
        return

    sys.stdout.write(''.join(tags + margins + ['+-', rname]) + u'\n')

    visited[rname] = 1

    if children:
        margin.append(1)
        idx = IDX(showtags)
        for C in children[:-1]:
            print_tree(C, child_func, prune, idx, margin, visited)
        margin[-1] = 0
        print_tree(children[-1], child_func, prune, idx, margin, visited)
        margin.pop()



# Functions for deciding if things are like various types, mainly to
# handle UserDict, UserList and UserString like their underlying types.
#
# Yes, all of this manual testing breaks polymorphism, and the real
# Pythonic way to do all of this would be to just try it and handle the
# exception, but handling the exception when it's not the right type is
# often too slow.

# We are using the following trick to speed up these
# functions. Default arguments are used to take a snapshot of the
# the global functions and constants used by these functions. This
# transforms accesses to global variable into local variables
# accesses (i.e. LOAD_FAST instead of LOAD_GLOBAL).
Print a tree of nodes.  This is like render_tree, except it prints
dataset/ETHPy150Open kayhayen/Nuitka/nuitka/build/inline_copy/lib/scons-2.3.2/SCons/Util.py/print_tree