configurationengine/source/cone/report/generation_report.py
changeset 4 0951727b8815
parent 3 e7e0ae78773e
--- a/configurationengine/source/cone/report/generation_report.py	Tue Aug 10 14:29:28 2010 +0300
+++ b/configurationengine/source/cone/report/generation_report.py	Wed Sep 08 12:20:56 2010 +0300
@@ -16,6 +16,7 @@
 
 import os, logging, pickle
 import time
+import types
 from time import strftime
 from cone.public import api, exceptions, utils, plugin
 from cone.confml import model
@@ -24,6 +25,41 @@
 ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
 SERIALISATION_FORMAT = 'pickle'
 
+def pickle_persistent_id(obj):
+    """
+    Prepare report data for pickler.
+    """
+    if isinstance(obj, (logging.Logger, types.ModuleType)):
+        return ""
+    elif isinstance(obj, (api.Configuration, api.ConfigurationProxy)):
+        try:    project_path = os.path.abspath(obj.get_project().get_storage().get_path())
+        except: project_path = None
+        return "conf:" + repr(pickle.dumps((project_path, obj.path)))
+    else:
+        return None
+
+def persistent_load(persid):
+    """
+    Prepare pickler for unpickling report data.
+    """
+    global loaded_project
+    if persid.startswith("impl:"):
+        type_id, ref, lineno = pickle.loads(eval(persid[5:]))
+        impl = plugin.ImplBase(ref, None)
+        impl.IMPL_TYPE_ID = type_id
+        impl.lineno = lineno
+        return impl
+    elif persid.startswith("conf:"):
+        project_path, config_path = pickle.loads(eval(persid[5:]))
+        configuration = api.ConfigurationProxy(config_path)
+        if project_path:
+            if not loaded_project:
+                loaded_project = api.Project(api.Storage.open(project_path))
+            configuration._set_parent(loaded_project)
+        return configuration
+    else:
+        return None
+
 def save_report_data(rep_data, file_path):
     """
     Save report data into an intermediary report data file.
@@ -32,13 +68,18 @@
     if dir != '' and not os.path.exists(dir):
         os.makedirs(dir)
     f = open(file_path, 'wb')
+    
     try:
         if SERIALISATION_FORMAT == 'yaml':
             yaml.dump(rep_data, f)
         elif SERIALISATION_FORMAT == 'pickle':
-            pickle.dump(rep_data, f)
+            pickler = pickle.Pickler(f)
+            pickler.persistent_id = pickle_persistent_id
+            pickler.dump(rep_data)
         elif SERIALISATION_FORMAT == 'pickle/2':
-            pickle.dump(rep_data, f, 2)
+            pickler = pickle.Pickler(f, 2)
+            pickler.persistent_id = pickle_persistent_id
+            pickler.dump(rep_data)
     finally:    
         f.close()
 
@@ -48,12 +89,17 @@
     """
     try:        
         f = open(file_path, "rb")
+        unpickler = pickle.Unpickler(f)
+        global loaded_project
+        loaded_project = None
+        unpickler.persistent_load = persistent_load
+        
         if SERIALISATION_FORMAT == 'yaml':
             data = yaml.load(f)
         elif SERIALISATION_FORMAT == 'pickle':
-            data = pickle.load(f)
+            data = unpickler.load()
         elif SERIALISATION_FORMAT == 'pickle/2':
-            data = pickle.load(f)
+            data = unpickler.load()
     finally:
         f.close()
         
@@ -88,9 +134,10 @@
     if template_file_path is None:
         template_file_path = 'gen_report_template.html'
     contexts = [report_data.context for report_data in rep_data]
+    merged_context = plugin.MergedContext(contexts)
     report_data = {'rep_data' : rep_data, 
                    'report_options' : report_options,
-                   'merged_context' : plugin.MergedContext(contexts)}
+                   'merged_context' : merged_context}
     report_util.generate_report(template_file_path, report_file_path, report_data, template_paths)
 
 def normalize_slash(path):
@@ -135,7 +182,25 @@
                                    self.options,
                                    self.duration,
                                    self.output_dir,
-                                   self.project_dir]    
+                                   self.project_dir]
+    
+    def __getstate__(self):
+        state = self.__dict__.copy()
+        if self.project:
+            state['project_path'] = os.path.abspath(self.project.get_path())
+        else:
+            state['project_path'] = None
+        del state['project']
+        return state
+    
+    def __setstate__(self, dict):
+        project_path = dict['project_path']
+        if project_path is None:
+            self.project = None
+        else:
+            self.project = api.Project(api.Storage.open(project_path))
+        
+        self.__dict__.update(dict)
 
 
 class RefLine(object):