configurationengine/source/cone/report/generation_report.py
changeset 4 0951727b8815
parent 3 e7e0ae78773e
equal deleted inserted replaced
3:e7e0ae78773e 4:0951727b8815
    14 # Description:
    14 # Description:
    15 #
    15 #
    16 
    16 
    17 import os, logging, pickle
    17 import os, logging, pickle
    18 import time
    18 import time
       
    19 import types
    19 from time import strftime
    20 from time import strftime
    20 from cone.public import api, exceptions, utils, plugin
    21 from cone.public import api, exceptions, utils, plugin
    21 from cone.confml import model
    22 from cone.confml import model
    22 from cone.report import report_util 
    23 from cone.report import report_util 
    23 
    24 
    24 ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
    25 ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
    25 SERIALISATION_FORMAT = 'pickle'
    26 SERIALISATION_FORMAT = 'pickle'
    26 
    27 
       
    28 def pickle_persistent_id(obj):
       
    29     """
       
    30     Prepare report data for pickler.
       
    31     """
       
    32     if isinstance(obj, (logging.Logger, types.ModuleType)):
       
    33         return ""
       
    34     elif isinstance(obj, (api.Configuration, api.ConfigurationProxy)):
       
    35         try:    project_path = os.path.abspath(obj.get_project().get_storage().get_path())
       
    36         except: project_path = None
       
    37         return "conf:" + repr(pickle.dumps((project_path, obj.path)))
       
    38     else:
       
    39         return None
       
    40 
       
    41 def persistent_load(persid):
       
    42     """
       
    43     Prepare pickler for unpickling report data.
       
    44     """
       
    45     global loaded_project
       
    46     if persid.startswith("impl:"):
       
    47         type_id, ref, lineno = pickle.loads(eval(persid[5:]))
       
    48         impl = plugin.ImplBase(ref, None)
       
    49         impl.IMPL_TYPE_ID = type_id
       
    50         impl.lineno = lineno
       
    51         return impl
       
    52     elif persid.startswith("conf:"):
       
    53         project_path, config_path = pickle.loads(eval(persid[5:]))
       
    54         configuration = api.ConfigurationProxy(config_path)
       
    55         if project_path:
       
    56             if not loaded_project:
       
    57                 loaded_project = api.Project(api.Storage.open(project_path))
       
    58             configuration._set_parent(loaded_project)
       
    59         return configuration
       
    60     else:
       
    61         return None
       
    62 
    27 def save_report_data(rep_data, file_path):
    63 def save_report_data(rep_data, file_path):
    28     """
    64     """
    29     Save report data into an intermediary report data file.
    65     Save report data into an intermediary report data file.
    30     """
    66     """
    31     dir = os.path.dirname(file_path)
    67     dir = os.path.dirname(file_path)
    32     if dir != '' and not os.path.exists(dir):
    68     if dir != '' and not os.path.exists(dir):
    33         os.makedirs(dir)
    69         os.makedirs(dir)
    34     f = open(file_path, 'wb')
    70     f = open(file_path, 'wb')
       
    71     
    35     try:
    72     try:
    36         if SERIALISATION_FORMAT == 'yaml':
    73         if SERIALISATION_FORMAT == 'yaml':
    37             yaml.dump(rep_data, f)
    74             yaml.dump(rep_data, f)
    38         elif SERIALISATION_FORMAT == 'pickle':
    75         elif SERIALISATION_FORMAT == 'pickle':
    39             pickle.dump(rep_data, f)
    76             pickler = pickle.Pickler(f)
       
    77             pickler.persistent_id = pickle_persistent_id
       
    78             pickler.dump(rep_data)
    40         elif SERIALISATION_FORMAT == 'pickle/2':
    79         elif SERIALISATION_FORMAT == 'pickle/2':
    41             pickle.dump(rep_data, f, 2)
    80             pickler = pickle.Pickler(f, 2)
       
    81             pickler.persistent_id = pickle_persistent_id
       
    82             pickler.dump(rep_data)
    42     finally:    
    83     finally:    
    43         f.close()
    84         f.close()
    44 
    85 
    45 def load_report_data(file_path):
    86 def load_report_data(file_path):
    46     """
    87     """
    47     Load report data from an intermediary report data file.
    88     Load report data from an intermediary report data file.
    48     """
    89     """
    49     try:        
    90     try:        
    50         f = open(file_path, "rb")
    91         f = open(file_path, "rb")
       
    92         unpickler = pickle.Unpickler(f)
       
    93         global loaded_project
       
    94         loaded_project = None
       
    95         unpickler.persistent_load = persistent_load
       
    96         
    51         if SERIALISATION_FORMAT == 'yaml':
    97         if SERIALISATION_FORMAT == 'yaml':
    52             data = yaml.load(f)
    98             data = yaml.load(f)
    53         elif SERIALISATION_FORMAT == 'pickle':
    99         elif SERIALISATION_FORMAT == 'pickle':
    54             data = pickle.load(f)
   100             data = unpickler.load()
    55         elif SERIALISATION_FORMAT == 'pickle/2':
   101         elif SERIALISATION_FORMAT == 'pickle/2':
    56             data = pickle.load(f)
   102             data = unpickler.load()
    57     finally:
   103     finally:
    58         f.close()
   104         f.close()
    59         
   105         
    60     data.label = get_generation_run_label(file_path)
   106     data.label = get_generation_run_label(file_path)
    61     return data
   107     return data
    86     """
   132     """
    87     # Determine the template file and directory to use
   133     # Determine the template file and directory to use
    88     if template_file_path is None:
   134     if template_file_path is None:
    89         template_file_path = 'gen_report_template.html'
   135         template_file_path = 'gen_report_template.html'
    90     contexts = [report_data.context for report_data in rep_data]
   136     contexts = [report_data.context for report_data in rep_data]
       
   137     merged_context = plugin.MergedContext(contexts)
    91     report_data = {'rep_data' : rep_data, 
   138     report_data = {'rep_data' : rep_data, 
    92                    'report_options' : report_options,
   139                    'report_options' : report_options,
    93                    'merged_context' : plugin.MergedContext(contexts)}
   140                    'merged_context' : merged_context}
    94     report_util.generate_report(template_file_path, report_file_path, report_data, template_paths)
   141     report_util.generate_report(template_file_path, report_file_path, report_data, template_paths)
    95 
   142 
    96 def normalize_slash(path):
   143 def normalize_slash(path):
    97     """
   144     """
    98     Normalize backslashes to slashes to make testing easier (no differences
   145     Normalize backslashes to slashes to make testing easier (no differences
   133         return "ReportData(%s)" % [self.generation_timestamp, 
   180         return "ReportData(%s)" % [self.generation_timestamp, 
   134                                    self.generation_time,
   181                                    self.generation_time,
   135                                    self.options,
   182                                    self.options,
   136                                    self.duration,
   183                                    self.duration,
   137                                    self.output_dir,
   184                                    self.output_dir,
   138                                    self.project_dir]    
   185                                    self.project_dir]
       
   186     
       
   187     def __getstate__(self):
       
   188         state = self.__dict__.copy()
       
   189         if self.project:
       
   190             state['project_path'] = os.path.abspath(self.project.get_path())
       
   191         else:
       
   192             state['project_path'] = None
       
   193         del state['project']
       
   194         return state
       
   195     
       
   196     def __setstate__(self, dict):
       
   197         project_path = dict['project_path']
       
   198         if project_path is None:
       
   199             self.project = None
       
   200         else:
       
   201             self.project = api.Project(api.Storage.open(project_path))
       
   202         
       
   203         self.__dict__.update(dict)
   139 
   204 
   140 
   205 
   141 class RefLine(object):
   206 class RefLine(object):
   142     """
   207     """
   143     Data object that stores information for one ref in report generation.
   208     Data object that stores information for one ref in report generation.