diff --git a/TODO b/TODO index e0f3fb893..2a25d946c 100644 --- a/TODO +++ b/TODO @@ -4,8 +4,6 @@ intended functionality. * Add plugin list and the ability to load/unload them from the preferences dialog. -* Have core keep track of which plugins are activated or not, so it only loads - those on start-up. * Have the UI request a list of activated plugins on start-up so it nows which plugins to load. * Figure out easy way for user-made plugins to add i18n support. diff --git a/deluge/core/alertmanager.py b/deluge/core/alertmanager.py index 898648669..d86f8db11 100644 --- a/deluge/core/alertmanager.py +++ b/deluge/core/alertmanager.py @@ -61,7 +61,7 @@ class AlertManager: # Append the handler to the list in the handlers dictionary self.handlers[alert_type].append(handler) - log.debug("Registered handler %s for alert %s", handler, alert_type) + log.debug("Registered handler for alert %s", alert_type) def deregister_handler(self, handler): """De-registers the 'handler' function from all alert types.""" diff --git a/deluge/core/core.py b/deluge/core/core.py index 414fc2444..609fdd778 100644 --- a/deluge/core/core.py +++ b/deluge/core/core.py @@ -71,7 +71,8 @@ DEFAULT_PREFS = { "max_download_speed": -1.0, "max_upload_slots_global": -1, "max_connections_per_torrent": -1, - "max_upload_slots_per_torrent": -1 + "max_upload_slots_per_torrent": -1, + "enabled_plugins": ["Queue"] } class Core(dbus.service.Object): diff --git a/deluge/core/pluginmanager.py b/deluge/core/pluginmanager.py index 3196b8d84..cf0827375 100644 --- a/deluge/core/pluginmanager.py +++ b/deluge/core/pluginmanager.py @@ -33,13 +33,10 @@ """PluginManager for Core""" -import os.path - -import pkg_resources - +import deluge.pluginmanagerbase from deluge.log import LOG as log -class PluginManager: +class PluginManager(deluge.pluginmanagerbase.PluginManagerBase): """PluginManager handles the loading of plugins and provides plugins with functions to access parts of the core.""" @@ -52,34 +49,10 @@ class PluginManager: self.status_fields = {} - # This will load any .eggs in the plugins folder inside the main - # deluge egg.. Need to scan the local plugin folder too. - - plugin_dir = os.path.join(os.path.dirname(__file__), "..", "plugins") - - pkg_resources.working_set.add_entry(plugin_dir) - pkg_env = pkg_resources.Environment([plugin_dir]) - - self.plugins = {} - for name in pkg_env: - egg = pkg_env[name][0] - egg.activate() - for name in egg.get_entry_map("deluge.plugin.core"): - entry_point = egg.get_entry_info("deluge.plugin.core", name) - cls = entry_point.load() - instance = cls(self) - self.plugins[name] = instance - log.info("Load plugin %s", name) - - def shutdown(self): - log.debug("PluginManager shutting down..") - for plugin in self.plugins.values(): - plugin.core.shutdown() - del self.plugins - - def __getitem__(self, key): - return self.plugins[key] - + # Call the PluginManagerBase constructor + deluge.pluginmanagerbase.PluginManagerBase.__init__( + self, "core.conf", "deluge.plugin.core") + def register_status_field(self, field, function): """Register a new status field. This can be used in the same way the client requests other status information from core.""" diff --git a/deluge/pluginmanagerbase.py b/deluge/pluginmanagerbase.py new file mode 100644 index 000000000..f65d7e263 --- /dev/null +++ b/deluge/pluginmanagerbase.py @@ -0,0 +1,104 @@ +# +# pluginmanagerbase.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. + +"""PluginManagerBase""" + +import os.path + +import pkg_resources + +import deluge.common +from deluge.configmanager import ConfigManager +from deluge.log import LOG as log + +class PluginManagerBase: + """PluginManagerBase is a base class for PluginManagers to inherit""" + + def __init__(self, config_file, entry_name): + log.debug("Plugin manager init..") + + self.config = ConfigManager(config_file) + + # This is the entry we want to load.. + self.entry_name = entry_name + + # Loaded plugins + self.plugins = {} + + # Scan the plugin folders for plugins + self.scan_for_plugins() + + # Load plugins that are enabled in the config. + for name in self.config["enabled_plugins"]: + self.load_plugin(name) + + def shutdown(self): + log.debug("PluginManager shutting down..") + for plugin in self.plugins.values(): + plugin.core.shutdown() + del self.plugins + + def __getitem__(self, key): + return self.plugins[key] + + def get_available_plugins(self): + """Returns a list of the available plugins (name, version)""" + return self.available_plugins + + def scan_for_plugins(self): + """Scans for available plugins""" + plugin_dir = os.path.join(os.path.dirname(__file__), "plugins") + user_plugin_dir = os.path.join(deluge.common.get_config_dir("plugins")) + + pkg_resources.working_set.add_entry(plugin_dir) + pkg_resources.working_set.add_entry(user_plugin_dir) + self.pkg_env = pkg_resources.Environment([plugin_dir, user_plugin_dir]) + + self.available_plugins = [] + for name in self.pkg_env: + pkg_name = str(self.pkg_env[name][0]).split()[0] + pkg_version = str(self.pkg_env[name][0]).split()[1] + + log.debug("Found plugin: %s %s", pkg_name, pkg_version) + self.available_plugins.append(pkg_name) + + def load_plugin(self, name, version=None): + """Loads a plugin with optional version""" + egg = self.pkg_env[name][0] + egg.activate() + for name in egg.get_entry_map(self.entry_name): + entry_point = egg.get_entry_info(self.entry_name, name) + cls = entry_point.load() + instance = cls(self) + self.plugins[name] = instance + log.info("Load plugin %s", name) diff --git a/deluge/ui/gtkui/gtkui.py b/deluge/ui/gtkui/gtkui.py index 8669c4f5a..5d4ab0e06 100644 --- a/deluge/ui/gtkui/gtkui.py +++ b/deluge/ui/gtkui/gtkui.py @@ -66,7 +66,8 @@ DEFAULT_PREFS = { "window_height": 480, "window_pane_position": -1, "tray_download_speed_list" : [5.0, 10.0, 30.0, 80.0, 300.0], - "tray_upload_speed_list" : [5.0, 10.0, 30.0, 80.0, 300.0] + "tray_upload_speed_list" : [5.0, 10.0, 30.0, 80.0, 300.0], + "enabled_plugins": ["Queue"] } class GtkUI: diff --git a/deluge/ui/gtkui/pluginmanager.py b/deluge/ui/gtkui/pluginmanager.py index 64424c920..07cbe1ca2 100644 --- a/deluge/ui/gtkui/pluginmanager.py +++ b/deluge/ui/gtkui/pluginmanager.py @@ -31,39 +31,16 @@ # this exception statement from your version. If you delete this exception # statement from all source files in the program, then also delete it here. -import os.path - -import pkg_resources - +import deluge.pluginmanagerbase from deluge.log import LOG as log -class PluginManager: +class PluginManager(deluge.pluginmanagerbase.PluginManagerBase): def __init__(self, gtkui): self._gtkui = gtkui - # This will load any .eggs in the plugins folder inside the main - # deluge egg.. Need to scan the local plugin folder too. - - plugin_dir = os.path.join(os.path.dirname(__file__), "../..", "plugins") - - pkg_resources.working_set.add_entry(plugin_dir) - pkg_env = pkg_resources.Environment([plugin_dir]) - - self.plugins = {} - for name in pkg_env: - egg = pkg_env[name][0] - egg.activate() - modules = [] - for name in egg.get_entry_map("deluge.plugin.ui.gtk"): - entry_point = egg.get_entry_info("deluge.plugin.ui.gtk", name) - cls = entry_point.load() - instance = cls(self) - self.plugins[name] = instance - log.info("Loaded plugin %s", name) - - def __getitem__(self, key): - return self.plugins[key] + deluge.pluginmanagerbase.PluginManagerBase.__init__( + self, "gtkui.conf", "deluge.plugin.ui.gtk") def get_torrentview(self): """Returns a reference to the torrentview component"""