mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-23 11:09:23 +01:00
Fix some problems in Infobot.py's sqlite implementation and genericize
some other errors to better fit in with db abstraction
This commit is contained in:
parent
376e67def3
commit
72f36efc18
@ -43,6 +43,7 @@ import re
|
|||||||
import random
|
import random
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
|
|
||||||
|
import supybot.dbi as dbi
|
||||||
import supybot.conf as conf
|
import supybot.conf as conf
|
||||||
import supybot.utils as utils
|
import supybot.utils as utils
|
||||||
import supybot.ircmsgs as ircmsgs
|
import supybot.ircmsgs as ircmsgs
|
||||||
@ -106,7 +107,10 @@ class PickleInfobotDB(object):
|
|||||||
self._is = utils.InsensitivePreservingDict()
|
self._is = utils.InsensitivePreservingDict()
|
||||||
self._are = utils.InsensitivePreservingDict()
|
self._are = utils.InsensitivePreservingDict()
|
||||||
else:
|
else:
|
||||||
|
try:
|
||||||
(self._is, self._are) = pickle.load(fd)
|
(self._is, self._are) = pickle.load(fd)
|
||||||
|
except cPickle.UnpicklingError, e:
|
||||||
|
raise dbi.InvalidDBError, str(e)
|
||||||
self._changes = 0
|
self._changes = 0
|
||||||
self._responses = 0
|
self._responses = 0
|
||||||
|
|
||||||
@ -119,7 +123,10 @@ class PickleInfobotDB(object):
|
|||||||
self.flush()
|
self.flush()
|
||||||
|
|
||||||
def changeIs(self, factoid, replacer):
|
def changeIs(self, factoid, replacer):
|
||||||
|
try:
|
||||||
old = self._is[factoid]
|
old = self._is[factoid]
|
||||||
|
except KeyError:
|
||||||
|
raise dbi.NoRecordError
|
||||||
if replacer is not None:
|
if replacer is not None:
|
||||||
self._is[factoid] = replacer(old)
|
self._is[factoid] = replacer(old)
|
||||||
self.flush()
|
self.flush()
|
||||||
@ -136,7 +143,10 @@ class PickleInfobotDB(object):
|
|||||||
self._changes += 1
|
self._changes += 1
|
||||||
|
|
||||||
def delIs(self, factoid):
|
def delIs(self, factoid):
|
||||||
|
try:
|
||||||
del self._is[factoid]
|
del self._is[factoid]
|
||||||
|
except KeyError:
|
||||||
|
raise dbi.NoRecordError
|
||||||
self.flush()
|
self.flush()
|
||||||
self._changes += 1
|
self._changes += 1
|
||||||
|
|
||||||
@ -144,7 +154,10 @@ class PickleInfobotDB(object):
|
|||||||
return factoid in self._is
|
return factoid in self._is
|
||||||
|
|
||||||
def changeAre(self, factoid, replacer):
|
def changeAre(self, factoid, replacer):
|
||||||
|
try:
|
||||||
old = self._are[factoid]
|
old = self._are[factoid]
|
||||||
|
except KeyError:
|
||||||
|
raise dbi.NoRecordError
|
||||||
if replacer is not None:
|
if replacer is not None:
|
||||||
self._are[factoid] = replacer(old)
|
self._are[factoid] = replacer(old)
|
||||||
self._changes += 1
|
self._changes += 1
|
||||||
@ -164,7 +177,10 @@ class PickleInfobotDB(object):
|
|||||||
self._changes += 1
|
self._changes += 1
|
||||||
|
|
||||||
def delAre(self, factoid):
|
def delAre(self, factoid):
|
||||||
|
try:
|
||||||
del self._are[factoid]
|
del self._are[factoid]
|
||||||
|
except KeyError:
|
||||||
|
raise dbi.NoRecordError
|
||||||
self.flush()
|
self.flush()
|
||||||
self._changes += 1
|
self._changes += 1
|
||||||
|
|
||||||
@ -186,21 +202,24 @@ class SqliteInfobotDB(object):
|
|||||||
self._responses = 0
|
self._responses = 0
|
||||||
|
|
||||||
def _getDb(self):
|
def _getDb(self):
|
||||||
|
try:
|
||||||
if os.path.exists(filename):
|
if os.path.exists(filename):
|
||||||
return sqlite.connect(filename)
|
return sqlite.connect(filename)
|
||||||
#else:
|
#else:
|
||||||
db = sqlite.connect(filename)
|
db = sqlite.connect(filename)
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute("""CREATE TABLE isFacts (
|
cursor.execute("""CREATE TABLE isFacts (
|
||||||
key TEXT PRIMARY KEY,
|
key TEXT UNIQUE ON CONFLICT REPLACE,
|
||||||
value TEXT
|
value TEXT
|
||||||
);""")
|
);""")
|
||||||
cursor.execute("""CREATE TABLE areFacts (
|
cursor.execute("""CREATE TABLE areFacts (
|
||||||
key TEXT PRIMARY KEY,
|
key TEXT UNIQUE ON CONFLICT REPLACE,
|
||||||
value TEXT
|
value TEXT
|
||||||
);""")
|
);""")
|
||||||
db.commit()
|
db.commit()
|
||||||
return db
|
return db
|
||||||
|
except sqlite.DatabaseError, e:
|
||||||
|
raise dbi.InvalidDBError, str(e)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
pass
|
pass
|
||||||
@ -209,6 +228,8 @@ class SqliteInfobotDB(object):
|
|||||||
db = self._getDb()
|
db = self._getDb()
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute("""SELECT value FROM isFacts WHERE key=%s""", factoid)
|
cursor.execute("""SELECT value FROM isFacts WHERE key=%s""", factoid)
|
||||||
|
if cursor.rowcount == 0:
|
||||||
|
raise dbi.NoRecordError
|
||||||
old = cursor.fetchone()[0]
|
old = cursor.fetchone()[0]
|
||||||
if replacer is not None:
|
if replacer is not None:
|
||||||
cursor.execute("""UPDATE isFacts SET value=%s WHERE key=%s""",
|
cursor.execute("""UPDATE isFacts SET value=%s WHERE key=%s""",
|
||||||
@ -235,6 +256,8 @@ class SqliteInfobotDB(object):
|
|||||||
db = self._getDb()
|
db = self._getDb()
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute("""DELETE FROM isFacts WHERE key=%s""", factoid)
|
cursor.execute("""DELETE FROM isFacts WHERE key=%s""", factoid)
|
||||||
|
if cursor.rowcount == 0:
|
||||||
|
raise dbi.NoRecordError
|
||||||
db.commit()
|
db.commit()
|
||||||
self._changes += 1
|
self._changes += 1
|
||||||
|
|
||||||
@ -248,6 +271,8 @@ class SqliteInfobotDB(object):
|
|||||||
db = self._getDb()
|
db = self._getDb()
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute("""SELECT value FROM areFacts WHERE key=%s""", factoid)
|
cursor.execute("""SELECT value FROM areFacts WHERE key=%s""", factoid)
|
||||||
|
if cursor.rowcount == 0:
|
||||||
|
raise dbi.NoRecordError
|
||||||
old = cursor.fetchone()[0]
|
old = cursor.fetchone()[0]
|
||||||
if replacer is not None:
|
if replacer is not None:
|
||||||
cursor.execute("""UPDATE areFacts SET value=%s WHERE key=%s""",
|
cursor.execute("""UPDATE areFacts SET value=%s WHERE key=%s""",
|
||||||
@ -274,6 +299,8 @@ class SqliteInfobotDB(object):
|
|||||||
db = self._getDb()
|
db = self._getDb()
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute("""DELETE FROM areFacts WHERE key=%s""", factoid)
|
cursor.execute("""DELETE FROM areFacts WHERE key=%s""", factoid)
|
||||||
|
if cursor.rowcount == 0:
|
||||||
|
raise dbi.NoRecordError
|
||||||
db.commit()
|
db.commit()
|
||||||
self._changes += 1
|
self._changes += 1
|
||||||
|
|
||||||
@ -320,6 +347,12 @@ class Infobot(callbacks.PrivmsgCommandAndRegexp):
|
|||||||
def die(self):
|
def die(self):
|
||||||
self.db.close()
|
self.db.close()
|
||||||
|
|
||||||
|
def _error(self, s):
|
||||||
|
if self.addressed:
|
||||||
|
self.irc.error(s)
|
||||||
|
else:
|
||||||
|
self.log.warning(s)
|
||||||
|
|
||||||
def reply(self, s, irc=None, msg=None, action=False):
|
def reply(self, s, irc=None, msg=None, action=False):
|
||||||
if self.replied:
|
if self.replied:
|
||||||
self.log.debug('Already replied, not replying again.')
|
self.log.debug('Already replied, not replying again.')
|
||||||
@ -355,12 +388,16 @@ class Infobot(callbacks.PrivmsgCommandAndRegexp):
|
|||||||
assert self.msg is not None
|
assert self.msg is not None
|
||||||
msg = self.msg
|
msg = self.msg
|
||||||
isAre = None
|
isAre = None
|
||||||
|
try:
|
||||||
if self.db.hasIs(key):
|
if self.db.hasIs(key):
|
||||||
isAre = 'is'
|
isAre = 'is'
|
||||||
value = self.db.getIs(key)
|
value = self.db.getIs(key)
|
||||||
elif self.db.hasAre(key):
|
elif self.db.hasAre(key):
|
||||||
isAre = 'are'
|
isAre = 'are'
|
||||||
value = self.db.getAre(key)
|
value = self.db.getAre(key)
|
||||||
|
except dbi.InvalidDBError:
|
||||||
|
self._error('Unable to access db: %s' % e)
|
||||||
|
return
|
||||||
if isAre is None:
|
if isAre is None:
|
||||||
if self.addressed:
|
if self.addressed:
|
||||||
if dunno:
|
if dunno:
|
||||||
@ -388,7 +425,7 @@ class Infobot(callbacks.PrivmsgCommandAndRegexp):
|
|||||||
s = s.strip() # After stripFormatting for formatted spaces.
|
s = s.strip() # After stripFormatting for formatted spaces.
|
||||||
s = utils.normalizeWhitespace(s)
|
s = utils.normalizeWhitespace(s)
|
||||||
contractions = [('what\'s', 'what is'), ('where\'s', 'where is'),
|
contractions = [('what\'s', 'what is'), ('where\'s', 'where is'),
|
||||||
('who\'s', 'who is'),]
|
('who\'s', 'who is'), ('wtf\'s', 'wtf is'),]
|
||||||
for (contraction, replacement) in contractions:
|
for (contraction, replacement) in contractions:
|
||||||
if s.startswith(contraction):
|
if s.startswith(contraction):
|
||||||
s = replacement + s[len(contraction):]
|
s = replacement + s[len(contraction):]
|
||||||
@ -467,7 +504,7 @@ class Infobot(callbacks.PrivmsgCommandAndRegexp):
|
|||||||
try:
|
try:
|
||||||
method(fact)
|
method(fact)
|
||||||
deleted = True
|
deleted = True
|
||||||
except KeyError:
|
except dbi.NoRecordError:
|
||||||
pass
|
pass
|
||||||
if deleted:
|
if deleted:
|
||||||
self.confirm()
|
self.confirm()
|
||||||
@ -492,7 +529,7 @@ class Infobot(callbacks.PrivmsgCommandAndRegexp):
|
|||||||
try:
|
try:
|
||||||
method(fact, r)
|
method(fact, r)
|
||||||
changed = True
|
changed = True
|
||||||
except KeyError:
|
except dbi.NoRecordError:
|
||||||
pass
|
pass
|
||||||
if changed:
|
if changed:
|
||||||
self.confirm()
|
self.confirm()
|
||||||
@ -501,7 +538,7 @@ class Infobot(callbacks.PrivmsgCommandAndRegexp):
|
|||||||
irc.reply('I\'ve never heard of %s, %s!' % (fact, msg.nick))
|
irc.reply('I\'ve never heard of %s, %s!' % (fact, msg.nick))
|
||||||
|
|
||||||
def doUnknown(self, irc, msg, match):
|
def doUnknown(self, irc, msg, match):
|
||||||
r"^(.+?)\?[?!. ]*$"
|
r"^(.+?)\s*\?[?!. ]*$"
|
||||||
key = match.group(1)
|
key = match.group(1)
|
||||||
if self.addressed or self.registryValue('answerUnaddressedQuestions'):
|
if self.addressed or self.registryValue('answerUnaddressedQuestions'):
|
||||||
self.factoid(key) # Does the dunno'ing for us itself.
|
self.factoid(key) # Does the dunno'ing for us itself.
|
||||||
@ -513,7 +550,7 @@ class Infobot(callbacks.PrivmsgCommandAndRegexp):
|
|||||||
r"^(.+)\s+(?<!\\)(was|is|am|were|are)\s+(also\s+)?(.+?)[?!. ]*$"
|
r"^(.+)\s+(?<!\\)(was|is|am|were|are)\s+(also\s+)?(.+?)[?!. ]*$"
|
||||||
(key, isAre, also, value) = match.groups()
|
(key, isAre, also, value) = match.groups()
|
||||||
key = key.replace('\\', '')
|
key = key.replace('\\', '')
|
||||||
if key.lower() in ('where', 'what', 'who'):
|
if key.lower() in ('where', 'what', 'who', 'wtf'):
|
||||||
# It's a question.
|
# It's a question.
|
||||||
if self.addressed or \
|
if self.addressed or \
|
||||||
self.registryValue('answerUnaddressedQuestions'):
|
self.registryValue('answerUnaddressedQuestions'):
|
||||||
|
@ -51,6 +51,9 @@ class Error(Exception):
|
|||||||
class NoRecordError(KeyError):
|
class NoRecordError(KeyError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class InvalidDBError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
class MappingInterface(object):
|
class MappingInterface(object):
|
||||||
"""This is a class to represent the underlying representation of a map
|
"""This is a class to represent the underlying representation of a map
|
||||||
from integer keys to strings."""
|
from integer keys to strings."""
|
||||||
|
@ -34,12 +34,12 @@ from testsupport import *
|
|||||||
import supybot.plugins.Infobot
|
import supybot.plugins.Infobot
|
||||||
confirms = supybot.plugins.Infobot.confirms
|
confirms = supybot.plugins.Infobot.confirms
|
||||||
dunnos = supybot.plugins.Infobot.dunnos
|
dunnos = supybot.plugins.Infobot.dunnos
|
||||||
|
ibot = conf.supybot.plugins.Infobot
|
||||||
|
|
||||||
class InfobotTestCase(ChannelPluginTestCase):
|
class InfobotTestCase(ChannelPluginTestCase):
|
||||||
plugins = ('Infobot',)
|
plugins = ('Infobot',)
|
||||||
_endRe = re.compile(r'!|, \S+\.|\.')
|
_endRe = re.compile(r'!|, \S+\.|\.')
|
||||||
def testIsSnarf(self):
|
def testIsSnarf(self):
|
||||||
ibot = conf.supybot.plugins.Infobot
|
|
||||||
learn = ibot.snarfUnaddressedDefinitions()
|
learn = ibot.snarfUnaddressedDefinitions()
|
||||||
answer = ibot.answerUnaddressedQuestions()
|
answer = ibot.answerUnaddressedQuestions()
|
||||||
try:
|
try:
|
||||||
@ -57,7 +57,6 @@ class InfobotTestCase(ChannelPluginTestCase):
|
|||||||
ibot.answerUnaddressedQuestions.setValue(answer)
|
ibot.answerUnaddressedQuestions.setValue(answer)
|
||||||
|
|
||||||
def testAreSnarf(self):
|
def testAreSnarf(self):
|
||||||
ibot = conf.supybot.plugins.Infobot
|
|
||||||
learn = ibot.snarfUnaddressedDefinitions()
|
learn = ibot.snarfUnaddressedDefinitions()
|
||||||
answer = ibot.answerUnaddressedQuestions()
|
answer = ibot.answerUnaddressedQuestions()
|
||||||
try:
|
try:
|
||||||
@ -72,7 +71,6 @@ class InfobotTestCase(ChannelPluginTestCase):
|
|||||||
ibot.answerUnaddressedQuestions.setValue(answer)
|
ibot.answerUnaddressedQuestions.setValue(answer)
|
||||||
|
|
||||||
def testIsResponses(self):
|
def testIsResponses(self):
|
||||||
ibot = conf.supybot.plugins.Infobot
|
|
||||||
learn = ibot.snarfUnaddressedDefinitions()
|
learn = ibot.snarfUnaddressedDefinitions()
|
||||||
answer = ibot.answerUnaddressedQuestions()
|
answer = ibot.answerUnaddressedQuestions()
|
||||||
try:
|
try:
|
||||||
@ -89,7 +87,6 @@ class InfobotTestCase(ChannelPluginTestCase):
|
|||||||
ibot.answerUnaddressedQuestions.setValue(answer)
|
ibot.answerUnaddressedQuestions.setValue(answer)
|
||||||
|
|
||||||
def testAnswerUnaddressed(self):
|
def testAnswerUnaddressed(self):
|
||||||
ibot = conf.supybot.plugins.Infobot
|
|
||||||
answer = ibot.answerUnaddressedQuestions()
|
answer = ibot.answerUnaddressedQuestions()
|
||||||
try:
|
try:
|
||||||
ibot.answerUnaddressedQuestions.setValue(True)
|
ibot.answerUnaddressedQuestions.setValue(True)
|
||||||
@ -100,4 +97,18 @@ class InfobotTestCase(ChannelPluginTestCase):
|
|||||||
finally:
|
finally:
|
||||||
ibot.answerUnaddressedQuestions.setValue(answer)
|
ibot.answerUnaddressedQuestions.setValue(answer)
|
||||||
|
|
||||||
|
def testReplaceFactoid(self):
|
||||||
|
answer = ibot.answerUnaddressedQuestions()
|
||||||
|
learn = ibot.snarfUnaddressedDefinitions()
|
||||||
|
try:
|
||||||
|
ibot.answerUnaddressedQuestions.setValue(True)
|
||||||
|
ibot.snarfUnaddressedDefinitions.setValue(True)
|
||||||
|
self.assertSnarfNoResponse('forums are good')
|
||||||
|
self.assertSnarfRegexp('forums?', 'good')
|
||||||
|
self.assertNotError('no, forums are evil')
|
||||||
|
self.assertSnarfRegexp('forums?', 'evil')
|
||||||
|
finally:
|
||||||
|
ibot.answerUnaddressedQuestions.setValue(answer)
|
||||||
|
ibot.snarfUnaddressedDefinitions.setValue(learn)
|
||||||
|
|
||||||
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|
||||||
|
Loading…
Reference in New Issue
Block a user