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 committed by Valentin Lorentz
parent bf6f0e2d18
commit e939cfd124
3 changed files with 198 additions and 191 deletions

View File

@ -41,6 +41,11 @@ import supybot.callbacks as callbacks
from supybot.i18n import PluginInternationalization, internationalizeDocstring from supybot.i18n import PluginInternationalization, internationalizeDocstring
_ = PluginInternationalization('Karma') _ = PluginInternationalization('Karma')
try:
import sqlite3
except ImportError:
from pysqlite2 import dbapi2 as sqlite3 # for python2.4
class SqliteKarmaDB(object): class SqliteKarmaDB(object):
def __init__(self, filename): def __init__(self, filename):
self.dbs = ircutils.IrcDict() self.dbs = ircutils.IrcDict()
@ -51,19 +56,16 @@ class SqliteKarmaDB(object):
db.close() db.close()
def _getDb(self, channel): 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) filename = plugins.makeChannelFilename(self.filename, channel)
if filename in self.dbs: if filename in self.dbs:
return self.dbs[filename] return self.dbs[filename]
if os.path.exists(filename): if os.path.exists(filename):
self.dbs[filename] = sqlite.connect(filename) db = sqlite3.connect(filename)
return self.dbs[filename] db.text_factory = str
db = sqlite.connect(filename) self.dbs[filename] = db
return db
db = sqlite3.connect(filename)
db.text_factory = str
self.dbs[filename] = db self.dbs[filename] = db
cursor = db.cursor() cursor = db.cursor()
cursor.execute("""CREATE TABLE karma ( cursor.execute("""CREATE TABLE karma (
@ -84,20 +86,21 @@ class SqliteKarmaDB(object):
thing = thing.lower() thing = thing.lower()
cursor = db.cursor() cursor = db.cursor()
cursor.execute("""SELECT added, subtracted FROM karma cursor.execute("""SELECT added, subtracted FROM karma
WHERE normalized=%s""", thing) WHERE normalized=?""", (thing,))
if cursor.rowcount == 0: results = cursor.fetchall()
if len(results) == 0:
return None return None
else: else:
return map(int, cursor.fetchone()) return map(int, results[0])
def gets(self, channel, things): def gets(self, channel, things):
db = self._getDb(channel) db = self._getDb(channel)
cursor = db.cursor() cursor = db.cursor()
normalizedThings = dict(zip(map(lambda s: s.lower(), things), things)) 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 sql = """SELECT name, added-subtracted FROM karma
WHERE %s ORDER BY added-subtracted DESC""" % criteria 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()] L = [(name, int(karma)) for (name, karma) in cursor.fetchall()]
for (name, _) in L: for (name, _) in L:
del normalizedThings[name.lower()] del normalizedThings[name.lower()]
@ -109,26 +112,27 @@ class SqliteKarmaDB(object):
db = self._getDb(channel) db = self._getDb(channel)
cursor = db.cursor() cursor = db.cursor()
cursor.execute("""SELECT name, added-subtracted FROM karma 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()] return [(t[0], int(t[1])) for t in cursor.fetchall()]
def bottom(self, channel, limit): def bottom(self, channel, limit):
db = self._getDb(channel) db = self._getDb(channel)
cursor = db.cursor() cursor = db.cursor()
cursor.execute("""SELECT name, added-subtracted FROM karma 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()] return [(t[0], int(t[1])) for t in cursor.fetchall()]
def rank(self, channel, thing): def rank(self, channel, thing):
db = self._getDb(channel) db = self._getDb(channel)
cursor = db.cursor() cursor = db.cursor()
cursor.execute("""SELECT added-subtracted FROM karma cursor.execute("""SELECT added-subtracted FROM karma
WHERE name=%s""", thing) WHERE name=?""", (thing,))
if cursor.rowcount == 0: results = cursor.fetchall()
if len(results) == 0:
return None return None
karma = int(cursor.fetchone()[0]) karma = int(results[0][0])
cursor.execute("""SELECT COUNT(*) FROM karma cursor.execute("""SELECT COUNT(*) FROM karma
WHERE added-subtracted > %s""", karma) WHERE added-subtracted > ?""", (karma,))
rank = int(cursor.fetchone()[0]) rank = int(cursor.fetchone()[0])
return rank+1 return rank+1
@ -142,20 +146,20 @@ class SqliteKarmaDB(object):
db = self._getDb(channel) db = self._getDb(channel)
cursor = db.cursor() cursor = db.cursor()
normalized = name.lower() normalized = name.lower()
cursor.execute("""INSERT INTO karma VALUES (NULL, %s, %s, 0, 0)""", cursor.execute("""INSERT INTO karma VALUES (NULL, ?, ?, 0, 0)""",
name, normalized) (name, normalized,))
cursor.execute("""UPDATE karma SET added=added+1 cursor.execute("""UPDATE karma SET added=added+1
WHERE normalized=%s""", normalized) WHERE normalized=?""", (normalized,))
db.commit() db.commit()
def decrement(self, channel, name): def decrement(self, channel, name):
db = self._getDb(channel) db = self._getDb(channel)
cursor = db.cursor() cursor = db.cursor()
normalized = name.lower() normalized = name.lower()
cursor.execute("""INSERT INTO karma VALUES (NULL, %s, %s, 0, 0)""", cursor.execute("""INSERT INTO karma VALUES (NULL, ?, ?, 0, 0)""",
name, normalized) (name, normalized,))
cursor.execute("""UPDATE karma SET subtracted=subtracted+1 cursor.execute("""UPDATE karma SET subtracted=subtracted+1
WHERE normalized=%s""", normalized) WHERE normalized=?""", (normalized,))
db.commit() db.commit()
def most(self, channel, kind, limit): def most(self, channel, kind, limit):
@ -179,7 +183,7 @@ class SqliteKarmaDB(object):
cursor = db.cursor() cursor = db.cursor()
normalized = name.lower() normalized = name.lower()
cursor.execute("""UPDATE karma SET subtracted=0, added=0 cursor.execute("""UPDATE karma SET subtracted=0, added=0
WHERE normalized=%s""", normalized) WHERE normalized=?""", (normalized,))
db.commit() db.commit()
def dump(self, channel, filename): def dump(self, channel, filename):
@ -203,13 +207,13 @@ class SqliteKarmaDB(object):
for (name, added, subtracted) in reader: for (name, added, subtracted) in reader:
normalized = name.lower() normalized = name.lower()
cursor.execute("""INSERT INTO karma cursor.execute("""INSERT INTO karma
VALUES (NULL, %s, %s, %s, %s)""", VALUES (NULL, ?, ?, ?, ?)""",
name, normalized, added, subtracted) (name, normalized, added, subtracted,))
db.commit() db.commit()
fd.close() fd.close()
KarmaDB = plugins.DB('Karma', KarmaDB = plugins.DB('Karma',
{'sqlite': SqliteKarmaDB}) {'sqlite3': SqliteKarmaDB})
class Karma(callbacks.Plugin): class Karma(callbacks.Plugin):
callBefore = ('Factoids', 'MoobotFactoids', 'Infobot') callBefore = ('Factoids', 'MoobotFactoids', 'Infobot')

View File

@ -30,11 +30,10 @@
from supybot.test import * from supybot.test import *
try: try:
import sqlite import sqlite3
except ImportError: except ImportError:
sqlite = None from pysqlite2 import dbapi2 as sqlite3 # for python2.4
if sqlite is not None:
class KarmaTestCase(ChannelPluginTestCase): class KarmaTestCase(ChannelPluginTestCase):
plugins = ('Karma',) plugins = ('Karma',)
def testKarma(self): def testKarma(self):

View File

@ -775,6 +775,10 @@ class Databases(registry.SpaceSeparatedListOfStrings):
v = ['anydbm', 'cdb', 'flat', 'pickle'] v = ['anydbm', 'cdb', 'flat', 'pickle']
if 'sqlite' in sys.modules: if 'sqlite' in sys.modules:
v.insert(0, 'sqlite') 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 return v
def serialize(self): def serialize(self):