|  | @@ 490-520 (lines=31) @@ | 
                                                            
                                    | 487 |  |  | 
                                                            
                                    | 488 |  |  | 
                                                            
                                    | 489 |  | class DependencyGraph(object): | 
                                                            
                                    | 490 |  |     """ | 
                                                            
                                    | 491 |  |     A visual representation of the dependency graph, using `Graphviz <http://graphviz.org/>`__. | 
                                                            
                                    | 492 |  |     """ | 
                                                            
                                    | 493 |  |  | 
                                                            
                                    | 494 |  |     def __init__(self, action): | 
                                                            
                                    | 495 |  |         self.__graphviz_graph = graphviz.Digraph("action", node_attr={"shape": "box"}) | 
                                                            
                                    | 496 |  |         nodes = {} | 
                                                            
                                    | 497 |  |         for (i, action) in enumerate(action.get_possible_execution_order()): | 
                                                            
                                    | 498 |  |             node = str(i) | 
                                                            
                                    | 499 |  |             nodes[action] = node | 
                                                            
                                    | 500 |  |             self.__graphviz_graph.node(node, str(action.label)) | 
                                                            
                                    | 501 |  |             for dependency in action.dependencies: | 
                                                            
                                    | 502 |  |                 assert dependency in nodes  # Because we are iterating a possible execution order | 
                                                            
                                    | 503 |  |                 self.__graphviz_graph.edge(node, nodes[dependency]) | 
                                                            
                                    | 504 |  |  | 
                                                            
                                    | 505 |  |     def write_to_png(self, filename):  # Not unittested: too difficult | 
                                                            
                                    | 506 |  |         """ | 
                                                            
                                    | 507 |  |         Write the graph as a PNG image to the specified file. | 
                                                            
                                    | 508 |  |  | 
                                                            
                                    | 509 |  |         See also :meth:`get_graphviz_graph` if you want to draw the graph somewhere else. | 
                                                            
                                    | 510 |  |         """ | 
                                                            
                                    | 511 |  |         directory = os.path.dirname(filename) | 
                                                            
                                    | 512 |  |         filename = os.path.basename(filename) | 
                                                            
                                    | 513 |  |         filename, ext = os.path.splitext(filename) | 
                                                            
                                    | 514 |  |         g = self.get_graphviz_graph() | 
                                                            
                                    | 515 |  |         g.format = "png" | 
                                                            
                                    | 516 |  |         g.render(directory=directory, filename=filename, cleanup=True) | 
                                                            
                                    | 517 |  |  | 
                                                            
                                    | 518 |  |     def get_graphviz_graph(self): | 
                                                            
                                    | 519 |  |         """ | 
                                                            
                                    | 520 |  |         Return a :class:`graphviz.Digraph` of this dependency graph. | 
                                                            
                                    | 521 |  |  | 
                                                            
                                    | 522 |  |         See also :meth:`write_to_png` for the simplest use-case. | 
                                                            
                                    | 523 |  |         """ | 
                                                                                
                                |  | @@ 522-551 (lines=30) @@ | 
                                                            
                                    | 519 |  |         """ | 
                                                            
                                    | 520 |  |         Return a :class:`graphviz.Digraph` of this dependency graph. | 
                                                            
                                    | 521 |  |  | 
                                                            
                                    | 522 |  |         See also :meth:`write_to_png` for the simplest use-case. | 
                                                            
                                    | 523 |  |         """ | 
                                                            
                                    | 524 |  |         return self.__graphviz_graph.copy() | 
                                                            
                                    | 525 |  |  | 
                                                            
                                    | 526 |  |  | 
                                                            
                                    | 527 |  | class GanttChart(object):  # Not unittested: too difficult | 
                                                            
                                    | 528 |  |     """ | 
                                                            
                                    | 529 |  |     A visual representation of the timing of an execution. | 
                                                            
                                    | 530 |  |     """ | 
                                                            
                                    | 531 |  |  | 
                                                            
                                    | 532 |  |     def __init__(self, report): | 
                                                            
                                    | 533 |  |         self.__actions = { | 
                                                            
                                    | 534 |  |             id(action): self.__make_action(action, status) | 
                                                            
                                    | 535 |  |             for (action, status) in report.get_actions_and_statuses() | 
                                                            
                                    | 536 |  |         } | 
                                                            
                                    | 537 |  |  | 
                                                            
                                    | 538 |  |         self.__ordinates = {} | 
                                                            
                                    | 539 |  |  | 
                                                            
                                    | 540 |  |         dependents = {} | 
                                                            
                                    | 541 |  |         for (action, _) in report.get_actions_and_statuses(): | 
                                                            
                                    | 542 |  |             dependents.setdefault(action, set()) | 
                                                            
                                    | 543 |  |             for dependency in action.dependencies: | 
                                                            
                                    | 544 |  |                 dependents.setdefault(dependency, set()).add(action) | 
                                                            
                                    | 545 |  |  | 
                                                            
                                    | 546 |  |         def compute(action, ordinate): | 
                                                            
                                    | 547 |  |             self.__ordinates[id(action)] = len(self.__actions) - ordinate | 
                                                            
                                    | 548 |  |             for d in sorted( | 
                                                            
                                    | 549 |  |                 action.dependencies, | 
                                                            
                                    | 550 |  |                 key=lambda d: report.get_action_status(d).success_time or report.get_action_status(d).failure_time | 
                                                            
                                    | 551 |  |             ): | 
                                                            
                                    | 552 |  |                 if len(dependents[d]) == 1: | 
                                                            
                                    | 553 |  |                     ordinate = compute(d, ordinate - 1) | 
                                                            
                                    | 554 |  |                 else: |