#!/usr/bin/env python2.3 #Copyright 2004 Sebastian Hagen # This file is part of eucharis. # eucharis is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 # as published by the Free Software Foundation # eucharis is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with eucharis; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # This really needs to be replaced by something sane someday. import os import types import re import logging import cPickle import socket_management import basic_io import __main__ import xml.parsers.expat import xml.sax.saxutils logger = logging.getLogger('data_pickling') type_mapping = {} if not ('variable_data_dict') in globals(): variable_data_dict = {} class xml_input: def __init__(self, filename, basename): self.logger = logger self.filename = filename self.basename = basename self.parser_expat = xml.parsers.expat.ParserCreate() self.parser_expat.StartElementHandler = self.start_element self.parser_expat.EndElementHandler = self.finish_element self.parser_expat.CharacterDataHandler = self.handle_data_character self.base_element = True self.data_buffer = '' self.logger.log(20, 'Opening xml input file ' + filename + '.') self.input_file = file(filename, 'r') self.parser_expat.ParseFile(self.input_file) self.logger.log(20, 'Closing xml input file ' + filename + '.') self.input_file.close() def finish_element(self, name): if (self.element_name != None): if ((self.element_module != None) and not (self.element_module in globals())): exec 'import ' + self.element_module globals()[self.element_module] = eval(self.element_module) try: exec '''%s = cPickle.loads("""%s""")''' % (self.element_name, self.data_buffer) except NameError: self.logger.log(40, 'Unable to restore state of variable %s. Dump:' % (self.element_name,), exc_info=True) self.element_name = None self.data_buffer = '' def start_element(self, name, attributes): self.data_buffer = '' if ((name == self.basename) or (self.base_element)): self.base_element = False else: for attribute in ['name', 'module']: if (attribute in attributes): self.__dict__['element_' + attribute] = attributes[attribute] else: self.__dict__['element_' + attribute] = None def handle_data_character(self, data): self.data_buffer = self.data_buffer + data class xml_output: def __init__(self, variable_data, filename, basename): self.logger = logger self.filename = filename self.basename = basename if (type(self.basename) != str): self.basename = repr(self.basename) self.file = file(filename + '_', 'w') self.perform_output(self.basename, variable_data) self.file.flush() self.file.close() os.rename(filename + '_', filename) def perform_output(self, basename, variable_data): """Write xml-file.""" self.file.write ('\n<%s>\n' % (basename,)) for (variable_name, module_name) in variable_data: if not (module_name in globals()): #Ugly but working. exec 'import ' + module_name globals()[module_name] = eval(module_name) self.write_data(variable_name, module_name, indenting=1) self.file.write('\n\n' % (basename,)) def write_data(self, varstring, module_string, indenting): """Write the tags and any values for a variable. Recurse as necessary.""" indent_offset = 3 indent_length = indenting*indent_offset self.file.write('%*s' % (indent_length, '', varstring, module_string)) value = eval(varstring) try: self.file.write(xml.sax.saxutils.escape(cPickle.dumps(value))) except TypeError: self.logger.log(40, 'Unable to pickle variable %s.' % (varstring,),exc_info=True) self.file.write('') def register_variable(variable_unit, filename): if not (filename in variable_data_dict): variable_data_dict[filename] = [] if not (variable_unit in variable_data_dict[filename]): variable_data_dict[filename].append(variable_unit) def unregister_variable(variable_unit, filename): if not (filename in variable_data_dict): raise ValueError('No records for filename ' + str(filename) + '.') elif not (variable_unit in variable_data_dict[filename]): raise ValueError('The specified record %s does not exist for filename %s.' % (variable_unit, filename)) else: variable_data_dict[filename].remove(variable_unit) if (variable_data_dict[filename] == []): del(variable_data_dict[filename]) def save_variables(): basename = 'data_pickling_output' for filename in variable_data_dict: xml_output_instance = xml_output(variable_data_dict[filename][:], filename, basename) def register_save_timer(delay=600): socket_management.timers_add(delay, callback_handler=save_variables, persistence=True)