summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2013-01-02 18:11:31 +0100
committerGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2013-01-02 18:11:31 +0100
commit6b20f5f6c063e4e6c94d719b607ad5a028b8beee (patch)
treea8c3dfa9962aa819507870553700a35b7dcc4c74
parentRemove '/' from filename to avoid filepath exception (diff)
downloadpyload-6b20f5f6c063e4e6c94d719b607ad5a028b8beee.tar.xz
new configManager for multi user configs
-rw-r--r--module/AddonManager.py9
-rw-r--r--module/Api.py4
-rw-r--r--module/PluginManager.py3
-rw-r--r--module/config/ConfigManager.py118
-rw-r--r--module/config/ConfigParser.py130
-rw-r--r--module/config/default.py30
-rw-r--r--module/database/ConfigDatabase.py5
-rw-r--r--module/datatypes/User.py5
-rw-r--r--module/remote/pyload.thrift4
-rw-r--r--module/remote/ttypes.py6
-rw-r--r--module/remote/ttypes_debug.py1
-rwxr-xr-xpyLoadCore.py15
-rw-r--r--tests/api/test_WebSocketBackend.py (renamed from tests/api/test_WebSocketAPI.py)2
-rw-r--r--tests/api/test_noargs.py2
-rw-r--r--tests/helper/Stubs.py14
-rw-r--r--tests/manager/test_configManager.py101
-rw-r--r--tests/other/test_configparser.py50
17 files changed, 330 insertions, 169 deletions
diff --git a/module/AddonManager.py b/module/AddonManager.py
index 4283b4652..ad6daaf83 100644
--- a/module/AddonManager.py
+++ b/module/AddonManager.py
@@ -45,9 +45,6 @@ class AddonManager:
self.lock = RLock()
self.createIndex()
- #registering callback for config event
- self.config.changeCB = MethodType(self.dispatchEvent, "configChanged", basestring)
-
# manage addons an config change
self.addEvent("configChanged", self.manageAddons)
@@ -64,8 +61,7 @@ class AddonManager:
return func(*args)
except Exception, e:
addon.logError(_("Error when executing %s" % f), e)
- if self.core.debug:
- print_exc()
+ self.core.print_exc()
def addRPC(self, plugin, func, doc):
doc = doc.strip() if doc else ""
@@ -114,8 +110,7 @@ class AddonManager:
except:
self.log.warning(_("Failed activating %(name)s") % {"name": pluginname})
- if self.core.debug:
- print_exc()
+ self.core.print_exc()
self.log.info(_("Activated addons: %s") % ", ".join(sorted(active)))
self.log.info(_("Deactivate addons: %s") % ", ".join(sorted(deactive)))
diff --git a/module/Api.py b/module/Api.py
index 0b777a659..fb3c59483 100644
--- a/module/Api.py
+++ b/module/Api.py
@@ -302,7 +302,8 @@ class Api(Iface):
def getConfig(self):
"""Retrieves complete config of core.
- :return: map of `ConfigHolder`
+ :rtype : ConfigHolder
+ :return: dict with section mapped to config
"""
# TODO
return dict([(section, ConfigHolder(section, data.name, data.description, data.long_desc, [
@@ -765,6 +766,7 @@ class Api(Iface):
p = self.core.files.getPackage(pid)
if not p: raise PackageDoesNotExists(pid)
+ #TODO: fix
for key, value in data.iteritems():
if key == "id": continue
setattr(p, key, value)
diff --git a/module/PluginManager.py b/module/PluginManager.py
index 2bd438c37..31ad38625 100644
--- a/module/PluginManager.py
+++ b/module/PluginManager.py
@@ -62,7 +62,8 @@ class PluginManager:
self.history = [] # match history to speedup parsing (type, name)
self.createIndex()
- self.core.config.parseValues(self.core.config.PLUGIN)
+ # TODO, replacement for this?
+ #self.core.config.parseValues(self.core.config.PLUGIN)
#register for import addon
sys.meta_path.append(self)
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
diff --git a/module/config/ConfigParser.py b/module/config/ConfigParser.py
index 3cad67bc2..135e84bbc 100644
--- a/module/config/ConfigParser.py
+++ b/module/config/ConfigParser.py
@@ -17,25 +17,20 @@ ConfigData = namedtuple("ConfigData", "name type description default")
class ConfigParser:
"""
- Holds and manages the configuration + meta data for core and every user.
+ Holds and manages the configuration + meta data for config read from file.
"""
CONFIG = "pyload.conf"
- PLUGIN = "plugin.conf"
- def __init__(self):
- """Constructor"""
+ def __init__(self, config=None):
- # core config sections from pyload
- self.baseSections = []
+ if config: self.CONFIG = config
# Meta data information
self.config = OrderedDict()
# The actual config values
self.values = {}
- self.changeCB = None # callback when config value was changed
-
self.checkVersion()
self.loadDefault()
@@ -50,22 +45,21 @@ class ConfigParser:
# workaround conflict, with GUI (which also accesses the config) so try read in 3 times
for i in range(0, 3):
try:
- for conf in (self.CONFIG, self.PLUGIN):
- if exists(conf):
- f = open(conf, "rb")
- v = f.readline()
- f.close()
- v = v[v.find(":") + 1:].strip()
-
- if not v or int(v) < CONF_VERSION:
- f = open(conf, "wb")
- f.write("version: " + str(CONF_VERSION))
- f.close()
- print "Old version of %s deleted" % conf
- else:
- f = open(conf, "wb")
- f.write("version:" + str(CONF_VERSION))
+ if exists(self.CONFIG):
+ f = open(self.CONFIG, "rb")
+ v = f.readline()
+ f.close()
+ v = v[v.find(":") + 1:].strip()
+
+ if not v or int(v) < CONF_VERSION:
+ f = open(self.CONFIG, "wb")
+ f.write("version: " + str(CONF_VERSION))
f.close()
+ print "Old version of %s deleted" % self.CONFIG
+ else:
+ f = open(self.CONFIG, "wb")
+ f.write("version:" + str(CONF_VERSION))
+ f.close()
except Exception, ex:
e = ex
@@ -112,19 +106,13 @@ class ConfigParser:
def save(self):
"""saves config to filename"""
- # separate pyload and plugin conf
configs = []
- for c in (self.CONFIG, self.PLUGIN):
- f = open(c, "wb")
- configs.append(f)
- chmod(c, 0600)
- f.write("version: %i\n\n" % CONF_VERSION)
-
+ f = open(self.CONFIG, "wb")
+ configs.append(f)
+ chmod(self.CONFIG, 0600)
+ f.write("version: %i\n\n" % CONF_VERSION)
- # write on 2 files
for section, data in self.config.iteritems():
- f = configs[0] if section in self.baseSections else configs[1]
-
f.write("[%s]\n" % section)
for option, data in data.config.iteritems():
@@ -136,17 +124,21 @@ class ConfigParser:
f.write("\n")
- [f.close() for f in configs]
+ f.close()
def __getitem__(self, section):
"""provides dictionary like access: c['section']['option']"""
return Section(self, section)
+ def __contains__(self, section):
+ """ checks if parser contains section """
+ return section in self.config
+
def get(self, section, option):
- """get value"""
- if option in self.values[section]:
+ """get value or default"""
+ try:
return self.values[section][option]
- else:
+ except KeyError:
return self.config[section].config[option].default
def set(self, section, option, value, sync=True):
@@ -154,45 +146,27 @@ class ConfigParser:
data = self.config[section].config[option]
value = from_string(value, data.type)
+ old_value = self.get(section, option)
- # only save when different to default values
- if value != data.default or (option in self.values[section] and value != self.values[section][option]):
+ # only save when different values
+ if value != old_value:
+ if section not in self.values: self.values[section] = {}
self.values[section][option] = value
if sync:
- if self.changeCB: self.changeCB(section, option, value)
self.save()
+ return True
- def getPlugin(self, *args):
- """gets a value for a plugin"""
- ret = self.get(*args)
- print "Deprecated method getPlugin%s -> %s" % (str(args), ret)
- return ret
-
- def setPlugin(self, *args):
- """sets a value for a plugin"""
- print "Deprecated method setPlugin%s" % str(args)
- self.set(*args)
+ return False
def getMetaData(self, section, option):
""" get all config data for an option """
return self.config[section].config[option]
- def getBaseSections(self):
- for section, data in self.config.iteritems():
- if section in self.baseSections:
- yield section, data
- return
-
- def getPluginSections(self):
- for section, data in self.config.iteritems():
- if section not in self.baseSections:
- yield section, data
- return
+ def iterSections(self):
+ return self.config.iteritems()
- def addConfigSection(self, section, name, desc, long_desc, config, base=False):
+ def addConfigSection(self, section, name, desc, long_desc, config):
"""Adds a section to the config. `config` is a list of config tuples as used in plugin api defined as:
- Either (name, type, verbose_name, default_value) or
- (name, type, verbose_name, short_description, default_value)
The order of the config elements is preserved with OrderedDict
"""
d = OrderedDict()
@@ -200,23 +174,15 @@ class ConfigParser:
for entry in config:
if len(entry) == 5:
conf_name, type, conf_desc, conf_verbose, default = entry
- else: # config options without tooltip / description
+ else: # config options without description
conf_name, type, conf_desc, default = entry
conf_verbose = ""
d[conf_name] = ConfigData(gettext(conf_desc), type, gettext(conf_verbose), from_string(default, type))
- if base:
- if section not in self.baseSections: self.baseSections.append(section)
- elif section in self.baseSections:
- return # would overwrite base section
-
data = SectionTuple(gettext(name), gettext(desc), gettext(long_desc), d)
self.config[section] = data
- if section not in self.values:
- self.values[section] = {}
-
class Section:
"""provides dictionary like access for configparser"""
@@ -232,21 +198,3 @@ class Section:
def __setitem__(self, item, value):
"""setitem"""
self.parser.set(self.section, item, value)
-
-
-if __name__ == "__main__":
- pypath = ""
-
- from time import time
-
- a = time()
-
- c = ConfigParser()
-
- b = time()
-
- print "sec", b - a
-
- print c.config
-
- c.saveConfig(c.config, "user.conf")
diff --git a/module/config/default.py b/module/config/default.py
index a9fad675c..e55ba6593 100644
--- a/module/config/default.py
+++ b/module/config/default.py
@@ -16,8 +16,7 @@ def make_config(config):
("activated", "bool", _("Activated"), _("Tooltip"), True),
("port", "int", _("Port"), _("Tooltip"), 7227),
("listenaddr", "ip", _("Adress"), _("Tooltip"), "0.0.0.0"),
- ],
- True)
+ ])
config.addConfigSection("log", _("Log"), _("Description"), _("Long description"),
[
@@ -26,8 +25,7 @@ def make_config(config):
("file_log", "bool", _("File Log"), _("Tooltip"), True),
("log_count", "int", _("Count"), _("Tooltip"), 5),
("log_rotate", "bool", _("Log Rotate"), _("Tooltip"), True),
- ],
- True)
+ ])
config.addConfigSection("permission", _("Permissions"), _("Description"), _("Long description"),
[
@@ -39,8 +37,7 @@ def make_config(config):
("change_group", "bool", _("Change group of running process"), _("Tooltip"), False),
("folder", "str", _("Folder Permission mode"), _("Tooltip"), "0755"),
("change_user", "bool", _("Change user of running process"), _("Tooltip"), False),
- ],
- True)
+ ])
config.addConfigSection("general", _("General"), _("Description"), _("Long description"),
[
@@ -51,16 +48,14 @@ def make_config(config):
("debug_mode", "bool", _("Debug Mode"), _("Tooltip"), False),
("min_free_space", "int", _("Min Free Space (MB)"), _("Tooltip"), 200),
("renice", "int", _("CPU Priority"), _("Tooltip"), 0),
- ],
- True)
+ ])
config.addConfigSection("ssl", _("SSL"), _("Description"), _("Long description"),
[
("cert", "file", _("SSL Certificate"), _("Tooltip"), "ssl.crt"),
("activated", "bool", _("Activated"), _("Tooltip"), False),
("key", "file", _("SSL Key"), _("Tooltip"), "ssl.key"),
- ],
- True)
+ ])
config.addConfigSection("webinterface", _("Webinterface"), _("Description"), _("Long description"),
[
@@ -71,8 +66,7 @@ def make_config(config):
("host", "ip", _("IP"), _("Tooltip"), "0.0.0.0"),
("https", "bool", _("Use HTTPS"), _("Tooltip"), False),
("port", "int", _("Port"), _("Tooltip"), 8001),
- ],
- True)
+ ])
config.addConfigSection("proxy", _("Proxy"), _("Description"), _("Long description"),
[
@@ -82,8 +76,7 @@ def make_config(config):
("password", "password", _("Password"), _("Tooltip"), ""),
("type", "http;socks4;socks5", _("Protocol"), _("Tooltip"), "http"),
("port", "int", _("Port"), _("Tooltip"), 7070),
- ],
- True)
+ ])
config.addConfigSection("reconnect", _("Reconnect"), _("Description"), _("Long description"),
[
@@ -91,8 +84,7 @@ def make_config(config):
("activated", "bool", _("Use Reconnect"), _("Tooltip"), False),
("method", "str", _("Method"), _("Tooltip"), "./reconnect.sh"),
("startTime", "time", _("Start"), _("Tooltip"), "0:00"),
- ],
- True)
+ ])
config.addConfigSection("download", _("Download"), _("Description"), _("Long description"),
[
@@ -104,12 +96,10 @@ def make_config(config):
("ipv6", "bool", _("Allow IPv6"), _("Tooltip"), False),
("chunks", "int", _("Max connections for one download"), _("Tooltip"), 3),
("restart_failed", "bool", _("Restart failed downloads on startup"), _("Tooltip"), False),
- ],
- True)
+ ])
config.addConfigSection("downloadTime", _("Download Time"), _("Description"), _("Long description"),
[
("start", "time", _("Start"), _("Tooltip"), "0:00"),
("end", "time", _("End"), _("Tooltip"), "0:00"),
- ],
- True)
+ ])
diff --git a/module/database/ConfigDatabase.py b/module/database/ConfigDatabase.py
index 198ae0173..7dd5909b8 100644
--- a/module/database/ConfigDatabase.py
+++ b/module/database/ConfigDatabase.py
@@ -16,11 +16,12 @@ class ConfigMethods(DatabaseMethods):
@queue
def loadConfig(self, plugin, user=None):
if user is None:
- self.c.execute('SELECT config FROM settings WHERE plugin=?', (plugin, ))
+ self.c.execute('SELECT config FROM settings WHERE plugin=? AND user=-1', (plugin, ))
else:
self.c.execute('SELECT config FROM settings WHERE plugin=? AND user=?', (plugin, user))
- return self.c.fetchone()[0]
+ r = self.c.fetchone()
+ return r[0] if r else ""
@async
def deleteConfig(self, plugin, user=None):
diff --git a/module/datatypes/User.py b/module/datatypes/User.py
index d48111182..3832653c7 100644
--- a/module/datatypes/User.py
+++ b/module/datatypes/User.py
@@ -28,12 +28,13 @@ class User(UserData):
return User(api, user.uid, user.name, user.email, user.role, user.permission, user.folder,
user.traffic, user.dllimit, user.dlquota, user.hddquota, user.user, user.templateName)
- def __init__(self, api, *args):
- UserData.__init__(self, *args)
+ def __init__(self, api, *args, **kwargs):
+ UserData.__init__(self, *args, **kwargs)
self.api = api
def toUserData(self):
+ # TODO
return UserData()
def hasPermission(self, perms):
diff --git a/module/remote/pyload.thrift b/module/remote/pyload.thrift
index 183fd3af8..47c371904 100644
--- a/module/remote/pyload.thrift
+++ b/module/remote/pyload.thrift
@@ -315,6 +315,10 @@ exception ServiceException {
1: string msg
}
+exception InvalidConfigSection {
+ 1: string section
+}
+
exception Unauthorized {
}
diff --git a/module/remote/ttypes.py b/module/remote/ttypes.py
index eb990f2e8..d661c684a 100644
--- a/module/remote/ttypes.py
+++ b/module/remote/ttypes.py
@@ -220,6 +220,12 @@ class InteractionTask(BaseObject):
self.description = description
self.plugin = plugin
+class InvalidConfigSection(Exception):
+ __slots__ = ['section']
+
+ def __init__(self, section=None):
+ self.section = section
+
class LinkStatus(BaseObject):
__slots__ = ['url', 'name', 'plugin', 'size', 'status', 'packagename']
diff --git a/module/remote/ttypes_debug.py b/module/remote/ttypes_debug.py
index 807a8451b..1e04624d9 100644
--- a/module/remote/ttypes_debug.py
+++ b/module/remote/ttypes_debug.py
@@ -18,6 +18,7 @@ classes = {
'FileDoesNotExists' : [int],
'FileInfo' : [int, basestring, int, int, int, int, int, int, int, (None, DownloadInfo)],
'InteractionTask' : [int, int, (list, basestring), int, (None, basestring), basestring, basestring, basestring],
+ 'InvalidConfigSection' : [basestring],
'LinkStatus' : [basestring, basestring, basestring, int, int, basestring],
'OnlineCheck' : [int, (dict, basestring, LinkStatus)],
'PackageDoesNotExists' : [int],
diff --git a/pyLoadCore.py b/pyLoadCore.py
index f47999a1e..4e249e22f 100755
--- a/pyLoadCore.py
+++ b/pyLoadCore.py
@@ -42,6 +42,7 @@ subprocess.__doc__ = None # the module with the largest doc we are using
from module import InitHomeDir
from module.AccountManager import AccountManager
from module.config.ConfigParser import ConfigParser
+from module.config.ConfigManager import ConfigManager
from module.PluginManager import PluginManager
from module.interaction.EventManager import EventManager
from module.network.RequestFactory import RequestFactory
@@ -365,7 +366,6 @@ class Core(object):
if not tests:
self.writePidFile()
-
self.check_install("Crypto", _("pycrypto to decode container files"))
self.captcha = True # checks seems to fail, although tesseract is available
@@ -373,10 +373,12 @@ class Core(object):
if self.config['ssl']['activated']:
self.check_install("OpenSSL", _("OpenSSL for secure connection"))
-
- self.eventManager = EventManager(self)
+ self.eventManager = self.evm = EventManager(self)
self.setupDB()
+ # Upgrade to configManager
+ self.config = ConfigManager(self, self.config)
+
if self.deleteLinks:
self.log.info(_("All links removed"))
self.db.purgeLinks()
@@ -384,7 +386,7 @@ class Core(object):
self.requestFactory = RequestFactory(self)
__builtin__.pyreq = self.requestFactory
- # later imported because they would trigger api import, and remote value not set correctly
+ # deferred import, could improve start-up time
from module import Api
from module.AddonManager import AddonManager
from module.interaction.InteractionManager import InteractionManager
@@ -396,7 +398,7 @@ class Core(object):
#hell yeah, so many important managers :D
self.pluginManager = PluginManager(self)
- self.interactionManager = InteractionManager(self)
+ self.interactionManager = self.im = InteractionManager(self)
self.accountManager = AccountManager(self)
self.threadManager = ThreadManager(self)
self.addonManager = AddonManager(self)
@@ -569,7 +571,8 @@ class Core(object):
self.eventManager.dispatchEvent("coreShutdown")
try:
if self.config['webinterface']['activated'] and hasattr(self, "webserver"):
- self.webserver.quit()
+ pass # TODO: quit webserver?
+# self.webserver.quit()
for thread in self.threadManager.threads:
thread.put("quit")
diff --git a/tests/api/test_WebSocketAPI.py b/tests/api/test_WebSocketBackend.py
index ac22d044e..be465e3d4 100644
--- a/tests/api/test_WebSocketAPI.py
+++ b/tests/api/test_WebSocketBackend.py
@@ -5,7 +5,7 @@ from nose.tools import raises
from module.remote.ttypes import Forbidden
from module.remote.WSClient import WSClient
-class TestWebSocketAPI:
+class TestWebSocketBackend:
def setUp(self):
self.client = WSClient()
diff --git a/tests/api/test_noargs.py b/tests/api/test_noargs.py
index 02e49cf13..aa010f293 100644
--- a/tests/api/test_noargs.py
+++ b/tests/api/test_noargs.py
@@ -6,7 +6,7 @@ from ApiTester import ApiTester
from module.remote.ttypes import Iface
-IGNORE = ('kill', 'restart')
+IGNORE = ('stop', 'restart')
class TestNoArgs(ApiTester):
def setUp(self):
diff --git a/tests/helper/Stubs.py b/tests/helper/Stubs.py
index 4ebd12592..f0e8d0614 100644
--- a/tests/helper/Stubs.py
+++ b/tests/helper/Stubs.py
@@ -11,6 +11,8 @@ sys.path.append(abspath(join(dirname(__file__), "..", "..")))
import __builtin__
+from module.Api import Role
+from module.datatypes.User import User
from module.datatypes.PyPackage import PyPackage
from module.threads.BaseThread import BaseThread
from module.config.ConfigParser import ConfigParser
@@ -69,7 +71,8 @@ class Core:
__builtin__.pyreq = self.requestFactory
self.accountManager = AccountManager()
self.addonManager = AddonManager()
- self.eventManager = self.interActionManager = NoopClass()
+ self.eventManager = self.evm = NoopClass()
+ self.interActionManager = self.im = NoopClass()
self.js = JsEngine()
self.cache = {}
self.packageCache = {}
@@ -95,7 +98,7 @@ class Core:
def getPackage(self, id):
return PyPackage(self, 0, "tmp", "tmp", "", "", 0, 0)
-
+
def print_exc(self):
log(ERROR, format_exc())
@@ -104,15 +107,17 @@ class NoopClass:
def __getattr__(self, item):
return noop
+
class AddonManager(NoopClass):
def activePlugins(self):
return []
-class AccountManager:
+class AccountManager:
def getAccountForPlugin(self, name):
return None
+
class Thread(BaseThread):
def __init__(self, core):
BaseThread.__init__(self, core)
@@ -131,3 +136,6 @@ __builtin__._ = lambda x: x
__builtin__.pypath = abspath(join(dirname(__file__), "..", ".."))
__builtin__.addonManager = AddonManager()
__builtin__.pyreq = None
+
+adminUser = User(None, uid=0, role=Role.Admin)
+normalUser = User(None, uid=1, role=Role.User) \ No newline at end of file
diff --git a/tests/manager/test_configManager.py b/tests/manager/test_configManager.py
new file mode 100644
index 000000000..1cfb6a5de
--- /dev/null
+++ b/tests/manager/test_configManager.py
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+
+from unittest import TestCase
+from collections import defaultdict
+
+from nose.tools import raises
+
+from tests.helper.Stubs import Core, adminUser, normalUser
+
+from module.Api import InvalidConfigSection
+from module.database import DatabaseBackend
+from module.config.ConfigParser import ConfigParser
+from module.config.ConfigManager import ConfigManager
+
+class TestConfigManager(TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.core = Core()
+ cls.db = DatabaseBackend(cls.core)
+ cls.core.db = cls.db
+ cls.db.manager = cls.core
+ cls.db.manager.statusMsg = defaultdict(lambda: "statusmsg")
+ cls.parser = ConfigParser()
+ cls.config = ConfigManager(cls.core, cls.parser)
+ cls.db.setup()
+
+ def setUp(self):
+ self.db.clearAllConfigs()
+
+ def addConfig(self):
+ self.config.addConfigSection("plugin", "Name", "desc", "something",
+ [("value", "str", "label", "desc", "default")])
+
+ def test_db(self):
+
+ self.db.saveConfig("plugin", "some value", 0)
+ self.db.saveConfig("plugin", "some other value", 1)
+
+ assert self.db.loadConfig("plugin", 0) == "some value"
+ assert self.db.loadConfig("plugin", 1) == "some other value"
+
+ d = self.db.loadAllConfigs()
+ assert d[0]["plugin"] == "some value"
+
+ self.db.deleteConfig("plugin", 0)
+
+ assert 0 not in self.db.loadAllConfigs()
+
+ self.db.deleteConfig("plugin")
+
+ assert not self.db.loadAllConfigs()
+ assert self.db.loadConfig("plugin") == ""
+
+ def test_parser(self):
+ assert self.config.get("general", "language")
+ self.config["general"]["language"] = "de"
+ assert self.config["general"]["language"] == "de"
+ assert self.config.get("general", "language", adminUser) == "de"
+
+ def test_user(self):
+ self.addConfig()
+
+ assert self.config["plugin"]["value"] == "default"
+ assert self.config.get("plugin", "value", adminUser) == "default"
+ assert self.config.get("plugin", "value", normalUser) == "default"
+
+ assert self.config.set("plugin", "value", False, user=normalUser)
+ assert self.config.get("plugin", "value", normalUser) is False
+ assert self.config["plugin"]["value"] == "default"
+
+ assert self.config.set("plugin", "value", True, user=adminUser)
+ assert self.config.get("plugin", "value", adminUser) is True
+ assert self.config["plugin"]["value"] is True
+ assert self.config.get("plugin", "value", normalUser) is False
+
+ self.config.delete("plugin", normalUser)
+ assert self.config.get("plugin", "value", normalUser) == "default"
+
+ self.config.delete("plugin")
+ assert self.config.get("plugin", "value", adminUser) == "default"
+ assert self.config["plugin"]["value"] == "default"
+
+ # should not trigger something
+ self.config.delete("foo")
+
+
+ def test_sections(self):
+ pass
+
+ @raises(InvalidConfigSection)
+ def test_restricted_access(self):
+ self.config.get("general", "language", normalUser)
+
+ @raises(InvalidConfigSection)
+ def test_error(self):
+ self.config.get("foo", "bar")
+
+ @raises(InvalidConfigSection)
+ def test_error_set(self):
+ self.config.set("foo", "bar", True) \ No newline at end of file
diff --git a/tests/other/test_configparser.py b/tests/other/test_configparser.py
index acb05c63e..51ffc5a68 100644
--- a/tests/other/test_configparser.py
+++ b/tests/other/test_configparser.py
@@ -1,44 +1,18 @@
# -*- coding: utf-8 -*-
-from collections import defaultdict
+from nose.tools import raises
+
from tests.helper.Stubs import Core
-from module.database import DatabaseBackend
from module.config.ConfigParser import ConfigParser
-# TODO
class TestConfigParser():
- db = None
-
@classmethod
def setUpClass(cls):
- cls.db = DatabaseBackend(Core())
- cls.db.manager = cls.db.core
- cls.db.manager.statusMsg = defaultdict(lambda: "statusmsg")
+ # Only needed to get imports right
+ cls.core = Core()
cls.config = ConfigParser()
- cls.db.setup()
- cls.db.clearAllConfigs()
-
- @classmethod
- def tearDownClass(cls):
- cls.db.shutdown()
-
- def test_db(self):
-
- self.db.saveConfig("plugin", "some value", 0)
- self.db.saveConfig("plugin", "some other value", 1)
-
- assert self.db.loadConfig("plugin", 0) == "some value"
- assert self.db.loadConfig("plugin", 1) == "some other value"
-
- d = self.db.loadAllConfigs()
- assert d[0]["plugin"] == "some value"
-
- self.db.deleteConfig("plugin")
-
- assert not self.db.loadAllConfigs()
-
def test_dict(self):
@@ -46,8 +20,16 @@ class TestConfigParser():
self.config["general"]["language"] = "de"
assert self.config["general"]["language"] == "de"
- def test_config(self):
- pass
+ def test_contains(self):
+
+ assert "general" in self.config
+ assert "foobaar" not in self.config
+
+
+ @raises(KeyError)
+ def test_invalid_config(self):
+ print self.config["invalid"]["config"]
- def test_userconfig(self):
- pass \ No newline at end of file
+ @raises(KeyError)
+ def test_invalid_section(self):
+ print self.config["general"]["invalid"] \ No newline at end of file