File indexing completed on 2024-06-23 04:27:59

0001 #
0002 #  SPDX-License-Identifier: GPL-3.0-or-later
0003 #
0004 
0005 from itertools import chain
0006 from pathlib import Path
0007 
0008 
0009 def iterPre(node, maxDepth=-1):
0010     """
0011     Visit nodes in pre order.
0012 
0013     Parameters
0014     ----------
0015     node: Node
0016     maxDepth: int
0017     Maximum depth level at which traversal will stop.
0018 
0019     Returns
0020     -------
0021     out: iter(Node)
0022     """
0023 
0024     def go(nodes, depth=0):
0025         for n in nodes:
0026             yield n
0027             # recursively call the generator if depth < maxDepth
0028             it = go(n.children, depth + 1) if maxDepth == -1 or depth < maxDepth else iter()
0029             yield from it
0030 
0031     return go([node])
0032 
0033 
0034 def iterLevel(node, maxDepth=-1):
0035     """
0036     Visit nodes in level order.
0037 
0038     Parameters
0039     ----------
0040     node: Node
0041     maxDepth: int
0042     Maximum depth level at which traversal will stop.
0043 
0044     Returns
0045     -------
0046     out: iter(Node)
0047     """
0048 
0049     def go(nodes, depth=0):
0050         yield from nodes
0051         it = map(lambda n: go(n.children, depth + 1), nodes)
0052         it = chain(*it) if maxDepth == -1 or depth < maxDepth else iter()
0053         yield from it
0054 
0055     return go([node])
0056 
0057 
0058 def iterLevelGroup(node, maxDepth=-1):
0059     """
0060     Visit nodes in level order just like `iterLevel`, but group nodes per level in an iterator.
0061 
0062     Parameters
0063     ----------
0064     node: Node
0065     maxDepth: int
0066     Maximum depth level at which traversal will stop.
0067 
0068     Returns
0069     -------
0070     out: iter(iter(Node))
0071     Returns an iterator that holds an iterator for each depth level.
0072     """
0073 
0074     def go(nodes, depth=0):
0075         yield iter(nodes)
0076         it = map(lambda n: go(n.children, depth + 1), nodes)
0077         it = chain(*it) if maxDepth == -1 or depth < maxDepth else iter()
0078         yield from filter(None, it)
0079 
0080     return go([node])
0081 
0082 
0083 def iterPost(node, maxDepth=-1):
0084     """
0085     Visit nodes in post order.
0086 
0087     Parameters
0088     ----------
0089     node: Node
0090     maxDepth: int
0091     Maximum depth level at which traversal will stop.
0092 
0093     Returns
0094     -------
0095     out: iter(Node)
0096     """
0097 
0098     def go(nodes, depth=0):
0099         for n in nodes:
0100             it = go(n.children, depth + 1) if maxDepth == -1 or depth < maxDepth else iter()
0101             yield from it
0102             yield n
0103 
0104     return go([node])
0105 
0106 
0107 def path(node):
0108     """
0109     Get the path of the given node.
0110 
0111     Parameters
0112     ----------
0113     node: Node
0114 
0115     Return
0116     ------
0117     out: list(Node)
0118     The path of nodes going through all the parents to the given node.
0119     """
0120 
0121     def go(n, acc=[]):
0122         acc += [n]
0123         n.parent and go(n.parent, acc)
0124         return reversed(acc)
0125 
0126     return list(go(node))
0127 
0128 
0129 def pathFS(node):
0130     """
0131     Get the path of the given node just like `path`, but returns a OS filesystem path based on
0132     node names.
0133 
0134     Parameters
0135     ----------
0136     node: Node
0137     A node that has a `name` method.
0138 
0139     Return
0140     ------
0141     out: str
0142     The path of nodes going through all the parents to the given node in filesystem-compatile
0143     string format.
0144     """
0145     it = filter(lambda n: n.parent, path(node))
0146     it = map(lambda n: n.name, it)
0147     return Path("").joinpath(*it)
0148 
0149 
0150 def iterDirs(node):
0151     it = iterPre(node)
0152     it = filter(lambda n: n.isGroupLayer(), it)
0153     it = filter(
0154         lambda n: any(i.isExportable() for i in chain(*map(lambda c: iterPre(c), n.children))), it
0155     )
0156     it = map(pathFS, it)
0157     return it