2015-04-30 17:36:36 +02:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
2015-05-04 12:30:31 +02:00
|
|
|
"""
|
2015-06-23 18:43:56 +02:00
|
|
|
Module utilitary
|
2015-05-04 12:30:31 +02:00
|
|
|
|
|
|
|
Usage:
|
2015-06-23 18:43:56 +02:00
|
|
|
module_handler.py print_descendant [<module_name>...]
|
|
|
|
module_handler.py create_png [<module_name>...]
|
|
|
|
module_handler.py clean [<module_name>...]
|
2015-06-25 16:52:08 +02:00
|
|
|
module_handler.py create_git_ignore [<module_name>...]
|
2015-05-04 15:03:53 +02:00
|
|
|
|
|
|
|
Options:
|
2015-06-04 16:40:00 +02:00
|
|
|
print_descendant Print the genealogy of the NEEDED_CHILDREN_MODULES
|
2015-05-04 15:36:58 +02:00
|
|
|
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
|
2015-05-04 12:30:31 +02:00
|
|
|
"""
|
2015-04-30 17:36:36 +02:00
|
|
|
import os
|
2015-05-04 14:44:30 +02:00
|
|
|
import sys
|
2015-04-30 17:36:36 +02:00
|
|
|
import os.path
|
2015-06-25 16:52:08 +02:00
|
|
|
import shutil
|
2015-05-27 11:02:13 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
try:
|
|
|
|
from docopt import docopt
|
2015-06-23 10:04:59 +02:00
|
|
|
from qp_path import QP_SRC
|
2015-06-04 16:40:00 +02:00
|
|
|
except ImportError:
|
|
|
|
print "source .quantum_package.rc"
|
|
|
|
raise
|
2015-05-27 11:02:13 +02:00
|
|
|
|
|
|
|
|
2015-06-01 19:32:02 +02:00
|
|
|
# Canot cache for namedtuple are not hashable
|
2015-06-23 18:43:56 +02:00
|
|
|
def is_module(path_module):
|
2015-06-23 18:46:09 +02:00
|
|
|
return os.path.isfile(os.path.join(QP_SRC,
|
|
|
|
path_module,
|
|
|
|
"NEEDED_CHILDREN_MODULES"))
|
2015-06-23 18:43:56 +02:00
|
|
|
|
|
|
|
|
2015-06-25 16:52:08 +02:00
|
|
|
def is_exe(fpath):
|
|
|
|
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
|
|
|
|
|
|
|
|
2015-06-09 16:34:52 +02:00
|
|
|
def get_dict_child(l_root_abs=None):
|
2015-06-08 14:49:10 +02:00
|
|
|
"""Loop over MODULE in QP_ROOT/src, open all the NEEDED_CHILDREN_MODULES
|
2015-05-04 10:30:22 +02:00
|
|
|
and create a dict[MODULE] = [sub module needed, ...]
|
|
|
|
"""
|
2015-04-30 17:36:36 +02:00
|
|
|
d_ref = dict()
|
|
|
|
|
2015-06-09 16:34:52 +02:00
|
|
|
if not l_root_abs:
|
2015-06-23 10:04:59 +02:00
|
|
|
l_root_abs = [QP_SRC]
|
2015-06-09 16:34:52 +02:00
|
|
|
|
|
|
|
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
|
2015-06-09 16:06:01 +02:00
|
|
|
else:
|
2015-06-09 16:34:52 +02:00
|
|
|
if module_rel not in d_ref:
|
|
|
|
d_ref[module_rel] = l_children
|
|
|
|
else:
|
|
|
|
print "Module {0} alredy defined"
|
|
|
|
print "Abort"
|
|
|
|
sys.exit(1)
|
2015-04-30 17:36:36 +02:00
|
|
|
|
2015-05-27 11:02:13 +02:00
|
|
|
return d_ref
|
2015-04-30 17:36:36 +02:00
|
|
|
|
|
|
|
|
2015-06-09 19:20:18 +02:00
|
|
|
def get_l_module_descendant(d_child, l_module):
|
2015-04-30 17:36:36 +02:00
|
|
|
"""
|
2015-06-09 15:08:06 +02:00
|
|
|
From a list of module return the module and descendant
|
2015-04-30 17:36:36 +02:00
|
|
|
"""
|
2015-05-04 10:30:22 +02:00
|
|
|
|
|
|
|
l = []
|
2015-04-30 17:36:36 +02:00
|
|
|
for module in l_module:
|
|
|
|
if module not in l:
|
|
|
|
l.append(module)
|
2015-05-04 14:44:30 +02:00
|
|
|
try:
|
2015-06-09 19:20:18 +02:00
|
|
|
l.extend(get_l_module_descendant(d_child, d_child[module]))
|
2015-05-04 14:44:30 +02:00
|
|
|
except KeyError:
|
2015-06-02 18:40:24 +02:00
|
|
|
print >> sys.stderr, "`{0}` not submodule".format(module)
|
2015-05-04 14:44:30 +02:00
|
|
|
print >> sys.stderr, "Check the corresponding NEEDED_CHILDREN_MODULES"
|
2015-06-30 10:34:28 +02:00
|
|
|
raise
|
2015-04-30 17:36:36 +02:00
|
|
|
|
|
|
|
return list(set(l))
|
|
|
|
|
|
|
|
|
2015-06-09 16:06:01 +02:00
|
|
|
class ModuleHandler():
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-09 16:34:52 +02:00
|
|
|
def __init__(self, l_root_abs=None):
|
|
|
|
self.dict_child = get_dict_child(l_root_abs)
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-09 16:06:01 +02:00
|
|
|
@property
|
2015-06-04 16:40:00 +02:00
|
|
|
def l_module(self):
|
|
|
|
return self.dict_child.keys()
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-09 16:06:01 +02:00
|
|
|
@property
|
2015-06-04 16:40:00 +02:00
|
|
|
def dict_parent(self):
|
|
|
|
"""
|
|
|
|
Get a dic of the first parent
|
|
|
|
"""
|
|
|
|
d_child = self.dict_child
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
d = {}
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
for module_name in d_child:
|
|
|
|
d[module_name] = [i for i in d_child.keys() if module_name in d_child[i]]
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
return d
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-09 16:06:01 +02:00
|
|
|
@property
|
2015-06-04 16:40:00 +02:00
|
|
|
def dict_descendant(self):
|
|
|
|
"""
|
|
|
|
Get a dic of all the genealogy desc (children and all_children)
|
|
|
|
"""
|
|
|
|
d = {}
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
d_child = self.dict_child
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
for module_name in d_child:
|
2015-06-30 10:34:28 +02:00
|
|
|
try :
|
|
|
|
d[module_name] = get_l_module_descendant(d_child,
|
|
|
|
d_child[module_name])
|
|
|
|
except KeyError:
|
|
|
|
print "Check NEEDED_CHILDREN_MODULES for {0}".format(module_name)
|
|
|
|
sys.exit(1)
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
return d
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-09 16:06:01 +02:00
|
|
|
@property
|
2015-06-04 16:40:00 +02:00
|
|
|
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
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
l_all_module = self.l_module
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
dict_root = {}
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
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]
|
2015-06-02 15:47:24 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
return dict_root
|
2015-05-04 10:30:22 +02:00
|
|
|
|
2015-06-09 16:06:01 +02:00
|
|
|
def l_descendant_unique(self, l_module):
|
|
|
|
d_desc = self.dict_descendant
|
2015-05-13 15:32:55 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
d = {}
|
|
|
|
for module in l_module:
|
|
|
|
for e in d_desc[module]:
|
|
|
|
d[e] = 1
|
2015-05-13 15:32:55 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
return d.keys()
|
2015-05-13 15:32:55 +02:00
|
|
|
|
2015-06-09 16:06:01 +02:00
|
|
|
def l_reduce_tree(self, l_module):
|
2015-06-05 09:50:24 +02:00
|
|
|
"""For a list of module in input return only the root"""
|
2015-06-09 16:06:01 +02:00
|
|
|
l_d_u = self.l_descendant_unique(l_module)
|
2015-06-04 16:40:00 +02:00
|
|
|
l_module_reduce = []
|
|
|
|
for module in l_module:
|
|
|
|
if module not in l_d_u:
|
|
|
|
l_module_reduce.append(module)
|
2015-05-13 18:15:01 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
return l_module_reduce
|
2015-05-04 12:30:31 +02:00
|
|
|
|
2015-06-09 16:06:01 +02:00
|
|
|
def create_png(self, l_module):
|
2015-06-04 16:40:00 +02:00
|
|
|
"""Create the png of the dependency tree for a l_module"""
|
2015-05-04 12:30:31 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
# Init
|
|
|
|
import pydot
|
|
|
|
all_ready_done = []
|
2015-05-04 12:30:31 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
def draw_module_edge(module, l_children):
|
|
|
|
"Draw all the module recursifly"
|
2015-05-04 12:30:31 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
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)
|
2015-05-04 12:30:31 +02:00
|
|
|
|
2015-06-19 19:13:35 +02:00
|
|
|
path = '{0}.png'.format("tree_dependency")
|
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
# Init
|
2015-06-19 19:13:35 +02:00
|
|
|
try:
|
|
|
|
graph = pydot.Dot(graph_type='digraph')
|
|
|
|
except:
|
|
|
|
with open(path, 'a'):
|
|
|
|
os.utime(path, None)
|
|
|
|
return
|
|
|
|
|
2015-06-09 16:06:01 +02:00
|
|
|
d_ref = self.dict_child
|
2015-05-04 12:30:31 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
# 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])
|
2015-05-04 12:30:31 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
# Save
|
|
|
|
graph.write_png(path)
|
2015-05-04 12:30:31 +02:00
|
|
|
|
2015-06-02 18:40:24 +02:00
|
|
|
|
2015-04-30 17:36:36 +02:00
|
|
|
if __name__ == '__main__':
|
|
|
|
|
2015-05-04 12:30:31 +02:00
|
|
|
arguments = docopt(__doc__)
|
|
|
|
|
2015-06-23 18:43:56 +02:00
|
|
|
if not arguments['<module_name>']:
|
2015-05-04 12:30:31 +02:00
|
|
|
dir_ = os.getcwd()
|
2015-06-23 18:43:56 +02:00
|
|
|
l_module = [os.path.basename(dir_)]
|
2015-05-04 12:30:31 +02:00
|
|
|
else:
|
2015-06-23 18:43:56 +02:00
|
|
|
l_module = arguments['<module_name>']
|
2015-06-23 18:46:09 +02:00
|
|
|
|
|
|
|
for module in l_module:
|
|
|
|
if not is_module(module):
|
2015-06-30 10:10:38 +02:00
|
|
|
print "{0} is not a valide module. Abort".format(module)
|
2015-06-24 09:02:22 +02:00
|
|
|
print "No NEEDED_CHILDREN_MODULES in it"
|
2015-06-23 18:46:09 +02:00
|
|
|
sys.exit(1)
|
|
|
|
|
2015-06-09 16:06:01 +02:00
|
|
|
m = ModuleHandler()
|
2015-06-01 19:32:02 +02:00
|
|
|
|
2015-06-04 16:40:00 +02:00
|
|
|
if arguments['print_descendant']:
|
2015-06-23 18:43:56 +02:00
|
|
|
|
|
|
|
for module in l_module:
|
|
|
|
print " ".join(sorted(m.l_descendant_unique([module])))
|
2015-05-04 12:30:31 +02:00
|
|
|
|
2015-05-13 15:32:55 +02:00
|
|
|
if arguments["create_png"]:
|
2015-06-23 18:43:56 +02:00
|
|
|
m.create_png(l_module)
|
|
|
|
|
2015-06-25 16:52:08 +02:00
|
|
|
if arguments["clean"] or arguments["create_git_ignore"]:
|
2015-06-24 09:02:22 +02:00
|
|
|
|
2015-06-25 16:52:08 +02:00
|
|
|
l_dir = ['IRPF90_temp', 'IRPF90_man']
|
|
|
|
l_file = ["irpf90_entities", "tags", "irpf90.make",
|
2015-06-30 10:10:38 +02:00
|
|
|
"Makefile", "Makefile.depend", ".ninja_log", ".ninja_deps",
|
2015-06-25 16:52:08 +02:00
|
|
|
"ezfio_interface.irp.f"]
|
2015-06-24 09:02:22 +02:00
|
|
|
|
2015-06-25 16:52:08 +02:00
|
|
|
for module in l_module:
|
|
|
|
module_abs = os.path.realpath(os.path.join(QP_SRC, module))
|
|
|
|
l_symlink = m.l_descendant_unique([module])
|
|
|
|
l_exe = [f for f in os.listdir(module_abs) if is_exe(os.path.join(module_abs,f))]
|
2015-06-24 09:02:22 +02:00
|
|
|
|
2015-06-25 16:52:08 +02:00
|
|
|
if arguments["clean"]:
|
|
|
|
for f in l_dir:
|
|
|
|
try:
|
|
|
|
shutil.rmtree(os.path.join(module_abs, f))
|
|
|
|
except:
|
|
|
|
pass
|
2015-06-24 09:02:22 +02:00
|
|
|
|
2015-06-25 16:52:08 +02:00
|
|
|
for symlink in l_symlink:
|
|
|
|
try:
|
|
|
|
os.unlink(os.path.join(module_abs, symlink))
|
|
|
|
except:
|
|
|
|
pass
|
2015-06-24 12:25:19 +02:00
|
|
|
|
2015-06-25 16:52:08 +02:00
|
|
|
for f in l_file:
|
|
|
|
try:
|
|
|
|
os.remove(os.path.join(module_abs, f))
|
|
|
|
except:
|
|
|
|
pass
|
2015-06-24 12:25:19 +02:00
|
|
|
|
2015-06-25 16:52:08 +02:00
|
|
|
for f in l_exe:
|
2015-06-24 12:25:19 +02:00
|
|
|
|
|
|
|
try:
|
|
|
|
os.remove(os.path.join(module_abs, f))
|
|
|
|
except:
|
|
|
|
pass
|
2015-06-25 16:52:08 +02:00
|
|
|
|
|
|
|
if arguments["create_git_ignore"]:
|
|
|
|
path = os.path.join(module_abs, ".gitignore")
|
|
|
|
|
|
|
|
with open(path, "w+") as f:
|
|
|
|
f.write("# Automatically created by {0} \n".format(__file__))
|
|
|
|
f.write("\n".join(l_dir + l_file + l_symlink + l_exe))
|