Author: andar

Revision: 5323

Log:
        Modify the Config class to version the config files now.
Add ability to register converter functions for config files to convert them to 
newer versions.

Diff:
Modified: trunk/deluge/config.py
===================================================================
--- trunk/deluge/config.py      2009-05-28 19:16:58 UTC (rev 5322)
+++ trunk/deluge/config.py      2009-05-28 23:43:45 UTC (rev 5323)
@@ -36,6 +36,35 @@
 
 """
 Deluge Config Module
+
+This module is used for loading and saving of configuration files.. or anything
+really.
+
+The format of the config file is as follows:
+
+<format version as int>
+<config file version as int>
+<content>
+
+The format version is controlled by the Config class.  It should only be 
changed
+when anything below it is changed directly by the Config class.  An example of
+this would be if we changed the serializer for the content to something 
different.
+
+The config file version is changed by the 'owner' of the config file.  This is
+to signify that there is a change in the naming of some config keys or 
something
+similar along those lines.
+
+The content is simply the dict to be saved and will be serialized before being
+written.
+
+Converting
+
+Since the format of the config could change, there needs to be a way to have
+the Config object convert to newer formats.  To do this, you will need to
+register conversion functions for various versions of the config file. Note 
that
+this can only be done for the 'config file version' and not for the 'format'
+version as this will be done internally.
+
 """
 
 import cPickle as pickle
@@ -74,6 +103,11 @@
         self.__config = {}
         self.__set_functions = {}
         self.__change_callback = None
+
+        # These hold the version numbers and they will be set when loaded
+        self.__format_version = None
+        self.__file_version = None
+
         # This will get set with a reactor.callLater whenever a config option
         # is set.
         self.__save_timer = None
@@ -247,16 +281,40 @@
         """
         if not filename:
             filename = self.__config_file
+        data = open(filename, "rb")
         try:
-            self.__config.update(json.load(open(filename, "rb")))
+            self.__format_version = int(data.readline())
+        except ValueError:
+            pass
+
+        try:
+            self.__file_version = int(data.readline())
+        except ValueError:
+            pass
+
+
+        if not self.__format_version:
+            data.seek(0)
+            self.__format_version = 1
+            self.__file_version = 1
+
+        fdata = data.read()
+        data.close()
+
+        try:
+            self.__config.update(json.loads(fdata))
         except Exception, e:
             try:
-                self.__config.update(pickle.load(open(filename, "rb")))
+                self.__config.update(pickle.loads(fdata))
             except Exception, e:
+                log.exception(e)
                 log.warning("Unable to load config file: %s", filename)
 
-        log.debug("Config %s loaded: %s", filename, self.__config)
 
+
+        log.debug("Config %s version: %s.%s loaded: %s", filename,
+            self.__format_version, self.__file_version, self.__config)
+
     def save(self, filename=None):
         """
         Save configuration to disk
@@ -271,7 +329,11 @@
         # Check to see if the current config differs from the one on disk
         # We will only write a new config file if there is a difference
         try:
-            if self.__config == json.load(open(filename, "rb")):
+            data = open(filename, "rb")
+            data.seek(2)
+            loaded_data = json.load(data)
+            data.close()
+            if self.__config == loaded_data:
                 # The config has not changed so lets just return
                 self.__save_timer = None
                 return
@@ -284,6 +346,8 @@
         try:
             log.debug("Saving new config file %s", filename + ".new")
             f = open(filename + ".new", "wb")
+            f.write(str(self.__format_version) + "\n")
+            f.write(str(self.__file_version) + "\n")
             json.dump(self.__config, f, indent=2)
             f.flush()
             os.fsync(f.fileno())
@@ -309,7 +373,40 @@
             return False
         else:
             return True
-    
+
+    def run_converter(self, input_range, output_version, func):
+        """
+        Runs a function that will convert file versions in the 
`:param:input_range`
+        to the `:param:output_version`.
+
+        :param input_range: tuple, (int, int) the range of input versions this
+            function will accept
+        :param output_version: int, the version this function will return
+        :param func: func, the function that will do the conversion, it will 
take
+            the config dict as an argument and return the augmented dict
+
+        :raises ValueError: if the output_version is less than the input_range
+
+        """
+        if output_version in input_range or output_version <= max(input_range):
+            raise ValueError("output_version needs to be greater than 
input_range")
+
+        if self.__file_version not in input_range:
+            log.debug("File version %s is not in input_range %s, ignoring 
converter function..",
+                self.__file_version, input_range)
+            return
+
+        try:
+            self.__config = func(self.__config)
+        except Exception, e:
+            log.exception(e)
+            log.error("There was an exception try to convert config file %s %s 
to %s",
+                self.__config_file, self.__file_version, output_version)
+            raise e
+        else:
+            self.__file_version = output_version
+            self.save()
+
     @property
     def config_file(self):
         return self.__config_file



--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"deluge-commit" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/deluge-commit?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to