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