[Pymoul-svn] SF.net SVN: pymoul: [291] pymoul/trunk/src/moul
Status: Alpha
Brought to you by:
tiran
|
From: <ti...@us...> - 2007-05-24 17:19:05
|
Revision: 291
http://pymoul.svn.sourceforge.net/pymoul/?rev=291&view=rev
Author: tiran
Date: 2007-05-24 10:19:06 -0700 (Thu, 24 May 2007)
Log Message:
-----------
Chatlog parser enhancements
Modified Paths:
--------------
pymoul/trunk/src/moul/chatrelay/io.py
pymoul/trunk/src/moul/chatrelay/ircclient.py
pymoul/trunk/src/moul/file/chatlog.py
pymoul/trunk/src/moul/file/tests/test_chatlog.py
Modified: pymoul/trunk/src/moul/chatrelay/io.py
===================================================================
--- pymoul/trunk/src/moul/chatrelay/io.py 2007-05-24 14:00:41 UTC (rev 290)
+++ pymoul/trunk/src/moul/chatrelay/io.py 2007-05-24 17:19:06 UTC (rev 291)
@@ -23,6 +23,10 @@
import os
+from moul.file.chatlog import ChatlogParser
+from moul.file.chatlog import ChatLineError
+from moul.file.chatlog import CHAT_PRIVMSG
+
class NullFormatter(object):
"""A formatter that doesn't change the msg
"""
@@ -62,10 +66,16 @@
return
lines = data.split(os.linesep)
# XXX - KISS, don't check for imcomplete lines
- for line in lines:
- line = line.strip()
- if line:
- self._fifo.append(line)
+ for line in ChatlogParser(lines):
+ if isinstance(ChatLineError):
+ self._fifo.append("PARSER ERROR: " + line)
+ else:
+ if line.typ & CHAT_PRIVMSG:
+ continue
+ elif line.important:
+ self._fifo.append("*** " + line)
+ else:
+ self._fifo.append(line)
def __iter__(self):
self._read()
@@ -80,8 +90,6 @@
class MessageWriter(object):
"""Write messages to a channel
"""
- maxlength = 80
-
def __init__(self, client, channel, formatter=None):
self._client = client
self._channel = channel
@@ -91,4 +99,4 @@
def log(self, msg):
msg = self._fmt.format(msg)
- self._client.say(self._channel, msg, self.maxlength)
+ self._client.say(self._channel, msg)
Modified: pymoul/trunk/src/moul/chatrelay/ircclient.py
===================================================================
--- pymoul/trunk/src/moul/chatrelay/ircclient.py 2007-05-24 14:00:41 UTC (rev 290)
+++ pymoul/trunk/src/moul/chatrelay/ircclient.py 2007-05-24 17:19:06 UTC (rev 291)
@@ -238,7 +238,7 @@
reactor.callLater(3.0, self.reply, reply, "0-/")
reactor.callLater(3.5, self.reply, reply, "0-\\")
- #@requirePasswd
+ @requirePasswd
@usage("Open the chatlog and start relaying")
def command_STARTLOG(self, user, reply, args):
self.reply(reply, 'Opening chatlog ...')
@@ -248,12 +248,12 @@
return
self.msg(self.channel, "*** I'm relaying chat ***")
- #@requirePasswd
+ @requirePasswd
@usage("Stop relaying")
def command_STOPLOG(self, user, reply, args):
self.stop()
self.reply(reply, 'chatlog closed')
- self.msg(self.channel, "*** I've stopped to relay chat ***")
+ self.msg(self.channel, "*** I've stopped relaying chat ***")
class ThrottledClientFactory(protocol.ClientFactory):
lostDelay = 2
Modified: pymoul/trunk/src/moul/file/chatlog.py
===================================================================
--- pymoul/trunk/src/moul/file/chatlog.py 2007-05-24 14:00:41 UTC (rev 290)
+++ pymoul/trunk/src/moul/file/chatlog.py 2007-05-24 17:19:06 UTC (rev 291)
@@ -41,7 +41,22 @@
from moul.file.utils import fileModTime
+# Chat line types
+CHAT_START = 1 << 0
+CHAT_STOP = 1 << 1
+CHAT_ERROR = 1 << 2
+CHAT_PRIVMSGFROM = 1 << 3
+CHAT_PRIVMSGTO = 1 << 4
+CHAT_PRIVMSG = CHAT_PRIVMSGFROM | CHAT_PRIVMSGTO
+CHAT_MSG = 1 << 5
+CHAT_ACTION = 1 << 6
+# users
+USER_CYAN = ['gregbert', 'greydragon']
+USER_DRC = ['Marie Sutherland', 'Douglas Sharper', 'Nick White',
+ 'Dr. Kodama', 'Victor Laxman', 'Michael Engberg']
+USER_IMPORTANT = USER_CYAN + USER_DRC
+
RE_FLAGS = re.LOCALE
CHAT_RE = re.compile(
r"^\((?P<M>\d{1,2})/(?P<D>\d{1,2})\ " # MM/DD
@@ -52,20 +67,20 @@
r"^\((?P<date>[\d/]*)\ (?P<time>[\d:]*)\)" # (date time)
r"(?P<space>\s{1,2})" # spaces
r"(?P<msg>.*)$", # message
- RE_FLAGS)
-CHATLOG_STARTED = "Chat.log started..."
-CHATLOG_STOPPED = "...Chat.log stopped."
-TEXT_MSGFROM_RE = re.compile(
+ RE_FLAGS)
+CHATLOG_START = "Chat.log started..."
+CHATLOG_STOP = "...Chat.log stopped."
+PRIVMSGFROM_RE = re.compile(
# From USER in LOCATION: msg
r"From (?P<user>.*) in (?P<location>.*): (?P<msg>.*)",
RE_FLAGS)
-TEXT_MSGTO_RE = re.compile(
+PRIVMSGTO_RE = re.compile(
r"To (?P<user>.*): (?P<msg>.*)", # From USER in LOCATION: msg
RE_FLAGS)
-TEXT_ERROR_RE = re.compile(
+ERROR_RE = re.compile(
r"Error: (?P<msg>.*)", # Error: message
RE_FLAGS)
-TEXT_RE = re.compile(
+MSG_RE = re.compile(
r"(?P<user>.*): (?P<msg>.*)", # User: message
RE_FLAGS)
CHATLOG_DATE_FNAME_RE = re.compile(
@@ -76,7 +91,6 @@
LOG = getLogger('moul.chat')
-
class ChatlogMover(object):
"""
"""
@@ -147,7 +161,7 @@
created = None
if mo:
data = mo.groupdict()
- if data['msg'].startswith(CHATLOG_STARTED):
+ if data['msg'].startswith(CHATLOG_START):
d = mo.groupdict()
created = (None, int(d['M']), int(d['D']), int(d['h']),
int(d['m']), int(d['s']), None, None, None)
@@ -255,6 +269,8 @@
class ChatlogView(object):
"""A view of a single chat log file
+
+ XXX replace it with ChatlogParser
"""
def __init__(self, fname):
@@ -326,3 +342,85 @@
"""
self.open()
return self._fd.read()
+
+class ChatlogParser(object):
+ """Yet another chatlog parser
+
+ New idea, new design
+ """
+ def __init__(self, iterable, year=2007):
+ self._iterable = iterable
+ self._year = year # XXX
+
+ def parse(self, line):
+ mo = CHAT_RE.match(line)
+ if mo is None:
+ self.error(line)
+ return
+ d = mo.groupdict()
+ date = (self._year, int(d['M']), int(d['D']),
+ int(d['h']), int(d['m']), int(d['s']))
+ typ = None
+ msg = d['msg']
+ info = {}
+ important = False
+ if len(d['space']) == 2:
+ typ = CHAT_MSG
+ mo = MSG_RE.match(msg)
+ if mo is None:
+ return ChatLineError(line)
+ info = mo.groupdict()
+ else:
+ if msg == CHATLOG_START:
+ typ = CHAT_START
+ elif msg == CHATLOG_STOP:
+ typ = CHAT_STOP
+ else:
+ for t, r in ((CHAT_PRIVMSGFROM, PRIVMSGFROM_RE),
+ (CHAT_PRIVMSGTO, PRIVMSGTO_RE),
+ (CHAT_ERROR, ERROR_RE)):
+ mo = r.match(msg)
+ if mo:
+ typ = t
+ info = mo.groupdict()
+ break
+ if typ is None:
+ typ = CHAT_ACTION
+ for user in USER_IMPORTANT:
+ if user in msg:
+ important = True
+
+ user = info.get('user', None)
+ if user:
+ if user in USER_IMPORTANT:
+ important = True
+ if typ is not None:
+ return ChatLine(msg, date, typ, important, info)
+ else:
+ return ChatLineError(line)
+
+ def __iter__(self):
+ for line in self._iterable:
+ yield self.parse(line)
+
+class ChatLine(unicode):
+ __slots__ = ('datetime', 'typ', 'important', 'info')
+
+ def __new__(cls, ustr, datetime, typ=None, important=False, info={}):
+ self = unicode.__new__(cls, ustr)
+ self.datetime = datetime
+ self.typ = typ
+ self.important = important
+ self.info = info
+ return self
+
+ def asDatetime(self):
+ return datetime(*self.date)
+
+class ChatLineError(unicode):
+ def __new__(cls, ustr):
+ self = unicode.__new__(cls, ustr)
+ return self
+
+ def __nonzero(self):
+ return False
\ No newline at end of file
Modified: pymoul/trunk/src/moul/file/tests/test_chatlog.py
===================================================================
--- pymoul/trunk/src/moul/file/tests/test_chatlog.py 2007-05-24 14:00:41 UTC (rev 290)
+++ pymoul/trunk/src/moul/file/tests/test_chatlog.py 2007-05-24 17:19:06 UTC (rev 291)
@@ -25,10 +25,37 @@
from doctest import DocTestSuite
import moul.file.chatlog
+from moul.file.chatlog import *
+TEST_LOG = """(01/02 03:04:05) Chat.log started...
+(01/02 03:04:05) ...Chat.log stopped.
+(01/02 03:04:05) From USER in LOCATION: MSG
+(01/02 03:04:05) Error: ERRORMSG
+(01/02 03:04:05) USER: TEXT (note the two spaces!)
+(01/02 03:04:05) To USER: TEXT
+(01/02 03:04:05) USER action""".split('\n')
+class ChatlogParserTest(unittest.TestCase):
+
+ def test_parse(self):
+ parser = ChatlogParser(TEST_LOG)
+ results = list(iter(parser))
+ fue = self.failUnlessEqual
+ for result in results:
+ fue(result.datetime, (2007, 1, 2, 3, 4, 5))
+ fue(results[0].typ, CHAT_START)
+ fue(results[1].typ, CHAT_STOP)
+ fue(results[2].typ, CHAT_PRIVMSGFROM)
+ fue(results[3].typ, CHAT_ERROR)
+ fue(results[4].typ, CHAT_MSG)
+ fue(results[5].typ, CHAT_PRIVMSGTO)
+ fue(results[6].typ, CHAT_ACTION)
+ for i in (2, 4, 5):
+ fue(results[i].info['user'], 'USER')
+
def test_suite():
return unittest.TestSuite((
+ unittest.makeSuite(ChatlogParserTest),
DocTestSuite('moul.file.chatlog')
))
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|