Add the option to copy tree in addition to making a symlink tree from elsewhere.
[htsworkflow.git] / htsworkflow / submission / results.py
1 """Help collect and process results for submission
2 """
3 from collections import MutableMapping
4 import os
5 import shutil
6 import logging
7
8 from collections import namedtuple
9
10 LOGGER = logging.getLogger(__name__)
11
12 class ResultMap(MutableMapping):
13     """Store list of results
14     """
15     def __init__(self):
16         self.results_order = []
17         self.results = {}
18
19     def __iter__(self):
20         for item in self.results_order:
21             yield item
22
23     def __len__(self):
24         l = len(self.results)
25         assert l == len(self.results_order)
26         return l
27
28     def __setitem__(self, key, value):
29         self.results_order.append(key)
30         self.results[key] = value
31
32     def __getitem__(self, key):
33         return self.results[key]
34
35     def __delitem__(self, key):
36         del self.results[key]
37         i = self.results_order.index(key)
38         del self.results_order[i]
39
40     def add_results_from_file(self, filename):
41         pathname = os.path.abspath(filename)
42         basepath, name = os.path.split(pathname)
43         results = read_result_list(filename)
44         for lib_id, lib_path in results:
45             if not os.path.isabs(lib_path):
46                 lib_path = os.path.join(basepath, lib_path)
47             self[lib_id] = lib_path
48
49     def make_tree_from(self, source_path, destpath = None, link=True):
50         """Create a tree using data files from source path.
51         """
52         if destpath is None:
53             destpath = os.getcwd()
54
55         LOGGER.debug("Source_path: %s", source_path)
56         LOGGER.debug("Dest_path: %s", destpath)
57         for lib_id in self.results_order:
58             lib_path = self.results[lib_id]
59             LOGGER.debug("lib_path: %s", lib_path)
60             if os.path.isabs(lib_path):
61                 lib_path = os.path.relpath(lib_path, destpath)
62
63             LOGGER.debug('lib_path: %s', lib_path)
64             lib_destination = os.path.join(destpath, lib_path)
65             if not os.path.exists(lib_destination):
66                 LOGGER.info("Making dir {0}".format(lib_destination))
67                 os.mkdir(lib_destination)
68
69             source_rel_dir = os.path.join(source_path, lib_path)
70             source_lib_dir = os.path.abspath(source_rel_dir)
71             LOGGER.debug("source_lib_dir: %s", source_lib_dir)
72
73             for filename in os.listdir(source_lib_dir):
74                 source_pathname = os.path.join(source_lib_dir, filename)
75                 target_pathname = os.path.join(lib_destination, filename)
76                 if not os.path.exists(source_pathname):
77                     raise IOError(
78                         "{0} does not exist".format(source_pathname))
79                 if not (os.path.exists(target_pathname) or os.path.isdir(source_pathname)):
80                     if link:
81                         os.symlink(source_pathname, target_pathname)
82                     else:
83                         shutil.copy(source_pathname, target_pathname)
84                     LOGGER.info(
85                         'LINK {0} to {1}'.format(source_pathname,
86                                                  target_pathname))
87
88 def read_result_list(filename):
89     """
90     Read a file that maps library id to result directory.
91     Does not support spaces in filenames.
92
93     For example:
94       10000 result/foo/bar
95     """
96     stream = open(filename, 'r')
97     results = parse_result_list(stream)
98     stream.close()
99     return results
100
101
102 def parse_result_list(stream):
103     results = []
104     for line in stream:
105         line = line.rstrip()
106         if not line.startswith('#') and len(line) > 0:
107             library_id, result_dir = line.split()
108             results.append((library_id, result_dir))
109     return results