summaryrefslogtreecommitdiffstats
path: root/module/config/ConfigManager.py
diff options
context:
space:
mode:
Diffstat (limited to 'module/config/ConfigManager.py')
-rw-r--r--module/config/ConfigManager.py118
1 files changed, 118 insertions, 0 deletions
diff --git a/module/config/ConfigManager.py b/module/config/ConfigManager.py
new file mode 100644
index 000000000..3ee66bc85
--- /dev/null
+++ b/module/config/ConfigManager.py
@@ -0,0 +1,118 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from new_collections import OrderedDict
+
+from module.Api import InvalidConfigSection
+from module.common.json_layer import json
+from module.utils import from_string
+
+from ConfigParser import ConfigParser
+
+
+def convertKeyError(func):
+ """ converts KeyError into InvalidConfigSection """
+
+ def conv(*args, **kwargs):
+ try:
+ return func(*args, **kwargs)
+ except KeyError:
+ raise InvalidConfigSection(args[1])
+
+ return conv
+
+
+class ConfigManager(ConfigParser):
+ """ Manages the core config and configs for addons and single user.
+ Has similar interface to ConfigParser. """
+
+ def __init__(self, core, parser):
+ # No __init__ call to super class is needed!
+
+ self.core = core
+ self.db = core.db
+ # The config parser, holding the core config
+ self.parser = parser
+
+ # similar to parser, separated meta data and values
+ self.config = OrderedDict()
+
+ # Value cache for multiple user configs
+ # Values are populated from db on first access
+ # Entries are saved as (user, section) keys
+ self.values = {}
+ # TODO: similar to a cache, could be deleted periodically
+
+ def save(self):
+ self.parser.save()
+
+ @convertKeyError
+ def get(self, section, option, user=None):
+ """get config value, core config only available for admins.
+ if user is not valid default value will be returned"""
+
+ # Core config loaded from parser, when no user is given or he is admin
+ if section in self.parser and (not user or(user and user.isAdmin())):
+ return self.parser.get(section, option)
+ else:
+ # We need the id and not the instance
+ # Will be None for admin user and so the same as internal access
+ user = user.handle if user else None
+ try:
+ # Check if this config exists
+ # Configs without meta data can not be loaded!
+ data = self.config[section].config[option]
+ self.loadValues(user, section)
+ return self.values[user, section][option]
+ except KeyError:
+ pass # Returns default value later
+
+ return self.config[section].config[option].default
+
+ def loadValues(self, user, section):
+ if (user, section) not in self.values:
+ conf = self.db.loadConfig(section, user)
+ try:
+ self.values[user, section] = json.loads(conf) if conf else {}
+ except ValueError: # Something did go wrong when parsing
+ self.values[user, section] = {}
+ self.core.print_exc()
+
+ @convertKeyError
+ def set(self, section, option, value, sync=True, user=None):
+ """ set config value """
+
+ changed = False
+ if section in self.parser and (not user or (user and user.isAdmin())):
+ changed = self.parser.set(section, option, value, sync)
+ else:
+ # associated id
+ user = user.handle if user else None
+ data = self.config[section].config[option]
+ value = from_string(value, data.type)
+ old_value = self.get(section, option)
+
+ # Values will always be saved to db, sync is ignored
+ if value != old_value:
+ changed = True
+ self.values[user, section][option] = value
+ self.saveValues(user, section)
+
+ if changed: self.core.evm.dispatchEvent("configChanged", value)
+ return changed
+
+ def saveValues(self, user, section):
+ self.db.saveConfig(section, json.dumps(self.values[user, section]), user)
+
+ def delete(self, section, user=False):
+ """ Deletes values saved in db and cached values for given user, NOT meta data
+ Does not trigger an error when nothing was deleted. """
+ user = user.handle if user else None
+ if (user, section) in self.values:
+ del self.values[user, section]
+
+ self.db.deleteConfig(section, user)
+
+
+ def iterSections(self):
+ pass \ No newline at end of file