From e939cfd124c91b83fb7f9323881fb3da8cbc412b Mon Sep 17 00:00:00 2001 From: Daniel Folkinshteyn Date: Fri, 16 Apr 2010 16:06:00 -0400 Subject: [PATCH] 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. --- plugins/Karma/plugin.py | 64 ++++---- plugins/Karma/test.py | 321 ++++++++++++++++++++-------------------- src/conf.py | 4 + 3 files changed, 198 insertions(+), 191 deletions(-) diff --git a/plugins/Karma/plugin.py b/plugins/Karma/plugin.py index 606ea57c5..dd2b4e0a6 100644 --- a/plugins/Karma/plugin.py +++ b/plugins/Karma/plugin.py @@ -41,6 +41,11 @@ import supybot.callbacks as callbacks from supybot.i18n import PluginInternationalization, internationalizeDocstring _ = PluginInternationalization('Karma') +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() @@ -51,19 +56,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 ' \ - '' 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 ( @@ -84,20 +86,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()] @@ -109,26 +112,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 @@ -142,20 +146,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): @@ -179,7 +183,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): @@ -203,13 +207,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') diff --git a/plugins/Karma/test.py b/plugins/Karma/test.py index 526dda225..7dbfbdf2c 100644 --- a/plugins/Karma/test.py +++ b/plugins/Karma/test.py @@ -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: diff --git a/src/conf.py b/src/conf.py index fee98b7d8..a9e01b892 100644 --- a/src/conf.py +++ b/src/conf.py @@ -775,6 +775,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):