From 863c0e6ad27a620ba8234c3187b4652abe6fcd30 Mon Sep 17 00:00:00 2001 From: Jeremy Fincher Date: Wed, 19 Jan 2005 23:22:35 +0000 Subject: [PATCH] Moved loadPlugin{Module,Class} to its own module in src/ --- plugins/Owner/plugin.py | 94 ++++----------------------------- plugins/Owner/test.py | 11 +--- src/plugin.py | 114 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 94 deletions(-) create mode 100644 src/plugin.py diff --git a/plugins/Owner/plugin.py b/plugins/Owner/plugin.py index 15c6d2a63..14d931fbc 100644 --- a/plugins/Owner/plugin.py +++ b/plugins/Owner/plugin.py @@ -46,6 +46,7 @@ import supybot.world as world import supybot.ircdb as ircdb from supybot.commands import * import supybot.irclib as irclib +import supybot.plugin as plugin import supybot.drivers as drivers import supybot.ircmsgs as ircmsgs import supybot.ircutils as ircutils @@ -54,82 +55,6 @@ import supybot.registry as registry import supybot.callbacks as callbacks import supybot.structures as structures -class Deprecated(ImportError): - pass - -def loadPluginModule(name, ignoreDeprecation=False): - """Loads (and returns) the module for the plugin with the given name.""" - files = [] - pluginDirs = conf.supybot.directories.plugins() - for dir in pluginDirs: - try: - files.extend(os.listdir(dir)) - except EnvironmentError: # OSError, IOError superclass. - log.warning('Invalid plugin directory: %s; removing.', - utils.quoted(dir)) - conf.supybot.directories.plugins().remove(dir) - loweredFiles = map(str.lower, files) - try: - index = loweredFiles.index(name.lower()+'.py') - name = os.path.splitext(files[index])[0] - if name in sys.modules: - m = sys.modules[name] - if not hasattr(m, 'Class'): - raise ImportError, 'Module is not a plugin.' - except ValueError: # We'd rather raise the ImportError, so we'll let go... - pass - moduleInfo = imp.find_module(name, pluginDirs) - try: - module = imp.load_module(name, *moduleInfo) - except: - sys.modules.pop(name, None) - raise - if 'deprecated' in module.__dict__ and module.deprecated: - if ignoreDeprecation: - log.warning('Deprecated plugin loaded: %s', name) - else: - raise Deprecated, 'Attempted to load deprecated plugin %s' % \ - utils.quoted(name) - if module.__name__ in sys.modules: - sys.modules[module.__name__] = module - linecache.checkcache() - return module - -def loadPluginClass(irc, module, register=None): - """Loads the plugin Class from the given module into the given Irc.""" - try: - cb = module.Class() - except AttributeError, e: - if 'Class' in str(e): - raise callbacks.Error, \ - 'This plugin module doesn\'t have a "Class" ' \ - 'attribute to specify which plugin should be ' \ - 'instantiated. If you didn\'t write this ' \ - 'plugin, but received it with Supybot, file ' \ - 'a bug with us about this error.' - else: - raise - plugin = cb.name() - public = True - if hasattr(cb, 'public'): - public = cb.public - conf.registerPlugin(plugin, register, public) - assert not irc.getCallback(plugin) - try: - renames = registerRename(plugin)() - if renames: - for command in renames: - v = registerRename(plugin, command) - newName = v() - assert newName - renameCommand(cb, command, newName) - else: - conf.supybot.commands.renames.unregister(plugin) - except registry.NonExistentRegistryEntry, e: - pass # The plugin isn't there. - irc.addCallback(cb) - return cb - ### # supybot.commands. ### @@ -302,8 +227,9 @@ class Owner(callbacks.Privmsg): # This is debug because each log logs its beginning. self.log.debug('Loading %s.' % name) try: - m = loadPluginModule(name, ignoreDeprecation=True) - loadPluginClass(irc, m) + m = plugin.loadPluginModule(name, + ignoreDeprecation=True) + plugin.loadPluginClass(irc, m) except callbacks.Error, e: # This is just an error message. log.warning(str(e)) @@ -314,7 +240,7 @@ class Owner(callbacks.Privmsg): else: # Let's import the module so configuration is preserved. try: - _ = loadPluginModule(name) + _ = plugin.loadPluginModule(name) except Exception, e: log.debug('Attempted to load %s to preserve its ' 'configuration, but load failed: %s', @@ -492,8 +418,8 @@ class Owner(callbacks.Privmsg): irc.error('%s is already loaded.' % name.capitalize()) return try: - module = loadPluginModule(name, ignoreDeprecation) - except Deprecated: + module = plugin.loadPluginModule(name, ignoreDeprecation) + except plugin.Deprecated: irc.error('%s is deprecated. Use --deprecated ' 'to force it to load.' % name.capitalize()) return @@ -503,7 +429,7 @@ class Owner(callbacks.Privmsg): else: irc.error(str(e)) return - cb = loadPluginClass(irc, module) + cb = plugin.loadPluginClass(irc, module) name = cb.name() # Let's normalize this. conf.registerPlugin(name, True) irc.replySuccess() @@ -521,14 +447,14 @@ class Owner(callbacks.Privmsg): if hasattr(module, 'reload'): x = module.reload() try: - module = loadPluginModule(name) + module = plugin.loadPluginModule(name) if hasattr(module, 'reload'): module.reload(x) for callback in callbacks: callback.die() del callback gc.collect() # This makes sure the callback is collected. - callback = loadPluginClass(irc, module) + callback = plugin.loadPluginClass(irc, module) irc.replySuccess() except ImportError: for callback in callbacks: diff --git a/plugins/Owner/test.py b/plugins/Owner/test.py index 3e6ed2867..d4a05547e 100644 --- a/plugins/Owner/test.py +++ b/plugins/Owner/test.py @@ -30,7 +30,7 @@ from supybot.test import * import supybot.conf as conf -import supybot.plugins.Owner as Owner +import supybot.plugin as plugin class OwnerTestCase(PluginTestCase): plugins = ('Utilities', 'Relay', 'Network', 'Admin', 'Channel') @@ -97,13 +97,4 @@ class OwnerTestCase(PluginTestCase): self.assertError('defaultplugin foobar owner') - -class FunctionsTestCase(SupyTestCase): - def testLoadPluginModule(self): - self.assertRaises(ImportError, Owner.loadPluginModule, 'asldj') - self.failUnless(Owner.loadPluginModule('Owner')) - self.failUnless(Owner.loadPluginModule('owner')) - - # vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: - diff --git a/src/plugin.py b/src/plugin.py new file mode 100644 index 000000000..19ba2268e --- /dev/null +++ b/src/plugin.py @@ -0,0 +1,114 @@ +### +# Copyright (c) 2002-2005, Jeremiah Fincher +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions, and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions, and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the author of this software nor the name of +# contributors to this software may be used to endorse or promote products +# derived from this software without specific prior written consent. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +### + +import os +import sys +import imp +import os.path +import linecache + +import supybot.log as log +import supybot.conf as conf +import supybot.registry as registry + +class Deprecated(ImportError): + pass + +def loadPluginModule(name, ignoreDeprecation=False): + """Loads (and returns) the module for the plugin with the given name.""" + files = [] + pluginDirs = conf.supybot.directories.plugins() + for dir in pluginDirs: + try: + files.extend(os.listdir(dir)) + except EnvironmentError: # OSError, IOError superclass. + log.warning('Invalid plugin directory: %s; removing.', + utils.quoted(dir)) + conf.supybot.directories.plugins().remove(dir) + loweredFiles = map(str.lower, files) + try: + index = loweredFiles.index(name.lower()+'.py') + name = os.path.splitext(files[index])[0] + if name in sys.modules: + m = sys.modules[name] + if not hasattr(m, 'Class'): + raise ImportError, 'Module is not a plugin.' + except ValueError: # We'd rather raise the ImportError, so we'll let go... + pass + moduleInfo = imp.find_module(name, pluginDirs) + try: + module = imp.load_module(name, *moduleInfo) + except: + sys.modules.pop(name, None) + raise + if 'deprecated' in module.__dict__ and module.deprecated: + if ignoreDeprecation: + log.warning('Deprecated plugin loaded: %s', name) + else: + raise Deprecated, 'Attempted to load deprecated plugin %s' % \ + utils.quoted(name) + if module.__name__ in sys.modules: + sys.modules[module.__name__] = module + linecache.checkcache() + return module + +def loadPluginClass(irc, module, register=None): + """Loads the plugin Class from the given module into the given Irc.""" + try: + cb = module.Class() + except AttributeError, e: + if 'Class' in str(e): + raise callbacks.Error, \ + 'This plugin module doesn\'t have a "Class" ' \ + 'attribute to specify which plugin should be ' \ + 'instantiated. If you didn\'t write this ' \ + 'plugin, but received it with Supybot, file ' \ + 'a bug with us about this error.' + else: + raise + plugin = cb.name() + public = True + if hasattr(cb, 'public'): + public = cb.public + conf.registerPlugin(plugin, register, public) + assert not irc.getCallback(plugin) + try: + renames = []#XXX registerRename(plugin)() + if renames: + for command in renames: + v = registerRename(plugin, command) + newName = v() + assert newName + renameCommand(cb, command, newName) + else: + conf.supybot.commands.renames.unregister(plugin) + except registry.NonExistentRegistryEntry, e: + pass # The plugin isn't there. + irc.addCallback(cb) + return cb