A bunch more %r -> %s conversions as well as wrap updates, new policy for

Channel.voice and some bug fixes for Debian
This commit is contained in:
James Vega 2004-10-25 22:59:03 +00:00
parent 2adef7c265
commit cbd5abbab7
17 changed files with 172 additions and 212 deletions

View File

@ -124,7 +124,7 @@ class Debian(callbacks.Privmsg,
# that).
if not optlist and not glob:
raise callbacks.ArgumentError
if optlist and glob > 1:
if optlist and glob:
irc.error('You must specify either a glob or a regexp/exact '
'search, but not both.')
for (option, arg) in optlist:
@ -181,8 +181,8 @@ class Debian(callbacks.Privmsg,
irc.reply('I found no packages with that file.')
else:
irc.reply(utils.commaAndify(packages))
file = wrap(file, [getopts({'regexp':'regexpMatcher', 'exact':'text'}),
additional('text')])
file = wrap(file, [getopts({'regexp':'regexpMatcher','exact':'something'}),
additional('glob')])
_debreflags = re.DOTALL | re.IGNORECASE
_deblistre = re.compile(r'<h3>Package ([^<]+)</h3>(.*?)</ul>', _debreflags)
@ -264,8 +264,8 @@ class Debian(callbacks.Privmsg,
archPredicate = lambda s, arg=arg: (arg in s)
predicates.append(archPredicate)
for glob in globs:
glob = glob.replace('*', '.*').replace('?', '.?')
predicates.append(re.compile(r'.*%s.*' % glob).search)
glob = fnmatch.translate(glob)
predicates.append(re.compile(glob).search)
packages = []
try:
fd = webutils.getUrlFd('http://incoming.debian.org/')
@ -285,18 +285,16 @@ class Debian(callbacks.Privmsg,
irc.reply(utils.commaAndify(packages))
incoming = thread(wrap(incoming,
[getopts({'regexp':'regexpMatcher', 'arch':'text'}),
any('text')]))
any('glob')]))
_newpkgre = re.compile(r'<li><a href[^>]+>([^<]+)</a>')
def new(self, irc, msg, args, optlist, glob):
def new(self, irc, msg, args, section, glob):
"""[{main,contrib,non-free}] [<glob>]
Checks for packages that have been added to Debian's unstable branch
in the past week. If no glob is specified, returns a list of all
packages. If no section is specified, defaults to main.
"""
if '?' not in glob and '*' not in glob:
glob = '*%s*' % glob
try:
fd = webutils.getUrlFd(
'http://packages.debian.org/unstable/newpkg_%s' % section)
@ -316,7 +314,7 @@ class Debian(callbacks.Privmsg,
irc.error('No packages matched that search.')
new = wrap(new, [optional(('literal', ('main', 'contrib', 'non-free')),
'main'),
additional('text', '*')])
additional('glob', '*')])
_severity = re.compile(r'.*(?:severity set to `([^\']+)\'|'
r'severity:\s+([^\s]+))', re.I)

View File

@ -163,7 +163,7 @@ class Channel(callbacks.Privmsg):
irc.queueMsg(ircmsgs.halfops(channel, nicks))
halfop = wrap(halfop, [('checkChannelCapability', 'halfop'),
('haveOp', 'halfop someone'),
many('nickInChannel')])
any('nickInChannel')])
def voice(self, irc, msg, args, channel, nicks):
"""[<channel>] [<nick> ...]
@ -173,12 +173,21 @@ class Channel(callbacks.Privmsg):
voice you. <channel> is only necessary if the message isn't sent in the
channel itself.
"""
if not nicks:
if nicks:
if len(nicks) == 1 and msg.nick in nicks:
capability = 'voice'
else:
capability = 'op'
else:
nicks = [msg.nick]
irc.queueMsg(ircmsgs.voices(channel, nicks))
voice = wrap(voice, [('checkChannelCapability', 'voice'),
('haveOp', 'voice someone'),
many('nickInChannel')])
capability = 'voice'
capability = ircdb.makeChannelCapability(channel, capability)
if ircdb.checkCapability(msg.prefix, capability):
irc.queueMsg(ircmsgs.voices(channel, nicks))
else:
irc.errorNoCapability(capability)
voice = wrap(voice, ['channel', ('haveOp', 'voice someone'),
any('nickInChannel')])
def deop(self, irc, msg, args, channel, nicks):
"""[<channel>] [<nick> ...]
@ -193,11 +202,10 @@ class Channel(callbacks.Privmsg):
'yourself.', Raise=True)
if not nicks:
nicks = [msg.nick]
else:
irc.queueMsg(ircmsgs.deops(channel, nicks))
irc.queueMsg(ircmsgs.deops(channel, nicks))
deop = wrap(deop, [('checkChannelCapability', 'op'),
('haveOp', 'deop someone'),
many('nickInChannel')])
any('nickInChannel')])
def dehalfop(self, irc, msg, args, channel, nicks):
"""[<channel>] [<nick> ...]
@ -212,11 +220,10 @@ class Channel(callbacks.Privmsg):
'dehalfop me yourself.', Raise=True)
if not nicks:
nicks = [msg.nick]
else:
irc.queueMsg(ircmsgs.dehalfops(channel, nicks))
irc.queueMsg(ircmsgs.dehalfops(channel, nicks))
dehalfop = wrap(dehalfop, [('checkChannelCapability', 'halfop'),
('haveOp', 'dehalfop someone'),
many('nickInChannel')])
any('nickInChannel')])
# XXX These nicks should really be sets, rather than lists, especially
# we check whether the bot's nick is in them.
@ -235,11 +242,10 @@ class Channel(callbacks.Privmsg):
'me yourself.', Raise=True)
if not nicks:
nicks = [msg.nick]
else:
irc.queueMsg(ircmsgs.devoices(channel, nicks))
irc.queueMsg(ircmsgs.devoices(channel, nicks))
devoice = wrap(devoice, [('checkChannelCapability', 'voice'),
('haveOp', 'devoice someone'),
many('nickInChannel')])
any('nickInChannel')])
def cycle(self, irc, msg, args, channel, key):
"""[<channel>] [<key>]
@ -299,11 +305,13 @@ class Channel(callbacks.Privmsg):
# Check that they're not trying to make us kickban ourself.
self.log.debug('In kban')
if not ircutils.isNick(bannedNick):
self.log.warning('%r tried to kban a non nick: %r',
msg.prefix, bannedNick)
self.log.warning('%s tried to kban a non nick: %s',
utils.quoted(msg.prefix),
utils.quoted(bannedNick))
raise callbacks.ArgumentError
elif bannedNick == irc.nick:
self.log.warning('%r tried to make me kban myself.', msg.prefix)
self.log.warning('%s tried to make me kban myself.',
utils.quoted(msg.prefix))
irc.error('I cowardly refuse to kickban myself.')
return
if not reason:
@ -337,7 +345,8 @@ class Channel(callbacks.Privmsg):
# Check (again) that they're not trying to make us kickban ourself.
if ircutils.hostmaskPatternEqual(banmask, irc.prefix):
if ircutils.hostmaskPatternEqual(banmask, irc.prefix):
self.log.warning('%r tried to make me kban myself.',msg.prefix)
self.log.warning('%s tried to make me kban myself.',
utils.quoted(msg.prefix))
irc.error('I cowardly refuse to ban myself.')
return
else:
@ -360,15 +369,16 @@ class Channel(callbacks.Privmsg):
doBan()
elif ircdb.checkCapability(msg.prefix, capability):
if ircdb.checkCapability(bannedHostmask, capability):
self.log.warning('%s tried to ban %r, but both have %s',
msg.prefix, bannedHostmask, capability)
self.log.warning('%s tried to ban %s, but both have %s',
msg.prefix, utils.quoted(bannedHostmask),
capability)
irc.error('%s has %s too, you can\'t ban him/her/it.' %
(bannedNick, capability))
else:
doBan()
else:
self.log.warning('%r attempted kban without %s',
msg.prefix, capability)
self.log.warning('%s attempted kban without %s',
utils.quoted(msg.prefix), capability)
irc.errorNoCapability(capability)
exact,nick,user,host
kban = wrap(kban,
@ -519,7 +529,8 @@ class Channel(callbacks.Privmsg):
# XXX Add the expirations.
c = ircdb.channels.getChannel(channel)
if len(c.ignores) == 0:
s = 'I\'m not currently ignoring any hostmasks in %r' % channel
s = 'I\'m not currently ignoring any hostmasks in %s' % \
utils.quoted(channel)
irc.reply(s)
else:
L = sorted(c.ignores)

View File

@ -387,8 +387,8 @@ class Misc(callbacks.Privmsg):
if irc.nested:
irc.reply(utils.commaAndify(names))
else:
irc.reply('The %r command is available in the %s %s.' %
(command, plugin,
irc.reply('The %s command is available in the %s %s.' %
(utils.quoted(command), plugin,
utils.pluralize('plugin', len(names))))
else:
irc.error('There is no such command %s.' % command)
@ -675,7 +675,7 @@ class Misc(callbacks.Privmsg):
if getattr(module, '__author__', False) == authorInfo:
isAuthor = True
# XXX Partition needs moved to utils.
(nonCommands, commands) = fix.partition(lambda s: ' ' in s,
(nonCommands, commands) = fix.partition(lambda s: ' ' in s,
contributions)
results = []
if commands:

View File

@ -75,7 +75,8 @@ def loadPluginModule(name, ignoreDeprecation=False):
try:
files.extend(os.listdir(dir))
except EnvironmentError: # OSError, IOError superclass.
log.warning('Invalid plugin directory: %r; removing.', dir)
log.warning('Invalid plugin directory: %s; removing.',
utils.quoted(dir))
conf.supybot.directories.plugins().remove(dir)
loweredFiles = map(str.lower, files)
try:
@ -98,7 +99,8 @@ def loadPluginModule(name, ignoreDeprecation=False):
if ignoreDeprecation:
log.warning('Deprecated plugin loaded: %s', name)
else:
raise Deprecated, 'Attempted to load deprecated plugin %r' % name
raise Deprecated, 'Attempted to load deprecated plugin %s' % \
utils.quoted(name)
if module.__name__ in sys.modules:
sys.modules[module.__name__] = module
linecache.checkcache()
@ -173,8 +175,8 @@ def renameCommand(cb, name, newName):
method = getattr(cb.__class__, name)
setattr(cb.__class__, newName, method)
delattr(cb.__class__, name)
registerDefaultPlugin('list', 'Misc')
registerDefaultPlugin('help', 'Misc')
registerDefaultPlugin('ignore', 'Admin')
@ -248,7 +250,7 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
# There are no plugins that are all-lowercase, so we'll at
# least attempt to capitalize them.
if name == name.lower():
name = name.capitalize()
name = name.capitalize()
conf.registerPlugin(name)
if name.startswith('supybot.commands.defaultPlugins'):
try:
@ -266,7 +268,7 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
self.log.warning('Tried to send a message to myself: %r.', msg)
return None
return msg
def isCommand(self, name):
return name == 'log' or \
self.__parent.isCommand(name)
@ -396,7 +398,8 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
self._evalEnv['_'] = x
irc.reply(repr(x))
except SyntaxError, e:
irc.reply('%s: %r' % (utils.exnToString(e), s))
irc.reply('%s: %s' % (utils.exnToString(e),
utils.quoted(s)))
except Exception, e:
self.log.exception('Uncaught exception in Owner.eval. '
'This is not a bug. Please do not '
@ -491,7 +494,6 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
Sends the raw string given to the server.
"""
s = privmsgs.getArgs(args)
try:
m = ircmsgs.IrcMsg(s)
except Exception, e:
@ -678,7 +680,7 @@ class Owner(privmsgs.CapabilityCheckingPrivmsg):
irc.replySuccess()
defaultcapability = wrap(defaultcapability,
[('literal', ['add','remove']), 'capability'])
def disable(self, irc, msg, args):
"""[<plugin>] <command>

View File

@ -46,6 +46,7 @@ from itertools import imap, ifilter
import supybot.conf as conf
import supybot.utils as utils
import supybot.ircdb as ircdb
from supybot.commands import *
import supybot.ircutils as ircutils
import supybot.privmsgs as privmsgs
import supybot.callbacks as callbacks
@ -55,26 +56,22 @@ class User(callbacks.Privmsg):
if password and ircutils.isChannel(msg.args[0]):
raise callbacks.Error, conf.supybot.replies.requiresPrivacy()
def list(self, irc, msg, args):
"""[--capability <capability>] [<glob>]
def list(self, irc, msg, args, optlist, glob):
"""[--capability=<capability>] [<glob>]
Returns the valid registered usernames matching <glob>. If <glob> is
not given, returns all registered usernames.
"""
(optlist, rest) = getopt.getopt(args, '', ['capability='])
predicates = []
for (option, arg) in optlist:
if option == '--capability':
if option == 'capability':
def p(u, cap=arg):
try:
return u.checkCapability(cap)
except KeyError:
return False
predicates.append(p)
glob = privmsgs.getArgs(rest, required=0, optional=1)
if glob:
if '*' not in glob and '?' not in glob:
glob = '*%s*' % glob
r = re.compile(fnmatch.translate(glob), re.I)
def p(u):
return r.match(u.name) is not None
@ -94,8 +91,10 @@ class User(callbacks.Privmsg):
irc.reply('There are no matching registered users.')
else:
irc.reply('There are no registered users.')
list = wrap(list, [getopts({'capability':'capability'}),
additional('glob')])
def register(self, irc, msg, args):
def register(self, irc, msg, args, optlist, name, password):
"""[--hashed] <name> <password>
Registers <name> with the given password <password> and the current
@ -104,14 +103,11 @@ class User(callbacks.Privmsg):
not in a channel. If --hashed is given, the password will be hashed
on disk, rather than being stored in the default configured format.
"""
(optlist, rest) = getopt.getopt(args, '', ['hashed'])
(name, password) = privmsgs.getArgs(rest, required=2)
addHostmask = True
hashed = conf.supybot.databases.users.hash()
for (option, arg) in optlist:
if option == '--hashed':
if option == 'hashed':
hashed = True
self._checkNotChannel(irc, msg, password)
try:
ircdb.users.getUserId(name)
irc.error('That name is already assigned to someone.', Raise=True)
@ -136,30 +132,26 @@ class User(callbacks.Privmsg):
user.addHostmask(msg.prefix)
ircdb.users.setUser(user)
irc.replySuccess()
register = wrap(register, ['private', getopts({'hashed':''}), 'something',
'something'])
def unregister(self, irc, msg, args):
def unregister(self, irc, msg, args, user, password):
"""<name> [<password>]
Unregisters <name> from the user database. If the user giving this
command is an owner user, the password is not necessary.
"""
(name, password) = privmsgs.getArgs(args, optional=1)
self._checkNotChannel(irc, msg, password)
try:
id = ircdb.users.getUserId(name)
u = ircdb.users.getUser(id)
except KeyError:
irc.error('That username isn\'t registered.')
return
if not u.checkPassword(password):
u = ircdb.users.getUser(msg.prefix)
if not u.checkCapability('owner'):
if not user.checkPassword(password):
user = ircdb.users.getUser(msg.prefix)
if not user.checkCapability('owner'):
irc.error(conf.supybot.replies.incorrectAuthentication())
return
ircdb.users.delUser(id)
ircdb.users.delUser(user.id)
irc.replySuccess()
unregister = wrap(unregister, ['private', 'otherUser',
additional('something')])
def changename(self, irc, msg, args):
def changename(self, irc, msg, args, user, newname, password):
"""<name> <new name> [<password>]
Changes your current user database name to the new name given.
@ -167,17 +159,9 @@ class User(callbacks.Privmsg):
If you include the <password> parameter, this message must be sent
to the bot privately (not on a channel).
"""
(name,newname,password) = privmsgs.getArgs(args,required=2,optional=1)
self._checkNotChannel(irc, msg, password)
try:
id = ircdb.users.getUserId(name)
user = ircdb.users.getUser(id)
except KeyError:
irc.error('That username isn\'t registered.')
return
try:
id = ircdb.users.getUserId(newname)
irc.error('%r is already registered.' % newname)
irc.error('%s is already registered.' % utils.quoted(newname))
return
except KeyError:
pass
@ -185,8 +169,10 @@ class User(callbacks.Privmsg):
user.name = newname
ircdb.users.setUser(user)
irc.replySuccess()
changename = wrap(changename, ['private', 'otherUser', 'something',
additional('something')])
def addhostmask(self, irc, msg, args):
def addhostmask(self, irc, msg, args, user, hostmask, password):
"""[<name>] [<hostmask>] [<password>]
Adds the hostmask <hostmask> to the user specified by <name>. The
@ -198,12 +184,8 @@ class User(callbacks.Privmsg):
hostmask. If <name> is not given, it defaults to your currently
identified name.
"""
(name, hostmask, password) = privmsgs.getArgs(args, 0, 3)
self._checkNotChannel(irc, msg, password)
if not hostmask:
hostmask = msg.prefix
if not name:
name = msg.prefix
if not ircutils.isUserHostmask(hostmask):
irc.errorInvalid('hostmask', hostmask, 'Make sure your hostmask '
'includes a nick, then an exclamation point (!), then '
@ -211,11 +193,6 @@ class User(callbacks.Privmsg):
'free to use wildcards (* and ?, which work just like '
'they do on the command line) in any of these parts.',
Raise=True)
try:
id = ircdb.users.getUserId(name)
user = ircdb.users.getUser(id)
except KeyError:
irc.errorNoUser(Raise=True)
try:
otherId = ircdb.users.getUserId(hostmask)
if otherId != id:
@ -241,8 +218,11 @@ class User(callbacks.Privmsg):
except ValueError, e:
irc.error(str(e), Raise=True)
irc.replySuccess()
addhostmask = wrap(addhostmask, [first('otherUser', 'user'),
optional('something'),
additional('something')])
def removehostmask(self, irc, msg, args):
def removehostmask(self, irc, msg, args, user, hostmask, password):
"""<name> <hostmask> [<password>]
Removes the hostmask <hostmask> from the record of the user specified
@ -251,14 +231,6 @@ class User(callbacks.Privmsg):
recognized by his hostmask. If you include the <password> parameter,
this message must be sent to the bot privately (not on a channel).
"""
(name, hostmask, password) = privmsgs.getArgs(args, 2, 1)
self._checkNotChannel(irc, msg, password)
try:
id = ircdb.users.getUserId(name)
user = ircdb.users.getUser(id)
except KeyError:
irc.errorNoUser()
return
if not user.checkPassword(password) and \
not user.checkHostmask(msg.prefix):
u = ircdb.users.getUser(msg.prefix)
@ -277,8 +249,10 @@ class User(callbacks.Privmsg):
return
ircdb.users.setUser(user)
irc.replySuccess(s)
removehostmask = wrap(removehostmask, ['private', 'otherUser', 'something',
additional('something')])
def setpassword(self, irc, msg, args):
def setpassword(self, irc, msg, args, optlist, user, password,newpassword):
"""[--hashed] <name> <old password> <new password>
Sets the new password for the user specified by <name> to
@ -289,57 +263,36 @@ class User(callbacks.Privmsg):
changed isn't that same owner user), then <old password> needn't be
correct.
"""
(optlist, rest) = getopt.getopt(args, '', ['hashed'])
(name, oldpassword, newpassword) = privmsgs.getArgs(rest, 3)
hashed = conf.supybot.databases.users.hash()
for (option, arg) in optlist:
if option == '--hashed':
if option == 'hashed':
hashed = True
self._checkNotChannel(irc, msg, oldpassword+newpassword)
try:
id = ircdb.users.getUserId(name)
user = ircdb.users.getUser(id)
except KeyError:
irc.errorNoUser()
return
u = ircdb.users.getUser(msg.prefix)
if user.checkPassword(oldpassword) or \
if user.checkPassword(password) or \
(u.checkCapability('owner') and not u == user):
user.setPassword(newpassword, hashed=hashed)
ircdb.users.setUser(user)
irc.replySuccess()
else:
irc.error(conf.supybot.replies.incorrectAuthentication())
setpassword = wrap(setpassword, [getopts({'hashed':''}), 'otherUser',
'something', 'something'])
def username(self, irc, msg, args):
def username(self, irc, msg, args, user):
"""<hostmask|nick>
Returns the username of the user specified by <hostmask> or <nick> if
the user is registered.
"""
hostmask = privmsgs.getArgs(args)
if not ircutils.isUserHostmask(hostmask):
try:
hostmask = irc.state.nickToHostmask(hostmask)
except KeyError:
irc.reply('I couldn\'t find %s in my user database.' %hostmask)
return
try:
user = ircdb.users.getUser(hostmask)
irc.reply(user.name)
except KeyError:
irc.reply('I couldn\'t find %s in my user database.' % hostmask)
irc.reply(user.name)
username = wrap(username, ['otherUser'])
def hostmasks(self, irc, msg, args):
def hostmasks(self, irc, msg, args, name):
"""[<name>]
Returns the hostmasks of the user specified by <name>; if <name> isn't
specified, returns the hostmasks of the user calling the command.
"""
if ircutils.isChannel(msg.args[0]):
irc.errorRequiresPrivacy()
return
name = privmsgs.getArgs(args, required=0, optional=1)
try:
user = ircdb.users.getUser(msg.prefix)
if name:
@ -355,38 +308,24 @@ class User(callbacks.Privmsg):
irc.reply(repr(user.hostmasks))
except KeyError:
irc.errorNotRegistered()
hostmasks = wrap(hostmasks, ['private', additional('something')])
def capabilities(self, irc, msg, args):
def capabilities(self, irc, msg, args, user):
"""[<name>]
Returns the capabilities of the user specified by <name>; if <name>
isn't specified, returns the hostmasks of the user calling the command.
"""
if not args:
name = msg.prefix
else:
name = privmsgs.getArgs(args)
try:
user = ircdb.users.getUser(name)
irc.reply('[%s]' % '; '.join(user.capabilities))
except KeyError:
irc.errorNoUser()
irc.reply('[%s]' % '; '.join(user.capabilities))
capabilities = wrap(capabilities, [first('otherUser', 'user')])
def identify(self, irc, msg, args):
def identify(self, irc, msg, args, user, password):
"""<name> <password>
Identifies the user as <name>. This command (and all other
commands that include a password) must be sent to the bot privately,
not in a channel.
"""
(name, password) = privmsgs.getArgs(args, 2)
self._checkNotChannel(irc, msg)
try:
id = ircdb.users.getUserId(name)
user = ircdb.users.getUser(id)
except KeyError:
irc.errorNoUser()
return
if user.checkPassword(password):
try:
user.addAuth(msg.prefix)
@ -397,8 +336,9 @@ class User(callbacks.Privmsg):
'doesn\'t match any of your known hostmasks.')
else:
irc.error(conf.supybot.replies.incorrectAuthentication())
identify = wrap(identify, ['private', 'otherUser', 'something'])
def unidentify(self, irc, msg, args):
def unidentify(self, irc, msg, args, user):
"""takes no arguments
Un-identifies you. Note that this may not result in the desired
@ -406,12 +346,6 @@ class User(callbacks.Privmsg):
have added hostmasks to your user that can cause the bot to continue to
recognize you.
"""
try:
id = ircdb.users.getUserId(msg.prefix)
user = ircdb.users.getUser(id)
except KeyError:
irc.errorNoUser()
return
user.clearAuth()
ircdb.users.setUser(user)
irc.replySuccess('If you remain recognized after giving this command, '
@ -419,6 +353,7 @@ class User(callbacks.Privmsg):
'by password. You must remove whatever hostmask is '
'causing you to be recognized in order not to be '
'recognized.')
unidentify = wrap(unidentify, ['user'])
def whoami(self, irc, msg, args):
"""takes no arguments
@ -430,8 +365,9 @@ class User(callbacks.Privmsg):
irc.reply(user.name)
except KeyError:
irc.reply('I don\'t recognize you.')
whoami = wrap(whoami)
def setsecure(self, irc, msg, args):
def setsecure(self, irc, msg, args, user, password, value):
"""<password> [<True|False>]
Sets the secure flag on the user of the person sending the message.
@ -441,21 +377,8 @@ class User(callbacks.Privmsg):
If a specific True/False value is not given, it inverts the current
value.
"""
(password, value) = privmsgs.getArgs(args, optional=1)
self._checkNotChannel(irc, msg, password)
try:
id = ircdb.users.getUserId(msg.prefix)
user = ircdb.users.getUser(id)
except KeyError:
irc.errorNotRegistered()
if value == '':
if value is None:
value = not user.secure
elif value.lower() in ('true', 'on', 'enable'):
value = True
elif value.lower() in ('false', 'off', 'disable'):
value = False
else:
irc.errorInvalid('boolean value', value, Raise=True)
if user.checkPassword(password) and \
user.checkHostmask(msg.prefix, useAuth=False):
user.secure = value
@ -463,6 +386,8 @@ class User(callbacks.Privmsg):
irc.reply('Secure flag set to %s' % value)
else:
irc.error(conf.supybot.replies.incorrectAuthentication())
setsecure = wrap(setsecure, ['private', 'user', 'something',
additional('boolean')])
def stats(self, irc, msg, args):
"""takes no arguments
@ -488,7 +413,8 @@ class User(callbacks.Privmsg):
'%s and %s.' % (users, hostmasks,
utils.nItems('owner', owners),
utils.nItems('admin', admins)))
stats = wrap(stats)
## def config(self, irc, msg, args):
## """[--list] <name> [<value>]

View File

@ -480,8 +480,8 @@ class RichReplyMethods(object):
if 'Raise' not in kwargs:
kwargs['Raise'] = True
if isinstance(capability, basestring): # checkCommandCapability!
log.warning('Denying %s for lacking %r capability.',
self.msg.prefix, capability)
log.warning('Denying %s for lacking %s capability.',
self.msg.prefix, utils.quoted(capability))
if not self._getConfig(conf.supybot.reply.noCapabilityError):
v = self._getConfig(conf.supybot.replies.noCapability)
s = self.__makeReply(v % capability, s)
@ -1092,7 +1092,8 @@ class Privmsg(irclib.IrcCallback):
def getCommand(self, name):
"""Gets the given command from this plugin."""
name = canonicalName(name)
assert self.isCommand(name), '%r is not a command.' % name
assert self.isCommand(name), '%s is not a command.' % \
utils.quoted(name)
return getattr(self, name)
def callCommand(self, name, irc, msg, *L, **kwargs):
@ -1243,7 +1244,8 @@ class PrivmsgRegexp(Privmsg):
r = re.compile(value.__doc__, self.flags)
self.res.append((r, name))
except re.error, e:
self.log.warning('Invalid regexp: %r (%s)',value.__doc__,e)
self.log.warning('Invalid regexp: %s (%s)',
utils.quoted(value.__doc__), e)
utils.sortBy(operator.itemgetter(1), self.res)
def callCommand(self, name, irc, msg, *L, **kwargs):

View File

@ -426,6 +426,12 @@ def checkCapability(irc, msg, args, state, cap):
def anything(irc, msg, args, state):
state.args.append(args.pop(0))
def getGlob(irc, msg, args, state):
glob = args.pop(0)
if '*' not in glob and '?' not in glob:
glob = '*%s*' % glob
state.args.append(glob)
def getUrl(irc, msg, args, state):
if webutils.urlRe.match(args[0]):
state.args.append(args.pop(0))
@ -521,6 +527,7 @@ wrappers = ircutils.IrcDict({
'something': getSomething,
'filename': getSomething, # XXX Check for validity.
'commandName': getCommandName,
'glob': getGlob,
'text': anything,
'somethingWithoutSpaces': getSomethingNoSpaces,
'capability': getSomethingNoSpaces,

View File

@ -457,7 +457,7 @@ registerChannelValue(supybot.replies, 'notRegistered',
but they're not currently recognized."""))
registerChannelValue(supybot.replies, 'noCapability',
registry.NormalizedString("""You don't have the %r capability. If you
registry.NormalizedString("""You don't have the %s capability. If you
think that you should have this capability, be sure that you are identified
before trying again. The 'whoami' command can tell you if you're
identified.""", """Determines what error message is given when the bot is

View File

@ -225,10 +225,11 @@ class IrcUser(object):
self.hostmasks = hostmasks
def __repr__(self):
return '%s(id=%s, ignore=%s, password="", name=%r, hashed=%r, ' \
return '%s(id=%s, ignore=%s, password="", name=%s, hashed=%r, ' \
'capabilities=%r, hostmasks=[], secure=%r)\n' % \
(self.__class__.__name__, self.id, self.ignore, self.name,
self.hashed, self.capabilities, self.secure)
(self.__class__.__name__, self.id, self.ignore,
utils.quoted(self.name), self.hashed, self.capabilities,
self.secure)
def __hash__(self):
return hash(self.id)
@ -655,7 +656,8 @@ class UsersDictionary(utils.IterableMap):
log.error('Multiple matches found in user database. '
'Removing the offending hostmasks.')
for (id, hostmask) in ids.iteritems():
log.error('Removing %r from user %s.', hostmask, id)
log.error('Removing %s from user %s.',
utils.quoted(hostmask), id)
self.users[id].removeHostmask(hostmask)
raise DuplicateHostmask, 'Ids %r matched.' % ids
else: # Not a hostmask, must be a name.
@ -855,7 +857,8 @@ class IgnoresDB(object):
expiration = 0
self.add(hostmask, expiration)
except Exception, e:
log.error('Invalid line in ignores database: %r', line)
log.error('Invalid line in ignores database: %s',
utils.quoted(line))
fd.close()
def flush(self):

View File

@ -172,7 +172,8 @@ class IrcMsgQueue(object):
if msg in self.msgs and \
not conf.supybot.protocols.irc.queueDuplicateMessages():
s = str(msg).strip()
log.warning('Not adding message %r to queue, already added.', s)
log.warning('Not adding message %s to queue, already added.',
utils.quoted(s))
return False
else:
self.msgs.add(msg)

View File

@ -43,6 +43,7 @@ import time
import string
import supybot.conf as conf
import supybot.utils as utils
import supybot.ircutils as ircutils
###
@ -197,13 +198,14 @@ class IrcMsg(object):
def __repr__(self):
if self._repr is not None:
return self._repr
self._repr = 'IrcMsg(prefix=%r, command=%r, args=%r)' % \
(self.prefix, self.command, self.args)
self._repr = 'IrcMsg(prefix=%s, command=%s, args=%r)' % \
(utils.quoted(self.prefix), utils.quoted(self.command),
self.args)
return self._repr
def __reduce__(self):
return (self.__class__, (str(self),))
def tag(self, tag, value=True):
self.tags[tag] = value

View File

@ -100,7 +100,7 @@ def toLower(s, casemapping=None):
elif casemapping == 'ascii': # freenode
return s.lower()
else:
raise ValueError, 'Invalid casemapping: %r' % casemapping
raise ValueError, 'Invalid casemapping: %s' % utils.quoted(casemapping)
def strEqual(nick1, nick2):
"""Returns True if nick1 == nick2 according to IRC case rules."""
@ -360,7 +360,7 @@ class FormatContext(object):
# Should we individually end formatters?
s += '\x0f'
return s
class FormatParser(object):
def __init__(self, s):
self.fd = sio(s)
@ -427,7 +427,7 @@ def wrap(s, length):
context = FormatParser(chunk).parse()
processed.append(context.end(chunk))
return processed
def isValidArgument(s):
"""Returns whether s is strictly a valid argument for an IRC message."""
return '\r' not in s and '\n' not in s and '\x00' not in s
@ -437,7 +437,7 @@ def safeArgument(s):
if isinstance(s, unicode):
s = s.encode('utf-8')
elif not isinstance(s, basestring):
debug('Got a non-string in safeArgument: %r', s)
debug('Got a non-string in safeArgument: %s', utils.quoted(s))
s = str(s)
if isValidArgument(s):
return s
@ -504,7 +504,7 @@ class IrcSet(utils.NormalizingSet):
"""A sets.Set using IrcStrings instead of regular strings."""
def normalize(self, s):
return IrcString(s)
def __reduce__(self):
return (self.__class__, (list(self),))
@ -548,7 +548,7 @@ class FloodQueue(object):
return q
else:
return None
def enqueue(self, msg, what=None):
if what is None:
what = msg
@ -571,7 +571,7 @@ class FloodQueue(object):
if elt == what:
return True
return False
mircColors = IrcDict({
'white': '0',

View File

@ -88,7 +88,8 @@ class Logger(logging.Logger):
eId = hex(hash(eStrId) & 0xFFFFF)
logging.Logger.exception(self, *args)
if hasattr(e, '__revision__') and e.__revision__:
self.error('Exception __revision__: %r', e.__revision__)
self.error('Exception __revision__: %s',
utils.quoted(e.__revision__))
self.error('Exception id: %s', eId)
# The traceback should be sufficient if we want it.
# self.error('Exception string: %s', eStrId)
@ -290,7 +291,7 @@ registry.exception = exception
def stat(*args):
level = conf.supybot.log.statistics()
_logger.log(level, *args)
setLevel = _logger.setLevel
atexit.register(logging.shutdown)

View File

@ -507,10 +507,10 @@ def safeEval(s, namespace={'True': True, 'False': False, 'None': None}):
if node.__class__ is compiler.ast.Module:
return node.doc
else:
raise ValueError, 'Unsafe string: %r' % s
raise ValueError, 'Unsafe string: %s' % quoted(s)
node = nodes[0]
if node.__class__ is not compiler.ast.Discard:
raise ValueError, 'Invalid expression: %r' % s
raise ValueError, 'Invalid expression: %s' % quoted(s)
node = node.getChildNodes()[0]
def checkNode(node):
if node.__class__ is compiler.ast.Const:
@ -529,7 +529,7 @@ def safeEval(s, namespace={'True': True, 'False': False, 'None': None}):
if checkNode(node):
return eval(s, namespace, namespace)
else:
raise ValueError, 'Unsafe string: %r' % s
raise ValueError, 'Unsafe string: %s' % quoted(s)
def exnToString(e):
"""Turns a simple exception instance into a string (better than str(e))"""
@ -726,7 +726,7 @@ class AtomicFile(file):
def __init__(self, filename, mode='w', allowEmptyOverwrite=True,
makeBackupIfSmaller=True, tmpDir=None, backupDir=None):
if mode not in ('w', 'wb'):
raise ValueError, 'Invalid mode: %r' % mode
raise ValueError, 'Invalid mode: %s' % quoted(mode)
self.rolledback = False
self.allowEmptyOverwrite = allowEmptyOverwrite
self.makeBackupIfSmaller = makeBackupIfSmaller
@ -826,12 +826,12 @@ def toBool(s):
elif s in ('false', 'off', 'disable', 'disabled'):
return False
else:
raise ValueError, 'Invalid string for toBool: %r' % s
raise ValueError, 'Invalid string for toBool: %s' % quoted(s)
def mapinto(f, L):
for (i, x) in enumerate(L):
L[i] = f(x)
if __name__ == '__main__':
import doctest
doctest.testmod(sys.modules['__main__'])

View File

@ -33,7 +33,7 @@ import supybot.conf as conf
import supybot.ircdb as ircdb
import supybot.ircmsgs as ircmsgs
class ChannelTestCase(ChannelPluginTestCase, PluginDocumentation):
class ChannelTestCase(ChannelPluginTestCase):
plugins = ('Channel', 'User')
def testLobotomies(self):
self.assertRegexp('lobotomies', 'not.*any')

View File

@ -32,29 +32,29 @@ import time
from testsupport import *
class DebianTestCase(PluginTestCase, PluginDocumentation):
class DebianTestCase(PluginTestCase):
plugins = ('Debian',)
timeout = 100
cleanDataDir = False
fileDownloaded = False
if network:
def setup(self, nick='test'):
plugintestcase.setup(self)
def setUp(self, nick='test'):
PluginTestCase.setUp(self)
try:
datadir = conf.supybot.directories.data()
if os.path.exists(os.path.join(datadir,
'contents-i386.gz')):
'Contents-i386.gz')):
pass
else:
print
print "downloading files, this may take awhile"
filename = os.path.join(datadir, 'contents-i386.gz')
print "Downloading files, this may take awhile"
filename = os.path.join(datadir, 'Contents-i386.gz')
while not os.path.exists(filename):
time.sleep(1)
print "download complete"
print "starting test ..."
self.filedownloaded = true
print "Download complete"
print "Starting test ..."
self.fileDownloaded = True
except KeyboardInterrupt:
pass

View File

@ -88,6 +88,7 @@ class CommandsTestCase(SupyTestCase):
def testAny(self):
self.assertState([any('int')], ['1', '2', '3'], [[1, 2, 3]])
self.assertState([None, any('int')], ['1', '2', '3'], ['1', [2, 3]])
self.assertState([any('int')], [], [[]])
## def testAny(self):
## self.assertState([None, any('int'), None],
@ -104,6 +105,12 @@ class CommandsTestCase(SupyTestCase):
self.assertState(spec, ['#foo', '+s'], ['#foo', '+s'])
self.assertState(spec, ['+s'], ['#foo', '+s'], target='#foo')
def testGlob(self):
spec = ['glob']
self.assertState(spec, ['foo'], ['*foo*'])
self.assertState(spec, ['?foo'], ['?foo'])
self.assertState(spec, ['foo*'], ['foo*'])
def testGetId(self):
spec = ['id']
self.assertState(spec, ['#12'], [12])