コード例 #1
0
    def __init__(self, core):
        self.lock = Lock()
        self.core = core
        self.tasks = OrderedDict()  #task store, for all outgoing tasks

        self.last_clients = {}
        self.ids = 0  #uniue interaction ids
コード例 #2
0
    def __init__(self, config=None):

        if config: self.CONFIG = config

        # Meta data information
        self.config = OrderedDict()
        # The actual config values
        self.values = {}

        self.checkVersion()

        self.loadDefault()
        self.parseValues(self.CONFIG)
コード例 #3
0
    def __init__(self, core):
        self.lock = Lock()
        self.core = core
        self.tasks = OrderedDict()  #task store, for outgoing tasks only
        self.notifications = []  #list of notifications

        self.last_clients = {
            Output.Notification: 0,
            Output.Captcha: 0,
            Output.Query: 0,
        }

        self.ids = 0  #only for internal purpose
コード例 #4
0
ファイル: ConfigManager.py プロジェクト: sebmaynard/pyload
    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 = {}
コード例 #5
0
    def __init__(self, core):
        self.lock = Lock()
        self.core = core
        self.tasks = OrderedDict() #task store, for all outgoing tasks

        self.last_clients = {}
        self.ids = 0 #uniue interaction ids
コード例 #6
0
    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 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()

        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] = {}
コード例 #7
0
ファイル: FileDatabase.py プロジェクト: keat01/pyLoad
    def getAllPackages(self, root=None, owner=None, tags=None):
        """ Return dict with package information

        :param root: optional root to filter
        :param owner: optional user id
        :param tags: optional tag list
        """
        qry = ('SELECT pid, name, folder, root, owner, site, comment, password, added, tags, status, packageorder '
               'FROM packages%s ORDER BY root, packageorder')

        if root is None:
            stats = self.getPackageStats(owner=owner)
            if owner is None:
                self.c.execute(qry % "")
            else:
                self.c.execute(qry % " WHERE owner=?", (owner,))
        else:
            stats = self.getPackageStats(root=root, owner=owner)
            if owner is None:
                self.c.execute(qry % ' WHERE root=? OR pid=?', (root, root))
            else:
                self.c.execute(qry % ' WHERE (root=? OR pid=?) AND owner=?', (root, root, owner))

        data = OrderedDict()
        for r in self.c:
            data[r[0]] = PackageInfo(
                r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9].split(","), r[10], r[11], stats.get(r[0], zero_stats)
            )

        return data
コード例 #8
0
    def addConfigSection(self, section, label, desc, expl, config):
        """Adds a section to the config. `config` is a list of config tuple as used in plugin api defined as:
        The order of the config elements is preserved with OrderedDict
        """
        d = OrderedDict()

        for entry in config:
            name, data = to_configdata(entry)
            d[name] = data

        data = SectionTuple(gettext(label), gettext(desc), gettext(expl), d)
        self.config[section] = data
コード例 #9
0
ファイル: InteractionManager.py プロジェクト: beefone/pyload
    def __init__(self, core):
        self.lock = Lock()
        self.core = core
        self.tasks = OrderedDict() #task store, for outgoing tasks only
        self.notifications = [] #list of notifications

        self.last_clients = {
            Output.Notification : 0,
            Output.Captcha : 0,
            Output.Query : 0,
        }

        self.ids = 0 #only for internal purpose
コード例 #10
0
ファイル: ConfigParser.py プロジェクト: DasLampe/pyload
    def __init__(self, config=None):

        if config: self.CONFIG = config

        # Meta data information
        self.config = OrderedDict()
        # The actual config values
        self.values = {}

        self.checkVersion()

        self.loadDefault()
        self.parseValues(self.CONFIG)
コード例 #11
0
ファイル: ConfigManager.py プロジェクト: beefone/pyload
    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 = {}
コード例 #12
0
def get_system_info():
    """ Returns system information as dict """
    global info

    if info is None:
        import platform

        info = OrderedDict([
            (_("Platform"), platform.platform()),
            (_("Version"), sys.version),
            (_("Path"), os.path.abspath("")),
            (_("Encoding"), sys.getdefaultencoding()),
            (_("FS-Encoding"), sys.getfilesystemencoding())
        ])

    return info
コード例 #13
0
    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)
コード例 #14
0
    def getAllFiles(self, package=None, search=None, state=None, owner=None):
        """ Return dict with file information

        :param package: optional package to filter out
        :param search: or search string for file name
        :param unfinished: filter by dlstatus not finished
        :param owner: only specific owner
        """
        qry = (
            'SELECT fid, name, owner, size, status, media, added, fileorder, '
            'url, plugin, hash, dlstatus, error, package FROM files WHERE ')

        arg = []

        if state is not None and state != DS.All:
            qry += 'dlstatus IN (%s) AND ' % state_string(state)
        if owner is not None:
            qry += 'owner=? AND '
            arg.append(owner)

        if package is not None:
            arg.append(package)
            qry += 'package=? AND '
        if search is not None:
            search = "%%%s%%" % search.strip("%")
            arg.append(search)
            qry += "name LIKE ? "

        # make qry valid
        if qry.endswith("WHERE "): qry = qry[:-6]
        if qry.endswith("AND "): qry = qry[:-4]

        self.c.execute(qry + "ORDER BY package, fileorder", arg)

        data = OrderedDict()
        for r in self.c:
            f = FileInfo(r[0], r[1], r[13], r[2], r[3], r[4], r[5], r[6], r[7])
            if r[11] > 0:  # dl status != NA
                f.download = DownloadInfo(r[8], r[9], r[10], r[11],
                                          self.manager.statusMsg[r[11]], r[12])

            data[r[0]] = f

        return data
コード例 #15
0
ファイル: ConfigParser.py プロジェクト: Kagenoshin/pyload
    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:
        The order of the config elements is preserved with OrderedDict
        """
        d = OrderedDict()

        for entry in config:
            if len(entry) == 5:
                conf_name, type, conf_desc, conf_verbose, default = entry
            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))

        data = SectionTuple(gettext(name), gettext(desc), gettext(long_desc),
                            d)
        self.config[section] = data
コード例 #16
0
ファイル: InteractionManager.py プロジェクト: beefone/pyload
class InteractionManager:
    """
    Class that gives ability to interact with the user.
    Arbitrary tasks with predefined output and input types can be set off.
    Asynchronous callbacks and default values keep the ability to fallback if no user is present.
    """

    # number of seconds a client is classified as active
    CLIENT_THRESHOLD = 60

    def __init__(self, core):
        self.lock = Lock()
        self.core = core
        self.tasks = OrderedDict() #task store, for outgoing tasks only
        self.notifications = [] #list of notifications

        self.last_clients = {
            Output.Notification : 0,
            Output.Captcha : 0,
            Output.Query : 0,
        }

        self.ids = 0 #only for internal purpose


    def isClientConnected(self, mode=Output.All):
        if mode == Output.All:
            return max(self.last_clients.values()) + self.CLIENT_THRESHOLD <= time()
        else:
            self.last_clients.get(mode, 0) + self.CLIENT_THRESHOLD <= time()

    def updateClient(self, mode):
        t = time()
        for output in self.last_clients:
            if bits_set(output, mode):
                self.last_clients[output] = t

    @lock
    def work(self):
        # old notifications will be removed
        for n in [x for x in self.notifications if x.timedOut()]:
            self.notifications.remove(n)

        # store at most 100 notifications
        del self.notifications[50:]


    @lock
    def createNotification(self, title, content, desc="", plugin=""):
        """ Creates and queues a new Notification

        :param title: short title
        :param content: text content
        :param desc: short form of the notification
        :param plugin: plugin name
        :return: :class:`InteractionTask`
        """
        task = InteractionTask(self.ids, Input.Text, [content], Output.Notification, "", title, desc, plugin)
        self.ids += 1
        self.notifications.insert(0, task)
        self.handleTask(task)
        return task

    @lock
    def newQueryTask(self, input, data, desc, default="", plugin=""):
        task = InteractionTask(self.ids, input, to_list(data), Output.Query, default, _("Query"), desc, plugin)
        self.ids += 1
        return task

    @lock
    def newCaptchaTask(self, img, format, filename, plugin="", input=Input.Text):
        #todo: title desc plugin
        task = InteractionTask(self.ids, input, [img, format, filename],Output.Captcha,
            "", _("Captcha request"), _("Please solve the captcha."), plugin)
        self.ids += 1
        return task

    @lock
    def removeTask(self, task):
        if task.iid in self.tasks:
            del self.tasks[task.iid]

    @lock
    def getTask(self, mode=Output.All):
        self.updateClient(mode)

        for task in self.tasks.itervalues():
            if mode == Output.All or bits_set(task.output, mode):
                return task

    @lock
    def getNotifications(self):
        """retrieves notifications, old ones are only deleted after a while\
             client has to make sure itself to dont display it twice"""
        for n in self.notifications:
            n.setWaiting(self.CLIENT_THRESHOLD * 5, True)
            #store notification for shorter period, lock the timeout

        return self.notifications

    def isTaskWaiting(self, mode=Output.All):
        return self.getTask(mode) is not None

    @lock
    def getTaskByID(self, iid):
        if iid in self.tasks:
            task = self.tasks[iid]
            del self.tasks[iid]
            return task

    def handleTask(self, task):
        cli = self.isClientConnected(task.output)

        if cli: #client connected -> should handle the task
            task.setWaiting(self.CLIENT_THRESHOLD) # wait for response

        if task.output == Output.Notification:
            task.setWaiting(60 * 60 * 30) # notifications are valid for 30h

        for plugin in self.core.addonManager.activePlugins():
            try:
                plugin.newInteractionTask(task)
            except:
                self.core.print_exc()

        if task.output != Output.Notification:
            self.tasks[task.iid] = task
コード例 #17
0
class InteractionManager:
    """
    Class that gives ability to interact with the user.
    Arbitrary tasks with predefined output and input types can be set off.
    """

    # number of seconds a client is classified as active
    CLIENT_THRESHOLD = 60
    NOTIFICATION_TIMEOUT = 60 * 60 * 30
    MAX_NOTIFICATIONS = 50

    def __init__(self, core):
        self.lock = Lock()
        self.core = core
        self.tasks = OrderedDict()  #task store, for all outgoing tasks

        self.last_clients = {}
        self.ids = 0  #uniue interaction ids

    def isClientConnected(self, user):
        return self.last_clients.get(user, 0) + self.CLIENT_THRESHOLD > time()

    @lock
    def work(self):
        # old notifications will be removed
        for n in [k for k, v in self.tasks.iteritems() if v.timedOut()]:
            del self.tasks[n]

        # keep notifications count limited
        n = [k for k, v in self.tasks.iteritems() if v.type == IA.Notification]
        n.reverse()
        for v in n[:self.MAX_NOTIFICATIONS]:
            del self.tasks[v]

    @lock
    def createNotification(self,
                           title,
                           content,
                           desc="",
                           plugin="",
                           owner=None):
        """ Creates and queues a new Notification

        :param title: short title
        :param content: text content
        :param desc: short form of the notification
        :param plugin: plugin name
        :return: :class:`InteractionTask`
        """
        task = InteractionTask(self.ids,
                               IA.Notification,
                               Input(InputType.Text, None, content),
                               title,
                               desc,
                               plugin,
                               owner=owner)
        self.ids += 1
        self.queueTask(task)
        return task

    @lock
    def createQueryTask(self, input, desc, plugin="", owner=None):
        # input type was given, create a input widget
        if type(input) == int:
            input = Input(input)
        if not isinstance(input, Input):
            raise TypeError("'Input' class expected not '%s'" % type(input))

        task = InteractionTask(self.ids,
                               IA.Query,
                               input,
                               _("Query"),
                               desc,
                               plugin,
                               owner=owner)
        self.ids += 1
        self.queueTask(task)
        return task

    @lock
    def createCaptchaTask(self,
                          img,
                          format,
                          filename,
                          plugin="",
                          type=InputType.Text,
                          owner=None):
        """ Createss a new captcha task.

        :param img: image content (not base encoded)
        :param format: img format
        :param type: :class:`InputType`
        :return:
        """
        if type == 'textual':
            type = InputType.Text
        elif type == 'positional':
            type = InputType.Click

        input = Input(type, data=[standard_b64encode(img), format, filename])

        #todo: title desc plugin
        task = InteractionTask(self.ids,
                               IA.Captcha,
                               input,
                               _("Captcha request"),
                               _("Please solve the captcha."),
                               plugin,
                               owner=owner)

        self.ids += 1
        self.queueTask(task)
        return task

    @lock
    def removeTask(self, task):
        if task.iid in self.tasks:
            del self.tasks[task.iid]
            self.core.evm.dispatchEvent("interaction:deleted", task.iid)

    @lock
    def getTaskByID(self, iid):
        return self.tasks.get(iid, None)

    @lock
    def getTasks(self, user, mode=IA.All):
        # update last active clients
        self.last_clients[user] = time()

        # filter current mode
        tasks = [
            t for t in self.tasks.itervalues()
            if mode == IA.All or bits_set(t.type, mode)
        ]
        # filter correct user / or shared
        tasks = [
            t for t in tasks if user is None or user == t.owner or t.shared
        ]

        return tasks

    def isTaskWaiting(self, user, mode=IA.All):
        tasks = [
            t for t in self.getTasks(user, mode)
            if not t.type == IA.Notification or not t.seen
        ]
        return len(tasks) > 0

    def queueTask(self, task):
        cli = self.isClientConnected(task.owner)

        # set waiting times based on threshold
        if cli:
            task.setWaiting(self.CLIENT_THRESHOLD)
        else:  # TODO: higher threshold after client connects?
            task.setWaiting(self.CLIENT_THRESHOLD / 3)

        if task.type == IA.Notification:
            task.setWaiting(
                self.NOTIFICATION_TIMEOUT)  # notifications are valid for 30h

        for plugin in self.core.addonManager.activePlugins():
            try:
                plugin.newInteractionTask(task)
            except:
                self.core.print_exc()

        self.tasks[task.iid] = task
        self.core.evm.dispatchEvent("interaction:added", task)
コード例 #18
0
class InteractionManager:
    """
    Class that gives ability to interact with the user.
    Arbitrary tasks with predefined output and input types can be set off.
    Asynchronous callbacks and default values keep the ability to fallback if no user is present.
    """

    # number of seconds a client is classified as active
    CLIENT_THRESHOLD = 60

    def __init__(self, core):
        self.lock = Lock()
        self.core = core
        self.tasks = OrderedDict()  #task store, for outgoing tasks only
        self.notifications = []  #list of notifications

        self.last_clients = {
            Output.Notification: 0,
            Output.Captcha: 0,
            Output.Query: 0,
        }

        self.ids = 0  #only for internal purpose

    def isClientConnected(self, mode=Output.All):
        if mode == Output.All:
            return max(
                self.last_clients.values()) + self.CLIENT_THRESHOLD <= time()
        else:
            self.last_clients.get(mode, 0) + self.CLIENT_THRESHOLD <= time()

    def updateClient(self, mode):
        t = time()
        for output in self.last_clients:
            if bits_set(output, mode):
                self.last_clients[output] = t

    @lock
    def work(self):
        # old notifications will be removed
        for n in [x for x in self.notifications if x.timedOut()]:
            self.notifications.remove(n)

        # store at most 100 notifications
        del self.notifications[50:]

    @lock
    def createNotification(self, title, content, desc="", plugin=""):
        """ Creates and queues a new Notification

        :param title: short title
        :param content: text content
        :param desc: short form of the notification
        :param plugin: plugin name
        :return: :class:`InteractionTask`
        """
        task = InteractionTask(self.ids, Input.Text, [content],
                               Output.Notification, "", title, desc, plugin)
        self.ids += 1
        self.notifications.insert(0, task)
        self.handleTask(task)
        return task

    @lock
    def newQueryTask(self, input, data, desc, default="", plugin=""):
        task = InteractionTask(self.ids, input, to_list(data), Output.Query,
                               default, _("Query"), desc, plugin)
        self.ids += 1
        return task

    @lock
    def newCaptchaTask(self,
                       img,
                       format,
                       filename,
                       plugin="",
                       input=Input.Text):
        #todo: title desc plugin
        task = InteractionTask(self.ids, input, [img, format, filename],
                               Output.Captcha, "", _("Captcha request"),
                               _("Please solve the captcha."), plugin)
        self.ids += 1
        return task

    @lock
    def removeTask(self, task):
        if task.iid in self.tasks:
            del self.tasks[task.iid]

    @lock
    def getTask(self, mode=Output.All):
        self.updateClient(mode)

        for task in self.tasks.itervalues():
            if mode == Output.All or bits_set(task.output, mode):
                return task

    @lock
    def getNotifications(self):
        """retrieves notifications, old ones are only deleted after a while\
             client has to make sure itself to dont display it twice"""
        for n in self.notifications:
            n.setWaiting(self.CLIENT_THRESHOLD * 5, True)
            #store notification for shorter period, lock the timeout

        return self.notifications

    def isTaskWaiting(self, mode=Output.All):
        return self.getTask(mode) is not None

    @lock
    def getTaskByID(self, iid):
        if iid in self.tasks:
            task = self.tasks[iid]
            del self.tasks[iid]
            return task

    def handleTask(self, task):
        cli = self.isClientConnected(task.output)

        if cli:  #client connected -> should handle the task
            task.setWaiting(self.CLIENT_THRESHOLD)  # wait for response

        if task.output == Output.Notification:
            task.setWaiting(60 * 60 * 30)  # notifications are valid for 30h

        for plugin in self.core.addonManager.activePlugins():
            try:
                plugin.newInteractionTask(task)
            except:
                self.core.print_exc()

        if task.output != Output.Notification:
            self.tasks[task.iid] = task
コード例 #19
0
ファイル: ConfigManager.py プロジェクト: beefone/pyload
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 = primary_uid(user)
            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 = primary_uid(user)
            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", section, option, 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.primary if user else None
        if (user, section) in self.values:
            del self.values[user, section]

        self.db.deleteConfig(section, user)

    def iterCoreSections(self):
        return self.parser.iterSections()

    def iterSections(self, user=None):
        """ Yields: section, metadata, values """

        user = primary_uid(user)
        values = self.db.loadConfigsForUser(user)

        # Every section needs to be json decoded
        for section, data in values.items():
            try:
                values[section] = json.loads(data) if data else {}
            except ValueError:
                values[section] = {}
                self.core.print_exc()

        for name, config in self.config.iteritems():
            yield name, config, values[name] if name in values else {}
コード例 #20
0
ファイル: ConfigManager.py プロジェクト: sebmaynard/pyload
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 user is None:
            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
            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()

        return self.values[user, section]

    @convertKeyError
    def set(self, section, option, value, sync=True, user=None):
        """ set config value  """

        changed = False
        if section in self.parser and user is None:
            changed = self.parser.set(section, option, value, sync)
        else:
            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
                if sync: self.saveValues(user, section)

        if changed: self.core.evm.dispatchEvent("config:changed", section, option, value)
        return changed

    def saveValues(self, user, section):
        self.db.saveConfig(section, json.dumps(self.values[user, section]), user)

    def delete(self, section, user=None):
        """ Deletes values saved in db and cached values for given user, NOT meta data
            Does not trigger an error when nothing was deleted. """
        if (user, section) in self.values:
            del self.values[user, section]

        self.db.deleteConfig(section, user)
        self.core.evm.dispatchEvent("config:deleted", section, user)

    def iterCoreSections(self):
        return self.parser.iterSections()

    def iterSections(self, user=None):
        """ Yields: section, metadata, values """
        values = self.db.loadConfigsForUser(user)

        # Every section needs to be json decoded
        for section, data in values.items():
            try:
                values[section] = json.loads(data) if data else {}
            except ValueError:
                values[section] = {}
                self.core.print_exc()

        for name, config in self.config.iteritems():
            yield name, config, values[name] if name in values else {}

    def getSection(self, section, user=None):
        if section in self.parser and user is None:
            return self.parser.getSection(section)

        values = self.loadValues(user, section)
        return self.config.get(section), values
コード例 #21
0
ファイル: ConfigParser.py プロジェクト: DasLampe/pyload
class ConfigParser:
    """
    Holds and manages the configuration + meta data for config read from file.
    """

    CONFIG = "pyload.conf"

    def __init__(self, config=None):

        if config: self.CONFIG = config

        # Meta data information
        self.config = OrderedDict()
        # The actual config values
        self.values = {}

        self.checkVersion()

        self.loadDefault()
        self.parseValues(self.CONFIG)

    def loadDefault(self):
        make_config(self)

    def checkVersion(self):
        """Determines if config needs to be deleted"""
        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()

    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 "Unrecognized 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"""

        configs = []
        f = open(self.CONFIG, "wb")
        configs.append(f)
        chmod(self.CONFIG, 0600)
        f.write("version: %i\n\n" % CONF_VERSION)

        for section, data in self.config.iteritems():
            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()

    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 or default"""
        try:
            return self.values[section][option]
        except KeyError:
            return self.config[section].config[option].input.default_value

    def set(self, section, option, value, sync=True):
        """set value"""

        data = self.config[section].config[option]
        value = from_string(value, data.input.type)
        old_value = self.get(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:
                self.save()
            return True

        return False

    def getMetaData(self, section, option):
        """ get all config data for an option """
        return self.config[section].config[option]

    def iterSections(self):
        """ Yields section, config info, values, for all sections """

        for name, config in self.config.iteritems():
            yield name, config, self.values[name] if name in self.values else {}

    def getSection(self, section):
        """ Retrieves single config as tuple (section, values) """
        return self.config[section], self.values[section] if section in self.values else {}

    def addConfigSection(self, section, label, desc, expl, config):
        """Adds a section to the config. `config` is a list of config tuples as used in plugin api defined as:
        The order of the config elements is preserved with OrderedDict
        """
        d = OrderedDict()

        for entry in config:
            if len(entry) != 4:
                raise ValueError("Config entry must be of length 4")

            # Values can have different roles depending on the two config formats
            conf_name, type_label, label_desc, default_input = entry

            # name, label, desc, input
            if isinstance(default_input, Input):
                input = default_input
                conf_label = type_label
                conf_desc = label_desc
            # name, type, label, default
            else:
                input = Input(to_input(type_label))
                input.default_value = from_string(default_input, input.type)
                conf_label = label_desc
                conf_desc = ""

            d[conf_name] = ConfigData(gettext(conf_label), gettext(conf_desc), input)

        data = SectionTuple(gettext(label), gettext(desc), gettext(expl), d)
        self.config[section] = data
コード例 #22
0
class ConfigParser:
    """
    Holds and manages the configuration + meta data for config read from file.
    """

    CONFIG = "pyload.conf"

    def __init__(self, config=None):

        if config: self.CONFIG = config

        # Meta data information
        self.config = OrderedDict()
        # The actual config values
        self.values = {}

        self.checkVersion()

        self.loadDefault()
        self.parseValues(self.CONFIG)

    def loadDefault(self):
        make_config(self)

    def checkVersion(self):
        """Determines if config needs to be deleted"""
        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()

    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 "Unrecognized 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"""

        configs = []
        f = open(self.CONFIG, "wb")
        configs.append(f)
        chmod(self.CONFIG, 0600)
        f.write("version: %i\n\n" % CONF_VERSION)

        for section, data in self.config.iteritems():
            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()

    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 or default"""
        try:
            return self.values[section][option]
        except KeyError:
            return self.config[section].config[option].input.default_value

    def set(self, section, option, value, sync=True):
        """set value"""

        data = self.config[section].config[option]
        value = from_string(value, data.input.type)
        old_value = self.get(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:
                self.save()
            return True

        return False

    def getMetaData(self, section, option):
        """ get all config data for an option """
        return self.config[section].config[option]

    def iterSections(self):
        """ Yields section, config info, values, for all sections """

        for name, config in self.config.iteritems():
            yield name, config, self.values[
                name] if name in self.values else {}

    def getSection(self, section):
        """ Retrieves single config as tuple (section, values) """
        return self.config[
            section], self.values[section] if section in self.values else {}

    def addConfigSection(self, section, label, desc, expl, config):
        """Adds a section to the config. `config` is a list of config tuple as used in plugin api defined as:
        The order of the config elements is preserved with OrderedDict
        """
        d = OrderedDict()

        for entry in config:
            name, data = to_configdata(entry)
            d[name] = data

        data = SectionTuple(gettext(label), gettext(desc), gettext(expl), d)
        self.config[section] = data
コード例 #23
0
class InteractionManager:
    """
    Class that gives ability to interact with the user.
    Arbitrary tasks with predefined output and input types can be set off.
    """

    # number of seconds a client is classified as active
    CLIENT_THRESHOLD = 60
    NOTIFICATION_TIMEOUT = 60 * 60 * 30
    MAX_NOTIFICATIONS = 50

    def __init__(self, core):
        self.lock = Lock()
        self.core = core
        self.tasks = OrderedDict() #task store, for all outgoing tasks

        self.last_clients = {}
        self.ids = 0 #uniue interaction ids

    def isClientConnected(self, user):
        return self.last_clients.get(user, 0) + self.CLIENT_THRESHOLD > time()

    @lock
    def work(self):
        # old notifications will be removed
        for n in [k for k, v in self.tasks.iteritems() if v.timedOut()]:
            del self.tasks[n]

        # keep notifications count limited
        n = [k for k,v in self.tasks.iteritems() if v.type == IA.Notification]
        n.reverse()
        for v in n[:self.MAX_NOTIFICATIONS]:
            del self.tasks[v]

    @lock
    def createNotification(self, title, content, desc="", plugin="", owner=None):
        """ Creates and queues a new Notification

        :param title: short title
        :param content: text content
        :param desc: short form of the notification
        :param plugin: plugin name
        :return: :class:`InteractionTask`
        """
        task = InteractionTask(self.ids, IA.Notification, Input(InputType.Text, None, content), title, desc, plugin,
                               owner=owner)
        self.ids += 1
        self.queueTask(task)
        return task

    @lock
    def createQueryTask(self, input, desc, plugin="", owner=None):
        # input type was given, create a input widget
        if type(input) == int:
            input = Input(input)
        if not isinstance(input, Input):
            raise TypeError("'Input' class expected not '%s'" % type(input))

        task = InteractionTask(self.ids, IA.Query, input, _("Query"), desc, plugin, owner=owner)
        self.ids += 1
        self.queueTask(task)
        return task

    @lock
    def createCaptchaTask(self, img, format, filename, plugin="", type=InputType.Text, owner=None):
        """ Createss a new captcha task.

        :param img: image content (not base encoded)
        :param format: img format
        :param type: :class:`InputType`
        :return:
        """
        if type == 'textual':
            type = InputType.Text
        elif type == 'positional':
            type = InputType.Click

        input = Input(type, data=[standard_b64encode(img), format, filename])

        #todo: title desc plugin
        task = InteractionTask(self.ids, IA.Captcha, input,
                            _("Captcha request"), _("Please solve the captcha."), plugin, owner=owner)

        self.ids += 1
        self.queueTask(task)
        return task

    @lock
    def removeTask(self, task):
        if task.iid in self.tasks:
            del self.tasks[task.iid]
            self.core.evm.dispatchEvent("interaction:deleted", task.iid)

    @lock
    def getTaskByID(self, iid):
        return self.tasks.get(iid, None)

    @lock
    def getTasks(self, user, mode=IA.All):
        # update last active clients
        self.last_clients[user] = time()

        # filter current mode
        tasks = [t for t in self.tasks.itervalues() if mode == IA.All or bits_set(t.type, mode)]
        # filter correct user / or shared
        tasks = [t for t in tasks if user is None or user == t.owner or t.shared]

        return tasks

    def isTaskWaiting(self, user, mode=IA.All):
        tasks = [t for t in self.getTasks(user, mode) if not t.type == IA.Notification or not t.seen]
        return len(tasks) > 0

    def queueTask(self, task):
        cli = self.isClientConnected(task.owner)

        # set waiting times based on threshold
        if cli:
            task.setWaiting(self.CLIENT_THRESHOLD)
        else: # TODO: higher threshold after client connects?
            task.setWaiting(self.CLIENT_THRESHOLD / 3)

        if task.type == IA.Notification:
            task.setWaiting(self.NOTIFICATION_TIMEOUT) # notifications are valid for 30h

        for plugin in self.core.addonManager.activePlugins():
            try:
                plugin.newInteractionTask(task)
            except:
                self.core.print_exc()

        self.tasks[task.iid] = task
        self.core.evm.dispatchEvent("interaction:added", task)