def testTopologicalSortCycle(self): n1 = Node("1") n2 = Node("2") n1.incoming = [n2] n2.incoming = [n1] generator = utils.topological_sort([n1, n2]) self.assertRaises(ValueError, list, generator)
def testTopologicalSort(self): n1 = Node("1") n2 = Node("2", n1) n3 = Node("3", n2) n4 = Node("4", n2, n3) for permutation in itertools.permutations([n1, n2, n3, n4]): self.assertEqual(list(utils.topological_sort(permutation)), [n1, n2, n3, n4])
def _postprocess_options(self, option_list, arguments): """Store all options in self._option in self, possibly postprocessed. This will iterate through all options in self._options and make them attributes on our Options instance. If, for an option {name}, there is a _store_{name} method on this class, it'll call the method instead of storing the option directly. Additionally, it'll store the remaining command line arguments as "arguments" (or call _store_arguments). Args: option_list: Same as optparse.OptionParser().option_list. arguments: Other arguments on the command-line (i.e., things that don't start with '-') """ # prepare function objects for topological sort: class Node(object): # pylint: disable=g-wrong-blank-lines def __init__(self, name, processor): # pylint: disable=g-wrong-blank-lines self.name = name self.processor = processor nodes = { opt.dest: Node(opt.dest, getattr(self, "_store_" + opt.dest, None)) for opt in option_list if opt.dest } # The "arguments" attribute is not an option, but we treat it as one, # for dependency checking: nodes["arguments"] = Node("arguments", getattr(self, "_store_arguments", None)) for f in nodes.values(): if f.processor: # option has a _store_{name} method dependencies = uses.lookup.get(f.processor.__name__) if dependencies: # that method has a @uses decorator f.incoming = tuple(nodes[use] for use in dependencies) # process the option list in the right order: for node in utils.topological_sort(nodes.values()): if node.name == "arguments": value = arguments else: value = getattr(self._options, node.name) if node.processor is not None: value = node.processor(value) else: setattr(self, node.name, value)
def _postprocess_options(self, names): """Store all options in self._options in self, possibly postprocessed. This will iterate through all options in self._options and make them attributes on our Options instance. If, for an option {name}, there is a _store_{name} method on this class, it'll call the method instead of storing the option directly. Additionally, it'll store the remaining command line arguments as "arguments" (or call _store_arguments). Args: names: The names of the options. """ # prepare function objects for topological sort: class Node(object): # pylint: disable=g-wrong-blank-lines def __init__(self, name, processor): # pylint: disable=g-wrong-blank-lines self.name = name self.processor = processor nodes = { name: Node(name, getattr(self, "_store_" + name, None)) for name in names } for f in nodes.values(): if f.processor: # option has a _store_{name} method dependencies = uses.lookup.get(f.processor.__name__) if dependencies: # that method has a @uses decorator f.incoming = tuple(nodes[use] for use in dependencies) # process the option list in the right order: for node in utils.topological_sort(nodes.values()): value = getattr(self._options, node.name) if node.processor is not None: node.processor(value) else: setattr(self, node.name, value)
def testTopologicalSortGetattr(self): self.assertEqual(list(utils.topological_sort([1])), [1])
def testTopologicalSort2(self): n1 = Node("1") n2 = Node("2", n1) self.assertEqual(list(utils.topological_sort([n1, n2, 3, 4]))[-1], n2)