configurationengine/source/scripts/conesub_report.py
changeset 0 2e8eeb919028
child 3 e7e0ae78773e
equal deleted inserted replaced
-1:000000000000 0:2e8eeb919028
       
     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
       
    18 import logging
       
    19 import pickle
       
    20 from optparse import OptionParser, OptionGroup
       
    21 import cone_common
       
    22 import generation_report
       
    23 from cone.public import api, plugin, utils, exceptions
       
    24 
       
    25 
       
    26 VERSION     = '1.0'
       
    27 
       
    28 logger    = logging.getLogger('cone')
       
    29 
       
    30 def main():
       
    31     parser = OptionParser(version="%%prog %s" % VERSION)
       
    32     
       
    33     parser.add_options(cone_common.COMMON_OPTIONS)
       
    34     
       
    35     group = OptionGroup(parser, 'Report options',
       
    36                         'The report function generates a report using previously generated '\
       
    37                         'intermediary report data as input.')
       
    38     
       
    39     group.add_option("-i", "--input-data",\
       
    40                         action="append",\
       
    41                         help="Defines an input file for report generation. "\
       
    42                              "If specified more than once, the data of all specified "\
       
    43                              "report data files is merged.",
       
    44                         metavar="FILE",
       
    45                         default=[])
       
    46     
       
    47     group.add_option("-d", "--input-data-dir",\
       
    48                         help="Defines a directory containing the data files to use for "\
       
    49                              "generating the report. This is an alternative to specifying "\
       
    50                              "a number of --input-data files. The order of the data files "\
       
    51                              "is determined by the generation time stamps found in the data "\
       
    52                              "files.",
       
    53                         metavar="DIR",
       
    54                         default=None)
       
    55     
       
    56     group.add_option("-r", "--report",\
       
    57                    dest="report",\
       
    58                    action="store",
       
    59                    type="string",
       
    60                    help="Specifies the report file to create."\
       
    61                         "Example -r report.html.",
       
    62                    metavar="FILE",\
       
    63                    default="report.html")
       
    64     
       
    65     group.add_option("-t", "--template",\
       
    66                    dest="template",\
       
    67                    action="store",
       
    68                    type="string",
       
    69                    help="Template used in report generation."\
       
    70                         "Example -t report_template.html.",
       
    71                    metavar="FILE",\
       
    72                    default=None)
       
    73     
       
    74     parser.add_option_group(group)
       
    75     (options, args) = parser.parse_args()
       
    76     
       
    77     cone_common.handle_common_options(options)
       
    78     
       
    79     if len(options.input_data) == 0 and not options.input_data_dir:
       
    80         parser.error("Input data must be specified with either --input-data or --input-data-dir")
       
    81     if len(options.input_data) > 0 and options.input_data_dir:
       
    82         parser.error("Both --input-data and --input-data-dir specified, use one or the other.")
       
    83     if options.input_data_dir and not os.path.isdir(options.input_data_dir):
       
    84         parser.error('Given --input-data-dir does not exist or is not a directory.')
       
    85     
       
    86     if options.input_data:
       
    87         files = options.input_data
       
    88     else:
       
    89         files = get_input_data_files(options.input_data_dir)
       
    90     
       
    91     if len(files) == 0:
       
    92         parser.error("At least one input data file must be specified.")
       
    93     
       
    94     
       
    95     class DataEntry(object):
       
    96         def __init__(self, label, data):
       
    97             self.label = label
       
    98             self.data = data
       
    99     
       
   100     # Load all data files
       
   101     data_entries = []
       
   102     for data_file in files:
       
   103         print "Loading data file '%s'" % data_file
       
   104         label = get_generation_run_label(data_file)
       
   105         data = generation_report.load_report_data(data_file)
       
   106         data_entries.append(DataEntry(label, data))
       
   107     
       
   108     # Sort by time stamp
       
   109     data_entries.sort(key=lambda entry: entry.data.generation_timestamp)
       
   110     
       
   111     # Use the first data object as the main report data
       
   112     main_entry = data_entries[0]
       
   113     
       
   114     # Merge the rest of the data objects into the main data
       
   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 
       
   134 def get_input_data_files(directory):
       
   135     files = []
       
   136     for name in os.listdir(directory):
       
   137         path = os.path.join(directory, name)
       
   138         if os.path.isfile(path):
       
   139             files.append(path)
       
   140     return files
       
   141     
       
   142 
       
   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 
       
   205 if __name__ == "__main__":
       
   206     main()