mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-12-24 11:42:52 +01:00
Finally got topological sorting working.
This commit is contained in:
parent
727145afbe
commit
9be4fd112d
11
src/Misc.py
11
src/Misc.py
@ -79,13 +79,12 @@ class Misc(callbacks.Privmsg):
|
|||||||
super(Misc, self).__init__()
|
super(Misc, self).__init__()
|
||||||
self.invalidCommands = ircutils.FloodQueue(60)
|
self.invalidCommands = ircutils.FloodQueue(60)
|
||||||
|
|
||||||
priority = sys.maxint + 1 # This is for working with IrcCallbacks.
|
def callPrecedence(self, irc):
|
||||||
callAfter = utils.Everything()
|
return ([cb for cb in irc.callbacks if cb is not self], [])
|
||||||
callBefore = utils.Nothing()
|
|
||||||
def __lt__(self, other):
|
|
||||||
return False # We should always be the last plugin.
|
|
||||||
|
|
||||||
def invalidCommand(self, irc, msg, tokens):
|
def invalidCommand(self, irc, msg, tokens):
|
||||||
|
assert not msg.repliedTo, 'repliedTo msg in Misc.invalidCommand.'
|
||||||
|
assert self is irc.callbacks[-1], 'Misc isn\'t last callback.'
|
||||||
self.log.debug('Misc.invalidCommand called (tokens %s)', tokens)
|
self.log.debug('Misc.invalidCommand called (tokens %s)', tokens)
|
||||||
# First, we check for invalidCommand floods. This is rightfully done
|
# First, we check for invalidCommand floods. This is rightfully done
|
||||||
# here since this will be the last invalidCommand called, and thus it
|
# here since this will be the last invalidCommand called, and thus it
|
||||||
|
20
src/Owner.py
20
src/Owner.py
@ -202,7 +202,6 @@ class LogProxy(object):
|
|||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
return getattr(self.log, attr)
|
return getattr(self.log, attr)
|
||||||
|
|
||||||
|
|
||||||
class Owner(privmsgs.CapabilityCheckingPrivmsg):
|
class Owner(privmsgs.CapabilityCheckingPrivmsg):
|
||||||
# This plugin must be first; its priority must be lowest; otherwise odd
|
# This plugin must be first; its priority must be lowest; otherwise odd
|
||||||
# things will happen when adding callbacks.
|
# things will happen when adding callbacks.
|
||||||
@ -249,12 +248,9 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
|
|||||||
continue
|
continue
|
||||||
registerDefaultPlugin(name, s)
|
registerDefaultPlugin(name, s)
|
||||||
|
|
||||||
priority = ~sys.maxint - 1 # For working with IrcCallbacks.
|
def callPrecedence(self, irc):
|
||||||
callAfter = utils.Nothing()
|
return ([], [cb for cb in irc.callbacks if cb is not self])
|
||||||
callBefore = utils.Everything()
|
|
||||||
def __lt__(self, other):
|
|
||||||
return True # We should always be the first plugin.
|
|
||||||
|
|
||||||
def outFilter(self, irc, msg):
|
def outFilter(self, irc, msg):
|
||||||
if msg.command == 'PRIVMSG' and not world.testing:
|
if msg.command == 'PRIVMSG' and not world.testing:
|
||||||
if ircutils.strEqual(msg.args[0], irc.nick):
|
if ircutils.strEqual(msg.args[0], irc.nick):
|
||||||
@ -415,12 +411,14 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
|
|||||||
do422 = do377 = do376
|
do422 = do377 = do376
|
||||||
|
|
||||||
def doPrivmsg(self, irc, msg):
|
def doPrivmsg(self, irc, msg):
|
||||||
callbacks.Privmsg.handled = False
|
assert self is irc.callbacks[0], 'Owner isn\'t first callback.'
|
||||||
callbacks.Privmsg.errored = False
|
msg.errored = False
|
||||||
msg.repliedTo = False
|
msg.repliedTo = False
|
||||||
ignored = ircdb.checkIgnored(msg.prefix)
|
if ircmsgs.isCtcp(msg):
|
||||||
|
return
|
||||||
s = callbacks.addressed(irc.nick, msg)
|
s = callbacks.addressed(irc.nick, msg)
|
||||||
if s:
|
if s:
|
||||||
|
ignored = ircdb.checkIgnored(msg.prefix)
|
||||||
if ignored:
|
if ignored:
|
||||||
self.log.info('Ignoring command from %s.' % msg.prefix)
|
self.log.info('Ignoring command from %s.' % msg.prefix)
|
||||||
return
|
return
|
||||||
@ -434,9 +432,7 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
|
|||||||
return
|
return
|
||||||
self.processTokens(irc, msg, tokens)
|
self.processTokens(irc, msg, tokens)
|
||||||
except SyntaxError, e:
|
except SyntaxError, e:
|
||||||
callbacks.Privmsg.errored = True
|
|
||||||
irc.queueMsg(callbacks.error(msg, str(e)))
|
irc.queueMsg(callbacks.error(msg, str(e)))
|
||||||
return
|
|
||||||
|
|
||||||
if conf.allowEval:
|
if conf.allowEval:
|
||||||
_evalEnv = {'_': None,
|
_evalEnv = {'_': None,
|
||||||
|
131
src/callbacks.py
131
src/callbacks.py
@ -194,6 +194,7 @@ def reply(msg, s, prefixName=None, private=None,
|
|||||||
def error(msg, s, **kwargs):
|
def error(msg, s, **kwargs):
|
||||||
"""Makes an error reply to msg with the appropriate error payload."""
|
"""Makes an error reply to msg with the appropriate error payload."""
|
||||||
kwargs['error'] = True
|
kwargs['error'] = True
|
||||||
|
msg.errored = True
|
||||||
return reply(msg, s, **kwargs)
|
return reply(msg, s, **kwargs)
|
||||||
|
|
||||||
def getHelp(method, name=None):
|
def getHelp(method, name=None):
|
||||||
@ -504,7 +505,6 @@ class IrcObjectProxy(RichReplyMethods):
|
|||||||
# tokenized commands.
|
# tokenized commands.
|
||||||
self.args = copy.deepcopy(args)
|
self.args = copy.deepcopy(args)
|
||||||
self.counter = 0
|
self.counter = 0
|
||||||
self.finished = False # Used in _callInvalidCommands.
|
|
||||||
self.commandMethod = None # Used in error.
|
self.commandMethod = None # Used in error.
|
||||||
self._resetReplyAttributes()
|
self._resetReplyAttributes()
|
||||||
if not args:
|
if not args:
|
||||||
@ -538,17 +538,34 @@ class IrcObjectProxy(RichReplyMethods):
|
|||||||
return
|
return
|
||||||
self.finalEval()
|
self.finalEval()
|
||||||
|
|
||||||
|
|
||||||
|
def _callTokenizedCommands(self):
|
||||||
|
log.debug('Calling tokenizedCommands.')
|
||||||
|
for cb in self.irc.callbacks:
|
||||||
|
if hasattr(cb, 'tokenizedCommand'):
|
||||||
|
log.debug('Trying to call %s.tokenizedCommand.' % cb.name())
|
||||||
|
self._callTokenizedCommand(cb)
|
||||||
|
if self.msg.repliedTo:
|
||||||
|
log.debug('Done calling tokenizedCommands: %s.' % cb.name())
|
||||||
|
return
|
||||||
|
|
||||||
|
def _callTokenizedCommand(self, cb):
|
||||||
|
try:
|
||||||
|
cb.tokenizedCommand(self, self.msg, self.args)
|
||||||
|
except Error, e:
|
||||||
|
self.error(str(e))
|
||||||
|
except Exception, e:
|
||||||
|
log.exception('Uncaught exception in %s.tokenizedCommand.' %
|
||||||
|
cb.name())
|
||||||
|
|
||||||
def _callInvalidCommands(self):
|
def _callInvalidCommands(self):
|
||||||
if ircmsgs.isCtcp(self.msg):
|
|
||||||
log.debug('Skipping invalidCommand, msg is CTCP.')
|
|
||||||
return
|
|
||||||
log.debug('Calling invalidCommands.')
|
log.debug('Calling invalidCommands.')
|
||||||
for cb in self.irc.callbacks:
|
for cb in self.irc.callbacks:
|
||||||
log.debug('Trying to call %s.invalidCommand.' % cb.name())
|
|
||||||
if hasattr(cb, 'invalidCommand'):
|
if hasattr(cb, 'invalidCommand'):
|
||||||
|
log.debug('Trying to call %s.invalidCommand.' % cb.name())
|
||||||
self._callInvalidCommand(cb)
|
self._callInvalidCommand(cb)
|
||||||
if self.finished:
|
if self.msg.repliedTo:
|
||||||
log.debug('Finished calling invalidCommand: %s.',cb.name())
|
log.debug('Done calling invalidCommands: %s.',cb.name())
|
||||||
return
|
return
|
||||||
|
|
||||||
def _callInvalidCommand(self, cb):
|
def _callInvalidCommand(self, cb):
|
||||||
@ -557,7 +574,8 @@ class IrcObjectProxy(RichReplyMethods):
|
|||||||
except Error, e:
|
except Error, e:
|
||||||
self.error(str(e))
|
self.error(str(e))
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
log.exception('Uncaught exception in %s.invalidCommand'% cb.name())
|
log.exception('Uncaught exception in %s.invalidCommand.'%
|
||||||
|
cb.name())
|
||||||
|
|
||||||
def _callCommand(self, name, cb):
|
def _callCommand(self, name, cb):
|
||||||
try:
|
try:
|
||||||
@ -581,31 +599,37 @@ class IrcObjectProxy(RichReplyMethods):
|
|||||||
name = self.args[0]
|
name = self.args[0]
|
||||||
cbs = findCallbackForCommand(self, name)
|
cbs = findCallbackForCommand(self, name)
|
||||||
if len(cbs) == 0:
|
if len(cbs) == 0:
|
||||||
|
# Normal command not found, let's go for the specialties now.
|
||||||
|
# First, check for addressedRegexps -- they take precedence over
|
||||||
|
# tokenizedCommands.
|
||||||
for cb in self.irc.callbacks:
|
for cb in self.irc.callbacks:
|
||||||
# We used not to run invalidCommands if regexps matched, but now I'd say that
|
|
||||||
# invalidCommands are more essential than regexps, so it is regexps that should
|
|
||||||
# have to work around invalidCommands, not vice-versa.
|
|
||||||
## if isinstance(cb, PrivmsgRegexp):
|
|
||||||
## for (r, name) in cb.res:
|
|
||||||
## if r.search(self.msg.args[1]):
|
|
||||||
## log.debug('Skipping invalidCommand: %s.%s',
|
|
||||||
## cb.name(), name)
|
|
||||||
## return
|
|
||||||
if isinstance(cb, PrivmsgCommandAndRegexp):
|
if isinstance(cb, PrivmsgCommandAndRegexp):
|
||||||
## for (r, name) in cb.res:
|
|
||||||
## if r.search(self.msg.args[1]):
|
|
||||||
## log.debug('Skipping invalidCommand: %s.%s',
|
|
||||||
## cb.name(), name)
|
|
||||||
## return
|
|
||||||
# Although we still consider addressedRegexps to be commands, so we don't call
|
|
||||||
# invalidCommnads if an addressedRegexp matches.
|
|
||||||
payload = addressed(self.irc.nick, self.msg)
|
payload = addressed(self.irc.nick, self.msg)
|
||||||
for (r, name) in cb.addressedRes:
|
for (r, name) in cb.addressedRes:
|
||||||
if r.search(payload):
|
if r.search(payload):
|
||||||
log.debug('Skipping invalidCommand: %s.%s',
|
log.debug('Skipping invalidCommand: %s.%s',
|
||||||
cb.name(), name)
|
cb.name(), name)
|
||||||
return
|
return
|
||||||
# Ok, no regexp-based things matched.
|
# Now we call tokenizedCommands.
|
||||||
|
self._callTokenizedCommands()
|
||||||
|
# Return if we've replied.
|
||||||
|
if self.msg.repliedTo:
|
||||||
|
return
|
||||||
|
# Now we check for regexp commands, which override invalidCommand.
|
||||||
|
for cb in self.irc.callbacks:
|
||||||
|
if isinstance(cb, PrivmsgRegexp):
|
||||||
|
for (r, name) in cb.res:
|
||||||
|
if r.search(self.msg.args[1]):
|
||||||
|
log.debug('Skipping invalidCommand: %s.%s',
|
||||||
|
cb.name(), name)
|
||||||
|
return
|
||||||
|
elif isinstance(cb, PrivmsgCommandAndRegexp):
|
||||||
|
for (r, name) in cb.res:
|
||||||
|
if r.search(self.msg.args[1]):
|
||||||
|
log.debug('Skipping invalidCommand: %s.%s',
|
||||||
|
cb.name(), name)
|
||||||
|
return
|
||||||
|
# No matching regexp commands, now we do invalidCommands.
|
||||||
self._callInvalidCommands()
|
self._callInvalidCommands()
|
||||||
else:
|
else:
|
||||||
# But we must canonicalName here, since we're comparing to a
|
# But we must canonicalName here, since we're comparing to a
|
||||||
@ -623,7 +647,6 @@ class IrcObjectProxy(RichReplyMethods):
|
|||||||
else:
|
else:
|
||||||
del self.args[0]
|
del self.args[0]
|
||||||
cb = cbs[0]
|
cb = cbs[0]
|
||||||
Privmsg.handled = True
|
|
||||||
if cb.threaded or conf.supybot.debug.threadAllCommands():
|
if cb.threaded or conf.supybot.debug.threadAllCommands():
|
||||||
t = CommandThread(target=self._callCommand,
|
t = CommandThread(target=self._callCommand,
|
||||||
args=(name, cb))
|
args=(name, cb))
|
||||||
@ -706,7 +729,6 @@ class IrcObjectProxy(RichReplyMethods):
|
|||||||
notice=self.notice,
|
notice=self.notice,
|
||||||
private=self.private,
|
private=self.private,
|
||||||
prefixName=self.prefixName))
|
prefixName=self.prefixName))
|
||||||
self.finished = True
|
|
||||||
return
|
return
|
||||||
msgs = ircutils.wrap(s, allowedLength-30) # -30 is for nick:
|
msgs = ircutils.wrap(s, allowedLength-30) # -30 is for nick:
|
||||||
msgs.reverse()
|
msgs.reverse()
|
||||||
@ -742,7 +764,6 @@ class IrcObjectProxy(RichReplyMethods):
|
|||||||
notice=self.notice,
|
notice=self.notice,
|
||||||
private=self.private,
|
private=self.private,
|
||||||
prefixName=self.prefixName))
|
prefixName=self.prefixName))
|
||||||
self.finished = True
|
|
||||||
finally:
|
finally:
|
||||||
self._resetReplyAttributes()
|
self._resetReplyAttributes()
|
||||||
else:
|
else:
|
||||||
@ -766,10 +787,9 @@ class IrcObjectProxy(RichReplyMethods):
|
|||||||
self.error(formatArgumentError(self.commandMethod), **kwargs)
|
self.error(formatArgumentError(self.commandMethod), **kwargs)
|
||||||
else:
|
else:
|
||||||
raise ArgumentError # We shouldn't get here, but just in case.
|
raise ArgumentError # We shouldn't get here, but just in case.
|
||||||
self.finished = True
|
|
||||||
|
|
||||||
def noReply(self):
|
def noReply(self):
|
||||||
self.finished = True
|
self.msg.repliedTo = True
|
||||||
|
|
||||||
def getRealIrc(self):
|
def getRealIrc(self):
|
||||||
"""Returns the real irclib.Irc object underlying this proxy chain."""
|
"""Returns the real irclib.Irc object underlying this proxy chain."""
|
||||||
@ -868,7 +888,6 @@ class DisabledCommands(object):
|
|||||||
|
|
||||||
class Privmsg(irclib.IrcCallback):
|
class Privmsg(irclib.IrcCallback):
|
||||||
"""Base class for all Privmsg handlers."""
|
"""Base class for all Privmsg handlers."""
|
||||||
__metaclass__ = log.MetaFirewall
|
|
||||||
# For awhile, a comment stood here to say, "Eventually callCommand." But
|
# For awhile, a comment stood here to say, "Eventually callCommand." But
|
||||||
# that's wrong, because we can't do generic error handling in this
|
# that's wrong, because we can't do generic error handling in this
|
||||||
# callCommand -- plugins need to be able to override callCommand and do
|
# callCommand -- plugins need to be able to override callCommand and do
|
||||||
@ -876,13 +895,9 @@ class Privmsg(irclib.IrcCallback):
|
|||||||
__firewalled__ = {'isCommand': None,}
|
__firewalled__ = {'isCommand': None,}
|
||||||
# 'invalidCommand': None} # Gotta raise callbacks.Error.
|
# 'invalidCommand': None} # Gotta raise callbacks.Error.
|
||||||
public = True
|
public = True
|
||||||
handled = False
|
|
||||||
errored = False
|
|
||||||
alwaysCall = ()
|
alwaysCall = ()
|
||||||
threaded = False
|
threaded = False
|
||||||
noIgnore = False
|
noIgnore = False
|
||||||
callAfter = ()
|
|
||||||
callBefore = ()
|
|
||||||
Proxy = IrcObjectProxy
|
Proxy = IrcObjectProxy
|
||||||
commandArgs = ['self', 'irc', 'msg', 'args']
|
commandArgs = ['self', 'irc', 'msg', 'args']
|
||||||
# This must be class-scope, so all plugins use the same one.
|
# This must be class-scope, so all plugins use the same one.
|
||||||
@ -944,24 +959,6 @@ class Privmsg(irclib.IrcCallback):
|
|||||||
dispatcher.isDispatcher = True
|
dispatcher.isDispatcher = True
|
||||||
setattr(self.__class__, canonicalname, dispatcher)
|
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 __lt__(self, other):
|
|
||||||
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 __lt__ is the most specific one, so
|
|
||||||
# we basically run the other callback's as well.
|
|
||||||
if isinstance(other, Privmsg):
|
|
||||||
if other.name() in self.callBefore or \
|
|
||||||
self.name() in other.callAfter:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
return self.__parent.__lt__(other)
|
|
||||||
|
|
||||||
def __call__(self, irc, msg):
|
def __call__(self, irc, msg):
|
||||||
if msg.command == 'PRIVMSG':
|
if msg.command == 'PRIVMSG':
|
||||||
if self.noIgnore or not ircdb.checkIgnored(msg.prefix,msg.args[0]):
|
if self.noIgnore or not ircdb.checkIgnored(msg.prefix,msg.args[0]):
|
||||||
@ -1151,9 +1148,8 @@ class PrivmsgRegexp(Privmsg):
|
|||||||
irc.replyError()
|
irc.replyError()
|
||||||
|
|
||||||
def doPrivmsg(self, irc, msg):
|
def doPrivmsg(self, irc, msg):
|
||||||
if Privmsg.errored:
|
if msg.errored:
|
||||||
self.log.info('%s not running due to Privmsg.errored.',
|
self.log.info('%s not running due to msg.errored.', self.name())
|
||||||
self.name())
|
|
||||||
return
|
return
|
||||||
for (r, name) in self.res:
|
for (r, name) in self.res:
|
||||||
spans = sets.Set()
|
spans = sets.Set()
|
||||||
@ -1218,24 +1214,21 @@ class PrivmsgCommandAndRegexp(Privmsg):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
def doPrivmsg(self, irc, msg):
|
def doPrivmsg(self, irc, msg):
|
||||||
if Privmsg.errored:
|
if msg.errored:
|
||||||
self.log.debug('%s not running due to Privmsg.errored.',
|
self.log.debug('%s not running due to msg.errored.', self.name())
|
||||||
self.name())
|
|
||||||
return
|
return
|
||||||
for (r, name) in self.res:
|
for (r, name) in self.res:
|
||||||
for m in r.finditer(msg.args[1]):
|
for m in r.finditer(msg.args[1]):
|
||||||
proxy = self.Proxy(irc, msg)
|
proxy = self.Proxy(irc, msg)
|
||||||
self.callCommand(name, proxy, msg, m, catchErrors=True)
|
self.callCommand(name, proxy, msg, m, catchErrors=True)
|
||||||
if not Privmsg.handled:
|
s = addressed(irc.nick, msg)
|
||||||
s = addressed(irc.nick, msg)
|
if s:
|
||||||
if s:
|
for (r, name) in self.addressedRes:
|
||||||
for (r, name) in self.addressedRes:
|
if msg.repliedTo and name not in self.alwaysCall:
|
||||||
if Privmsg.handled and name not in self.alwaysCall:
|
continue
|
||||||
continue
|
for m in r.finditer(s):
|
||||||
for m in r.finditer(s):
|
proxy = self.Proxy(irc, msg)
|
||||||
proxy = self.Proxy(irc, msg)
|
self.callCommand(name, proxy, msg, m, catchErrors=True)
|
||||||
self.callCommand(name, proxy, msg, m, catchErrors=True)
|
|
||||||
Privmsg.handled = True
|
|
||||||
|
|
||||||
|
|
||||||
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|
||||||
|
@ -72,12 +72,8 @@ class IrcCallback(IrcCommandDispatcher):
|
|||||||
"doCommand" -- doPrivmsg, doNick, do433, etc. These will be called
|
"doCommand" -- doPrivmsg, doNick, do433, etc. These will be called
|
||||||
on matching messages.
|
on matching messages.
|
||||||
"""
|
"""
|
||||||
# priority determines the order in which callbacks are called. Lower
|
callAfter = ()
|
||||||
# numbers mean *higher* priority (like nice values in *nix). Higher
|
callBefore = ()
|
||||||
# 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
|
__metaclass__ = log.MetaFirewall
|
||||||
__firewalled__ = {'die': None,
|
__firewalled__ = {'die': None,
|
||||||
'reset': None,
|
'reset': None,
|
||||||
@ -87,19 +83,30 @@ class IrcCallback(IrcCommandDispatcher):
|
|||||||
'outFilter': lambda self, irc, msg: msg,
|
'outFilter': lambda self, irc, msg: msg,
|
||||||
'name': lambda self: self.__class__.__name__,}
|
'name': lambda self: self.__class__.__name__,}
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __repr__(self):
|
||||||
if isinstance(other, IrcCallback):
|
return '<%s %s>' % (self.__class__.__name__, self.name())
|
||||||
ret = self.priority < other.priority
|
|
||||||
if not ret:
|
|
||||||
ret = self.name() < other.name()
|
|
||||||
return ret
|
|
||||||
else:
|
|
||||||
return super(IrcCallback, self).__lt__(other)
|
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Returns the name of the callback."""
|
"""Returns the name of the callback."""
|
||||||
return self.__class__.__name__
|
return self.__class__.__name__
|
||||||
|
|
||||||
|
def callPrecedence(self, irc):
|
||||||
|
"""Returns a pair of (callbacks to call before me,
|
||||||
|
callbacks to call after me)"""
|
||||||
|
after = []
|
||||||
|
before = []
|
||||||
|
for name in self.callAfter:
|
||||||
|
cb = irc.getCallback(name)
|
||||||
|
if cb is not None:
|
||||||
|
after.append(cb)
|
||||||
|
for name in self.callBefore:
|
||||||
|
cb = irc.getCallback(name)
|
||||||
|
if cb is not None:
|
||||||
|
before.append(cb)
|
||||||
|
assert self not in after, '%s was in its own after.' % self.name()
|
||||||
|
assert self not in before, '%s was in its own before.' % self.name()
|
||||||
|
return (before, after)
|
||||||
|
|
||||||
def inFilter(self, irc, msg):
|
def inFilter(self, irc, msg):
|
||||||
"""Used for filtering/modifying messages as they're entering.
|
"""Used for filtering/modifying messages as they're entering.
|
||||||
|
|
||||||
@ -595,12 +602,43 @@ class Irc(IrcCommandDispatcher):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<irclib.Irc object for %s>' % self.network
|
return '<irclib.Irc object for %s>' % self.network
|
||||||
|
|
||||||
|
# This *isn't* threadsafe!
|
||||||
def addCallback(self, callback):
|
def addCallback(self, callback):
|
||||||
"""Adds a callback to the callbacks list."""
|
"""Adds a callback to the callbacks list."""
|
||||||
self.callbacks.append(callback)
|
self.callbacks.append(callback)
|
||||||
self.callbacks.sort()
|
# This is the new list we're building, which will be tsorted.
|
||||||
# We used to do this, then we implemented sorting in IrcCallback.
|
cbs = []
|
||||||
# utils.sortBy(operator.attrgetter('priority'), self.callbacks)
|
# The vertices are self.callbacks itself. Now we make the edges.
|
||||||
|
edges = sets.Set()
|
||||||
|
for cb in self.callbacks:
|
||||||
|
(before, after) = cb.callPrecedence(self)
|
||||||
|
assert cb not in after, 'cb was in its own after.'
|
||||||
|
assert cb not in before, 'cb was in its own before.'
|
||||||
|
for otherCb in before:
|
||||||
|
edges.add((otherCb, cb))
|
||||||
|
for otherCb in after:
|
||||||
|
edges.add((cb, otherCb))
|
||||||
|
def getFirsts():
|
||||||
|
firsts = sets.Set(self.callbacks) - sets.Set(cbs)
|
||||||
|
for (before, after) in edges:
|
||||||
|
firsts.discard(after)
|
||||||
|
return firsts
|
||||||
|
firsts = getFirsts()
|
||||||
|
while firsts:
|
||||||
|
# Then we add these to our list of cbs, and remove all edges that
|
||||||
|
# originate with these cbs.
|
||||||
|
for cb in firsts:
|
||||||
|
cbs.append(cb)
|
||||||
|
edgesToRemove = []
|
||||||
|
for edge in edges:
|
||||||
|
if edge[0] is cb:
|
||||||
|
edgesToRemove.append(edge)
|
||||||
|
for edge in edgesToRemove:
|
||||||
|
edges.remove(edge)
|
||||||
|
firsts = getFirsts()
|
||||||
|
assert len(cbs) == len(self.callbacks), \
|
||||||
|
'cbs: %s, self.callbacks: %s' % (cbs, self.callbacks)
|
||||||
|
self.callbacks[:] = cbs
|
||||||
|
|
||||||
def getCallback(self, name):
|
def getCallback(self, name):
|
||||||
"""Gets a given callback by name."""
|
"""Gets a given callback by name."""
|
||||||
|
Loading…
Reference in New Issue
Block a user