Changeset ded6bb


Ignore:
Timestamp:
08/01/2009 02:26:26 AM (16 years ago)
Author:
Andrew Resch <andrewresch@gmail.com>
Branches:
2.0.x, develop, extjs4-port, master
Children:
9b0d4f
Parents:
838cef
Message:

Change the config format
Add test_config

Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • deluge/config.py

    r838cef rded6bb  
    4141really.
    4242
    43 The format of the config file is as follows:
    44 
    45 <format version as int>
    46 <config file version as int>
    47 <content>
    48 
    49 The format version is controlled by the Config class.  It should only be changed
    50 when anything below it is changed directly by the Config class.  An example of
    51 this would be if we changed the serializer for the content to something different.
     43The format of the config file is two json encoded dicts:
     44
     45<version dict>
     46<content dict>
     47
     48The version dict contains two keys: file and format.  The format version is
     49controlled by the Config class.  It should only be changed when anything below
     50it is changed directly by the Config class.  An example of this would be if we
     51changed the serializer for the content to something different.
    5252
    5353The config file version is changed by the 'owner' of the config file.  This is
     
    9191    return property(doc=func.__doc__, **func())
    9292
     93def find_json_objects(s):
     94    """
     95    Find json objects in a string.
     96   
     97    :param s: the string to find json objects in
     98    :type s: string
     99   
     100    :returns: a list of tuples containing start and end locations of json objects in the string `s`
     101    :rtype: [(start, end), ...]
     102   
     103    """
     104    objects = []
     105    opens = 0
     106    start = s.find("{")
     107    offset = start
     108
     109    if start < 0:
     110        return []
     111
     112    for index, c in enumerate(s[offset:]):
     113        if c == "{":
     114            opens += 1
     115        elif c == "}":
     116            opens -= 1
     117        if opens == 0:
     118            objects.append((start, index+offset+1))
     119            start = index + offset + 1
     120
     121    return objects
     122   
     123   
    93124class Config(object):
    94125    """
     
    106137
    107138        # These hold the version numbers and they will be set when loaded
    108         self.__format_version = 1
    109         self.__file_version = 1
     139        self.__version = {
     140            "format": 1,
     141            "file": 1
     142        }
    110143
    111144        # This will get set with a reactor.callLater whenever a config option
    112145        # is set.
    113         self.__save_timer = None
     146        self._save_timer = None
    114147
    115148        if defaults:
     
    135168        """
    136169        Sets item 'key' to 'value' in the config dictionary, but does not allow
    137         changing the item's type unless it is None
     170        changing the item's type unless it is None.  If the types do not match,
     171        it will attempt to convert it to the set type before raising a ValueError.
    138172
    139173        :param key: string, item to change to change
    140174        :param value: the value to change item to, must be same type as what is currently in the config
    141175
    142         :raises ValueError: raised when the type of value is not the same as what is currently in the config
     176        :raises ValueError: raised when the type of value is not the same as\
     177what is currently in the config and it could not convert the value
    143178
    144179        **Usage**
     
    187222
    188223        # We set the save_timer for 5 seconds if not already set
    189         if not self.__save_timer or not self.__save_timer.active():
    190             self.__save_timer = reactor.callLater(5, self.save)
     224        if not self._save_timer or not self._save_timer.active():
     225            self._save_timer = reactor.callLater(5, self.save)
    191226
    192227    def __getitem__(self, key):
     
    305340
    306341        try:
    307             data = open(filename, "rb")
     342            data = open(filename, "rb").read()
    308343        except IOError, e:
    309344            log.warning("Unable to open config file %s: %s", filename, e)
    310345            return
    311346
    312         try:
    313             self.__format_version = int(data.readline())
    314         except ValueError:
    315             data.seek(0)
    316         else:
     347        objects = find_json_objects(data)
     348       
     349        if not len(objects):
     350            # No json objects found, try depickling it
    317351            try:
    318                 self.__file_version = int(data.readline())
    319             except ValueError:
    320                 pass
    321 
    322         fdata = data.read()
    323         data.close()
    324 
    325         try:
    326             self.__config.update(json.loads(fdata))
    327         except Exception, e:
    328             log.exception(e)
    329             try:
    330                 self.__config.update(pickle.loads(fdata))
     352                self.__config.update(pickle.loads(data))
    331353            except Exception, e:
    332354                log.exception(e)
    333                 log.warning("Unable to load config file: %s", filename)
    334 
    335 
    336 
     355                log.warning("Unable to load config file: %s", filename)               
     356        elif len(objects) == 1:
     357            start, end = objects[0]
     358            try:
     359                self.__config.update(json.loads(data[start:end]))
     360            except Exception, e:
     361                log.exception(e)
     362                log.warning("Unable to load config file: %s", filename)               
     363        elif len(objects) == 2:
     364            try:
     365                start, end = objects[0]
     366                self.__version.update(json.loads(data[start:end]))
     367                start, end = objects[1]
     368                self.__config.update(json.loads(data[start:end]))
     369            except Exception, e:
     370                log.exception(e)
     371                log.warning("Unable to load config file: %s", filename)               
     372           
    337373        log.debug("Config %s version: %s.%s loaded: %s", filename,
    338             self.__format_version, self.__file_version, self.__config)
     374            self.__version["format"], self.__version["file"], self.__config)
    339375
    340376    def save(self, filename=None):
     
    352388        # We will only write a new config file if there is a difference
    353389        try:
    354             data = open(filename, "rb")
    355             data.readline()
    356             data.readline()
    357             loaded_data = json.loads(data.read())
    358             data.close()
    359             if self.__config == loaded_data:
     390            data = open(filename, "rb").read()
     391            objects = find_json_objects(data)
     392            start, end = objects[0]
     393            version = json.loads(data[start:end])
     394            start, end = objects[1]
     395            loaded_data = json.loads(data[start:end])
     396
     397            if self.__config == loaded_data and self.__version == version:
    360398                # The config has not changed so lets just return
    361                 self.__save_timer = None
     399                self._save_timer = None
    362400                return
    363401        except Exception, e:
    364402            log.warning("Unable to open config file: %s", filename)
    365403
    366         self.__save_timer = None
     404        self._save_timer = None
    367405
    368406        # Save the new config and make sure it's written to disk
     
    370408            log.debug("Saving new config file %s", filename + ".new")
    371409            f = open(filename + ".new", "wb")
    372             f.write(str(self.__format_version) + "\n")
    373             f.write(str(self.__file_version) + "\n")
     410            json.dump(self.__version, f, indent=2)           
    374411            json.dump(self.__config, f, indent=2)
    375412            f.flush()
     
    415452            raise ValueError("output_version needs to be greater than input_range")
    416453
    417         if self.__file_version not in input_range:
     454        if self.__version["file"] not in input_range:
    418455            log.debug("File version %s is not in input_range %s, ignoring converter function..",
    419                 self.__file_version, input_range)
     456                self.__version["file"], input_range)
    420457            return
    421458
     
    425462            log.exception(e)
    426463            log.error("There was an exception try to convert config file %s %s to %s",
    427                 self.__config_file, self.__file_version, output_version)
     464                self.__config_file, self.__version["file"], output_version)
    428465            raise e
    429466        else:
    430             self.__file_version = output_version
     467            self.__version["file"] = output_version
    431468            self.save()
    432469
  • tests/common.py

    r838cef rded6bb  
    99    config_directory = tempfile.mkdtemp()
    1010    deluge.configmanager.set_config_dir(config_directory)
     11    return config_directory
    1112
    1213import gettext
Note: See TracChangeset for help on using the changeset viewer.