summaryrefslogtreecommitdiffstats
path: root/module/config
diff options
context:
space:
mode:
Diffstat (limited to 'module/config')
-rw-r--r--module/config/ConfigParser.py253
-rw-r--r--module/config/__init__.py1
-rw-r--r--module/config/default.conf65
-rw-r--r--module/config/default.py114
-rw-r--r--module/config/gui_default.xml13
5 files changed, 368 insertions, 78 deletions
diff --git a/module/config/ConfigParser.py b/module/config/ConfigParser.py
new file mode 100644
index 000000000..a9e74dd20
--- /dev/null
+++ b/module/config/ConfigParser.py
@@ -0,0 +1,253 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+from time import sleep
+from os.path import exists
+from gettext import gettext
+from new_collections import namedtuple, OrderedDict
+
+from module.utils import from_string
+from module.utils.fs import chmod
+
+from default import make_config
+
+CONF_VERSION = 2
+SectionTuple = namedtuple("SectionTuple", "name description long_desc config")
+ConfigData = namedtuple("ConfigData", "name type description default")
+
+class ConfigParser:
+ """
+ Holds and manage the configuration + meta data.
+ Actually only the values are read from disk, all meta data have to be provided first via addConfigSection.
+ """
+
+ CONFIG = "pyload.conf"
+ PLUGIN = "plugin.conf"
+
+ def __init__(self):
+ """Constructor"""
+
+ # core config sections from pyload
+ self.baseSections = []
+
+ # 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()
+ self.parseValues(self.CONFIG)
+
+ def loadDefault(self):
+ make_config(self)
+
+ def checkVersion(self):
+ """Determines if config need to be deleted"""
+ e = None
+ # workaround conflict, with GUI (which also access 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))
+ f.close()
+
+ except Exception, ex:
+ e = ex
+ sleep(0.3)
+ if e: raise e
+
+
+ def parseValues(self, filename):
+ """read config values from file"""
+ f = open(filename, "rb")
+ config = f.readlines()[1:]
+
+ # save the current section
+ section = ""
+
+ for line in config:
+ line = line.strip()
+
+ # comment line, different variants
+ if not line or line.startswith("#") or line.startswith("//") or line.startswith(";"): continue
+
+ if line.startswith("["):
+ section = line.replace("[", "").replace("]", "")
+
+ if section not in self.config:
+ print "Unrecognzied section", section
+ section = ""
+
+ else:
+ name, non, value = line.rpartition("=")
+ name = name.strip()
+ value = value.strip()
+
+ if not section:
+ print "Value without section", name
+ continue
+
+ if name in self.config[section].config:
+ self.set(section, name, value, sync=False)
+ else:
+ print "Unrecognized option", section, name
+
+
+ def save(self):
+ """saves config to filename"""
+
+ # seperate 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)
+
+
+ # 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():
+ value = self.get(section, option)
+ if type(value) == unicode: value = value.encode("utf8")
+ else: value = str(value)
+
+ f.write('%s = %s\n' % (option, value))
+
+ f.write("\n")
+
+ [f.close() for f in configs]
+
+ def __getitem__(self, section):
+ """provides dictonary like access: c['section']['option']"""
+ return Section(self, section)
+
+ def get(self, section, option):
+ """get value"""
+ if option in self.values[section]:
+ return self.values[section][option]
+ else:
+ return self.config[section].config[option].default
+
+ def set(self, section, option, value, sync=True):
+ """set value"""
+
+ data = self.config[section].config[option]
+ value = from_string(value, data.type)
+
+ # only save when different to defaul values
+ if value != data.default or (option in self.values[section] and value != self.values[section][option]):
+ self.values[section][option] = value
+ if sync:
+ if self.changeCB: self.changeCB(section, option, value)
+ self.save()
+
+ 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)
+
+ 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 addConfigSection(self, section, name, desc, long_desc, config, base=False):
+ """Adds a section to the config. `config` is a list of config tuples as used in plugin api definied as:
+ Either (name, type, verbose_name, default_value) or
+ (name, type, verbose_name, short_description, default_value)
+ The ordner of the config elements are preserved with OrdererDict
+ """
+ d = OrderedDict()
+
+ for entry in config:
+ if len(entry) == 5:
+ conf_name, type, conf_desc, conf_verbose, default = entry
+ else: # config options without tooltip / 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"""
+
+ def __init__(self, parser, section):
+ """Constructor"""
+ self.parser = parser
+ self.section = section
+
+ def __getitem__(self, item):
+ """getitem"""
+ return self.parser.get(self.section, item)
+
+ 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/__init__.py b/module/config/__init__.py
new file mode 100644
index 000000000..4b31e848b
--- /dev/null
+++ b/module/config/__init__.py
@@ -0,0 +1 @@
+__author__ = 'christian'
diff --git a/module/config/default.conf b/module/config/default.conf
deleted file mode 100644
index 335ca10fe..000000000
--- a/module/config/default.conf
+++ /dev/null
@@ -1,65 +0,0 @@
-version: 1
-
-remote - "Remote":
- int port : "Port" = 7227
- ip listenaddr : "Adress" = 0.0.0.0
- bool nolocalauth : "No authentication on local connections" = True
- bool activated : "Activated" = True
-ssl - "SSL":
- bool activated : "Activated"= False
- file cert : "SSL Certificate" = ssl.crt
- file key : "SSL Key" = ssl.key
-webinterface - "Webinterface":
- bool activated : "Activated" = True
- builtin;threaded;fastcgi;lightweight server : "Server" = builtin
- bool https : "Use HTTPS" = False
- ip host : "IP" = 0.0.0.0
- int port : "Port" = 8001
- str template : "Template" = default
- str prefix: "Path Prefix" =
-log - "Log":
- bool file_log : "File Log" = True
- folder log_folder : "Folder" = Logs
- int log_count : "Count" = 5
- int log_size : "Size in kb" = 100
- bool log_rotate : "Log Rotate" = True
-general - "General":
- en;de;fr;it;es;nl;sv;ru;pl;cs;sr;pt_BR language : "Language" = en
- folder download_folder : "Download Folder" = Downloads
- bool debug_mode : "Debug Mode" = False
- bool checksum : "Use Checksum" = False
- int min_free_space : "Min Free Space (MB)" = 200
- bool folder_per_package : "Create folder for each package" = True
- int renice : "CPU Priority" = 0
-download - "Download":
- int chunks : "Max connections for one download" = 3
- int max_downloads : "Max Parallel Downloads" = 3
- int max_speed : "Max Download Speed in kb/s" = -1
- bool limit_speed : "Limit Download Speed" = False
- str interface : "Download interface to bind (ip or Name)" = None
- bool ipv6 : "Allow IPv6" = False
- bool skip_existing : "Skip already existing files" = False
-permission - "Permissions":
- bool change_user : "Change user of running process" = False
- str user : "Username" = user
- str folder : "Folder Permission mode" = 0755
- bool change_file : "Change file mode of downloads" = False
- str file : "Filemode for Downloads" = 0644
- bool change_group : "Change group of running process" = False
- str group : "Groupname" = users
- bool change_dl : "Change Group and User of Downloads" = False
-reconnect - "Reconnect":
- bool activated : "Use Reconnect" = False
- str method : "Method" = None
- time startTime : "Start" = 0:00
- time endTime : "End" = 0:00
-downloadTime - "Download Time":
- time start : "Start" = 0:00
- time end : "End" = 0:00
-proxy - "Proxy":
- str address : "Address" = "localhost"
- int port : "Port" = 7070
- http;socks4;socks5 type : "Protocol" = http
- str username : "Username" = None
- password password : "Password" = None
- bool proxy : "Use Proxy" = False
diff --git a/module/config/default.py b/module/config/default.py
new file mode 100644
index 000000000..1dbb58eca
--- /dev/null
+++ b/module/config/default.py
@@ -0,0 +1,114 @@
+# -*- coding: utf-8 -*-
+
+"""
+Configuration layout for default base config
+"""
+
+#TODO: write tooltips and descriptions
+
+def make_config(config):
+ # Check if gettext is installed
+ _ = lambda x: x
+
+ config.addConfigSection("remote", _("Remote"), _("Description"), _("Long description"),
+ [
+ ("nolocalauth", "bool", _("No authentication on local connections"), _("Tooltip"), True),
+ ("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"),
+ [
+ ("log_size", "int", _("Size in kb"), _("Tooltip"), 100),
+ ("log_folder", "folder", _("Folder"), _("Tooltip"), "Logs"),
+ ("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"),
+ [
+ ("group", "str", _("Groupname"), _("Tooltip"), "users"),
+ ("change_dl", "bool", _("Change Group and User of Downloads"), _("Tooltip"), False),
+ ("change_file", "bool", _("Change file mode of downloads"), _("Tooltip"), False),
+ ("user", "str", _("Username"), _("Tooltip"), "user"),
+ ("file", "str", _("Filemode for Downloads"), _("Tooltip"), "0644"),
+ ("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"),
+ [
+ ("language", "en;de;fr;it;es;nl;sv;ru;pl;cs;sr;pt_BR", _("Language"), _("Tooltip"), "en"),
+ ("download_folder", "folder", _("Download Folder"), _("Tooltip"), "Downloads"),
+ ("checksum", "bool", _("Use Checksum"), _("Tooltip"), False),
+ ("folder_per_package", "bool", _("Create folder for each package"), _("Tooltip"), True),
+ ("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"),
+ [
+ ("template", "str", _("Template"), _("Tooltip"), "default"),
+ ("activated", "bool", _("Activated"), _("Tooltip"), True),
+ ("prefix", "str", _("Path Prefix"), _("Tooltip"), ""),
+ ("server", "builtin;threaded;fastcgi;lightweight", _("Server"), _("Tooltip"), "builtin"),
+ ("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"),
+ [
+ ("username", "str", _("Username"), _("Tooltip"), ""),
+ ("proxy", "bool", _("Use Proxy"), _("Tooltip"), False),
+ ("address", "str", _("Address"), _("Tooltip"), "localhost"),
+ ("password", "password", _("Password"), _("Tooltip"), ""),
+ ("type", "http;socks4;socks5", _("Protocol"), _("Tooltip"), "http"),
+ ("port", "int", _("Port"), _("Tooltip"), 7070),
+ ],
+ True)
+
+ config.addConfigSection("reconnect", _("Reconnect"), _("Description"), _("Long description"),
+ [
+ ("endTime", "time", _("End"), _("Tooltip"), "0:00"),
+ ("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"),
+ [
+ ("max_downloads", "int", _("Max Parallel Downloads"), _("Tooltip"), 3),
+ ("limit_speed", "bool", _("Limit Download Speed"), _("Tooltip"), False),
+ ("interface", "str", _("Download interface to bind (ip or Name)"), _("Tooltip"), ""),
+ ("skip_existing", "bool", _("Skip already existing files"), _("Tooltip"), False),
+ ("max_speed", "int", _("Max Download Speed in kb/s"), _("Tooltip"), -1),
+ ("ipv6", "bool", _("Allow IPv6"), _("Tooltip"), False),
+ ("chunks", "int", _("Max connections for one download"), _("Tooltip"), 3),
+ ],
+ 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/config/gui_default.xml b/module/config/gui_default.xml
deleted file mode 100644
index 1faed776f..000000000
--- a/module/config/gui_default.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" ?>
-<root>
- <connections>
- <connection default="True" type="local" id="33965310e19b4a869112c43b39a16440">
- <name>Local</name>
- </connection>
- </connections>
- <mainWindow>
- <state></state>
- <geometry></geometry>
- </mainWindow>
- <language>en</language>
-</root>