|
1 # |
|
2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 # All rights reserved. |
|
4 # This component and the accompanying materials are made available |
|
5 # under the terms of "Eclipse Public License v1.0" |
|
6 # which accompanies this distribution, and is available |
|
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 # |
|
9 # Initial Contributors: |
|
10 # Nokia Corporation - initial contribution. |
|
11 # |
|
12 # Contributors: |
|
13 # |
|
14 # Description: |
|
15 # |
|
16 |
|
17 import os, logging, pickle |
|
18 import time |
|
19 from time import strftime |
|
20 from cone.public import api, exceptions, utils, plugin |
|
21 from cone.confml import model |
|
22 from cone.report import report_util |
|
23 |
|
24 ROOT_PATH = os.path.dirname(os.path.abspath(__file__)) |
|
25 SERIALISATION_FORMAT = 'pickle' |
|
26 |
|
27 def save_report_data(rep_data, file_path): |
|
28 """ |
|
29 Save report data into an intermediary report data file. |
|
30 """ |
|
31 dir = os.path.dirname(file_path) |
|
32 if dir != '' and not os.path.exists(dir): |
|
33 os.makedirs(dir) |
|
34 f = open(file_path, 'wb') |
|
35 try: |
|
36 if SERIALISATION_FORMAT == 'yaml': |
|
37 yaml.dump(rep_data, f) |
|
38 elif SERIALISATION_FORMAT == 'pickle': |
|
39 pickle.dump(rep_data, f) |
|
40 elif SERIALISATION_FORMAT == 'pickle/2': |
|
41 pickle.dump(rep_data, f, 2) |
|
42 finally: |
|
43 f.close() |
|
44 |
|
45 def load_report_data(file_path): |
|
46 """ |
|
47 Load report data from an intermediary report data file. |
|
48 """ |
|
49 try: |
|
50 f = open(file_path, "rb") |
|
51 if SERIALISATION_FORMAT == 'yaml': |
|
52 data = yaml.load(f) |
|
53 elif SERIALISATION_FORMAT == 'pickle': |
|
54 data = pickle.load(f) |
|
55 elif SERIALISATION_FORMAT == 'pickle/2': |
|
56 data = pickle.load(f) |
|
57 finally: |
|
58 f.close() |
|
59 |
|
60 data.label = get_generation_run_label(file_path) |
|
61 return data |
|
62 |
|
63 def get_generation_run_label(datafile_path): |
|
64 filename = os.path.split(datafile_path)[1] |
|
65 filename_noext = os.path.splitext(filename)[0] |
|
66 return filename_noext |
|
67 |
|
68 def _get_parent_sequence_or_self(feature): |
|
69 current = feature._parent |
|
70 while current is not None: |
|
71 if isinstance(current, api.FeatureSequence): |
|
72 return current |
|
73 current = current._parent |
|
74 return feature |
|
75 |
|
76 |
|
77 def generate_report(rep_data, report_file_path, template_file_path=None, template_paths=[], report_options=[]): |
|
78 """ |
|
79 Generate a generation report based on the given report data. |
|
80 @param rep_data: The report data. |
|
81 @param report_file_path: Path to the report file to generate. |
|
82 @param template_file_path: Path to the template file to use. |
|
83 If None, the default template is used. |
|
84 @param template_paths: the additional search paths for templates. The default location cone.report is |
|
85 always included. |
|
86 """ |
|
87 # Determine the template file and directory to use |
|
88 if template_file_path is None: |
|
89 template_file_path = 'gen_report_template.html' |
|
90 contexts = [report_data.context for report_data in rep_data] |
|
91 report_data = {'rep_data' : rep_data, |
|
92 'report_options' : report_options, |
|
93 'merged_context' : plugin.MergedContext(contexts)} |
|
94 report_util.generate_report(template_file_path, report_file_path, report_data, template_paths) |
|
95 |
|
96 def normalize_slash(path): |
|
97 """ |
|
98 Normalize backslashes to slashes to make testing easier (no differences |
|
99 between reports in linux and windows). |
|
100 """ |
|
101 return path.replace('\\', '/') |
|
102 |
|
103 class ReportData(object): |
|
104 """ |
|
105 Data object that stores all information used in report generation. |
|
106 """ |
|
107 |
|
108 def __init__(self): |
|
109 self.project = None |
|
110 self.generation_timestamp = time.time() |
|
111 self.generation_time = strftime("%d.%m.%Y %H:%M:%S") |
|
112 self.options = None |
|
113 self.duration = 0 |
|
114 self.output_dir = os.getcwd() |
|
115 self.project_dir = '' |
|
116 self.context = None |
|
117 self.label = '' |
|
118 |
|
119 def set_output_dir(self, dir): |
|
120 self.output_dir = os.path.abspath(os.path.normpath(dir)) |
|
121 |
|
122 def set_duration(self, duration): |
|
123 self.duration = duration |
|
124 |
|
125 def set_options(self, options): |
|
126 self.options = options |
|
127 self.project_dir = os.path.abspath(options.project) |
|
128 |
|
129 def set_report_filename(self, filename): |
|
130 self.report_filename = filename |
|
131 |
|
132 def __repr__(self): |
|
133 return "ReportData(%s)" % [self.generation_timestamp, |
|
134 self.generation_time, |
|
135 self.options, |
|
136 self.duration, |
|
137 self.output_dir, |
|
138 self.project_dir] |
|
139 |
|
140 |
|
141 class RefLine(object): |
|
142 """ |
|
143 Data object that stores information for one ref in report generation. |
|
144 """ |
|
145 |
|
146 def __init__(self, ref, type): |
|
147 self.ref = ref |
|
148 self.feat_type = type |
|
149 self.feat_name = None |
|
150 self.feat_value = None |
|
151 self.config_path = None |
|
152 self.impls = [] |
|
153 self.output = None |
|
154 self.nbr_impls = 0 |
|
155 self.nbr_outputfiles = 0 |
|
156 self.datas = [] |
|
157 self.nbr_of_datas = 0 |
|
158 self.nbr_of_rows = 0 |
|
159 self.seq_data = [] |
|
160 self.is_temp_feature = False |
|
161 |
|
162 def add_impl(self, impl_file, impl_type, outputfiles): |
|
163 self.impls.append(ImplLine(impl_file, impl_type, outputfiles)) |
|
164 self.nbr_impls = len(self.impls) |
|
165 self.nbr_outputfiles = len(outputfiles) + self.nbr_outputfiles |
|
166 |
|
167 def add_data(self, layer, value): |
|
168 self.datas.append(DataLine(layer,value)) |
|
169 self.nbr_of_datas = len(self.datas) |
|
170 |
|
171 def add_sequence(self, subsetting, values): |
|
172 self.seq_data.append([subsetting, values]) |
|
173 |
|
174 def set_feat_name(self, name): |
|
175 self.feat_name = name |
|
176 |
|
177 def set_feat_value(self, value): |
|
178 self.feat_value = value |
|
179 |
|
180 def set_config_path(self, filename): |
|
181 self.config_path = normalize_slash(os.path.normpath(filename)) |
|
182 |
|
183 |
|
184 class ImplLine(): |
|
185 def __init__(self, impl_file, impl_type, outputfiles, generation_runs=[]): |
|
186 self.name = normalize_slash(os.path.normpath(impl_file)) |
|
187 self.type = impl_type |
|
188 files = [] |
|
189 |
|
190 for outputfile in outputfiles: |
|
191 files.append(Outputfile(outputfile)) |
|
192 |
|
193 self.outputfiles = files |
|
194 self.generation_runs = generation_runs |
|
195 |
|
196 class Outputfile(): |
|
197 def __init__(self, filename): |
|
198 self.filename = normalize_slash(os.path.normpath(filename)) |
|
199 self.abs_filename = normalize_slash(os.path.abspath(filename)) |
|
200 self.exists = os.path.isfile(self.abs_filename) |
|
201 |
|
202 def __eq__(self, other): |
|
203 if type(self) is type(other): |
|
204 return self.filename == other.filename |
|
205 else: |
|
206 return False |
|
207 |
|
208 class DataLine(): |
|
209 def __init__(self, layer, value): |
|
210 self.layer = normalize_slash(os.path.normpath(layer)) |
|
211 self.value = value |