Misc: Add --unloaded option.

This commit is contained in:
Valentin Lorentz 2011-09-01 17:48:09 +00:00
parent 6be6c91657
commit 2f6acdf42f
4 changed files with 69 additions and 16 deletions

View File

@ -46,6 +46,11 @@ conf.registerGlobalValue(Misc, 'listPrivatePlugins',
plugins with the list command if given the --private switch. If this is
disabled, non-owner users should be unable to see what private plugins
are loaded.""")))
conf.registerGlobalValue(Misc, 'listUnloadedPlugins',
registry.Boolean(True, _("""Determines whether the bot will list unloaded
plugins with the list command if given the --unloaded switch. If this is
disabled, non-owner users should be unable to see what unloaded plugins
are available.""")))
conf.registerGlobalValue(Misc, 'timestampFormat',
registry.String('[%H:%M:%S]', _("""Determines the format string for
timestamps in the Misc.last command. Refer to the Python documentation

View File

@ -30,6 +30,7 @@
import re
import os
import imp
import sys
import time
@ -49,6 +50,23 @@ from supybot.utils.iter import ifilter
from supybot.i18n import PluginInternationalization, internationalizeDocstring
_ = PluginInternationalization('Misc')
def get_suffix(file):
for suffix in imp.get_suffixes():
if file[-len(suffix[0]):] == suffix[0]:
return suffix
return None
def getPluginsInDirectory(directory):
# get modules in a given directory
plugins = []
for filename in os.listdir(directory):
pluginPath = os.path.join(directory, filename)
if os.path.isdir(pluginPath):
if all(os.path.isfile(os.path.join(pluginPath, x))
for x in ['__init__.py', 'config.py', 'plugin.py']):
plugins.append(filename)
return plugins
class RegexpTimeout(Exception):
pass
@ -121,34 +139,57 @@ class Misc(callbacks.Plugin):
@internationalizeDocstring
def list(self, irc, msg, args, optlist, cb):
"""[--private] [<plugin>]
"""[--private] [--unloaded] [<plugin>]
Lists the commands available in the given plugin. If no plugin is
given, lists the public plugins available. If --private is given,
lists the private plugins.
lists the private plugins. If --unloaded is given, it will list
available plugins that are not loaded.
"""
private = False
unloaded = False
for (option, argument) in optlist:
if option == 'private':
private = True
if not self.registryValue('listPrivatePlugins') and \
not ircdb.checkCapability(msg.prefix, 'owner'):
irc.errorNoCapability('owner')
elif option == 'unloaded':
unloaded = True
if not self.registryValue('listUnloadedPlugins') and \
not ircdb.checkCapability(msg.prefix, 'owner'):
irc.errorNoCapability('owner')
if unloaded and private:
irc.error(_('--private and --unloaded are uncompatible options.'))
return
if not cb:
def isPublic(cb):
name = cb.name()
return conf.supybot.plugins.get(name).public()
names = [cb.name() for cb in irc.callbacks
if (private and not isPublic(cb)) or
(not private and isPublic(cb))]
names.sort()
if names:
irc.reply(format('%L', names))
if unloaded:
installedPluginsDirectory = os.path.join(
os.path.dirname(__file__), '..')
plugins = getPluginsInDirectory(installedPluginsDirectory)
for directory in conf.supybot.directories.plugins()[:]:
plugins.extend(getPluginsInDirectory(directory))
# Remove loaded plugins:
loadedPlugins = [x.name() for x in irc.callbacks]
plugins = [x for x in plugins if x not in loadedPlugins]
plugins.sort()
irc.reply(format('%L', plugins))
else:
if private:
irc.reply(_('There are no private plugins.'))
def isPublic(cb):
name = cb.name()
return conf.supybot.plugins.get(name).public()
names = [cb.name() for cb in irc.callbacks
if (private and not isPublic(cb)) or
(not private and isPublic(cb))]
names.sort()
if names:
irc.reply(format('%L', names))
else:
irc.reply(_('There are no public plugins.'))
if private:
irc.reply(_('There are no private plugins.'))
else:
irc.reply(_('There are no public plugins.'))
else:
commands = cb.listCommands()
if commands:
@ -162,7 +203,8 @@ class Misc(callbacks.Plugin):
'Try "config list supybot.plugins.%s" to see '
'what configuration variables it has.'),
cb.name()))
list = wrap(list, [getopts({'private':''}), additional('plugin')])
list = wrap(list, [getopts({'private':'', 'unloaded':''}),
additional('plugin')])
@internationalizeDocstring
def apropos(self, irc, msg, args, s):

View File

@ -114,6 +114,12 @@ class MiscTestCase(ChannelPluginTestCase):
self.assertRegexp('list', name)
self.assertNotRegexp('list --private', name)
def testListUnloaded(self):
unloadedPlugin = 'Alias'
loadedPlugin = 'Anonymous'
self.assertRegexp('list --unloaded', 'Alias')
self.assertNotRegexp('list --unloaded', 'Anonymous')
def testListDoesNotIncludeNonCanonicalName(self):
self.assertNotRegexp('list Owner', '_exec')

View File

@ -1,3 +1,3 @@
"""stick the various versioning attributes in here, so we only have to change
them once."""
version = '0.83.4.1+limnoria (2011-08-30T17:21:39+0000)'
version = '0.83.4.1+limnoria (2011-09-01T17:48:08+0000)'