90 |
100 |
91 if len(files) == 0: |
101 if len(files) == 0: |
92 parser.error("At least one input data file must be specified.") |
102 parser.error("At least one input data file must be specified.") |
93 |
103 |
94 |
104 |
95 class DataEntry(object): |
|
96 def __init__(self, label, data): |
|
97 self.label = label |
|
98 self.data = data |
|
99 |
105 |
100 # Load all data files |
106 # Load all data files |
101 data_entries = [] |
107 data_reports = [] |
102 for data_file in files: |
108 for data_file in files: |
103 print "Loading data file '%s'" % data_file |
109 print "Loading data file '%s'" % data_file |
104 label = get_generation_run_label(data_file) |
|
105 data = generation_report.load_report_data(data_file) |
110 data = generation_report.load_report_data(data_file) |
106 data_entries.append(DataEntry(label, data)) |
111 data_reports.append(data) |
107 |
112 |
108 # Sort by time stamp |
113 # Sort by time stamp |
109 data_entries.sort(key=lambda entry: entry.data.generation_timestamp) |
114 data_reports.sort(key=lambda entry: entry.generation_timestamp) |
110 |
115 |
111 # Use the first data object as the main report data |
116 # Generate the report |
112 main_entry = data_entries[0] |
117 print "Generating report to '%s'" % options.report |
|
118 generation_report.generate_report(data_reports, options.report, options.template, [ROOT_PATH], options.report_option) |
113 |
119 |
114 # Merge the rest of the data objects into the main data |
120 print "Done!'" |
115 if len(data_entries) > 1: |
|
116 # Update the generation_runs attribute of all implementations |
|
117 # in the main data |
|
118 for line in main_entry.data.lines: |
|
119 for impl in line.impls: |
|
120 impl.generation_runs = [main_entry.label] |
|
121 |
|
122 # Load other report data files and merge them to the main data object |
|
123 for i in xrange(len(data_entries) - 1): |
|
124 entry = data_entries[i + 1] |
|
125 print "Merging data for '%s'" % entry.label |
|
126 merge_report_data(main_entry.data, entry.data, entry.label) |
|
127 |
|
128 # Generate the report |
|
129 main_entry.data.report_filename = options.report |
|
130 generation_report.generate_report(main_entry.data, options.report, options.template) |
|
131 |
|
132 print "Generated report to '%s'" % options.report |
|
133 |
121 |
134 def get_input_data_files(directory): |
122 def get_input_data_files(directory): |
135 files = [] |
123 files = [] |
136 for name in os.listdir(directory): |
124 for name in os.listdir(directory): |
137 path = os.path.join(directory, name) |
125 path = os.path.join(directory, name) |
138 if os.path.isfile(path): |
126 if os.path.isfile(path): |
139 files.append(path) |
127 files.append(path) |
140 return files |
128 return files |
141 |
|
142 |
129 |
143 def get_generation_run_label(datafile_path): |
|
144 filename = os.path.split(datafile_path)[1] |
|
145 filename_noext = os.path.splitext(filename)[0] |
|
146 return filename_noext |
|
147 |
|
148 def get_feature(rep_data, ref): |
|
149 for feat in rep_data.lines: |
|
150 if feat.ref == ref: |
|
151 return feat |
|
152 raise RuntimeError("Feature '%s' not found in refs with impl" % ref) |
|
153 |
|
154 def get_impl(rep_data, ref, impl_name): |
|
155 feat = get_feature(rep_data, ref) |
|
156 for impl in feat.impls: |
|
157 if impl.name == impl_name: |
|
158 return impl |
|
159 raise RuntimeError("Impl '%s' not found for feature '%s'" % (impl_name, ref)) |
|
160 |
|
161 def merge_report_data(data, data_to_merge, generation_run_label): |
|
162 impls_by_ref = {} |
|
163 for feat in data.lines: |
|
164 impls_dict = {} |
|
165 impls_by_ref[feat.ref] = impls_dict |
|
166 for impl in feat.impls: |
|
167 impls_dict[impl.name] = impl |
|
168 |
|
169 for feat in data_to_merge.lines: |
|
170 if feat.ref in impls_by_ref: |
|
171 # Feature has implementations in both report data objects |
|
172 # ------------------------------------------------------- |
|
173 impls_dict = impls_by_ref[feat.ref] |
|
174 |
|
175 for impl in feat.impls: |
|
176 if impl.name in impls_dict: |
|
177 # Same implementation in both: add the generation run to merge to the impl |
|
178 impl = get_impl(data, feat.ref, impl.name) |
|
179 impl.generation_runs.append(generation_run_label) |
|
180 else: |
|
181 # Implementation only in the data to merge: add to the main data |
|
182 impl = get_impl(data_to_merge, feat.ref, impl.name) |
|
183 impl.generation_runs = [generation_run_label] |
|
184 feat = get_feature(data, feat.ref) |
|
185 feat.impls.append(impl) |
|
186 feat.nbr_impls += 1 |
|
187 else: |
|
188 # Feature has implementations only in the data to merge |
|
189 # ----------------------------------------------------- |
|
190 |
|
191 # Add the feature and impls to the main data |
|
192 feat = get_feature(data_to_merge, feat.ref) |
|
193 for impl in feat.impls: |
|
194 impl.generation_runs = [generation_run_label] |
|
195 data.lines.append(feat) |
|
196 data.nbr_of_refs += 1 |
|
197 |
|
198 # Remove from features with no impl in the main data |
|
199 for i, noimpl_feat in enumerate(data.ref_noimpl): |
|
200 if feat.ref == noimpl_feat.ref: |
|
201 del data.ref_noimpl[i] |
|
202 data.nbr_of_refs_noimpl -= 1 |
|
203 break |
|
204 |
130 |
205 if __name__ == "__main__": |
131 if __name__ == "__main__": |
206 main() |
132 main() |