From 1c2eb0c737229f0abda312dfe521d9a262bf4743 Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Fri, 10 Dec 2010 03:15:36 +0000 Subject: [PATCH] Improve and port the `create_plugin.py` script to generate the plugins under the "deluge.plugins" namespace. Any plugin not using the "deluge.plugins" namespace will get a `DeprecationWarning` printed on the console. --- deluge/pluginmanagerbase.py | 17 ++++++ deluge/scripts/create_plugin.py | 95 ++++++++++++++++++++------------- 2 files changed, 75 insertions(+), 37 deletions(-) diff --git a/deluge/pluginmanagerbase.py b/deluge/pluginmanagerbase.py index 4256a46c4..f4707af7d 100644 --- a/deluge/pluginmanagerbase.py +++ b/deluge/pluginmanagerbase.py @@ -58,6 +58,16 @@ METADATA_KEYS = [ "Description", ] +DEPRECATION_WARNING = """ +The plugin %s is not using the "deluge.plugins" namespace. +In order to avoid package name clashes between regular python packages and +deluge plugins, the way deluge plugins should be created has changed. +If you're seeing this message and you're not the developer of the plugin which +triggered this warning, please report to it's author. +If you're the developer, please take a look at the plugins hosted on deluge's +git repository to have an idea of what needs to be changed. +""" + class PluginManagerBase: """PluginManagerBase is a base class for PluginManagers to inherit""" @@ -139,6 +149,13 @@ class PluginManagerBase: log.exception(e) continue instance.enable() + if not instance.__module__.startswith("deluge.plugins"): + import warnings + warnings.warn_explicit( + DEPRECATION_WARNING % name, + DeprecationWarning, + instance.__module__, 0 + ) if self._component_state == "Started": component.start([instance.plugin._component_name]) plugin_name = plugin_name.replace("-", " ") diff --git a/deluge/scripts/create_plugin.py b/deluge/scripts/create_plugin.py index d195fbccf..8ce6da1f5 100644 --- a/deluge/scripts/create_plugin.py +++ b/deluge/scripts/create_plugin.py @@ -12,6 +12,7 @@ import os import deluge.common parser = OptionParser() parser.add_option("-n", "--name", dest="name",help="plugin name") +parser.add_option("-m", "--module-name", dest="module",help="plugin name") parser.add_option("-p", "--basepath", dest="path",help="base path") parser.add_option("-a", "--author-name", dest="author_name",help="author name,for the GPL header") parser.add_option("-e", "--author-email", dest="author_email",help="author email,for the GPL header") @@ -46,41 +47,53 @@ def create_plugin(): if not options.configdir: options.configdir = deluge.common.get_default_config_dir() - name = options.name.replace(" ", "_") + options.configdir = os.path.realpath(options.configdir) + + real_name = options.name + name = real_name.replace(" ", "_") safe_name = name.lower() - plugin_base = os.path.realpath(os.path.join(options.path, safe_name)) - src = os.path.join(plugin_base, safe_name) + if options.module: + safe_name = options.module.lower() + plugin_base = os.path.realpath(os.path.join(options.path, name)) + deluge_namespace = os.path.join(plugin_base, "deluge") + plugins_namespace = os.path.join(deluge_namespace, "plugins") + src = os.path.join(plugins_namespace, safe_name) data_dir = os.path.join(src, "data") if os.path.exists(plugin_base): print "the directory %s already exists, delete it first" % plugin_base return - def write_file(path, filename, template): - args = {"author_name":options.author_name, - "author_email":options.author_email , - "name":name, - "safe_name":safe_name, - "filename":filename, - "plugin_base":plugin_base, - "url": options.url, - "configdir": options.configdir + def write_file(path, filename, template, include_gpl=True): + args = { + "author_name": options.author_name, + "author_email": options.author_email, + "name": name, + "safe_name": safe_name, + "filename": filename, + "plugin_base": plugin_base, + "url": options.url, + "configdir": options.configdir } filename = os.path.join(path, filename) f = open(filename,"w") - if filename.endswith(".py"): + if filename.endswith(".py") and include_gpl: f.write(GPL % args) f.write(template % args) f.close() print "creating folders.." os.mkdir(plugin_base) + os.mkdir(deluge_namespace) + os.mkdir(plugins_namespace) os.mkdir(src) os.mkdir(data_dir) print "creating files.." write_file(plugin_base,"setup.py", SETUP) + write_file(deluge_namespace, "__init__.py", NAMESPACE_INIT, False) + write_file(plugins_namespace, "__init__.py", NAMESPACE_INIT, False) write_file(src,"__init__.py", INIT) write_file(src,"gtkui.py", GTKUI) write_file(src,"webui.py", WEBUI) @@ -92,7 +105,7 @@ def create_plugin(): #add an input parameter for this? print "building dev-link.." write_file(plugin_base,"create_dev_link.sh", CREATE_DEV_LINK) - dev_link_path = os.path.realpath(os.path.join(plugin_base, "create_dev_link.sh")) + dev_link_path = os.path.join(plugin_base, "create_dev_link.sh") os.system("chmod +x %s" % dev_link_path) #lazy.. os.system(dev_link_path) @@ -155,7 +168,7 @@ class WebUIPlugin(PluginInitBase): SETUP = """ -from setuptools import setup +from setuptools import setup, find_packages __plugin_name__ = "%(name)s" __author__ = "%(author_name)s" @@ -165,7 +178,7 @@ __url__ = "%(url)s" __license__ = "GPLv3" __description__ = "" __long_description__ = \"\"\"\"\"\" -__pkg_data__ = {__plugin_name__.lower(): ["template/*", "data/*"]} +__pkg_data__ = {"deluge.plugins."+__plugin_name__.lower(): ["template/*", "data/*"]} setup( name=__plugin_name__, @@ -177,16 +190,17 @@ setup( license=__license__, long_description=__long_description__ if __long_description__ else __description__, - packages=[__plugin_name__.lower()], + packages=find_packages(), + namespace_packages = ["deluge", "deluge.plugins"], package_data = __pkg_data__, entry_points=\"\"\" [deluge.plugin.core] - %%s = %%s:CorePlugin + %%s = deluge.plugins.%%s:CorePlugin [deluge.plugin.gtkui] - %%s = %%s:GtkUIPlugin + %%s = deluge.plugins.%%s:GtkUIPlugin [deluge.plugin.web] - %%s = %%s:WebUIPlugin + %%s = deluge.plugins.%%s:WebUIPlugin \"\"\" %% ((__plugin_name__, __plugin_name__.lower())*3) ) """ @@ -194,7 +208,8 @@ setup( COMMON = """ def get_resource(filename): import pkg_resources, os - return pkg_resources.resource_filename("%(safe_name)s", os.path.join("data", filename)) + return pkg_resources.resource_filename("deluge.plugins.%(safe_name)s", + os.path.join("data", filename)) """ GTKUI = """ @@ -318,20 +333,20 @@ Copyright: */ %(name)sPlugin = Ext.extend(Deluge.Plugin, { - constructor: function(config) { - config = Ext.apply({ - name: "%(name)s" - }, config); - %(name)sPlugin.superclass.constructor.call(this, config); - }, + constructor: function(config) { + config = Ext.apply({ + name: "%(name)s" + }, config); + %(name)sPlugin.superclass.constructor.call(this, config); + }, - onDisable: function() { + onDisable: function() { - }, + }, - onEnable: function() { + onEnable: function() { - } + } }); new %(name)sPlugin(); """ @@ -376,13 +391,19 @@ GPL = """# # """ +NAMESPACE_INIT="""# this is a namespace package +import pkg_resources +pkg_resources.declare_namespace(__name__) +""" + CREATE_DEV_LINK = """#!/bin/bash -cd %(plugin_base)s -mkdir temp -export PYTHONPATH=./temp -python setup.py build develop --install-dir ./temp -cp ./temp/%(name)s.egg-link %(configdir)s/plugins -rm -fr ./temp +BASEDIR=$(cd `dirname $0` && pwd) +cd $BASEDIR +test -d $BASEDIR/temp || mkdir $BASEDIR/temp +export PYTHONPATH=$BASEDIR/temp +python setup.py build develop --install-dir $BASEDIR/temp +cp $BASEDIR/temp/*.egg-link %(configdir)s/plugins +rm -fr $BASEDIR/temp """ create_plugin()