mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-27 21:29:24 +01:00
New plugin prioritization method.
This commit is contained in:
parent
6243fe6baf
commit
c573ab5996
@ -65,12 +65,16 @@ conf.registerGlobalValue(conf.supybot.plugins.Misc, 'listPrivatePlugins',
|
||||
are loaded."""))
|
||||
|
||||
class Misc(callbacks.Privmsg):
|
||||
priority = sys.maxint
|
||||
def __init__(self):
|
||||
super(Misc, self).__init__()
|
||||
timeout = conf.supybot.abuse.flood.command.invalid
|
||||
self.invalidCommands = ircutils.FloodQueue(timeout)
|
||||
|
||||
callAfter = utils.Everything()
|
||||
callBefore = utils.Nothing()
|
||||
def __cmp__(self, other):
|
||||
return 1 # We should always be the last plugin.
|
||||
|
||||
def invalidCommand(self, irc, msg, tokens):
|
||||
self.log.debug('Misc.invalidCommand called (tokens %s)', tokens)
|
||||
# First, we check for invalidCommand floods. This is rightfully done
|
||||
|
20
src/Owner.py
20
src/Owner.py
@ -183,7 +183,6 @@ class LogProxy(object):
|
||||
class Owner(privmsgs.CapabilityCheckingPrivmsg):
|
||||
# This plugin must be first; its priority must be lowest; otherwise odd
|
||||
# things will happen when adding callbacks.
|
||||
priority = ~sys.maxint-1 # This must be first!
|
||||
capability = 'owner'
|
||||
_srcPlugins = ircutils.IrcSet(('Admin', 'Channel', 'Config',
|
||||
'Misc', 'Owner', 'User'))
|
||||
@ -227,6 +226,11 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
|
||||
continue
|
||||
registerDefaultPlugin(name, s)
|
||||
|
||||
callAfter = utils.Nothing()
|
||||
callBefore = utils.Everything()
|
||||
def __cmp__(self, other):
|
||||
return -1 # We should always be the first plugin.
|
||||
|
||||
def _getIrc(self, network):
|
||||
network = network.lower()
|
||||
for irc in world.ircs:
|
||||
@ -376,10 +380,12 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
|
||||
def doPrivmsg(self, irc, msg):
|
||||
callbacks.Privmsg.handled = False
|
||||
callbacks.Privmsg.errored = False
|
||||
if ircdb.checkIgnored(msg.prefix):
|
||||
return
|
||||
ignored = ircdb.checkIgnored(msg.prefix)
|
||||
s = callbacks.addressed(irc.nick, msg)
|
||||
if s:
|
||||
if ignored:
|
||||
self.log.info('Ignoring command from %s.' % msg.prefix)
|
||||
return
|
||||
brackets = conf.supybot.reply.brackets.get(msg.args[0])()
|
||||
try:
|
||||
tokens = callbacks.tokenize(s, brackets=brackets)
|
||||
@ -595,17 +601,17 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
|
||||
if name.endswith('.py'):
|
||||
name = name[:-3]
|
||||
if irc.getCallback(name):
|
||||
irc.error('That plugin is already loaded.')
|
||||
irc.error('%s is already loaded.' % name.capitalize())
|
||||
return
|
||||
try:
|
||||
module = loadPluginModule(name, ignoreDeprecation)
|
||||
except Deprecated:
|
||||
irc.error('That plugin is deprecated. '
|
||||
'Use --deprecated to force it to load.')
|
||||
irc.error('%s is deprecated. Use --deprecated '
|
||||
'to force it to load.' % name.capitalize())
|
||||
return
|
||||
except ImportError, e:
|
||||
if name in str(e):
|
||||
irc.error('No plugin %s exists.' % name)
|
||||
irc.error('No plugin named %s exists.' % utils.dqrepr(name))
|
||||
else:
|
||||
irc.error(str(e))
|
||||
return
|
||||
|
@ -570,6 +570,7 @@ class IrcObjectProxy(RichReplyMethods):
|
||||
def finalEval(self):
|
||||
assert not self.finalEvaled, 'finalEval called twice.'
|
||||
self.finalEvaled = True
|
||||
# We can't canonicalName here because it might be a regexp method.
|
||||
name = self.args[0]
|
||||
cbs = findCallbackForCommand(self, name)
|
||||
if len(cbs) == 0:
|
||||
@ -595,6 +596,9 @@ class IrcObjectProxy(RichReplyMethods):
|
||||
# Ok, no regexp-based things matched.
|
||||
self._callInvalidCommands()
|
||||
else:
|
||||
# But we must canonicalName here, since we're comparing to a
|
||||
# canonicalName.
|
||||
name = canonicalName(name)
|
||||
if len(cbs) > 1:
|
||||
for cb in cbs:
|
||||
if canonicalName(cb.name()) == name:
|
||||
@ -862,6 +866,8 @@ class Privmsg(irclib.IrcCallback):
|
||||
alwaysCall = ()
|
||||
threaded = False
|
||||
noIgnore = False
|
||||
callAfter = ()
|
||||
callBefore = ()
|
||||
Proxy = IrcObjectProxy
|
||||
commandArgs = ['self', 'irc', 'msg', 'args']
|
||||
# This must be class-scope, so all plugins use the same one.
|
||||
@ -871,6 +877,10 @@ class Privmsg(irclib.IrcCallback):
|
||||
self.__parent = super(Privmsg, self)
|
||||
myName = self.name()
|
||||
self.log = log.getPluginLogger(myName)
|
||||
# We can't do this because of the specialness that Owner and Misc do.
|
||||
# I guess plugin authors will have to get the capitalization right.
|
||||
# self.callAfter = map(str.lower, self.callAfter)
|
||||
# self.callBefore = map(str.lower, self.callBefore)
|
||||
### Setup the dispatcher command.
|
||||
canonicalname = canonicalName(myName)
|
||||
self._original = getattr(self, canonicalname, None)
|
||||
@ -919,6 +929,37 @@ class Privmsg(irclib.IrcCallback):
|
||||
dispatcher.isDispatcher = True
|
||||
setattr(self.__class__, canonicalname, dispatcher)
|
||||
|
||||
# In addition to priority, plugins may specify callBefore and callAfter
|
||||
# attributes which are lists of plugin names which the plugin should be
|
||||
# called before and after, respectively. We may, at some future point,
|
||||
# remove priority entirely.
|
||||
def __cmp__(self, other, doAssert=True):
|
||||
selfName = self.name()
|
||||
otherName = other.name()
|
||||
# We can't be certain of the order the callbacks list is in, so we
|
||||
# can't be certain that our __cmp__ is the most specific one, so
|
||||
# we basically run the other callback's as well.
|
||||
if isinstance(other, Privmsg):
|
||||
if otherName in self.callAfter or selfName in other.callBefore:
|
||||
ret = 1
|
||||
elif otherName in self.callBefore or selfName in other.callAfter:
|
||||
ret = -1
|
||||
else:
|
||||
ret = self.__parent.__cmp__(other)
|
||||
else:
|
||||
ret = self.__parent.__cmp__(other)
|
||||
if doAssert:
|
||||
try:
|
||||
otherRet = other.__cmp__(self, doAssert=False)
|
||||
except TypeError, e:
|
||||
if 'doAssert' in str(e): # unexpected keyword argument.
|
||||
otherRet = cmp(other, self)
|
||||
else:
|
||||
otherRet = ret
|
||||
assert ret+otherRet==0, 'callbacks\' __cmp__ disagree: %s, %s' % \
|
||||
(selfName, otherName)
|
||||
return ret
|
||||
|
||||
def __call__(self, irc, msg):
|
||||
if msg.command == 'PRIVMSG':
|
||||
if self.noIgnore or not ircdb.checkIgnored(msg.prefix,msg.args[0]):
|
||||
|
@ -76,14 +76,23 @@ class IrcCallback(IrcCommandDispatcher):
|
||||
# numbers mean *higher* priority (like nice values in *nix). Higher
|
||||
# priority means the callback is called *earlier* on the inFilter chain,
|
||||
# *earlier* on the __call__ chain, and *later* on the outFilter chain.
|
||||
|
||||
priority = 99
|
||||
__metaclass__ = log.MetaFirewall
|
||||
__firewalled__ = {'die': None,
|
||||
'reset': None,
|
||||
'__call__': None,
|
||||
'__cmp__': lambda self: 0,
|
||||
'inFilter': lambda self, irc, msg: msg,
|
||||
'outFilter': lambda self, irc, msg: msg,
|
||||
'name': lambda self: self.__class__.__name__,}
|
||||
|
||||
def __cmp__(self, other):
|
||||
ret = cmp(self.priority, other.priority)
|
||||
if not ret:
|
||||
ret = cmp(self.name(), other.name())
|
||||
return ret
|
||||
|
||||
def name(self):
|
||||
"""Returns the name of the callback."""
|
||||
return self.__class__.__name__
|
||||
@ -586,7 +595,9 @@ class Irc(IrcCommandDispatcher):
|
||||
def addCallback(self, callback):
|
||||
"""Adds a callback to the callbacks list."""
|
||||
self.callbacks.append(callback)
|
||||
utils.sortBy(operator.attrgetter('priority'), self.callbacks)
|
||||
self.callbacks.sort()
|
||||
# We used to do this, then we implemented sorting in IrcCallback.
|
||||
# utils.sortBy(operator.attrgetter('priority'), self.callbacks)
|
||||
|
||||
def getCallback(self, name):
|
||||
"""Gets a given callback by name."""
|
||||
|
Loading…
Reference in New Issue
Block a user