#!/usr/bin/env python # -*- coding: utf-8 -*- """ Module utilitary Usage: module_handler.py print_descendant [...] module_handler.py create_png [...] module_handler.py clean [...] Options: print_descendant Print the genealogy of the NEEDED_CHILDREN_MODULES aka (children, subchildren, etc) create_png Create a png of the file NEEDED_CHILDREN_MODULES The path of NEEDED_CHILDREN_MODULES by default try to open the file in the current path """ import os import sys import os.path try: from docopt import docopt from qp_path import QP_SRC except ImportError: print "source .quantum_package.rc" raise # Canot cache for namedtuple are not hashable def is_module(path_module): return os.path.isfile(os.path.join(QP_SRC, path_module, "NEEDED_CHILDREN_MODULES")) def get_dict_child(l_root_abs=None): """Loop over MODULE in QP_ROOT/src, open all the NEEDED_CHILDREN_MODULES and create a dict[MODULE] = [sub module needed, ...] """ d_ref = dict() if not l_root_abs: l_root_abs = [QP_SRC] for root_abs in l_root_abs: for module_rel in os.listdir(root_abs): module_abs = os.path.join(root_abs, module_rel) try: path_file = os.path.join(module_abs, "NEEDED_CHILDREN_MODULES") with open(path_file, "r") as f: l_children = f.read().split() except IOError: pass else: if module_rel not in d_ref: d_ref[module_rel] = l_children else: print "Module {0} alredy defined" print "Abort" sys.exit(1) return d_ref def get_l_module_descendant(d_child, l_module): """ From a list of module return the module and descendant """ l = [] for module in l_module: if module not in l: l.append(module) try: l.extend(get_l_module_descendant(d_child, d_child[module])) except KeyError: print >> sys.stderr, "`{0}` not submodule".format(module) print >> sys.stderr, "Check the corresponding NEEDED_CHILDREN_MODULES" sys.exit(1) return list(set(l)) class ModuleHandler(): def __init__(self, l_root_abs=None): self.dict_child = get_dict_child(l_root_abs) @property def l_module(self): return self.dict_child.keys() @property def dict_parent(self): """ Get a dic of the first parent """ d_child = self.dict_child d = {} for module_name in d_child: d[module_name] = [i for i in d_child.keys() if module_name in d_child[i]] return d @property def dict_descendant(self): """ Get a dic of all the genealogy desc (children and all_children) """ d = {} d_child = self.dict_child for module_name in d_child: d[module_name] = get_l_module_descendant(d_child, d_child[module_name]) return d @property def dict_root(self): """ Return a dict(module_name) = module_boss The top node in a tree. """ d_asc = self.dict_parent d_desc = self.dict_descendant l_all_module = self.l_module dict_root = {} for module in l_all_module: dict_root[module] = [ p for p in l_all_module if module in [p] + d_desc[p] and not d_asc[p]][0] return dict_root def l_descendant_unique(self, l_module): d_desc = self.dict_descendant d = {} for module in l_module: for e in d_desc[module]: d[e] = 1 return d.keys() def l_reduce_tree(self, l_module): """For a list of module in input return only the root""" l_d_u = self.l_descendant_unique(l_module) l_module_reduce = [] for module in l_module: if module not in l_d_u: l_module_reduce.append(module) return l_module_reduce def create_png(self, l_module): """Create the png of the dependency tree for a l_module""" # Init import pydot all_ready_done = [] def draw_module_edge(module, l_children): "Draw all the module recursifly" if module not in all_ready_done: for children in l_children: # Add Edge edge = pydot.Edge(module, children) graph.add_edge(edge) # Recurs draw_module_edge(children, d_ref[children]) all_ready_done.append(module) path = '{0}.png'.format("tree_dependency") # Init try: graph = pydot.Dot(graph_type='digraph') except: with open(path, 'a'): os.utime(path, None) return d_ref = self.dict_child # Create all the edge for module in l_module: node_a = pydot.Node(module, fontcolor="red") graph.add_node(node_a) draw_module_edge(module, d_ref[module]) # Save graph.write_png(path) if __name__ == '__main__': arguments = docopt(__doc__) if not arguments['']: dir_ = os.getcwd() l_module = [os.path.basename(dir_)] else: l_module = arguments[''] for module in l_module: if not is_module(module): print "{0} is not a volide module. Abort".format(module) print "No NEEDED_CHILDREN_MODULES in it" sys.exit(1) m = ModuleHandler() if arguments['print_descendant']: for module in l_module: print " ".join(sorted(m.l_descendant_unique([module]))) if arguments["create_png"]: m.create_png(l_module) if arguments["clean"]: for module in l_module: module_abs = os.path.realpath(os.path.join(QP_SRC, module)) import shutil for f in ['IRPF90_temp', 'IRPF90_man']: try: shutil.rmtree(os.path.join(module_abs, f)) except: pass for symlink in m.l_descendant_unique([module]): try: os.unlink(os.path.join(module_abs,symlink)) except: pass for f in ["irpf90_entities", "tags", "irpf90.make", "Makefile"]: try: os.remove(os.path.join(module_abs,f)) except: pass