Converted Random to wrap. Added a long converter to assist this.

This commit is contained in:
James Vega 2004-11-28 02:23:59 +00:00
parent d31b672634
commit 7eed44eef7
4 changed files with 48 additions and 60 deletions

View File

@ -38,9 +38,9 @@ import random
import supybot.conf as conf
import supybot.utils as utils
from supybot.commands import *
import supybot.ircmsgs as ircmsgs
import supybot.ircutils as ircutils
import supybot.privmsgs as privmsgs
import supybot.registry as registry
import supybot.callbacks as callbacks
@ -65,7 +65,7 @@ class Seed(registry.Integer):
def serialize(self):
# We do this so if it's 0, it doesn't store a real time.
return str(self.value)
conf.registerPlugin('Random')
conf.registerGlobalValue(conf.supybot.plugins.Random, 'seed', Seed(0, """
Sets the seed of the random number generator. The seed must be a valid
@ -84,78 +84,53 @@ class Random(callbacks.Privmsg):
generator.
"""
irc.reply(str(self.rng.random()))
random = wrap(random)
def seed(self, irc, msg, args):
def seed(self, irc, msg, args, seed):
"""<seed>
Sets the seed of the random number generator. <seed> must be an int
or a long.
"""
seed = privmsgs.getArgs(args)
try:
seed = long(seed)
except ValueError:
# It wasn't a valid long!
irc.errorInvalid('number', seed)
return
self.rng.seed(seed)
irc.replySuccess()
seed = wrap(seed, ['long'])
def range(self, irc, msg, args):
def range(self, irc, msg, args, start, end):
"""<start> <end>
Returns a number between <start> and <end>, inclusive (i.e., the number
can be either of the endpoints.
"""
(start, end) = privmsgs.getArgs(args, required=2)
try:
end = int(end)
start = int(start)
except ValueError:
irc.error('<start> and <end> must both be integers.')
return
# .randrange() doesn't include the endpoint, so we use end+1.
irc.reply(str(self.rng.randrange(start, end+1)))
range = wrap(range, ['int', 'int'])
def sample(self, irc, msg, args):
def sample(self, irc, msg, args, n, items):
"""<number of items> [<text> ...]
Returns a sample of the <number of items> taken from the remaining
arguments. Obviously <number of items> must be less than the number
of arguments given.
"""
try:
n = args.pop(0)
n = int(n)
except IndexError: # raised by .pop(0)
raise callbacks.ArgumentError
except ValueError:
irc.errorInvalid('number', n)
return
if n > len(args):
if n > len(items):
irc.error('<number of items> must be less than the number '
'of arguments.')
return
sample = self.rng.sample(args, n)
sample = self.rng.sample(items, n)
sample.sort()
irc.reply(utils.commaAndify(sample))
sample = wrap(sample, ['int', many('something')])
def diceroll(self, irc, msg, args):
def diceroll(self, irc, msg, args, n):
"""[<number of sides>]
Rolls a die with <number of sides> sides. The default number of
sides is 6.
"""
try:
n = privmsgs.getArgs(args, required=0, optional=1)
if not n:
n = 6
n = int(n)
except ValueError:
irc.error('Dice have integer numbers of sides. Use one.')
return
s = 'rolls a %s' % self.rng.randrange(1, n)
irc.reply(s, action=True)
diceroll = wrap(diceroll, [additional(('int', 'number of sides'), 6)])
Class = Random

View File

@ -147,7 +147,11 @@ def urlSnarfer(f):
###
# This is just so we can centralize this, since it may change.
def _int(s):
def _int(s, Long=False):
if not Long:
Type = int
else:
Type = long
base = 10
if s.startswith('0x'):
base = 16
@ -159,59 +163,62 @@ def _int(s):
base = 8
s = s[1:]
try:
return int(s, base)
return Type(s, base)
except ValueError:
if base == 10:
return int(float(s))
return Type(float(s))
else:
raise
def getInt(irc, msg, args, state, type='integer', p=None):
def getInt(irc, msg, args, state, Type='integer', p=None, Long=False):
try:
i = _int(args[0])
i = _int(args[0], Long)
if p is not None:
if not p(i):
irc.errorInvalid(type, args[0])
irc.errorInvalid(Type, args[0])
state.args.append(i)
del args[0]
except ValueError:
irc.errorInvalid(type, args[0])
irc.errorInvalid(Type, args[0])
def getNonInt(irc, msg, args, state, type='non-integer value'):
def getNonInt(irc, msg, args, state, Type='non-integer value'):
try:
i = _int(args[0])
irc.errorInvalid(type, args[0])
irc.errorInvalid(Type, args[0])
except ValueError:
state.args.append(args.pop(0))
def getFloat(irc, msg, args, state, type='floating point number'):
def getLong(irc, msg, args, state, Type='long number'):
getInt(irc, msg, args, state, Type, Long=True)
def getFloat(irc, msg, args, state, Type='floating point number'):
try:
state.args.append(float(args[0]))
del args[0]
except ValueError:
irc.errorInvalid(type, args[0])
irc.errorInvalid(Type, args[0])
def getPositiveInt(irc, msg, args, state, *L):
getInt(irc, msg, args, state,
p=lambda i: i>0, type='positive integer', *L)
p=lambda i: i>0, Type='positive integer', *L)
def getNonNegativeInt(irc, msg, args, state, *L):
getInt(irc, msg, args, state,
p=lambda i: i>=0, type='non-negative integer', *L)
p=lambda i: i>=0, Type='non-negative integer', *L)
def getIndex(irc, msg, args, state):
getInt(irc, msg, args, state, type='index')
getInt(irc, msg, args, state, Type='index')
if state.args[-1] > 0:
state.args[-1] -= 1
def getId(irc, msg, args, state, kind=None):
type = 'id'
Type = 'id'
if kind is not None and not kind.endswith('id'):
type = kind + ' id'
Type = kind + ' id'
original = args[0]
try:
args[0] = args[0].lstrip('#')
getInt(irc, msg, args, state, type=type)
getInt(irc, msg, args, state, Type=Type)
except Exception, e:
args[0] = original
raise
@ -527,6 +534,7 @@ wrappers = ircutils.IrcDict({
'url': getUrl,
'httpUrl': getHttpUrl,
'float': getFloat,
'long': getLong,
'nonInt': getNonInt,
'positiveInt': getPositiveInt,
'nonNegativeInt': getNonNegativeInt,
@ -725,7 +733,7 @@ class commalist(context):
except Exception, e:
args[:] = original
raise
class getopts(context):
"""The empty string indicates that no argument is taken; None indicates
that there is no converter for the argument."""
@ -761,7 +769,7 @@ class getopts(context):
state.args.append(getopts)
args[:] = rest
log.debug('args after %r: %r', self, args)
###
# This is our state object, passed to converters along with irc, msg, and args.
###
@ -785,7 +793,7 @@ class State(object):
return '%s(args=%r, kwargs=%r, channel=%r)' % (self.__class__.__name__,
self.args, self.kwargs,
self.channel)
###
# This is a compiled Spec object.

View File

@ -40,11 +40,11 @@ class RandomTestCase(PluginTestCase):
def testRange(self):
for x in range(iters):
self.assertRegexp('range 1 2', '^(1|2)$')
def testDiceroll(self):
for x in range(iters):
self.assertActionRegexp('diceroll', '^rolls a (1|2|3|4|5|6)$')
def testSample(self):
for x in range(iters):
self.assertRegexp('sample 1 a b c', '^(a|b|c)$')

View File

@ -54,6 +54,11 @@ class CommandsTestCase(SupyTestCase):
self.assertState(['int'], ['1'], [1])
self.assertState(['int', 'int', 'int'], ['1', '2', '3'], [1, 2, 3])
def testSpecLong(self):
self.assertState(['long'], ['1'], [1L])
self.assertState(['long', 'long', 'long'], ['1', '2', '3'],
[1L, 2L, 3L])
def testRestHandling(self):
self.assertState([rest(None)], ['foo', 'bar', 'baz'], ['foo bar baz'])