update Karma plugin and test code to use sqlite3.

This involved also updating src/conf.py to look for sqlite3 and add it to supybot.conf.databases list,
since karma uses the plugins.DB() constructor for its database, which checks the available databases list.
This commit is contained in:
Daniel Folkinshteyn 2010-04-16 16:06:00 -04:00
parent 4890e2e80d
commit b5058cc5c2
3 changed files with 198 additions and 191 deletions

View File

@ -39,6 +39,11 @@ import supybot.ircmsgs as ircmsgs
import supybot.ircutils as ircutils
import supybot.callbacks as callbacks
try:
import sqlite3
except ImportError:
from pysqlite2 import dbapi2 as sqlite3 # for python2.4
class SqliteKarmaDB(object):
def __init__(self, filename):
self.dbs = ircutils.IrcDict()
@ -49,19 +54,16 @@ class SqliteKarmaDB(object):
db.close()
def _getDb(self, channel):
try:
import sqlite
except ImportError:
raise callbacks.Error, 'You need to have PySQLite installed to ' \
'use Karma. Download it at ' \
'<http://code.google.com/p/pysqlite/>'
filename = plugins.makeChannelFilename(self.filename, channel)
if filename in self.dbs:
return self.dbs[filename]
if os.path.exists(filename):
self.dbs[filename] = sqlite.connect(filename)
return self.dbs[filename]
db = sqlite.connect(filename)
db = sqlite3.connect(filename)
db.text_factory = str
self.dbs[filename] = db
return db
db = sqlite3.connect(filename)
db.text_factory = str
self.dbs[filename] = db
cursor = db.cursor()
cursor.execute("""CREATE TABLE karma (
@ -82,20 +84,21 @@ class SqliteKarmaDB(object):
thing = thing.lower()
cursor = db.cursor()
cursor.execute("""SELECT added, subtracted FROM karma
WHERE normalized=%s""", thing)
if cursor.rowcount == 0:
WHERE normalized=?""", (thing,))
results = cursor.fetchall()
if len(results) == 0:
return None
else:
return map(int, cursor.fetchone())
return map(int, results[0])
def gets(self, channel, things):
db = self._getDb(channel)
cursor = db.cursor()
normalizedThings = dict(zip(map(lambda s: s.lower(), things), things))
criteria = ' OR '.join(['normalized=%s'] * len(normalizedThings))
criteria = ' OR '.join(['normalized=?'] * len(normalizedThings))
sql = """SELECT name, added-subtracted FROM karma
WHERE %s ORDER BY added-subtracted DESC""" % criteria
cursor.execute(sql, *normalizedThings)
cursor.execute(sql, normalizedThings.keys())
L = [(name, int(karma)) for (name, karma) in cursor.fetchall()]
for (name, _) in L:
del normalizedThings[name.lower()]
@ -107,26 +110,27 @@ class SqliteKarmaDB(object):
db = self._getDb(channel)
cursor = db.cursor()
cursor.execute("""SELECT name, added-subtracted FROM karma
ORDER BY added-subtracted DESC LIMIT %s""", limit)
ORDER BY added-subtracted DESC LIMIT ?""", (limit,))
return [(t[0], int(t[1])) for t in cursor.fetchall()]
def bottom(self, channel, limit):
db = self._getDb(channel)
cursor = db.cursor()
cursor.execute("""SELECT name, added-subtracted FROM karma
ORDER BY added-subtracted ASC LIMIT %s""", limit)
ORDER BY added-subtracted ASC LIMIT ?""", (limit,))
return [(t[0], int(t[1])) for t in cursor.fetchall()]
def rank(self, channel, thing):
db = self._getDb(channel)
cursor = db.cursor()
cursor.execute("""SELECT added-subtracted FROM karma
WHERE name=%s""", thing)
if cursor.rowcount == 0:
WHERE name=?""", (thing,))
results = cursor.fetchall()
if len(results) == 0:
return None
karma = int(cursor.fetchone()[0])
karma = int(results[0][0])
cursor.execute("""SELECT COUNT(*) FROM karma
WHERE added-subtracted > %s""", karma)
WHERE added-subtracted > ?""", (karma,))
rank = int(cursor.fetchone()[0])
return rank+1
@ -140,20 +144,20 @@ class SqliteKarmaDB(object):
db = self._getDb(channel)
cursor = db.cursor()
normalized = name.lower()
cursor.execute("""INSERT INTO karma VALUES (NULL, %s, %s, 0, 0)""",
name, normalized)
cursor.execute("""INSERT INTO karma VALUES (NULL, ?, ?, 0, 0)""",
(name, normalized,))
cursor.execute("""UPDATE karma SET added=added+1
WHERE normalized=%s""", normalized)
WHERE normalized=?""", (normalized,))
db.commit()
def decrement(self, channel, name):
db = self._getDb(channel)
cursor = db.cursor()
normalized = name.lower()
cursor.execute("""INSERT INTO karma VALUES (NULL, %s, %s, 0, 0)""",
name, normalized)
cursor.execute("""INSERT INTO karma VALUES (NULL, ?, ?, 0, 0)""",
(name, normalized,))
cursor.execute("""UPDATE karma SET subtracted=subtracted+1
WHERE normalized=%s""", normalized)
WHERE normalized=?""", (normalized,))
db.commit()
def most(self, channel, kind, limit):
@ -177,7 +181,7 @@ class SqliteKarmaDB(object):
cursor = db.cursor()
normalized = name.lower()
cursor.execute("""UPDATE karma SET subtracted=0, added=0
WHERE normalized=%s""", normalized)
WHERE normalized=?""", (normalized,))
db.commit()
def dump(self, channel, filename):
@ -201,13 +205,13 @@ class SqliteKarmaDB(object):
for (name, added, subtracted) in reader:
normalized = name.lower()
cursor.execute("""INSERT INTO karma
VALUES (NULL, %s, %s, %s, %s)""",
name, normalized, added, subtracted)
VALUES (NULL, ?, ?, ?, ?)""",
(name, normalized, added, subtracted,))
db.commit()
fd.close()
KarmaDB = plugins.DB('Karma',
{'sqlite': SqliteKarmaDB})
{'sqlite3': SqliteKarmaDB})
class Karma(callbacks.Plugin):
callBefore = ('Factoids', 'MoobotFactoids', 'Infobot')

View File

@ -30,182 +30,181 @@
from supybot.test import *
try:
import sqlite
import sqlite3
except ImportError:
sqlite = None
from pysqlite2 import dbapi2 as sqlite3 # for python2.4
if sqlite is not None:
class KarmaTestCase(ChannelPluginTestCase):
plugins = ('Karma',)
def testKarma(self):
self.assertError('karma')
self.assertRegexp('karma foobar', 'neutral karma')
try:
conf.replyWhenNotCommand = True
self.assertNoResponse('foobar++', 2)
finally:
conf.replyWhenNotCommand = False
self.assertRegexp('karma foobar', 'increased 1.*total.*1')
self.assertRegexp('karma FOOBAR', 'increased 1.*total.*1')
self.assertNoResponse('foobar--', 2)
self.assertRegexp('karma foobar', 'decreased 1.*total.*0')
self.assertRegexp('karma FOOBAR', 'decreased 1.*total.*0')
self.assertNoResponse('FOO++', 2)
self.assertNoResponse('BAR--', 2)
self.assertRegexp('karma foo bar foobar', '.*foo.*foobar.*bar.*')
self.assertRegexp('karma FOO BAR FOOBAR', '.*foo.*foobar.*bar.*')
self.assertRegexp('karma FOO BAR FOOBAR',
'.*FOO.*foobar.*BAR.*', flags=0)
self.assertRegexp('karma foo bar foobar asdfjkl', 'asdfjkl')
# Test case-insensitive
self.assertNoResponse('MOO++', 2)
self.assertRegexp('karma moo',
'Karma for [\'"]moo[\'"].*increased 1.*total.*1')
self.assertRegexp('karma MoO',
'Karma for [\'"]MoO[\'"].*increased 1.*total.*1')
class KarmaTestCase(ChannelPluginTestCase):
plugins = ('Karma',)
def testKarma(self):
self.assertError('karma')
self.assertRegexp('karma foobar', 'neutral karma')
try:
conf.replyWhenNotCommand = True
self.assertNoResponse('foobar++', 2)
finally:
conf.replyWhenNotCommand = False
self.assertRegexp('karma foobar', 'increased 1.*total.*1')
self.assertRegexp('karma FOOBAR', 'increased 1.*total.*1')
self.assertNoResponse('foobar--', 2)
self.assertRegexp('karma foobar', 'decreased 1.*total.*0')
self.assertRegexp('karma FOOBAR', 'decreased 1.*total.*0')
self.assertNoResponse('FOO++', 2)
self.assertNoResponse('BAR--', 2)
self.assertRegexp('karma foo bar foobar', '.*foo.*foobar.*bar.*')
self.assertRegexp('karma FOO BAR FOOBAR', '.*foo.*foobar.*bar.*')
self.assertRegexp('karma FOO BAR FOOBAR',
'.*FOO.*foobar.*BAR.*', flags=0)
self.assertRegexp('karma foo bar foobar asdfjkl', 'asdfjkl')
# Test case-insensitive
self.assertNoResponse('MOO++', 2)
self.assertRegexp('karma moo',
'Karma for [\'"]moo[\'"].*increased 1.*total.*1')
self.assertRegexp('karma MoO',
'Karma for [\'"]MoO[\'"].*increased 1.*total.*1')
def testKarmaRankingDisplayConfigurable(self):
try:
orig = conf.supybot.plugins.Karma.response()
conf.supybot.plugins.Karma.response.setValue(True)
original = conf.supybot.plugins.Karma.rankingDisplay()
self.assertNotError('foo++')
self.assertNotError('foo++')
self.assertNotError('foo++')
self.assertNotError('foo++')
self.assertNotError('bar++')
self.assertNotError('bar++')
self.assertNotError('bar++')
self.assertNotError('baz++')
self.assertNotError('baz++')
self.assertNotError('quux++')
self.assertNotError('xuuq--')
self.assertNotError('zab--')
self.assertNotError('zab--')
self.assertNotError('rab--')
self.assertNotError('rab--')
self.assertNotError('rab--')
self.assertNotError('oof--')
self.assertNotError('oof--')
self.assertNotError('oof--')
self.assertNotError('oof--')
self.assertRegexp('karma', 'foo.*bar.*baz.*oof.*rab.*zab')
conf.supybot.plugins.Karma.rankingDisplay.setValue(4)
self.assertRegexp('karma', 'foo.*bar.*baz.*quux')
finally:
conf.supybot.plugins.Karma.response.setValue(orig)
conf.supybot.plugins.Karma.rankingDisplay.setValue(original)
def testKarmaRankingDisplayConfigurable(self):
try:
orig = conf.supybot.plugins.Karma.response()
conf.supybot.plugins.Karma.response.setValue(True)
original = conf.supybot.plugins.Karma.rankingDisplay()
self.assertNotError('foo++')
self.assertNotError('foo++')
self.assertNotError('foo++')
self.assertNotError('foo++')
self.assertNotError('bar++')
self.assertNotError('bar++')
self.assertNotError('bar++')
self.assertNotError('baz++')
self.assertNotError('baz++')
self.assertNotError('quux++')
self.assertNotError('xuuq--')
self.assertNotError('zab--')
self.assertNotError('zab--')
self.assertNotError('rab--')
self.assertNotError('rab--')
self.assertNotError('rab--')
self.assertNotError('oof--')
self.assertNotError('oof--')
self.assertNotError('oof--')
self.assertNotError('oof--')
self.assertRegexp('karma', 'foo.*bar.*baz.*oof.*rab.*zab')
conf.supybot.plugins.Karma.rankingDisplay.setValue(4)
self.assertRegexp('karma', 'foo.*bar.*baz.*quux')
finally:
conf.supybot.plugins.Karma.response.setValue(orig)
conf.supybot.plugins.Karma.rankingDisplay.setValue(original)
def testMost(self):
self.assertError('most increased')
self.assertError('most decreased')
self.assertError('most active')
self.assertHelp('most aldsfkj')
self.assertNoResponse('foo++', 1)
self.assertNoResponse('foo++', 1)
self.assertNoResponse('bar++', 1)
self.assertNoResponse('bar--', 1)
self.assertNoResponse('bar--', 1)
self.assertRegexp('karma most active', 'bar.*foo')
self.assertRegexp('karma most increased', 'foo.*bar')
self.assertRegexp('karma most decreased', 'bar.*foo')
self.assertNoResponse('foo--', 1)
self.assertNoResponse('foo--', 1)
self.assertNoResponse('foo--', 1)
self.assertNoResponse('foo--', 1)
self.assertRegexp('karma most active', 'foo.*bar')
self.assertRegexp('karma most increased', 'foo.*bar')
self.assertRegexp('karma most decreased', 'foo.*bar')
def testMost(self):
self.assertError('most increased')
self.assertError('most decreased')
self.assertError('most active')
self.assertHelp('most aldsfkj')
self.assertNoResponse('foo++', 1)
self.assertNoResponse('foo++', 1)
self.assertNoResponse('bar++', 1)
self.assertNoResponse('bar--', 1)
self.assertNoResponse('bar--', 1)
self.assertRegexp('karma most active', 'bar.*foo')
self.assertRegexp('karma most increased', 'foo.*bar')
self.assertRegexp('karma most decreased', 'bar.*foo')
self.assertNoResponse('foo--', 1)
self.assertNoResponse('foo--', 1)
self.assertNoResponse('foo--', 1)
self.assertNoResponse('foo--', 1)
self.assertRegexp('karma most active', 'foo.*bar')
self.assertRegexp('karma most increased', 'foo.*bar')
self.assertRegexp('karma most decreased', 'foo.*bar')
def testSimpleOutput(self):
try:
orig = conf.supybot.plugins.Karma.simpleOutput()
conf.supybot.plugins.Karma.simpleOutput.setValue(True)
self.assertNoResponse('foo++', 2)
self.assertResponse('karma foo', 'foo: 1')
self.assertNoResponse('bar--', 2)
self.assertResponse('karma bar', 'bar: -1')
finally:
conf.supybot.plugins.Karma.simpleOutput.setValue(orig)
def testSelfRating(self):
nick = self.nick
try:
orig = conf.supybot.plugins.Karma.allowSelfRating()
conf.supybot.plugins.Karma.allowSelfRating.setValue(False)
self.assertError('%s++' % nick)
self.assertResponse('karma %s' % nick,
'%s has neutral karma.' % nick)
conf.supybot.plugins.Karma.allowSelfRating.setValue(True)
self.assertNoResponse('%s++' % nick, 2)
self.assertRegexp('karma %s' % nick,
'Karma for [\'"]%s[\'"].*increased 1.*total.*1' % nick)
finally:
conf.supybot.plugins.Karma.allowSelfRating.setValue(orig)
def testKarmaOutputConfigurable(self):
def testSimpleOutput(self):
try:
orig = conf.supybot.plugins.Karma.simpleOutput()
conf.supybot.plugins.Karma.simpleOutput.setValue(True)
self.assertNoResponse('foo++', 2)
try:
orig = conf.supybot.plugins.Karma.response()
conf.supybot.plugins.Karma.response.setValue(True)
self.assertNotError('foo++')
finally:
conf.supybot.plugins.Karma.response.setValue(orig)
self.assertResponse('karma foo', 'foo: 1')
self.assertNoResponse('bar--', 2)
self.assertResponse('karma bar', 'bar: -1')
finally:
conf.supybot.plugins.Karma.simpleOutput.setValue(orig)
def testKarmaMostDisplayConfigurable(self):
self.assertNoResponse('foo++', 1)
self.assertNoResponse('foo++', 1)
self.assertNoResponse('bar++', 1)
self.assertNoResponse('bar--', 1)
self.assertNoResponse('bar--', 1)
self.assertNoResponse('foo--', 1)
self.assertNoResponse('foo--', 1)
self.assertNoResponse('foo--', 1)
self.assertNoResponse('foo--', 1)
try:
orig = conf.supybot.plugins.Karma.mostDisplay()
conf.supybot.plugins.Karma.mostDisplay.setValue(1)
self.assertRegexp('karma most active', '(?!bar)')
conf.supybot.plugins.Karma.mostDisplay.setValue(25)
self.assertRegexp('karma most active', 'bar')
finally:
conf.supybot.plugins.Karma.mostDisplay.setValue(orig)
def testSelfRating(self):
nick = self.nick
try:
orig = conf.supybot.plugins.Karma.allowSelfRating()
conf.supybot.plugins.Karma.allowSelfRating.setValue(False)
self.assertError('%s++' % nick)
self.assertResponse('karma %s' % nick,
'%s has neutral karma.' % nick)
conf.supybot.plugins.Karma.allowSelfRating.setValue(True)
self.assertNoResponse('%s++' % nick, 2)
self.assertRegexp('karma %s' % nick,
'Karma for [\'"]%s[\'"].*increased 1.*total.*1' % nick)
finally:
conf.supybot.plugins.Karma.allowSelfRating.setValue(orig)
def testKarmaOutputConfigurable(self):
self.assertNoResponse('foo++', 2)
try:
orig = conf.supybot.plugins.Karma.response()
conf.supybot.plugins.Karma.response.setValue(True)
self.assertNotError('foo++')
finally:
conf.supybot.plugins.Karma.response.setValue(orig)
def testKarmaMostDisplayConfigurable(self):
self.assertNoResponse('foo++', 1)
self.assertNoResponse('foo++', 1)
self.assertNoResponse('bar++', 1)
self.assertNoResponse('bar--', 1)
self.assertNoResponse('bar--', 1)
self.assertNoResponse('foo--', 1)
self.assertNoResponse('foo--', 1)
self.assertNoResponse('foo--', 1)
self.assertNoResponse('foo--', 1)
try:
orig = conf.supybot.plugins.Karma.mostDisplay()
conf.supybot.plugins.Karma.mostDisplay.setValue(1)
self.assertRegexp('karma most active', '(?!bar)')
conf.supybot.plugins.Karma.mostDisplay.setValue(25)
self.assertRegexp('karma most active', 'bar')
finally:
conf.supybot.plugins.Karma.mostDisplay.setValue(orig)
def testIncreaseKarmaWithNickNotCallingInvalidCommand(self):
self.assertSnarfNoResponse('%s: foo++' % self.irc.nick, 3)
def testIncreaseKarmaWithNickNotCallingInvalidCommand(self):
self.assertSnarfNoResponse('%s: foo++' % self.irc.nick, 3)
def testClear(self):
self.assertNoResponse('foo++', 1)
self.assertRegexp('karma foo', '1')
self.assertNotError('karma clear foo')
self.assertRegexp('karma foo', '0')
self.assertNotRegexp('karma foo', '1')
def testClear(self):
self.assertNoResponse('foo++', 1)
self.assertRegexp('karma foo', '1')
self.assertNotError('karma clear foo')
self.assertRegexp('karma foo', '0')
self.assertNotRegexp('karma foo', '1')
# def testNoKarmaDunno(self):
# self.assertNotError('load Infobot')
# self.assertNoResponse('foo++')
def testMultiWordKarma(self):
self.assertNoResponse('(foo bar)++', 1)
self.assertRegexp('karma "foo bar"', '1')
def testMultiWordKarma(self):
self.assertNoResponse('(foo bar)++', 1)
self.assertRegexp('karma "foo bar"', '1')
def testUnaddressedKarma(self):
karma = conf.supybot.plugins.Karma
resp = karma.response()
unaddressed = karma.allowUnaddressedKarma()
try:
karma.response.setValue(True)
karma.allowUnaddressedKarma.setValue(True)
for m in ('++', '--'):
self.assertRegexp('foo%s' % m, 'operation')
self.assertSnarfRegexp('foo%s' % m, 'operation')
#self.assertNoResponse('foo bar%s' % m)
#self.assertSnarfNoResponse('foo bar%s' % m)
self.assertRegexp('(foo bar)%s' % m, 'operation')
self.assertSnarfRegexp('(foo bar)%s' % m, 'operation')
finally:
karma.response.setValue(resp)
karma.allowUnaddressedKarma.setValue(unaddressed)
def testUnaddressedKarma(self):
karma = conf.supybot.plugins.Karma
resp = karma.response()
unaddressed = karma.allowUnaddressedKarma()
try:
karma.response.setValue(True)
karma.allowUnaddressedKarma.setValue(True)
for m in ('++', '--'):
self.assertRegexp('foo%s' % m, 'operation')
self.assertSnarfRegexp('foo%s' % m, 'operation')
#self.assertNoResponse('foo bar%s' % m)
#self.assertSnarfNoResponse('foo bar%s' % m)
self.assertRegexp('(foo bar)%s' % m, 'operation')
self.assertSnarfRegexp('(foo bar)%s' % m, 'operation')
finally:
karma.response.setValue(resp)
karma.allowUnaddressedKarma.setValue(unaddressed)
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

View File

@ -765,6 +765,10 @@ class Databases(registry.SpaceSeparatedListOfStrings):
v = ['anydbm', 'cdb', 'flat', 'pickle']
if 'sqlite' in sys.modules:
v.insert(0, 'sqlite')
if 'sqlite3' in sys.modules:
v.insert(0, 'sqlite3')
if 'pysqlite2' in sys.modules: # for python 2.4
v.insert(0, 'sqlite3')
return v
def serialize(self):