Adding EPL version of configurationengine.
#
# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
# This component and the accompanying materials are made available
# under the terms of "Eclipse Public License v1.0"
# which accompanies this distribution, and is available
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
#
# Initial Contributors:
# Nokia Corporation - initial contribution.
#
# Contributors:
#
# Description:
#
import os, logging, pickle
import time
from time import gmtime, strftime
from jinja2 import Environment, PackageLoader, FileSystemLoader, Template
from cone.public import api, exceptions, utils, plugin
from cone.confml import model
import report_util
ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
def save_report_data(rep_data, file_path):
"""
Save report data into an intermediary report data file.
"""
dir = os.path.dirname(file_path)
if dir != '' and not os.path.exists(dir):
os.makedirs(dir)
pickle_data = pickle.dumps(rep_data)
f = open(file_path, 'wb')
try: f.write(pickle_data)
finally: f.close()
def load_report_data(file_path):
"""
Load report data from an intermediary report data file.
"""
f = open(file_path, "rb")
try: data = f.read()
finally: f.close()
return pickle.loads(data)
def _get_parent_sequence_or_self(feature):
current = feature._parent
while current is not None:
if isinstance(current, api.FeatureSequence):
return current
current = current._parent
return feature
def collect_report_data(config, options, all_refs, impl_set, rule_exec_results):
"""
Collect data for report generation.
"""
impls = impl_set.get_all_implementations()
impls.sort(key=lambda impl: (impl.ref, impl.index))
rep_data = ReportData()
# Sort the rule results for unit testing purposes
rep_data.rule_exec_results = sorted(rule_exec_results, key=lambda e: (e.source, e.index))
# Collect a dictionary that maps refs shown in the report to a list of
# actual sub-refs used in the generation.
# This is done because for sequence settings only an entry for the main
# sequence setting is shown, but the actual refs used in generation point
# to the individual sub-settings (and possibly even under them).
# An example entry in the dictionary could be
# 'MyFeature.MySequence' : ['MyFeature.MySequence.Name',
# 'MyFeature.MySequence.File.localPath',
# 'MyFeature.MySequence.File.targetPath']
dview = config.get_default_view()
refs_dict = {}
for ref in all_refs:
try:
feature = dview.get_feature(ref)
except exceptions.NotFound:
logging.getLogger('cone.generation_report').warning("Feature for data ref not found: %s" % ref)
continue
feature = _get_parent_sequence_or_self(feature._obj)
ref_to_report = feature.fqr
if ref_to_report not in refs_dict:
refs_dict[ref_to_report] = []
refs_dict[ref_to_report].append(ref)
# msg = []
# for ref, sub_refs in refs_dict.iteritems():
# msg.append("Ref: %s\nSub-refs:\n%s" % (ref, '\n'.join(sub_refs)))
# logging.getLogger('cone').debug('\n--------------------------------------\n'.join(msg))
# Go through the refs and create report data entries
for ref in sorted(refs_dict.iterkeys()):
sub_refs = refs_dict[ref]
#print "Ref: %s" % ref
try:
feat = dview.get_feature(ref)
# Skip imaker-internal settings
if isinstance(feat._obj, model.ConfmlSetting):
try:
prop = feat.get_property('cone-report-ignore')
if prop.value.lower() in ('1', 'true'):
continue
except exceptions.NotFound:
pass
#print "Still %s" % ref
found_output = False
line = RefLine(ref, feat.get_type())
if plugin.is_temp_feature(feat):
line.is_temp_feature = True
if feat.get_type() == 'sequence':
for f in feat.list_all_features():
line.add_sequence(feat.get_feature(f).get_name(), feat.get_feature(f).get_value())
else:
if isinstance(feat.get_datas(), list):
for d in feat.get_datas():
line.add_data(d.find_parent(type=api.Configuration).get_full_path(), d.get_value())
else:
line.add_data(feat.get_data().find_parent(type=api.Configuration).get_full_path(), feat.get_value())
# Impl and output files
has_impl = False
for impl in impls:
# Check for implementations using the actual sub-refs
if impl.has_ref(sub_refs):
has_impl = True
line.add_impl(impl.ref, impl.IMPL_TYPE_ID, impl.list_output_files())
if has_impl: rep_data.add_line(line)
else: rep_data.add_ref_noimpl(line)
# For localPath and targetPath, the name should be the one from its parent file/folder setting
if isinstance(feat._obj, (model.ConfmlLocalPath, model.ConfmlTargetPath)):
name = feat._obj._parent.name
else:
name = feat.name
line.set_feat_name(name)
line.set_config_path( feat._obj.find_parent(type=api.Configuration).get_full_path())
except Exception, e:
utils.log_exception(logging.getLogger('cone'), 'Failed to collect data for report. Exception: %s' % e)
# create one list of not generated files
for myline in rep_data.lines:
for myimpl in myline.impls:
for output_file in myimpl.outputfiles:
if not output_file.exists and output_file not in rep_data.missing_output_files:
rep_data.missing_output_files.append(output_file)
rep_data.set_options(options)
rep_data.set_output_dir(options.output)
rep_data.update_nbr_of_refs()
rep_data.update_nbr_of_refs_noimpl()
return rep_data
def generate_report(rep_data, report_file_path, template_file_path=None):
"""
Generate a generation report based on the given report data.
@param rep_data: The report data.
@param report_file_path: Path to the report file to generate.
@param template_file_path: Path to the template file to use.
If None, the default template is used.
"""
# Determine the template file and directory to use
if template_file_path is None:
template_file_path = os.path.join(ROOT_PATH, 'gen_report_template.html')
report_util.generate_report(template_file_path, report_file_path, {'rep_data' : rep_data})
class ReportData(object):
"""
Data object that stores all information used in report generation.
"""
def __init__(self):
self.generation_timestamp = time.time()
self.generation_time = strftime("%d.%m.%Y %H:%M:%S")
self.options = None
self.lines = []
self.nbr_of_refs = 0
self.nbr_of_refs_noimpl = 0
self.cwd = os.getcwd()
self.ref_noimpl = []
self.duration = 0
self.output_dir = os.getcwd()
self.project_dir = ''
self.rule_exec_results = []
self.missing_output_files = []
def set_output_dir(self, dir):
self.output_dir = os.path.abspath(os.path.normpath(dir))
def add_line(self, line):
self.lines.append(line)
def set_duration(self, duration):
self.duration = duration
def set_options(self, options):
self.options = options
self.project_dir = os.path.abspath(options.project)
def set_report_filename(self, filename):
self.report_filename = filename
def add_ref_noimpl(self, ref):
self.ref_noimpl.append(ref)
def update_nbr_of_refs(self):
self.nbr_of_refs = len(self.lines)
def update_nbr_of_refs_noimpl(self):
self.nbr_of_refs_noimpl = len(self.ref_noimpl)
def __repr__(self):
return "ReportData(%s)" % [self.generation_timestamp,
self.generation_time,
self.options,
self.lines,
self.nbr_of_refs,
self.nbr_of_refs_noimpl,
self.cwd,
self.ref_noimpl,
self.duration,
self.output_dir,
self.project_dir,
self.rule_exec_results,
self.missing_output_files]
class RefLine(object):
"""
Data object that stores information for one ref in report generation.
"""
def __init__(self, ref, type):
self.ref = ref
self.feat_type = type
self.feat_name = None
self.feat_value = None
self.config_path = None
self.impls = []
self.output = None
self.nbr_impls = 0
self.nbr_outputfiles = 0
self.datas = []
self.nbr_of_datas = 0
self.nbr_of_rows = 0
self.seq_data = []
self.is_temp_feature = False
def add_impl(self, impl_file, impl_type, outputfiles):
self.impls.append(ImplLine(impl_file, impl_type, outputfiles))
self.nbr_impls = len(self.impls)
self.nbr_outputfiles = len(outputfiles) + self.nbr_outputfiles
def add_data(self, layer, value):
self.datas.append(DataLine(layer,value))
self.nbr_of_datas = len(self.datas)
def add_sequence(self, subsetting, values):
self.seq_data.append([subsetting, values])
def set_feat_name(self, name):
self.feat_name = name
def set_feat_value(self, value):
self.feat_value = value
def set_config_path(self, filename):
self.config_path = os.path.normpath(filename)
class ImplLine():
def __init__(self, impl_file, impl_type, outputfiles, generation_runs=[]):
self.name = os.path.normpath(impl_file)
self.type = impl_type
files = []
for outputfile in outputfiles:
files.append(Outputfile(outputfile))
self.outputfiles = files
self.generation_runs = generation_runs
class Outputfile():
def __init__(self, filename):
self.filename = os.path.normpath(filename)
self.abs_filename = os.path.abspath(filename)
self.exists = os.path.isfile(self.abs_filename)
def __eq__(self, other):
if type(self) is type(other):
return self.filename == other.filename
else:
return False
class DataLine():
def __init__(self, layer, value):
self.layer = os.path.normpath(layer)
self.value = value