Added log.firewall and log.MetaFirewall, and converted several classes to use them.

This commit is contained in:
Jeremy Fincher 2004-02-06 09:20:47 +00:00
parent 4fec15f40e
commit 47d81547aa
6 changed files with 64 additions and 49 deletions

View File

@ -83,11 +83,7 @@ class AsyncoreDriver(asynchat.async_chat, object):
def writable(self):
while self.connected:
try:
m = self.irc.takeMsg()
except Exception, e:
log.exception('Uncaught exception in irclib.Irc.takeMsg:')
return
m = self.irc.takeMsg()
if m:
self.push(str(m))
else:

View File

@ -434,13 +434,7 @@ class IrcObjectProxy(RichReplyMethods):
log.debug('Finished calling invalidCommand: %s', cb.name())
return
if hasattr(cb, 'invalidCommand'):
try:
cb.invalidCommand(self, self.msg, self.args)
except Exception, e:
cb.log.exception('Uncaught exception in invalidCommand:')
log.warning('Uncaught exception in %s.invalidCommand, '
'continuing to call other invalidCommands.' %
cb.name())
cb.invalidCommand(self, self.msg, self.args)
def _callCommand(self, name, command, cb):
try:
@ -669,6 +663,8 @@ class ConfigIrcProxy(RichReplyMethods):
class Privmsg(irclib.IrcCallback):
"""Base class for all Privmsg handlers."""
__metaclass__ = log.MetaFirewall
__firewalled__ = {'invalidCommand': None} # Eventually callCommand.
threaded = False
public = True
alwaysCall = ()

View File

@ -75,6 +75,13 @@ class IrcCallback(IrcCommandDispatcher):
# 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,
'inFilter': lambda self, irc, msg: msg,
'outFilter': lambda self, irc, msg: msg,
'name': lambda self: self.__class__.__name__,}
def name(self):
"""Returns the name of the callback."""
return self.__class__.__name__
@ -99,11 +106,7 @@ class IrcCallback(IrcCommandDispatcher):
"""Used for handling each message."""
method = self.dispatchCommand(msg.command)
if method is not None:
try:
method(irc, msg)
except Exception, e:
s = 'Exception caught in generic IrcCallback.__call__:'
log.exception(s)
method(irc, msg)
def reset(self):
"""Resets the callback. Called when reconnecting to the server."""
@ -263,6 +266,8 @@ class IrcState(IrcCommandDispatcher):
"""Maintains state of the Irc connection. Should also become smarter.
"""
__slots__ = ('history', 'nicksToHostmasks', 'channels')
__metaclass__ = log.MetaFirewall
__firewalled__ = {'addMsg': None}
def __init__(self):
self.history = RingBuffer(conf.supybot.maxHistoryLength())
self.reset()
@ -411,6 +416,10 @@ class Irc(IrcCommandDispatcher):
Handles PING commands already.
"""
__metaclass__ = log.MetaFirewall
__firewalled__ = {'die': None,
'feedMsg': None,
'takeMsg': None,}
_nickSetters = sets.Set(['001', '002', '003', '004', '250', '251', '252',
'254', '255', '265', '266', '372', '375', '376',
'333', '353', '332', '366', '005'])
@ -520,31 +529,16 @@ class Irc(IrcCommandDispatcher):
if msg:
log.debug(repr(msg))
for callback in reviter(self.callbacks):
try:
outFilter = getattr(callback, 'outFilter')
except AttributeError, e:
continue
try:
msg = outFilter(self, msg)
except:
log.exception('Exception caught in outFilter:')
continue
msg = callback.outFilter(self, msg)
if msg is None:
log.debug('%s.outFilter returned None' % callback.name())
log.debug('%s.outFilter returned None.' % callback.name())
return self.takeMsg()
if len(str(msg)) > 512:
# Yes, this violates the contract, but at this point it doesn't
# matter. That's why we gotta go munging in private attributes
msg._str = msg._str[:500] + '\r\n'
msg._len = len(str(msg))
try:
self.state.addMsg(self, msg)
except Exception, e:
log.exception('Uncaught exception in IrcState.addMsg. This '
'could be a bug, but it could also be the '
'result of an invalid message being sent via '
'Owner.ircquote.')
return
self.state.addMsg(self, msg)
log.debug('Outgoing message: ' + str(msg).rstrip('\r\n'))
return msg
else:
@ -668,10 +662,7 @@ class Irc(IrcCommandDispatcher):
log.info('Irc object for %s dying.' % self.server)
if self in world.ircs:
for cb in self.callbacks:
try:
cb.die()
except Exception, e:
log.exception('Uncaught exception in %s.die:', cb.name())
cb.die()
world.ircs.remove(self)
else:
log.warning('Irc object killed twice.')

View File

@ -42,6 +42,7 @@ import logging
import ansi
import conf
import utils
import registry
deadlyExceptions = [KeyboardInterrupt, SystemExit]
@ -166,6 +167,45 @@ def timestamp(when=None):
format = conf.supybot.log.timestampFormat()
return time.strftime(format, time.localtime(when))
def firewall(f, errorHandler=None):
def logException(self, s=None):
if s is None:
s = 'Uncaught exception'
if hasattr(self, 'log'):
self.log.exception('%s:', s)
else:
exception('%s in %s.%s:', s, self.__class__.__name__, f.func_name)
def m(self, *args, **kwargs):
try:
return f(self, *args, **kwargs)
except Exception, e:
logException(self)
if errorHandler is not None:
try:
errorHandler(self, *args, **kwargs)
except Exception, e:
logException(self, 'Uncaught exception in errorHandler')
m = utils.changeFunctionName(m, f.func_name, f.__doc__)
return m
class MetaFirewall(type):
def __new__(cls, name, bases, dict):
firewalled = {}
for base in bases:
if hasattr(base, '__firewalled__'):
firewalled.update(base.__firewalled__)
if '__firewalled__' in dict:
firewalled.update(dict['__firewalled__'])
for attr in firewalled:
if attr in dict:
try:
errorHandler = firewalled[attr]
except:
errorHandler = None
dict[attr] = firewall(dict[attr], errorHandler)
return type.__new__(cls, name, bases, dict)
class LogLevel(registry.Value):
def set(self, s):

View File

@ -75,11 +75,7 @@ class SocketDriver(drivers.IrcDriver):
self.reconnect()
def _sendIfMsgs(self):
try:
msgs = [self.irc.takeMsg()]
except Exception, e:
log.exception('Uncaught exception in irclib.Irc.takeMsg:')
return
msgs = [self.irc.takeMsg()]
while msgs[-1] is not None:
msgs.append(self.irc.takeMsg())
del msgs[-1]

View File

@ -69,11 +69,7 @@ class SupyIrcProtocol(LineReceiver):
def checkIrcForMsgs(self):
if self.connected:
try:
msg = self.irc.takeMsg()
except Exception, e:
log.exception('Uncaught exception in irclib.Irc.takeMsg:')
return
msg = self.irc.takeMsg()
if msg:
self.transport.write(str(msg))
self.mostRecentCall = reactor.callLater(1, self.checkIrcForMsgs)