def rule_dot2(self):
    dag = defaultdict(list)
    visited = set()
    preselect = set()

    def preselect_parents(job):
        for parent in self.depending[job]:
            if (parent in preselect):
                continue
            preselect.add(parent)
            preselect_parents(parent)

    def build_ruledag(job, key=(lambda job: job.rule.name)):
        if (job in visited):
            return
        visited.add(job)
        deps = sorted(self.dependencies[job], key=key)
        deps = [(group[0] if preselect.isdisjoint(group) else preselect.intersection(group).pop()) for group in (list(g) for (_, g) in groupby(deps, key))]
        dag[job].extend(deps)
        preselect_parents(job)
        for dep in deps:
            build_ruledag(dep)
    for job in self.targetjobs:
        build_ruledag(job)
    return self._dot(dag.keys(), print_wildcards=False, print_types=False, dag=dag)
def rule_dot2(self):
    dag = defaultdict(list)
    visited = set()
    preselect = set()

    def preselect_parents(job):
        for parent in self.depending[job]:
            if (parent in preselect):
                continue
            preselect.add(parent)
            preselect_parents(parent)

    def build_ruledag(job, key=(lambda job: job.rule.name)):
        if (job in visited):
            return
        visited.add(job)
        deps = sorted(self.dependencies[job], key=key)
        deps = [(group[0] if preselect.isdisjoint(group) else preselect.intersection(group).pop()) for group in (list(g) for (_, g) in groupby(deps, key))]
        dag[job].extend(deps)
        preselect_parents(job)
        for dep in deps:
            build_ruledag(dep)
    for job in self.targetjobs:
        build_ruledag(job)
    return self._dot(dag.keys(), print_wildcards=False, print_types=False, dag=dag)