* LOTS of updates to the MoobotFactoids test suite, parts of which aren't ready

yet, but the test targets should be pretty static from here on out, except
  adding new tests.
* Fixed up lock and coded unlock in MoobotFactoids (actually, factored the
  common code out into one helper function that each call).
* Added the changeFactoids (=~) portion.
* Changed the table structure again (should be the last time).  Locked_by was
  redundant if we're only going to let factoid creators lock/unlock.  Removed
  it.
This commit is contained in:
Daniel DiPaolo 2003-10-16 02:03:35 +00:00
parent f567f36e4c
commit ddfd7e10e1
2 changed files with 187 additions and 41 deletions

View File

@ -125,7 +125,7 @@ def pick(L, recursed=False):
class MoobotFactoids(callbacks.PrivmsgCommandAndRegexp): class MoobotFactoids(callbacks.PrivmsgCommandAndRegexp):
priority = 1000 priority = 1000
addressedRegexps = sets.Set(['addFactoids']) addressedRegexps = sets.Set(['addFactoids', 'changeFactoids'])
def __init__(self): def __init__(self):
callbacks.PrivmsgCommandAndRegexp.__init__(self) callbacks.PrivmsgCommandAndRegexp.__init__(self)
self.makeDB(dbfilename) self.makeDB(dbfilename)
@ -149,7 +149,6 @@ class MoobotFactoids(callbacks.PrivmsgCommandAndRegexp):
created_at TIMESTAMP, created_at TIMESTAMP,
modified_by INTEGER, modified_by INTEGER,
modified_at TIMESTAMP, modified_at TIMESTAMP,
locked_by INTEGER,
locked_at TIMESTAMP, locked_at TIMESTAMP,
last_requested_by TEXT, last_requested_by TEXT,
last_requested_at TIMESTAMP, last_requested_at TIMESTAMP,
@ -237,12 +236,47 @@ class MoobotFactoids(callbacks.PrivmsgCommandAndRegexp):
return return
# Otherwise, # Otherwise,
cursor.execute("""INSERT INTO factoids VALUES cursor.execute("""INSERT INTO factoids VALUES
(%s, %s, %s, NULL, NULL, NULL, NULL, NULL, NULL, (%s, %s, %s, NULL, NULL, NULL, NULL, NULL,
%s, 0)""", %s, 0)""",
key, id, int(time.time()), fact) key, id, int(time.time()), fact)
self.db.commit() self.db.commit()
irc.reply(msg, conf.replySuccess) irc.reply(msg, conf.replySuccess)
def changeFactoids(self, irc, msg, match):
r"(\S+)\s+=~\s+(\S+)"
# Must be registered!
try:
id = ircdb.users.getUserId(msg.prefix)
except KeyError:
irc.error(msg, conf.replyNotRegistered)
return
key, regexp = match.groups()
cursor = self.db.cursor()
# Check and make sure it's in the DB
cursor.execute("""SELECT locked_at, fact FROM factoids
WHERE key = %s""", key)
if cursor.rowcount == 0:
irc.error(msg, "Factoid '%s' not found." % key)
return
# No dice if it's locked, no matter who it is
(locked_at, fact) = cursor.fetchone()
if locked_at is not None:
irc.error(msg, "Factoid '%s' is locked." % key)
return
# It's fair game if we get to here
try:
r = utils.perlReToReplacer(regexp)
except ValueError, e:
irc.error(msg, "Invalid regexp: %s" % regexp)
return
new_fact = r(fact)
cursor.execute("""UPDATE factoids
SET fact = %s, modified_by = %s,
modified_at = %s WHERE key = %s""",
new_fact, id, int(time.time()), key)
self.db.commit()
irc.reply(msg, conf.replySuccess)
def literal(self, irc, msg, args): def literal(self, irc, msg, args):
"""<factoid key> """<factoid key>
@ -271,14 +305,13 @@ class MoobotFactoids(callbacks.PrivmsgCommandAndRegexp):
cursor = self.db.cursor() cursor = self.db.cursor()
cursor.execute("""SELECT created_by, created_at, modified_by, cursor.execute("""SELECT created_by, created_at, modified_by,
modified_at, last_requested_by, last_requested_at, modified_at, last_requested_by, last_requested_at,
requested_count, locked_by, locked_at FROM requested_count, locked_at FROM
factoids WHERE key = %s""", key) factoids WHERE key = %s""", key)
if cursor.rowcount == 0: if cursor.rowcount == 0:
irc.error(msg, "No such factoid: %s" % key) irc.error(msg, "No such factoid: %s" % key)
return return
(created_by, created_at, modified_by, modified_at, last_requested_by, (created_by, created_at, modified_by, modified_at, last_requested_by,
last_requested_at, requested_count, locked_by, locked_at) = \ last_requested_at, requested_count, locked_at) = cursor.fetchone()
cursor.fetchone()
# First, creation info. # First, creation info.
# Map the integer created_by to the username # Map the integer created_by to the username
creat_by = ircdb.users.getUser(created_by).name creat_by = ircdb.users.getUser(created_by).name
@ -297,45 +330,72 @@ class MoobotFactoids(callbacks.PrivmsgCommandAndRegexp):
last_at = time.strftime(conf.humanTimestampFormat, last_at = time.strftime(conf.humanTimestampFormat,
time.localtime(int(last_requested_at))) time.localtime(int(last_requested_at)))
req_count = requested_count req_count = requested_count
s += " Last requested by %s on %s, requested %s times." % \ times_str = utils.nItems(requested_count, 'time')
(last_by, last_at, req_count) s += " Last requested by %s on %s, requested %s." % \
(last_by, last_at, times_str)
# Last, locked info # Last, locked info
if locked_by is not None: if locked_at is not None:
lock_by = ircdb.users.getUser(locked_by).name
lock_at = time.strftime(conf.humanTimestampFormat, lock_at = time.strftime(conf.humanTimestampFormat,
time.localtime(int(locked_at))) time.localtime(int(locked_at)))
s += " Locked by %s on %s." % (lock_by, lock_at) s += " Locked on %s." % lock_at
irc.reply(msg, s) irc.reply(msg, s)
def _lock(self, irc, msg, args, lock=True):
try:
id = ircdb.users.getUserId(msg.prefix)
except KeyError:
irc.error(msg, conf.replyNotRegistered)
return
key = privmsgs.getArgs(args, needed=1)
cursor = self.db.cursor()
cursor.execute("""SELECT created_by, locked_at FROM factoids
WHERE key = %s""", key)
if cursor.rowcount == 0:
irc.error(msg, "No such factoid: %s" % key)
return
(created_by, locked_at) = cursor.fetchone()
# Don't perform redundant operations
if lock:
if locked_at is not None:
irc.error(msg, "Factoid '%s' is already locked." % key)
return
else:
if locked_at is None:
irc.error(msg, "Factoid '%s' is not locked." % key)
return
# Can only lock/unlock own factoids
if created_by != id:
s = "unlock"
if lock:
s = "lock"
irc.error(msg, "Cannot %s someone else's factoid." % s)
return
# Okay, we're done, ready to lock/unlock
if lock:
locked_at = int(time.time())
else:
locked_at = None
cursor.execute("""UPDATE factoids SET locked_at = %s
WHERE key = %s""", locked_at, key)
self.db.commit()
irc.reply(msg, conf.replySuccess)
def lock(self, irc, msg, args): def lock(self, irc, msg, args):
"""<factoid key> """<factoid key>
Locks the factoid with the given factoid key. Requires that the user Locks the factoid with the given factoid key. Requires that the user
be registered and have created the factoid originally. be registered and have created the factoid originally.
""" """
try: self._lock(irc, msg, args, True)
id = ircdb.users.getUserId(msg.prefix)
except KeyError: def unlock(self, irc, msg, args):
irc.error(msg, conf.replyNotRegistered) """<factoid key>
return
key = privmsgs.getArgs(args, needed=1) Unlocks the factoid with the given factoid key. Requires that the
cursor = self.db.cursor() user be registered and have locked the factoid.
cursor.execute("""SELECT created_by, locked_by FROM factoids """
WHERE key = %s""", key) self._lock(irc, msg, args, False)
if cursor.rowcount == 0:
irc.error(msg, "No such factoid: %s" % key)
return
(created_by, locked_by) = cursor.fetchone()
if locked_by is not None:
irc.error(msg, "Factoid '%s' is already locked." % key)
return
if created_by != id:
irc.error(msg, "Cannot lock someone else's factoid." % key)
return
cursor.execute("""UPDATE factoids SET locked_by = %s, locked_at = %s
WHERE key = %s""", id, int(time.time()), key)
self.db.commit()
irc.reply(msg, conf.replySuccess)
Class = MoobotFactoids Class = MoobotFactoids

View File

@ -44,24 +44,110 @@ if sqlite is not None:
# Create a valid user to use # Create a valid user to use
self.prefix = 'foo!bar@baz' self.prefix = 'foo!bar@baz'
self.assertNotError('register tester moo') self.assertNotError('register tester moo')
def testLiteral(self): def testLiteral(self):
self.assertError('literal moo') # no factoids yet self.assertError('literal moo') # no factoids yet
self.assertNotError('moo is <reply>foo') self.assertNotError('moo is <reply>foo')
self.assertRegexp('literal moo', '<reply>foo') self.assertResponse('literal moo', '<reply>foo')
self.assertNotError('moo2 is moo!') self.assertNotError('moo2 is moo!')
self.assertRegexp('literal moo2', 'moo!') self.assertResponse('literal moo2', 'moo!')
self.assertNotError('moo3 is <action>foo') self.assertNotError('moo3 is <action>foo')
self.assertRegexp('literal moo3', '<action>foo') self.assertResponse('literal moo3', '<action>foo')
def testGetFactoid(self): def testGetFactoid(self):
self.assertNotError('moo is <reply>foo') self.assertNotError('moo is <reply>foo')
self.assertRegexp('moo', 'foo') self.assertResponse('moo', 'foo')
self.assertNotError('moo2 is moo!') self.assertNotError('moo2 is moo!')
self.assertRegexp('moo2', 'moo2 is moo!') self.assertResponse('moo2', 'moo2 is moo!')
self.assertNotError('moo3 is <action>foo') self.assertNotError('moo3 is <action>foo')
self.assertAction('moo3', 'foo') self.assertAction('moo3', 'foo')
# Test and make sure it's parsing
self.assertNotError('moo4 is <reply>(1|2|3)')
self.assertRegexp('moo4', '^(1|2|3)$')
def testFactinfo(self):
self.assertNotError('moo is <reply>foo')
self.assertRegexp('factinfo moo', '^moo: Created by tester on.*$')
self.assertNotError('moo')
self.assertRegexp('factinfo moo', '^moo: Created by tester on'
'.*?\. Last requested by foo!bar@baz on .*?, '
'requested 1 time.$')
self.assertNotError('moo')
self.assertRegexp('factinfo moo', '^moo: Created by tester on'
'.*?\. Last requested by foo!bar@baz on .*?, '
'requested 2 times.$')
self.assertNotError('moo =~ s/foo/bar/')
self.assertRegexp('factinfo moo', '^moo: Created by tester on'
'.*?\. Last modified by tester on .*?\. '
'Last requested by foo!bar@baz on .*?, '
'requested 2 times.$')
self.assertNotError('lock moo')
self.assertRegexp('factinfo moo', '^moo: Created by tester on'
'.*?\. Last modified by tester on .*?\. '
'Last requested by foo!bar@baz on .*?, '
'requested 2 times. Locked on .*\.$')
self.assertNotError('unlock moo')
self.assertRegexp('factinfo moo', '^moo: Created by tester on'
'.*?\. Last modified by tester on .*?\. '
'Last requested by foo!bar@baz on .*?, '
'requested 2 times.$')
def testLockUnlock(self):
self.assertNotError('moo is <reply>moo')
self.assertNotError('lock moo')
self.assertRegexp('factinfo moo', '^moo: Created by tester on'
'.*?\. Locked on .*?\.')
# switch user
self.prefix = 'moo!moo@moo'
self.assertNotError('register nottester moo')
self.assertError('unlock moo')
self.assertRegexp('factinfo moo', '^moo: Created by tester on'
'.*?\. Locked on .*?\.')
# switch back
self.prefix = 'foo!bar@baz'
self.assertNotError('identify tester moo')
self.assertNotError('unlock moo')
self.assertRegexp('factinfo moo', '^moo: Created by tester on'
'.*?\.')
def testChangeFactoid(self):
self.assertNotError('moo is <reply>moo')
self.assertNotError('moo =~ s/moo/moos/')
self.assertResponse('moo', 'moos')
self.assertNotError('moo =~ s/reply/action/')
self.assertAction('moo', 'moos')
self.assertNotError('moo =~ s/moos/(moos|woofs)/')
self.assertActionRegexp('moo', '^(moos|woofs)$')
self.assertError('moo =~ s/moo/')
def testListkeys(self):
self.assertResponse('listkeys *', 'No keys found matching \'*\'.')
self.assertNotError('moo is <reply>moo')
self.assertResponse('listkeys moo', 'Key search for \'moo\' '
'(1 found): moo')
self.assertResponse('listkeys foo', 'No keys found matching '
'\'foo\'.')
# Throw in a bunch more
for i in range(10):
self.assertNotError('moo%s is <reply>moo' % i)
self.assertRegexp('listkeys moo', '^Key search for \'moo\' '
'(11 found): (moo\d*, )+ and moo9$')
self.assertRegexp('listkeys *', '^Key search for \'*\' '
'(12 found): foo, (moo\d*, )+ and moo9$')
def testListvalues(self):
self.assertNotError('moo is <reply>moo')
self.assertResponse('listvalues moo', 'Value search for \'moo\' '
'(1 found): moo')
def testListauth(self):
self.assertNotError('moo is <reply>moo')
self.assertResponse('listauth tester', 'Author search for tester '
'(1 found): moo')
class DunnoTestCase(PluginTestCase, PluginDocumentation):
plugins = ('MiscCommands', 'MoobotFactoids', 'UserCommands')
def testDunno(self):
self.assertNotError('apfasdfjoia') # Should say a dunno, no error
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: # vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78: