From 8cf72ca2dc97900546d4de96d4d30527fba811a7 Mon Sep 17 00:00:00 2001 From: Martijn Voncken Date: Tue, 4 Mar 2008 19:51:31 +0000 Subject: [PATCH] organize core-plugin --- deluge/plugins/organize/organize/__init__.py | 56 ++++++++ deluge/plugins/organize/organize/core.py | 135 +++++++++++++++++++ deluge/plugins/organize/organize/test.py | 41 ++++++ deluge/plugins/organize/setup.py | 55 ++++++++ 4 files changed, 287 insertions(+) create mode 100644 deluge/plugins/organize/organize/__init__.py create mode 100644 deluge/plugins/organize/organize/core.py create mode 100644 deluge/plugins/organize/organize/test.py create mode 100644 deluge/plugins/organize/setup.py diff --git a/deluge/plugins/organize/organize/__init__.py b/deluge/plugins/organize/organize/__init__.py new file mode 100644 index 000000000..140cfc73f --- /dev/null +++ b/deluge/plugins/organize/organize/__init__.py @@ -0,0 +1,56 @@ +# +# __init__.py +# +# Copyright (C) 2007 Andrew Resch ('andar') +# +# Deluge is free software. +# +# You may redistribute it and/or modify it under the terms of the +# GNU General Public License, as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# deluge is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with deluge. If not, write to: +# The Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor +# Boston, MA 02110-1301, USA. +# +# In addition, as a special exception, the copyright holders give +# permission to link the code of portions of this program with the OpenSSL +# library. +# You must obey the GNU General Public License in all respects for all of +# the code used other than OpenSSL. If you modify file(s) with this +# exception, you may extend this exception to your version of the file(s), +# but you are not obligated to do so. If you do not wish to do so, delete +# this exception statement from your version. If you delete this exception +# statement from all source files in the program, then also delete it here. + +from deluge.log import LOG as log + +from deluge.plugins.init import PluginBase + +class CorePlugin(PluginBase): + def __init__(self, plugin_api, plugin_name): + # Load the Core portion of the plugin + try: + from core import Core + self.plugin = Core(plugin_api, plugin_name) + except Exception, e: + log.debug("Did not load a Core plugin: %s", e) +""" +class GtkUIPlugin(PluginBase): + def __init__(self, plugin_api, plugin_name): + # Load the GtkUI portion of the plugin + try: + from gtkui import GtkUI + self.plugin = GtkUI(plugin_api, plugin_name) + except Exception, e: + log.debug("Did not load a GtkUI plugin: %s", e) +""" + diff --git a/deluge/plugins/organize/organize/core.py b/deluge/plugins/organize/organize/core.py new file mode 100644 index 000000000..0b7078c86 --- /dev/null +++ b/deluge/plugins/organize/organize/core.py @@ -0,0 +1,135 @@ +""" +torrent-organize core plugin. + +adds a status field for tracker. +""" + +from deluge.log import LOG as log +from deluge.plugins.corepluginbase import CorePluginBase + +from urlparse import urlparse + +STATE_FILTERS = { + 'Allocating': lambda t: (t.state == 'Allocating'), + 'Checking': lambda t: (t.state == 'Checking'), + 'Downloading': lambda t: (t.state == 'Downloadig'), + 'Seeding':lambda t: (t.state == 'Seeding'), + 'Paused':lambda t: (t.state == 'Paused'), + 'Error':lambda t: (t.state == 'Error'), + 'Queued':lambda t: (t.state == 'Queued') + #'Traffic':lambda t: (t.download_payload_rate > 0 or t.upload_payload_rate > 0) +} + +class Core(CorePluginBase): + def enable(self): + log.info("*** START Organize plugin***") + + self.plugin.register_status_field("tracker_name", self._status_get_tracker) + log.debug("Organize plugin enabled..") + + #__init__.... + core = self.plugin.get_core() + self.torrents = core.torrents.torrents + + def disable(self): + # De-register the label field + + self.plugin.deregister_status_field("tracker_name") + + def update(self): + pass + + + ## Utils ## + def get_tracker(self, torrent): + "returns 1st tracker." + log.debug(torrent) + log.debug(torrent.trackers) + if not torrent.trackers: + return 'tracker-less' + url = urlparse(torrent.trackers[0]['url']) + if hasattr(url,'hostname'): + return (url.hostname or 'unknown?') + return 'No-tracker?' + + ## Filters ## + def filter_state(self, torrents, state): + "in/out: a list of torrent objects." + filter_func = STATE_FILTERS[state] + return [t for t in torrents if filter_func(t)] + + def filter_tracker(self, torrents, tracker): + "in/out: a list of torrent objects." + return [t for t in torrents if self.get_tracker(t) == tracker] + + def filter_keyword(self, torrents, keyword): + "in/out: a list of torrent objects." + return [t for t in torrents if keyword in t.filename.lower()] + + ## Public ## + def export_state_filter_items(self): + """ + returns a sorted list of tuples: + [(state, count), ...] + """ + #maybe I should explain this.. .. + #or just fix it to be less generic, and more readable. + return [("All", len(self.torrents))] + [ + (state, len(self.filter_state(self.torrents.values(), state))) + for state in STATE_FILTERS] + + def export_tracker_filter_items(self): + """ + returns a sorted list of tuples: + [(tracker_name, count), ...] + """ + trackers = [self.get_tracker(t) for t in self.torrents.values()] + tcounter = {} + for tracker in trackers: + tcounter[tracker] = tcounter.get(tracker,0) + 1 + #tcounter= {'tracker-name':count, ...} + return sorted([x for x in tcounter.iteritems()]) + + def export_all_filter_items(self): + """ + for sclient, returns:{ + 'tracker':, + 'state':} + """ + return { + 'tracker':self.export_tracker_filter_items(), + 'state':self.export_state_filter_items() + } + + def export_get_session_state(self,filter_dict): + """ + in: a dict of filters: + { + 'keyword':'a keyword', + 'state':'Seeding', + 'tracker':'tracker.aelitis.com' + } + returns a list of torrent_id's + """ + torrents = self.torrents.values() + + if 'keyword' in filter_dict: + filter_dict['keyword'] = filter_dict['keyword'].lower() + torrents = self.filter_keyword(torrents, filter_dict['keyword']) + + if 'state' in filter_dict and filter_dict['state'] <> "All": + torrents = self.filter_state(torrents, filter_dict['state']) + + if 'tracker' in filter_dict: + torrents = self.filter_tracker(torrents, filter_dict['tracker']) + + return [t.torrent_id for t in torrents] + + + ## Status fields ## + def _status_get_tracker(self, torrent_id): + return self.get_tracker(self.torrents[torrent_id]) + +if __name__ == "__main__": + import test + diff --git a/deluge/plugins/organize/organize/test.py b/deluge/plugins/organize/organize/test.py new file mode 100644 index 000000000..fbc575e45 --- /dev/null +++ b/deluge/plugins/organize/organize/test.py @@ -0,0 +1,41 @@ +from deluge.ui.client import sclient + +sclient.set_core_uri() + +ids = sclient.get_session_state() + +for t in sclient.get_torrents_status(ids, ['name','tracker_name','tracker']).itervalues(): + print t + +for tracker,count in sclient.organize_tracker_filter_items(): + print tracker, count + +for state,count in sclient.organize_state_filter_items(): + print state, count + +print sclient.organize_all_filter_items() + + +print 'tracker.aelitis.com:' +print sclient.organize_get_session_state({'tracker':'tracker.aelitis.com'} ) + +print 'no results' +print sclient.organize_get_session_state({'tracker':'no results'} ) + + +print 'seeding' +print sclient.organize_get_session_state({'state':'Seeding'} ) + +print 'paused' +print sclient.organize_get_session_state({'state':'Paused'} ) + +print 'seeding+tracker.aelitis.com' +print sclient.organize_get_session_state({ + 'tracker':'tracker.aelitis.com', + 'state':'Seeding'}) + +print 'on keyword:' +print sclient.organize_get_session_state({'keyword':'client'}) + +print 'on keyword:no results' +print sclient.organize_get_session_state({'keyword':'lasjhdinewhjdeg'}) diff --git a/deluge/plugins/organize/setup.py b/deluge/plugins/organize/setup.py new file mode 100644 index 000000000..486b83947 --- /dev/null +++ b/deluge/plugins/organize/setup.py @@ -0,0 +1,55 @@ +# setup.py +# +# Copyright (C) 2008 Martijn Voncken +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, write to: +# The Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor +# Boston, MA 02110-1301, USA. +# +# In addition, as a special exception, the copyright holders give +# permission to link the code of portions of this program with the OpenSSL +# library. +# You must obey the GNU General Public License in all respects for all of +# the code used other than OpenSSL. If you modify file(s) with this +# exception, you may extend this exception to your version of the file(s), +# but you are not obligated to do so. If you do not wish to do so, delete +# this exception statement from your version. If you delete this exception +# statement from all source files in the program, then also delete it here. + +""" +Organize plugin. + +Offers filters on state,tracker and keyword. +Core only for now, moving builtin webui stuff to a plugin. + +Future: Labels/Tags +""" + +from setuptools import setup + +__author__ = "Martijn Voncken" + +setup( + name="Organize", + version="0.1", + description=__doc__, + author=__author__, + packages=["organize"], + #package_data = {"testp": ["glade/*.glade"]}, + entry_points=""" + [deluge.plugin.core] + Organize = organize:CorePlugin + """ +)