def make_tree_from_dotfile(stream): attributes = re.compile("\[.+\]") # # remember node # for linenum, line in enumerate(stream): line = line.strip() if "digraph" in line: continue if not len(line) or line[0] in '#{}/': continue line = line.strip(';') line = attributes.sub("", line) if "=" in line: continue nodes = [x.strip() for x in line.split('->')] for name1, name2 in adjacent_pairs_iterate(nodes): if not node._is_node(name1): node(name1) if not node._is_node(name2): node(name2) node._lookup_node_from_name(name2).add_child( node._lookup_node_from_name(name1)) # # task hack node._lookup_node_from_name(name2)._action = 1 node._lookup_node_from_name(name1)._action = 1
def make_tree_from_dotfile (stream): attributes = re.compile("\[.+\]") # # remember node # for linenum, line in enumerate(stream): line = line.strip() if "digraph" in line: continue; if not len(line) or line[0] in '#{}/': continue; line = line.strip(';') line = attributes.sub("", line) if "=" in line: continue; nodes = [x.strip() for x in line.split('->')] for name1, name2 in adjacent_pairs_iterate(nodes): if not node._is_node(name1): node(name1) if not node._is_node(name2): node(name2) node._lookup_node_from_name(name2).add_child(node._lookup_node_from_name(name1)) # # task hack node._lookup_node_from_name(name2)._action = 1 node._lookup_node_from_name(name1)._action = 1
def task_dependencies_from_dotfile(stream): """ Read programme task specified in dot file format """ decorator_regex = re.compile(r"([a-z_]+) *(\(.*)") attributes_regex = re.compile(r"\[.*\]") which_task_follows = defaultdict(list) task_decorators = defaultdict(list) task_descriptions = dict() # # remember node # all_tasks = dict() io_tasks = set() for linenum, line in enumerate(stream): # remove heading and trailing spaces line = line.strip() if "digraph" in line: continue if not len(line): continue # # decorators # if line[0:2] == '#@': fields = line[2:].split('::', 2) if len(fields) != 3: raise Exception( "Unexpected task specification on line# %d\n(%s)" % (linenum, line)) task_name, decorators, description = fields if decorators[0] != '@': raise Exception( "Task decorator missing starting ampersand '@' on line# %d\n(%s)" % (linenum, line)) for d in decorators[1:].split("@"): m = decorator_regex.match(d) if not m: raise Exception( "Task decorator (%s) missing parentheses on line# %d\n(%s)" % (d, linenum, line)) task_decorators[task_name].append((m.group(1), m.group(2))) if m.group(1)[0:5] == "files" or m.group(1) == "parallel": io_tasks.add(task_name) task_descriptions[task_name] = description continue # # other comments # if line[0] in '#{}/': continue line = line.strip(';') line = attributes_regex.sub("", line) # # ignore assignments # if "=" in line: continue nodes = map(lambda x: x.strip(), line.split('->')) for name1, name2 in adjacent_pairs_iterate(nodes): which_task_follows[name2].append(name1) all_tasks[name1] = 1 all_tasks[name2] = 1 for task in task_decorators: if task not in all_tasks: raise Exception("Decorated task %s not in dependencies") # order tasks by precedence the dump way: iterating until true disordered = True while (disordered): disordered = False for to_task, from_tasks in which_task_follows.iteritems(): for f in from_tasks: if all_tasks[to_task] <= all_tasks[f]: all_tasks[to_task] += all_tasks[f] disordered = True sorted_task_names = list( sorted(all_tasks.keys(), key=lambda x: all_tasks[x])) return which_task_follows, sorted_task_names, task_decorators, io_tasks, task_descriptions
def task_dependencies_from_dotfile(stream): """ Read programme task specified in dot file format """ decorator_regex = re.compile(r"([a-z_]+) *(\(.*)") attributes_regex = re.compile(r"\[.*\]") which_task_follows = defaultdict(list) task_decorators = defaultdict(list) task_descriptions = dict() # # remember node # all_tasks = dict() io_tasks = set() for linenum, line in enumerate(stream): # remove heading and trailing spaces line = line.strip() if "digraph" in line: continue; if not len(line): continue # # decorators # if line[0:2] == '#@': fields = line[2:].split('::', 2) if len(fields) != 3: raise Exception("Unexpected task specification on line# %d\n(%s)" % (linenum, line)) task_name, decorators, description = fields if decorators[0] != '@': raise Exception("Task decorator missing starting ampersand '@' on line# %d\n(%s)" % (linenum, line)) for d in decorators[1:].split("@"): m = decorator_regex.match(d) if not m: raise Exception("Task decorator (%s) missing parentheses on line# %d\n(%s)" % (d, linenum, line)) task_decorators[task_name].append((m.group(1), m.group(2))) if m.group(1)[0:5] == "files" or m.group(1) == "parallel": io_tasks.add(task_name) task_descriptions[task_name] = description continue # # other comments # if line[0] in '#{}/': continue; line = line.strip(';') line = attributes_regex.sub("", line) # # ignore assignments # if "=" in line: continue; nodes = map(lambda x: x.strip(), line.split('->')) for name1, name2 in adjacent_pairs_iterate(nodes): which_task_follows[name2].append(name1) all_tasks[name1] = 1 all_tasks[name2] = 1 for task in task_decorators: if task not in all_tasks: raise Exception("Decorated task %s not in dependencies") # order tasks by precedence the dump way: iterating until true disordered = True while (disordered): disordered = False for to_task, from_tasks in which_task_follows.iteritems(): for f in from_tasks: if all_tasks[to_task] <= all_tasks[f]: all_tasks[to_task] += all_tasks[f] disordered = True sorted_task_names = list(sorted(all_tasks.keys(), key=lambda x:all_tasks[x])) return which_task_follows, sorted_task_names, task_decorators, io_tasks, task_descriptions
def write_legend_key (stream, used_task_types, minimal_key_legend, colour_scheme, key_name = "Key:", subgraph_index = 1): """ Write legend/key to dependency tree graph """ if not len(used_task_types): return stream.write( 'subgraph clusterkey%d\n' % subgraph_index) stream.write( '{\n') stream.write( 'rank="min";\n') stream.write( 'style=filled;\n') #stream.write( 'fontsize=30;\n') stream.write( 'color=%s;\n' % (colour_scheme["Key"]["fillcolor"])) stream.write( 'label = "%s";\n' % key_name) stream.write( 'fontcolor = %s;' % (colour_scheme["Key"]["fontcolor"])) stream.write( 'node[margin=0.2,0.2];\n') # # Only include used task types # all_task_types = [ "Vicious cycle" , "Down stream" , "Up-to-date task" , "Explicitly specified task" , "Task to run" , "Up-to-date task forced to rerun" , "Up-to-date Final target" , "Final target" ,] if not minimal_key_legend: used_task_types |= set(all_task_types) wrapped_task_types = [ "Vicious cycle" , "Down stream" , "Up-to-date task" , "Explicitly specified task" , "Task to run" , "Up-to-date task\\nforced to rerun" , "Up-to-date\\nFinal target" , "Final target" ,] wrapped_task_types = dict(zip(all_task_types, wrapped_task_types)) def outputkey (key, task_type, stream): ignore_used_task_types = set() attributes = dict() attributes["shape"]="box3d" #attributes["shape"] = "rect" get_dot_format_for_task_type (task_type, attributes, colour_scheme, ignore_used_task_types) #attributes["fontsize"] = '15' stream.write(key + attributes_to_str(attributes, wrapped_task_types[task_type])) sorted_used_task_types = [] for t in all_task_types: if t in used_task_types: sorted_used_task_types.append(t) # print first key type outputkey("k1_%d" % subgraph_index, sorted_used_task_types[0], stream) for i, (from_task_type, to_task_type) in enumerate(adjacent_pairs_iterate(sorted_used_task_types)): from_key = 'k%d_%d' % (i + 1, subgraph_index) to_key = 'k%d_%d' % (i + 2, subgraph_index) # write key outputkey(to_key, to_task_type, stream) # connection between keys stream.write(get_arrow_str_for_legend_key (from_task_type, to_task_type, from_key, to_key, colour_scheme)) stream.write("}\n")