Markov: some minor formatting/pylint cleanups

This commit is contained in:
Brian S. Stephan 2013-02-07 23:51:41 -06:00
parent 9ea3e9d688
commit 60ac4d25bd
1 changed files with 42 additions and 28 deletions

View File

@ -14,6 +14,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from datetime import datetime
@ -22,7 +23,7 @@ import re
import thread
import time
from dateutil.relativedelta import *
from dateutil.relativedelta import relativedelta
import MySQLdb as mdb
from extlib import irclib
@ -31,18 +32,21 @@ from Module import Module
class Markov(Module):
"""
Create a chatterbot very similar to a MegaHAL, but simpler and
"""Create a chatterbot very similar to a MegaHAL, but simpler and
implemented in pure Python. Proof of concept code from Ape.
Ape wrote: based on this:
http://uswaretech.com/blog/2009/06/pseudo-random-text-markov-chains-python/
and this:
http://code.activestate.com/recipes/194364-the-markov-chain-algorithm/
"""
def __init__(self, irc, config):
"""Create the Markov chainer, and learn text from a file if available."""
"""Create the Markov chainer, and learn text from a file if
available.
"""
# set up some keywords for use in the chains --- don't change these
# once you've created a brain
@ -67,7 +71,8 @@ class Markov(Module):
self.connection = None
thread.start_new_thread(self.thread_do, ())
irc.xmlrpc_register_function(self._generate_line, "markov_generate_line")
irc.xmlrpc_register_function(self._generate_line,
"markov_generate_line")
def db_init(self):
"""Create the markov chain table."""
@ -118,7 +123,8 @@ class Markov(Module):
ON markov_chain (v, context_id)''')
db.commit()
self.db_register_module_version(self.__class__.__name__, version)
self.db_register_module_version(self.__class__.__name__,
version)
except mdb.Error as e:
db.rollback()
self.log.error("database error trying to create tables")
@ -129,16 +135,24 @@ class Markov(Module):
def register_handlers(self):
"""Handle pubmsg/privmsg, to learn and/or reply to IRC events."""
self.irc.server.add_global_handler('pubmsg', self.on_pub_or_privmsg, self.priority())
self.irc.server.add_global_handler('privmsg', self.on_pub_or_privmsg, self.priority())
self.irc.server.add_global_handler('pubmsg', self.learn_from_irc_event)
self.irc.server.add_global_handler('privmsg', self.learn_from_irc_event)
self.irc.server.add_global_handler('pubmsg', self.on_pub_or_privmsg,
self.priority())
self.irc.server.add_global_handler('privmsg', self.on_pub_or_privmsg,
self.priority())
self.irc.server.add_global_handler('pubmsg',
self.learn_from_irc_event)
self.irc.server.add_global_handler('privmsg',
self.learn_from_irc_event)
def unregister_handlers(self):
self.irc.server.remove_global_handler('pubmsg', self.on_pub_or_privmsg)
self.irc.server.remove_global_handler('privmsg', self.on_pub_or_privmsg)
self.irc.server.remove_global_handler('pubmsg', self.learn_from_irc_event)
self.irc.server.remove_global_handler('privmsg', self.learn_from_irc_event)
self.irc.server.remove_global_handler('pubmsg',
self.on_pub_or_privmsg)
self.irc.server.remove_global_handler('privmsg',
self.on_pub_or_privmsg)
self.irc.server.remove_global_handler('pubmsg',
self.learn_from_irc_event)
self.irc.server.remove_global_handler('privmsg',
self.learn_from_irc_event)
def learn_from_irc_event(self, connection, event):
"""Learn from IRC events."""
@ -167,11 +181,11 @@ class Markov(Module):
target = event.target()
if self.learnre.search(what):
return self.irc.reply(event, self.markov_learn(connection, event, nick,
userhost, what, admin_unlocked))
return self.irc.reply(event, self.markov_learn(connection, event,
nick, userhost, what, admin_unlocked))
elif self.replyre.search(what) and not self.shut_up:
return self.irc.reply(event, self.markov_reply(connection, event, nick,
userhost, what, admin_unlocked))
return self.irc.reply(event, self.markov_reply(connection, event,
nick, userhost, what, admin_unlocked))
if not self.shut_up:
# not a command, so see if i'm being mentioned
@ -179,7 +193,8 @@ class Markov(Module):
addressed_pattern = '^' + connection.get_nickname() + '[:,]\s+(.*)'
addressed_re = re.compile(addressed_pattern)
if addressed_re.match(what):
# i was addressed directly, so respond, addressing the speaker
# i was addressed directly, so respond, addressing
# the speaker
self.lines_seen.append(('.self.said.', datetime.now()))
return self.irc.reply(event, '{0:s}: {1:s}'.format(nick,
self._generate_line(target, line=addressed_re.match(what).group(1))))
@ -261,14 +276,14 @@ class Markov(Module):
last_30_sec_lines = []
for (nick,then) in self.lines_seen:
for (nick, then) in self.lines_seen:
rdelta = relativedelta(datetime.now(), then)
if (rdelta.years == 0 and rdelta.months == 0 and rdelta.days == 0 and
rdelta.hours == 0 and rdelta.minutes == 0 and rdelta.seconds <= 29):
last_30_sec_lines.append((nick,then))
last_30_sec_lines.append((nick, then))
if len(last_30_sec_lines) >= 8:
lines_i_said = len(filter(lambda (a,b): a == '.self.said.', last_30_sec_lines))
lines_i_said = len(filter(lambda (a, b): a == '.self.said.', last_30_sec_lines))
if lines_i_said >= 8:
self.shut_up = True
targets = self._get_chatter_targets()
@ -309,14 +324,15 @@ class Markov(Module):
finally: cur.close()
def _generate_line(self, target, line='', min_size=15, max_size=100):
"""
Create a line, optionally using some text in a seed as a point in the chain.
"""Create a line, optionally using some text in a seed as a point in
the chain.
Keyword arguments:
target - the target to retrieve the context for (i.e. a channel or nick)
line - the line to reply to, by picking a random word and seeding with it
min_size - the minimum desired size in words. not guaranteed
max_size - the maximum desired size in words. not guaranteed
"""
# if the limit is too low, there's nothing to do
@ -496,7 +512,7 @@ class Markov(Module):
# hack. get a quasi-random start from the database, in
# a faster fashion than selecting all starts
max_id = self._get_max_chain_id()
rand_id = random.randint(1,max_id)
rand_id = random.randint(1, max_id)
query = ('SELECT v FROM markov_chain WHERE k1 = %s AND k2 = %s AND '
'(context_id = %s) AND id >= {0:d} LIMIT 1'.format(rand_id))
else:
@ -583,7 +599,6 @@ class Markov(Module):
finally: cur.close()
def _get_context_id_for_target(self, target):
"""Get the context ID for the desired/input target."""
db = self.get_db()
@ -611,7 +626,6 @@ class Markov(Module):
finally: cur.close()
def _add_context_for_target(self, target):
"""Create a new context for the desired/input target."""
db = self.get_db()
@ -623,7 +637,7 @@ class Markov(Module):
INSERT INTO markov_target_to_context_map (target, context_id)
VALUES (%s, (SELECT id FROM markov_context WHERE context = %s))
'''
cur.execute(statement, (target,target))
cur.execute(statement, (target, target))
db.commit()
except mdb.Error as e:
db.rollback()