* [gentoo-commits] proj/council-webapp:master commit in: bot/tests/, bot/ircmeeting/
@ 2011-06-05 20:37 Petteri Räty
0 siblings, 0 replies; 12+ messages in thread
From: Petteri Räty @ 2011-06-05 20:37 UTC (permalink / raw
To: gentoo-commits
commit: d93c2e59b3e1b0a077c34ad9f560b79a9f1670df
Author: Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
AuthorDate: Mon May 23 11:17:40 2011 +0000
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Fri Jun 3 17:17:48 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=d93c2e59
Bot obtains voters, agenda items and voting options lists from webapp
---
bot/ircmeeting/agenda.py | 91 ++++++++++++++
bot/ircmeeting/meeting.py | 26 ++++-
bot/tests/MeetBot | 1 +
bot/tests/ircmeeting | 1 +
bot/tests/run_test.py | 71 +++++++++++
bot/tests/test-script-1.html | 256 ++++++++++++++++++++++++++++++++++++++
bot/tests/test-script-1.log.html | 91 ++++++++++++++
bot/tests/test-script-1.txt | 98 +++++++++++++++
8 files changed, 633 insertions(+), 2 deletions(-)
diff --git a/bot/ircmeeting/agenda.py b/bot/ircmeeting/agenda.py
new file mode 100644
index 0000000..7ee9beb
--- /dev/null
+++ b/bot/ircmeeting/agenda.py
@@ -0,0 +1,91 @@
+import json
+import urllib
+
+class Agenda(object):
+
+ # Messages
+ empty_agenda_msg = "Agenda is empty so I can't help you manage meeting (and voting)."
+ current_item_msg = "Current agenda item is {}."
+ voting_already_open_msg = "Voting is already open. You can end it with #endvote."
+ voting_open_msg = "Voting started. Your choices are: {} Vote #vote <option number>.\n End voting with #endvote."
+ voting_close_msg = "Voting is closed."
+ voting_already_closed_msg = "Voting is already closed. You can start it with #startvote."
+ voting_open_so_item_not_changed_msg = "Voting is currently open so I didn't change item. Please #endvote first"
+ can_not_vote_msg = "You can not vote. Only {} can vote"
+ not_a_number_msg = "Your vote was not recognized as a number. Please retry."
+ out_of_range_msg = "Your vote was out of range!"
+ vote_confirm_msg = "You voted for #{} - {}"
+
+ # Internal
+ _voters = []
+ _votes = []
+ _agenda = []
+ _current_item = 0
+ _vote_open = False
+
+ def __init__(self, conf):
+ self.conf = conf
+
+ def get_agenda_item(self):
+ if self._current_item < len(self._agenda):
+ return str.format(self.current_item_msg, self._agenda[self._current_item][0])
+ else:
+ return self.empty_agenda_msg
+
+ def next_agenda_item(self):
+ if self._vote_open:
+ return voting_open_so_item_not_changed_msg
+ else:
+ if (self._current_item + 1) < len(self._agenda):
+ self._current_item += 1
+ return(self.get_agenda_item())
+
+ def prev_agenda_item(self):
+ if self._vote_open:
+ return voting_open_so_item_not_changed_msg
+ else:
+ if self._current_item > 0:
+ self._current_item -= 1
+ return(self.get_agenda_item())
+
+ def start_vote(self):
+ if self._vote_open:
+ return self.voting_already_open_msg
+ self._vote_open = True
+ options = "\n"
+ for i in range(len(self._agenda[self._current_item][1])):
+ options += str.format("{}. {}\n", i, self._agenda[self._current_item][i])
+ return str.format(self.voting_open_msg, options)
+
+ def end_vote(self):
+ if self._vote_open:
+ self._vote_open = False
+ return voting_already_closed_msg
+ return voting_close_msg
+
+ def get_data(self):
+ self._voters = self._get_json(self.conf.voters_url)
+ self._agenda = self._get_json(self.conf.agenda_url)
+ self._votes = { }
+ for i in self._agenda:
+ self._votes[i[0]] = { }
+
+ def vote(self, nick, line):
+ if not nick in self._voters:
+ return str.format(self.can_not_vote_msg, ", ".join(self._voters))
+ if not line.isdigit():
+ return self.not_a_number_msg
+
+ opt = int(line)
+
+ if opt < 0 or opt >= len(self._agenda[self._current_item][1]):
+ return self.out_of_range_msg
+
+ self._votes[self._agenda[self._current_item][0]][nick] = self._agenda[self._current_item][1][opt]
+ return str.format(self.vote_confirm_msg, opt, self._agenda[self._current_item][opt])
+
+ def _get_json(self, url):
+ str = urllib.urlopen(url).read()
+ str = urllib.unquote(str)
+ result = json.loads(str)
+ return result
diff --git a/bot/ircmeeting/meeting.py b/bot/ircmeeting/meeting.py
index 85880a6..b22dac6 100644
--- a/bot/ircmeeting/meeting.py
+++ b/bot/ircmeeting/meeting.py
@@ -36,6 +36,7 @@ import stat
import writers
import items
+import agenda
reload(writers)
reload(items)
@@ -96,6 +97,11 @@ class Config(object):
input_codec = 'utf-8'
output_codec = 'utf-8'
# Functions to do the i/o conversion.
+
+ # Meeting management urls
+ voters_url = 'http://localhost:3000/users/voters'
+ agenda_url = 'http://localhost:3000/agendas/current_items'
+
def enc(self, text):
return text.encode(self.output_codec, 'replace')
def dec(self, text):
@@ -118,7 +124,6 @@ class Config(object):
#'.rst.html':writers.HTMLfromReST,
}
-
def __init__(self, M, writeRawLog=False, safeMode=False,
extraConfig={}):
self.M = M
@@ -134,6 +139,7 @@ class Config(object):
for extension, writer in self.writer_map.iteritems():
self.writers[extension] = writer(self.M)
self.safeMode = safeMode
+ self.agenda = agenda.Agenda(self)
def filename(self, url=False):
# provide a way to override the filename. If it is
# overridden, it must be a full path (and the URL-part may not
@@ -308,6 +314,22 @@ class MeetingCommands(object):
self.reply(messageline)
if line.strip():
self.do_meetingtopic(nick=nick, line=line, time_=time_, **kwargs)
+ self.config.agenda.get_data()
+ self.reply(self.config.agenda.get_agenda_item())
+
+ def do_nextitem(self, nick, time_, line, **kwargs):
+ self.reply(self.config.agenda.next_agenda_item())
+
+ def do_previtem(self, nick, time_, line, **kwargs):
+ self.reply(self.config.agenda.prev_agenda_item())
+
+ def do_startvote(self, nick, time_, line, **kwargs):
+ for messageline in self.config.agenda.start_vote().split('\n'):
+ self.reply(messageline)
+
+ def do_vote(self, nick, time_, line, **kwargs):
+ self.reply(self.config.agenda.vote(nick, line))
+
def do_endmeeting(self, nick, time_, **kwargs):
"""End the meeting."""
if not self.isChair(nick): return
@@ -454,7 +476,7 @@ class MeetingCommands(object):
commands = [ "#"+x[3:] for x in dir(self) if x[:3]=="do_" ]
commands.sort()
self.reply("Available commands: "+(" ".join(commands)))
-
+
class Meeting(MeetingCommands, object):
diff --git a/bot/tests/MeetBot b/bot/tests/MeetBot
new file mode 120000
index 0000000..f06815a
--- /dev/null
+++ b/bot/tests/MeetBot
@@ -0,0 +1 @@
+../MeetBot
\ No newline at end of file
diff --git a/bot/tests/ircmeeting b/bot/tests/ircmeeting
new file mode 120000
index 0000000..90e99f6
--- /dev/null
+++ b/bot/tests/ircmeeting
@@ -0,0 +1 @@
+../ircmeeting
\ No newline at end of file
diff --git a/bot/tests/run_test.py b/bot/tests/run_test.py
index 213cd43..f304a2b 100644
--- a/bot/tests/run_test.py
+++ b/bot/tests/run_test.py
@@ -7,6 +7,7 @@ import shutil
import sys
import tempfile
import unittest
+import time
os.environ['MEETBOT_RUNNING_TESTS'] = '1'
import ircmeeting.meeting as meeting
@@ -14,6 +15,12 @@ import ircmeeting.writers as writers
running_tests = True
+def parse_time(time_):
+ try: return time.strptime(time_, "%H:%M:%S")
+ except ValueError: pass
+ try: return time.strptime(time_, "%H:%M")
+ except ValueError: pass
+
def process_meeting(contents, extraConfig={}, dontSave=True,
filename='/dev/null'):
"""Take a test script, return Meeting object of that meeting.
@@ -337,9 +344,73 @@ class MeetBotTest(unittest.TestCase):
assert M.config.filename().endswith('somechannel-blah1234'),\
"Filename not as expected: "+M.config.filename()
+ def test_agenda(self):
+ """ Test agenda management
+ """
+ logline_re = re.compile(r'\[?([0-9: ]*)\]? *<[@+]?([^>]+)> *(.*)')
+ loglineAction_re = re.compile(r'\[?([0-9: ]*)\]? *\* *([^ ]+) *(.*)')
+
+ M = process_meeting('#startmeeting')
+ log = []
+ M._sendReply = lambda x: log.append(x)
+ M.config.agenda._voters = ['x', 'z']
+ M.config.agenda._agenda = [['first item', ['opt1', 'opt2']], ['second item', []]]
+ M.config.agenda._votes = { }
+ for i in M.config.agenda._agenda:
+ M.config.agenda._votes[i[0]] = { }
+
+
+ M.starttime = time.gmtime(0)
+ contents = """20:13:50 <x> #nextitem
+ 20:13:50 <x> #nextitem
+ 20:13:50 <x> #previtem
+ 20:13:50 <x> #previtem
+ 20:13:50 <x> #startvote
+ 20:13:50 <x> #vote 10
+ 20:13:50 <x> #vote 1
+ 20:13:50 <y> #vote 0
+ 20:13:50 <z> #vote 0
+ 20:13:50 <x> #endvote
+ 20:13:50 <x> #endmeeting"""
+
+ for line in contents.split('\n'):
+ # match regular spoken lines:
+ m = logline_re.match(line)
+ if m:
+ time_ = parse_time(m.group(1).strip())
+ nick = m.group(2).strip()
+ line = m.group(3).strip()
+ if M.owner is None:
+ M.owner = nick ; M.chairs = {nick:True}
+ M.addline(nick, line, time_=time_)
+ # match /me lines
+ m = loglineAction_re.match(line)
+ if m:
+ time_ = parse_time(m.group(1).strip())
+ nick = m.group(2).strip()
+ line = m.group(3).strip()
+ M.addline(nick, "ACTION "+line, time_=time_)
+
+ self.assert_(M.config.agenda._votes == {'first item': {u'x': 'opt2', u'z': 'opt1'}, 'second item': {}})
+
+ answers = ['Current agenda item is second item.',
+ 'Current agenda item is second item.',
+ 'Current agenda item is first item.',
+ 'Current agenda item is first item.',
+ 'Voting started. Your choices are: ',
+ '0. first item',
+ "1. ['opt1', 'opt2']",
+ ' Vote #vote <option number>.',
+ ' End voting with #endvote.',
+ 'Your vote was out of range!',
+ "You voted for #1 - ['opt1', 'opt2']",
+ 'You can not vote. Only x, z can vote',
+ 'You voted for #0 - first item']
+ self.assert_(log[0:len(answers)] == answers)
if __name__ == '__main__':
os.chdir(os.path.join(os.path.dirname(__file__), '.'))
+
if len(sys.argv) <= 1:
unittest.main()
else:
diff --git a/bot/tests/test-script-1.html b/bot/tests/test-script-1.html
new file mode 100644
index 0000000..fa42143
--- /dev/null
+++ b/bot/tests/test-script-1.html
@@ -0,0 +1,256 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
+<title>#test-script-1 Meeting</title>
+<style type="text/css">
+/* This is for the .html in the HTML2 writer */
+body {
+ font-family: Helvetica, sans-serif;
+ font-size:14px;
+}
+h1 {
+ text-align: center;
+}
+a {
+ color:navy;
+ text-decoration: none;
+ border-bottom:1px dotted navy;
+}
+a:hover {
+ text-decoration:none;
+ border-bottom: 0;
+ color:#0000B9;
+}
+hr {
+ border: 1px solid #ccc;
+}
+/* The (nick, time) item pairs, and other body text things. */
+.details {
+ font-size: 12px;
+ font-weight:bold;
+}
+/* The 'AGREED:', 'IDEA', etc, prefix to lines. */
+.itemtype {
+ font-style: normal; /* un-italics it */
+ font-weight: bold;
+}
+/* Example: change single item types. Capitalized command name.
+/* .TOPIC { color:navy; } */
+/* .AGREED { color:lime; } */
+
+</style>
+</head>
+
+<body>
+<h1>#test-script-1 Meeting</h1>
+<span class="details">
+Meeting started by MrBeige at 20:13:46 UTC
+(<a href="test-script-1.log.html">full logs</a>).</span>
+
+<br><br>
+
+
+
+<h3>Meeting summary</h3>
+<ol>
+<li>
+<ol type="a">
+ <li><span class="INFO">this command is just before the first
+ topic</span> <span class="details">(<a
+ href='test-script-1.log.html#l-2'>T-Rex</a>, 20:13:50)</span></li>
+</ol>
+<br></li>
+<li><b class="TOPIC">General command tests</b> <span class="details">(<a href='test-script-1.log.html#l-7'>MrBeige</a>, 20:13:50)</span>
+<ol type="a">
+ <li><i class="itemtype">ACCEPTED</i>: <span class="ACCEPTED"><font
+ color="green">we will include this new format if we so
+ choose.</font></span> <span class="details">(<a
+ href='test-script-1.log.html#l-8'>MrBeige</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">REJECTED</i>: <span class="REJECTED"><font
+ color="red">we will not include this new format.</font></span> <span
+ class="details">(<a href='test-script-1.log.html#l-9'>MrBeige</a>,
+ 20:13:50)</span></li>
+</ol>
+<br></li>
+<li><b class="TOPIC">Test of all commands with different arguments</b> <span class="details">(<a href='test-script-1.log.html#l-16'>MrBeige</a>, 20:13:50)</span>
+<br></li>
+<li><b class="TOPIC"></b> <span class="details">(<a href='test-script-1.log.html#l-17'>MrBeige</a>, 20:13:50)</span>
+<ol type="a">
+ <li><i class="itemtype">IDEA</i>: <span class="IDEA"></span> <span
+ class="details">(<a href='test-script-1.log.html#l-18'>MrBeige</a>,
+ 20:13:50)</span></li>
+ <li><span class="INFO"></span> <span class="details">(<a
+ href='test-script-1.log.html#l-19'>MrBeige</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">ACTION</i>: <span class="ACTION"></span> <span
+ class="details">(<a href='test-script-1.log.html#l-20'>MrBeige</a>,
+ 20:13:50)</span></li>
+ <li><i class="itemtype">AGREED</i>: <span class="AGREED"></span> <span
+ class="details">(<a href='test-script-1.log.html#l-21'>MrBeige</a>,
+ 20:13:50)</span></li>
+ <li><i class="itemtype">HELP</i>: <span class="HELP"></span> <span
+ class="details">(<a href='test-script-1.log.html#l-22'>MrBeige</a>,
+ 20:13:50)</span></li>
+ <li><i class="itemtype">ACCEPTED</i>: <span class="ACCEPTED"><font
+ color="green"></font></span> <span class="details">(<a
+ href='test-script-1.log.html#l-23'>MrBeige</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">REJECTED</i>: <span class="REJECTED"><font
+ color="red"></font></span> <span class="details">(<a
+ href='test-script-1.log.html#l-24'>MrBeige</a>, 20:13:50)</span></li>
+</ol>
+<br></li>
+<li><b class="TOPIC">Commands with non-ascii</b> <span class="details">(<a href='test-script-1.log.html#l-25'>MrBeige</a>, 20:13:50)</span>
+<br></li>
+<li><b class="TOPIC">üáç€</b> <span class="details">(<a href='test-script-1.log.html#l-26'>MrBeige</a>, 20:13:50)</span>
+<ol type="a">
+ <li><i class="itemtype">IDEA</i>: <span class="IDEA">üáç€</span> <span
+ class="details">(<a href='test-script-1.log.html#l-27'>MrBeige</a>,
+ 20:13:50)</span></li>
+ <li><span class="INFO">üáç€</span> <span class="details">(<a
+ href='test-script-1.log.html#l-28'>MrBeige</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">ACTION</i>: <span class="ACTION">üáç€</span>
+ <span class="details">(<a
+ href='test-script-1.log.html#l-29'>MrBeige</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">AGREED</i>: <span class="AGREED">üáç€</span>
+ <span class="details">(<a
+ href='test-script-1.log.html#l-30'>MrBeige</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">HELP</i>: <span class="HELP">üáç€</span> <span
+ class="details">(<a href='test-script-1.log.html#l-31'>MrBeige</a>,
+ 20:13:50)</span></li>
+ <li><i class="itemtype">ACCEPTED</i>: <span class="ACCEPTED"><font
+ color="green">üáç€</font></span> <span class="details">(<a
+ href='test-script-1.log.html#l-32'>MrBeige</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">REJECTED</i>: <span class="REJECTED"><font
+ color="red">üáç€</font></span> <span class="details">(<a
+ href='test-script-1.log.html#l-33'>MrBeige</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">IDEA</i>: <span class="IDEA">blah</span> <span
+ class="details">(<a href='test-script-1.log.html#l-35'>MrBeige</a>,
+ 20:13:50)</span></li>
+ <li><i class="itemtype">ACTION</i>: <span class="ACTION">blah</span>
+ <span class="details">(<a
+ href='test-script-1.log.html#l-36'>MrBeige</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">AGREED</i>: <span class="AGREED">blah</span>
+ <span class="details">(<a
+ href='test-script-1.log.html#l-37'>Utahraptor</a>, 20:13:50)</span></li>
+</ol>
+<br></li>
+<li><b class="TOPIC">Escapes</b> <span class="details">(<a href='test-script-1.log.html#l-38'>MrBeige</a>, 20:13:50)</span>
+<ol type="a">
+ <li><i class="itemtype">IDEA</i>: <span class="IDEA">blah_ blah_ ReST
+ link reference...</span> <span class="details">(<a
+ href='test-script-1.log.html#l-41'>Utahraptor</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">IDEA</i>: <span class="IDEA">blah blah
+ blah</span> <span class="details">(<a
+ href='test-script-1.log.html#l-42'>ReST1_</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">IDEA</i>: <span
+ class="IDEA">under_score</span> <span class="details">(<a
+ href='test-script-1.log.html#l-44'>ReST2_</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">IDEA</i>: <span
+ class="IDEA">under_score</span> <span class="details">(<a
+ href='test-script-1.log.html#l-45'>Re_ST</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">IDEA</i>: <span
+ class="IDEA">under1_1score</span> <span class="details">(<a
+ href='test-script-1.log.html#l-46'>Re_ST</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">IDEA</i>: <span
+ class="IDEA">under1_score</span> <span class="details">(<a
+ href='test-script-1.log.html#l-47'>Re_ST</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">IDEA</i>: <span
+ class="IDEA">under_1score</span> <span class="details">(<a
+ href='test-script-1.log.html#l-48'>Re_ST</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">IDEA</i>: <span
+ class="IDEA">under-_score</span> <span class="details">(<a
+ href='test-script-1.log.html#l-49'>Re_ST</a>, 20:13:50)</span></li>
+ <li><i class="itemtype">IDEA</i>: <span
+ class="IDEA">under_-score</span> <span class="details">(<a
+ href='test-script-1.log.html#l-50'>Re_ST</a>, 20:13:50)</span></li>
+</ol>
+<br></li>
+<li><b class="TOPIC">Links</b> <span class="details">(<a href='test-script-1.log.html#l-51'>MrBeige</a>, 20:13:50)</span>
+<ol type="a">
+ <li><a
+ href="http://test<b>.zgib.net">http://test<b>.zgib.net</a>
+ <span class="details">(<a
+ href='test-script-1.log.html#l-52'>Utahraptor</a>, 20:13:50)</span></li>
+ <li><a
+ href="ftp://test<b>.zgib.net">ftp://test<b>.zgib.net</a>
+ " <span class="details">(<a
+ href='test-script-1.log.html#l-53'>Utahraptor</a>, 20:13:50)</span></li>
+ <li><a href="mailto://a@bla%22h.com">mailto://a@bla"h.com</a> <span
+ class="details">(<a
+ href='test-script-1.log.html#l-54'>Utahraptor</a>, 20:13:50)</span></li>
+ <li><a
+ href="http://test.zgib.net/&testpage">http://test.zgib.net/&testpage</a>
+ <span class="details">(<a
+ href='test-script-1.log.html#l-55'>Utahraptor</a>, 20:13:50)</span></li>
+ <li>prefix <a
+ href="http://test.zgib.net/&testpage">http://test.zgib.net/&testpage</a>
+ suffix <span class="details">(<a
+ href='test-script-1.log.html#l-56'>Utahraptor</a>, 20:13:50)</span></li>
+ <li>prefix <a
+ href="ftp://test.zg%22ib.net/&testpage">ftp://test.zg"ib.net/&testpage</a>
+ suffix <span class="details">(<a
+ href='test-script-1.log.html#l-57'>Utahraptor</a>, 20:13:50)</span></li>
+ <li>prefix <a
+ href="mailto://a@blah.com&testpage">mailto://a@blah.com&testpage</a>
+ suffix <span class="details">(<a
+ href='test-script-1.log.html#l-58'>Utahraptor</a>, 20:13:50)</span></li>
+ <li>prefix <a href="http://google.com/">http://google.com/</a>. suffix
+ <span class="details">(<a
+ href='test-script-1.log.html#l-59'>Utahraptor</a>, 20:13:50)</span></li>
+ <li>prefix (<a href="http://google.com/">http://google.com/</a>)
+ suffix <span class="details">(<a
+ href='test-script-1.log.html#l-60'>Utahraptor</a>, 20:13:50)</span></li>
+</ol>
+<br></li>
+<li><b class="TOPIC">Character sets</b> <span class="details">(<a href='test-script-1.log.html#l-61'>MrBeige</a>, 20:13:50)</span>
+<ol type="a">
+ <li><i class="itemtype">IDEA</i>: <span class="IDEA">Nick with
+ accents.</span> <span class="details">(<a
+ href='test-script-1.log.html#l-63'>Üţáhraptõr</a>, 20:13:50)</span></li>
+</ol>
+</li>
+</ol>
+<br><br>
+
+
+
+<span class="details">
+Meeting ended at 20:13:52 UTC
+(<a href="test-script-1.log.html">full logs</a>).</span>
+
+<br><br>
+
+
+
+<h3>Action items</h3>
+<ol>
+ <li></li>
+ <li>üáç€</li>
+ <li>blah</li>
+</ol>
+<br><br>
+
+
+
+<h3>People present (lines said)</h3>
+<ol>
+ <li>MrBeige (35)</li>
+ <li>Utahraptor (13)</li>
+ <li>Re_ST (6)</li>
+ <li>T-Rex (5)</li>
+ <li>ReST2_ (2)</li>
+ <li>Üţáhraptõr (2)</li>
+ <li>ReST1_ (1)</li>
+ <li>áccents (0)</li>
+ <li>not-here (0)</li>
+ <li>** (0)</li>
+ <li>áccenẗs (0)</li>
+ <li>someone-not-present (0)</li>
+ <li><b> (0)</li>
+</ol>
+<br><br>
+
+
+
+<span class="details">Generated by <a href="http://wiki.debian.org/MeetBot">MeetBot</a> 0.1.4.</span>
+</body></html>
diff --git a/bot/tests/test-script-1.log.html b/bot/tests/test-script-1.log.html
new file mode 100644
index 0000000..5e7642c
--- /dev/null
+++ b/bot/tests/test-script-1.log.html
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
+<title>#test-script-1 log</title>
+<style type="text/css">
+/* For the .log.html */
+pre { /*line-height: 125%;*/
+ white-space: pre-wrap; }
+body { background: #f0f0f0; }
+
+body .tm { color: #007020 } /* time */
+body .nk { color: #062873; font-weight: bold } /* nick, regular */
+body .nka { color: #007020; font-weight: bold } /* action nick */
+body .ac { color: #00A000 } /* action line */
+body .hi { color: #4070a0 } /* hilights */
+/* Things to make particular MeetBot commands stick out */
+body .topic { color: #007020; font-weight: bold }
+body .topicline { color: #000080; font-weight: bold }
+body .cmd { color: #007020; font-weight: bold }
+body .cmdline { font-weight: bold }
+
+</style>
+</head>
+
+<body>
+<pre><a name="l-1"></a><span class="tm">20:13:46</span><span class="nk"> <MrBeige></span> <span class="cmd">#startmeeting</span><span class="cmdline"></span>
+<a name="l-2"></a><span class="tm">20:13:50</span><span class="nk"> <T-Rex></span> <span class="cmd">#info </span><span class="cmdline">this command is just before the first topic</span>
+<a name="l-3"></a><span class="tm">20:13:50</span><span class="nk"> <T-Rex></span> <span class="topic">#topic </span><span class="topicline">Test of topics</span>
+<a name="l-4"></a><span class="tm">20:13:50</span><span class="nk"> <T-Rex></span> <span class="topic">#topic </span><span class="topicline">Second topic</span>
+<a name="l-5"></a><span class="tm">20:13:50</span><span class="nk"> <T-Rex></span> <span class="cmd">#meetingtopic </span><span class="cmdline">the meeting topic</span>
+<a name="l-6"></a><span class="tm">20:13:50</span><span class="nk"> <T-Rex></span> <span class="topic">#topic </span><span class="topicline">With áccents</span>
+<a name="l-7"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="topic">#topic </span><span class="topicline">General command tests</span>
+<a name="l-8"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#accepted </span><span class="cmdline">we will include this new format if we so choose.</span>
+<a name="l-9"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#rejected </span><span class="cmdline">we will not include this new format.</span>
+<a name="l-10"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#chair </span><span class="cmdline">Utahraptor T-Rex not-here</span>
+<a name="l-11"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#chair </span><span class="cmdline">Utahraptor T-Rex</span>
+<a name="l-12"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#nick </span><span class="cmdline">someone-not-present</span>
+<a name="l-13"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#chair </span><span class="cmdline">áccents</span>
+<a name="l-14"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#nick </span><span class="cmdline">áccenẗs</span>
+<a name="l-15"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#unchar </span><span class="cmdline">not-here</span>
+<a name="l-16"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="topic">#topic </span><span class="topicline">Test of all commands with different arguments</span>
+<a name="l-17"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="topic">#topic</span><span class="topicline"></span>
+<a name="l-18"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#idea</span><span class="cmdline"></span>
+<a name="l-19"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#info</span><span class="cmdline"></span>
+<a name="l-20"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#action</span><span class="cmdline"></span>
+<a name="l-21"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#agreed</span><span class="cmdline"></span>
+<a name="l-22"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#halp</span><span class="cmdline"></span>
+<a name="l-23"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#accepted</span><span class="cmdline"></span>
+<a name="l-24"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#rejected</span><span class="cmdline"></span>
+<a name="l-25"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="topic">#topic </span><span class="topicline">Commands with non-ascii</span>
+<a name="l-26"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="topic">#topic </span><span class="topicline">üáç€</span>
+<a name="l-27"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#idea </span><span class="cmdline">üáç€</span>
+<a name="l-28"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#info </span><span class="cmdline">üáç€</span>
+<a name="l-29"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#action </span><span class="cmdline">üáç€</span>
+<a name="l-30"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#agreed </span><span class="cmdline">üáç€</span>
+<a name="l-31"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#halp </span><span class="cmdline">üáç€</span>
+<a name="l-32"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#accepted </span><span class="cmdline">üáç€</span>
+<a name="l-33"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#rejected </span><span class="cmdline">üáç€</span>
+<a name="l-34"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#item </span><span class="cmdline">blah</span>
+<a name="l-35"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#idea </span><span class="cmdline">blah</span>
+<a name="l-36"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="cmd">#action </span><span class="cmdline">blah</span>
+<a name="l-37"></a><span class="tm">20:13:50</span><span class="nk"> <Utahraptor></span> <span class="cmd">#agreed </span><span class="cmdline">blah</span>
+<a name="l-38"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="topic">#topic </span><span class="topicline">Escapes</span>
+<a name="l-39"></a><span class="tm">20:13:50</span><span class="nk"> <Utahraptor></span> <span class="cmd">#nick </span><span class="cmdline"><b></span>
+<a name="l-40"></a><span class="tm">20:13:50</span><span class="nk"> <Utahraptor></span> <span class="cmd">#nick </span><span class="cmdline">**</span>
+<a name="l-41"></a><span class="tm">20:13:50</span><span class="nk"> <Utahraptor></span> <span class="cmd">#idea </span><span class="cmdline">blah_ blah_ ReST link reference...</span>
+<a name="l-42"></a><span class="tm">20:13:50</span><span class="nk"> <ReST1_></span> <span class="cmd">#idea </span><span class="cmdline">blah blah blah</span>
+<a name="l-43"></a><span class="tm">20:13:50</span><span class="nk"> <ReST2_></span> this is some text
+<a name="l-44"></a><span class="tm">20:13:50</span><span class="nk"> <ReST2_></span> <span class="cmd">#idea </span><span class="cmdline">under_score</span>
+<a name="l-45"></a><span class="tm">20:13:50</span><span class="nk"> <Re_ST></span> <span class="cmd">#idea </span><span class="cmdline">under_score</span>
+<a name="l-46"></a><span class="tm">20:13:50</span><span class="nk"> <Re_ST></span> <span class="cmd">#idea </span><span class="cmdline">under1_1score</span>
+<a name="l-47"></a><span class="tm">20:13:50</span><span class="nk"> <Re_ST></span> <span class="cmd">#idea </span><span class="cmdline">under1_score</span>
+<a name="l-48"></a><span class="tm">20:13:50</span><span class="nk"> <Re_ST></span> <span class="cmd">#idea </span><span class="cmdline">under_1score</span>
+<a name="l-49"></a><span class="tm">20:13:50</span><span class="nk"> <Re_ST></span> <span class="cmd">#idea </span><span class="cmdline">under-_score</span>
+<a name="l-50"></a><span class="tm">20:13:50</span><span class="nk"> <Re_ST></span> <span class="cmd">#idea </span><span class="cmdline">under_-score</span>
+<a name="l-51"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="topic">#topic </span><span class="topicline">Links</span>
+<a name="l-52"></a><span class="tm">20:13:50</span><span class="nk"> <Utahraptor></span> <span class="cmd">#link </span><span class="cmdline">http://test<b>.zgib.net</span>
+<a name="l-53"></a><span class="tm">20:13:50</span><span class="nk"> <Utahraptor></span> <span class="cmd">#link </span><span class="cmdline">ftp://test<b>.zgib.net "</span>
+<a name="l-54"></a><span class="tm">20:13:50</span><span class="nk"> <Utahraptor></span> <span class="cmd">#link </span><span class="cmdline">mailto://a@bla"h.com</span>
+<a name="l-55"></a><span class="tm">20:13:50</span><span class="nk"> <Utahraptor></span> <span class="cmd">#link </span><span class="cmdline">http://test.zgib.net/&testpage</span>
+<a name="l-56"></a><span class="tm">20:13:50</span><span class="nk"> <Utahraptor></span> <span class="cmd">#link </span><span class="cmdline">prefix http://test.zgib.net/&testpage suffix</span>
+<a name="l-57"></a><span class="tm">20:13:50</span><span class="nk"> <Utahraptor></span> <span class="cmd">#link </span><span class="cmdline">prefix ftp://test.zg"ib.net/&testpage suffix</span>
+<a name="l-58"></a><span class="tm">20:13:50</span><span class="nk"> <Utahraptor></span> <span class="cmd">#link </span><span class="cmdline">prefix mailto://a@blah.com&testpage suffix</span>
+<a name="l-59"></a><span class="tm">20:13:50</span><span class="nk"> <Utahraptor></span> <span class="cmd">#link </span><span class="cmdline">prefix http://google.com/. suffix</span>
+<a name="l-60"></a><span class="tm">20:13:50</span><span class="nk"> <Utahraptor></span> <span class="cmd">#link </span><span class="cmdline">prefix (http://google.com/) suffix</span>
+<a name="l-61"></a><span class="tm">20:13:50</span><span class="nk"> <MrBeige></span> <span class="topic">#topic </span><span class="topicline">Character sets</span>
+<a name="l-62"></a><span class="tm">20:13:50</span><span class="nk"> <Üţáhraptõr></span> Nick with accents.
+<a name="l-63"></a><span class="tm">20:13:50</span><span class="nk"> <Üţáhraptõr></span> <span class="cmd">#idea </span><span class="cmdline">Nick with accents.</span>
+<a name="l-64"></a><span class="tm">20:13:52</span><span class="nk"> <MrBeige></span> <span class="cmd">#endmeeting</span><span class="cmdline"></span></pre>
+</body></html>
diff --git a/bot/tests/test-script-1.txt b/bot/tests/test-script-1.txt
new file mode 100644
index 0000000..0e279bb
--- /dev/null
+++ b/bot/tests/test-script-1.txt
@@ -0,0 +1,98 @@
+======================
+#test-script-1 Meeting
+======================
+
+
+Meeting started by MrBeige at 20:13:46 UTC. The full logs are available
+at test-script-1.log.html .
+
+
+
+Meeting summary
+---------------
+
+* this command is just before the first topic (T-Rex, 20:13:50)
+* General command tests (MrBeige, 20:13:50)
+ * ACCEPTED: we will include this new format if we so choose.
+ (MrBeige, 20:13:50)
+ * REJECTED: we will not include this new format. (MrBeige, 20:13:50)
+
+* Test of all commands with different arguments (MrBeige, 20:13:50)
+
+* (MrBeige, 20:13:50)
+ * IDEA: (MrBeige, 20:13:50)
+ * (MrBeige, 20:13:50)
+ * ACTION: (MrBeige, 20:13:50)
+ * AGREED: (MrBeige, 20:13:50)
+ * HELP: (MrBeige, 20:13:50)
+ * ACCEPTED: (MrBeige, 20:13:50)
+ * REJECTED: (MrBeige, 20:13:50)
+
+* Commands with non-ascii (MrBeige, 20:13:50)
+
+* üáç€ (MrBeige, 20:13:50)
+ * IDEA: üáç€ (MrBeige, 20:13:50)
+ * üáç€ (MrBeige, 20:13:50)
+ * ACTION: üáç€ (MrBeige, 20:13:50)
+ * AGREED: üáç€ (MrBeige, 20:13:50)
+ * HELP: üáç€ (MrBeige, 20:13:50)
+ * ACCEPTED: üáç€ (MrBeige, 20:13:50)
+ * REJECTED: üáç€ (MrBeige, 20:13:50)
+ * IDEA: blah (MrBeige, 20:13:50)
+ * ACTION: blah (MrBeige, 20:13:50)
+ * AGREED: blah (Utahraptor, 20:13:50)
+
+* Escapes (MrBeige, 20:13:50)
+ * IDEA: blah_ blah_ ReST link reference... (Utahraptor, 20:13:50)
+ * IDEA: blah blah blah (ReST1_, 20:13:50)
+ * IDEA: under_score (ReST2_, 20:13:50)
+ * IDEA: under_score (Re_ST, 20:13:50)
+ * IDEA: under1_1score (Re_ST, 20:13:50)
+ * IDEA: under1_score (Re_ST, 20:13:50)
+ * IDEA: under_1score (Re_ST, 20:13:50)
+ * IDEA: under-_score (Re_ST, 20:13:50)
+ * IDEA: under_-score (Re_ST, 20:13:50)
+
+* Links (MrBeige, 20:13:50)
+ * LINK: http://test<b>.zgib.net (Utahraptor, 20:13:50)
+ * LINK: ftp://test<b>.zgib.net " (Utahraptor, 20:13:50)
+ * LINK: mailto://a@bla"h.com (Utahraptor, 20:13:50)
+ * LINK: http://test.zgib.net/&testpage (Utahraptor, 20:13:50)
+ * LINK: prefix http://test.zgib.net/&testpage suffix (Utahraptor,
+ 20:13:50)
+ * LINK: prefix ftp://test.zg"ib.net/&testpage suffix (Utahraptor,
+ 20:13:50)
+ * LINK: prefix mailto://a@blah.com&testpage suffix (Utahraptor,
+ 20:13:50)
+ * LINK: prefix http://google.com/. suffix (Utahraptor, 20:13:50)
+ * LINK: prefix (http://google.com/) suffix (Utahraptor, 20:13:50)
+
+* Character sets (MrBeige, 20:13:50)
+ * IDEA: Nick with accents. (Üţáhraptõr, 20:13:50)
+
+
+
+Meeting ended at 20:13:52 UTC.
+
+
+
+People present (lines said)
+---------------------------
+
+* MrBeige (35)
+* Utahraptor (13)
+* Re_ST (6)
+* T-Rex (5)
+* ReST2_ (2)
+* Üţáhraptõr (2)
+* ReST1_ (1)
+* áccents (0)
+* not-here (0)
+* ** (0)
+* áccenẗs (0)
+* someone-not-present (0)
+* <b> (0)
+
+
+
+Generated by `MeetBot`_ 0.1.4
\ No newline at end of file
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [gentoo-commits] proj/council-webapp:master commit in: bot/tests/, bot/ircmeeting/
@ 2011-06-18 15:46 Petteri Räty
0 siblings, 0 replies; 12+ messages in thread
From: Petteri Räty @ 2011-06-18 15:46 UTC (permalink / raw
To: gentoo-commits
commit: e2ff317cf9c8832a98d805e7a04e1a2b3ed5520c
Author: Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
AuthorDate: Mon Jun 13 16:25:17 2011 +0000
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Mon Jun 13 16:25:17 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=e2ff317c
Make Meetbot tests cleaner, fix one bug found in the process
---
bot/ircmeeting/agenda.py | 2 +-
bot/tests/run_test.py | 56 +++++++++-------------------------------
bot/tests/test_meeting.py | 61 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 75 insertions(+), 44 deletions(-)
diff --git a/bot/ircmeeting/agenda.py b/bot/ircmeeting/agenda.py
index 2269f6f..e3f456c 100644
--- a/bot/ircmeeting/agenda.py
+++ b/bot/ircmeeting/agenda.py
@@ -60,7 +60,7 @@ class Agenda(object):
def end_vote(self):
if self._vote_open:
self._vote_open = False
- return voting_already_closed_msg
+ return self.voting_already_closed_msg
return voting_close_msg
def get_data(self):
diff --git a/bot/tests/run_test.py b/bot/tests/run_test.py
index f304a2b..79bb9d7 100644
--- a/bot/tests/run_test.py
+++ b/bot/tests/run_test.py
@@ -7,19 +7,14 @@ import shutil
import sys
import tempfile
import unittest
-import time
os.environ['MEETBOT_RUNNING_TESTS'] = '1'
import ircmeeting.meeting as meeting
import ircmeeting.writers as writers
-running_tests = True
+import test_meeting
-def parse_time(time_):
- try: return time.strptime(time_, "%H:%M:%S")
- except ValueError: pass
- try: return time.strptime(time_, "%H:%M")
- except ValueError: pass
+running_tests = True
def process_meeting(contents, extraConfig={}, dontSave=True,
filename='/dev/null'):
@@ -347,21 +342,13 @@ class MeetBotTest(unittest.TestCase):
def test_agenda(self):
""" Test agenda management
"""
- logline_re = re.compile(r'\[?([0-9: ]*)\]? *<[@+]?([^>]+)> *(.*)')
- loglineAction_re = re.compile(r'\[?([0-9: ]*)\]? *\* *([^ ]+) *(.*)')
-
- M = process_meeting('#startmeeting')
- log = []
- M._sendReply = lambda x: log.append(x)
- M.config.agenda._voters = ['x', 'z']
- M.config.agenda._agenda = [['first item', ['opt1', 'opt2']], ['second item', []]]
- M.config.agenda._votes = { }
- for i in M.config.agenda._agenda:
- M.config.agenda._votes[i[0]] = { }
-
- M.starttime = time.gmtime(0)
- contents = """20:13:50 <x> #nextitem
+ test = test_meeting.TestMeeting()
+ test.set_voters(['x', 'z'])
+ test.set_agenda([['first item', ['opt1', 'opt2']], ['second item', []]])
+ test.process("""
+ 20:13:50 <x> #startmeeting
+ 20:13:50 <x> #nextitem
20:13:50 <x> #nextitem
20:13:50 <x> #previtem
20:13:50 <x> #previtem
@@ -371,27 +358,8 @@ class MeetBotTest(unittest.TestCase):
20:13:50 <y> #vote 0
20:13:50 <z> #vote 0
20:13:50 <x> #endvote
- 20:13:50 <x> #endmeeting"""
-
- for line in contents.split('\n'):
- # match regular spoken lines:
- m = logline_re.match(line)
- if m:
- time_ = parse_time(m.group(1).strip())
- nick = m.group(2).strip()
- line = m.group(3).strip()
- if M.owner is None:
- M.owner = nick ; M.chairs = {nick:True}
- M.addline(nick, line, time_=time_)
- # match /me lines
- m = loglineAction_re.match(line)
- if m:
- time_ = parse_time(m.group(1).strip())
- nick = m.group(2).strip()
- line = m.group(3).strip()
- M.addline(nick, "ACTION "+line, time_=time_)
-
- self.assert_(M.config.agenda._votes == {'first item': {u'x': 'opt2', u'z': 'opt1'}, 'second item': {}})
+ 20:13:50 <x> #endmeeting""")
+
answers = ['Current agenda item is second item.',
'Current agenda item is second item.',
@@ -406,7 +374,9 @@ class MeetBotTest(unittest.TestCase):
"You voted for #1 - ['opt1', 'opt2']",
'You can not vote. Only x, z can vote',
'You voted for #0 - first item']
- self.assert_(log[0:len(answers)] == answers)
+
+ self.assert_(test.votes == {'first item': {u'x': 'opt2', u'z': 'opt1'}, 'second item': {}})
+ self.assert_(test.log[0:len(answers)] == answers)
if __name__ == '__main__':
os.chdir(os.path.join(os.path.dirname(__file__), '.'))
diff --git a/bot/tests/test_meeting.py b/bot/tests/test_meeting.py
new file mode 100644
index 0000000..9315b63
--- /dev/null
+++ b/bot/tests/test_meeting.py
@@ -0,0 +1,61 @@
+import ircmeeting.meeting as meeting
+import ircmeeting.writers as writers
+import re
+import time
+def process_meeting(contents, extraConfig={}, dontSave=True,
+ filename='/dev/null'):
+ """Take a test script, return Meeting object of that meeting.
+
+ To access the results (a dict keyed by extensions), use M.save(),
+ with M being the return of this function.
+ """
+class TestMeeting:
+ logline_re = re.compile(r'\[?([0-9: ]*)\]? *<[@+]?([^>]+)> *(.*)')
+ loglineAction_re = re.compile(r'\[?([0-9: ]*)\]? *\* *([^ ]+) *(.*)')
+ M = meeting.process_meeting(contents = '',
+ channel = "#none", filename = '/dev/null',
+ dontSave = True, safeMode = False,
+ extraConfig = {})
+ log = []
+
+ def __init__(self):
+ self.M._sendReply = lambda x: self.log.append(x)
+ self.M.starttime = time.gmtime(0)
+
+ def set_voters(self, voters):
+ self.M.config.agenda._voters = voters
+
+ def set_agenda(self, agenda):
+ self.M.config.agenda._agenda = agenda
+ self.M.config.agenda._votes = { }
+ for i in agenda:
+ self.M.config.agenda._votes[i[0]] = { }
+
+
+ def parse_time(self, time_):
+ try: return time.strptime(time_, "%H:%M:%S")
+ except ValueError: pass
+ try: return time.strptime(time_, "%H:%M")
+ except ValueError: pass
+
+ def process(self, content):
+ for line in content.split('\n'):
+ # match regular spoken lines:
+ m = self.logline_re.match(line)
+ if m:
+ time_ = self.parse_time(m.group(1).strip())
+ nick = m.group(2).strip()
+ line = m.group(3).strip()
+ if self.M.owner is None:
+ self.M.owner = nick ; self.M.chairs = {nick:True}
+ self.M.addline(nick, line, time_=time_)
+ # match /me lines
+ self.m = self.loglineAction_re.match(line)
+ if m:
+ time_ = self.parse_time(m.group(1).strip())
+ nick = m.group(2).strip()
+ line = m.group(3).strip()
+ self.M.addline(nick, "ACTION "+line, time_=time_)
+
+ def votes(self):
+ return(self.M.config.agenda._votes)
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [gentoo-commits] proj/council-webapp:master commit in: bot/tests/, bot/ircmeeting/
@ 2011-06-18 15:46 Petteri Räty
0 siblings, 0 replies; 12+ messages in thread
From: Petteri Räty @ 2011-06-18 15:46 UTC (permalink / raw
To: gentoo-commits
commit: 2460e74c1a09fe988017437bbebdc8c6e5e41694
Author: Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
AuthorDate: Thu Jun 16 14:31:05 2011 +0000
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Thu Jun 16 15:06:46 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=2460e74c
Add #option list command
---
bot/ircmeeting/agenda.py | 18 ++++++++++----
bot/ircmeeting/meeting.py | 6 +++++
bot/tests/run_test.py | 55 ++++++++++++++++++++++++++++++++------------
3 files changed, 59 insertions(+), 20 deletions(-)
diff --git a/bot/ircmeeting/agenda.py b/bot/ircmeeting/agenda.py
index cfecc61..32ddb9f 100644
--- a/bot/ircmeeting/agenda.py
+++ b/bot/ircmeeting/agenda.py
@@ -7,7 +7,7 @@ class Agenda(object):
empty_agenda_msg = "Agenda is empty so I can't help you manage meeting (and voting)."
current_item_msg = "Current agenda item is {}."
voting_already_open_msg = "Voting is already open. You can end it with #endvote."
- voting_open_msg = "Voting started. Your choices are:{}Vote #vote <option number>.\nEnd voting with #endvote."
+ voting_open_msg = "Voting started. {}Vote #vote <option number>.\nEnd voting with #endvote."
voting_close_msg = "Voting closed."
voting_already_closed_msg = "Voting is already closed. You can start it with #startvote."
voting_open_so_item_not_changed_msg = "Voting is currently open so I didn't change item. Please #endvote first"
@@ -60,10 +60,7 @@ class Agenda(object):
if self._vote_open:
return self.voting_already_open_msg
self._vote_open = True
- options = "\n"
- for i in range(len(self._agenda[self._current_item][1])):
- options += str.format("{}. {}\n", i, self._agenda[self._current_item][1][i])
- return str.format(self.voting_open_msg, options)
+ return str.format(self.voting_open_msg, self.options())
def end_vote(self):
if not self.conf.manage_agenda:
@@ -104,6 +101,17 @@ class Agenda(object):
result = json.loads(str)
return result
+ def options(self):
+ options_list = self._agenda[self._current_item][1]
+ n = len(options_list)
+ if n == 0:
+ return 'No voting options available.'
+ else:
+ options = "Available voting options are:\n"
+ for i in range(n):
+ options += str.format("{}. {}\n", i, options_list[i])
+ return options
+
def post_result(self):
if not self.conf.manage_agenda:
return('')
diff --git a/bot/ircmeeting/meeting.py b/bot/ircmeeting/meeting.py
index 26138a2..d8589c4 100644
--- a/bot/ircmeeting/meeting.py
+++ b/bot/ircmeeting/meeting.py
@@ -340,6 +340,12 @@ class MeetingCommands(object):
for messageline in self.config.agenda.vote(nick, line).split('\n'):
self.reply(messageline)
+ def do_option(self, nick, time_, line, **kwargs):
+ if re.match( ' *?list', line):
+ result = self.config.agenda.options()
+ for messageline in result.split('\n'):
+ self.reply(messageline)
+
def do_endmeeting(self, nick, time_, **kwargs):
"""End the meeting."""
if not self.isChair(nick): return
diff --git a/bot/tests/run_test.py b/bot/tests/run_test.py
index 2b6c6f3..c28f1ae 100644
--- a/bot/tests/run_test.py
+++ b/bot/tests/run_test.py
@@ -339,40 +339,65 @@ class MeetBotTest(unittest.TestCase):
assert M.config.filename().endswith('somechannel-blah1234'),\
"Filename not as expected: "+M.config.filename()
- def test_agenda(self):
- """ Test agenda management
- """
-
+ def get_simple_agenda_test(self):
test = test_meeting.TestMeeting()
test.set_voters(['x', 'z'])
test.set_agenda([['first item', ['opt1', 'opt2']], ['second item', []]])
+ test.M.config.manage_agenda = False
-
- # Test starting meeting. Enable agenda management after that
test.answer_should_match("20:13:50 <x> #startmeeting",
"Meeting started .*\nUseful Commands: #action #agreed #help #info #idea #link #topic.\n")
test.M.config.manage_agenda = True
- # Test moving through items
+ return(test)
+
+ def test_agenda_item_changing(self):
+ test = self.get_simple_agenda_test()
+
+ # Test changing item before vote
test.answer_should_match('20:13:50 <x> #nextitem', 'Current agenda item is second item.')
test.answer_should_match('20:13:50 <x> #nextitem', 'Current agenda item is second item.')
test.answer_should_match('20:13:50 <x> #previtem', 'Current agenda item is first item.')
test.answer_should_match('20:13:50 <x> #previtem', 'Current agenda item is first item.')
- # Test voting
+ # Test changing item during vote
+ test.process('20:13:50 <x> #startvote')
+ test.answer_should_match('20:13:50 <x> #nextitem', 'Voting is currently ' +\
+ 'open so I didn\'t change item. Please #endvote first')
+ test.answer_should_match('20:13:50 <x> #previtem', 'Voting is currently ' +\
+ 'open so I didn\'t change item. Please #endvote first')
+
+ # Test changing item after vote
+ test.process('20:13:50 <x> #endvote')
+ test.answer_should_match('20:13:50 <x> #nextitem', 'Current agenda item is second item.')
+ test.answer_should_match('20:13:50 <x> #nextitem', 'Current agenda item is second item.')
+ test.answer_should_match('20:13:50 <x> #previtem', 'Current agenda item is first item.')
+ test.answer_should_match('20:13:50 <x> #previtem', 'Current agenda item is first item.')
+
+ def test_agenda_option_listing(self):
+ test = self.get_simple_agenda_test()
+
+ test.answer_should_match('20:13:50 <x> #option list', 'Available voting options ' +\
+ 'are:\n0. opt1\n1. opt2\n')
+ test.process('20:13:50 <x> #nextitem')
+ test.answer_should_match('20:13:50 <x> #option list', 'No voting options available.')
+ test.process('20:13:50 <x> #previtem')
+ test.answer_should_match('20:13:50 <x> #option list', 'Available voting options ' +\
+ 'are:\n0. opt1\n1. opt2\n')
+
+ def test_agenda_voting(self):
+ test = self.get_simple_agenda_test()
test.answer_should_match('20:13:50 <x> #startvote', 'Voting started\. ' +\
- 'Your choices are:\n0. opt1\n1. opt2\nVote ' +\
+ 'Available voting options are:\n0. opt1\n1. opt2\nVote ' +\
'#vote <option number>.\nEnd voting with #endvote.')
test.answer_should_match('20:13:50 <x> #startvote', 'Voting is already open. ' +\
'You can end it with #endvote.')
test.answer_should_match('20:13:50 <x> #vote 10', 'Your vote was out of range\!')
- test.answer_should_match('20:13:50 <x> #vote 1', 'You voted for #1 - opt2')
test.answer_should_match('20:13:50 <x> #vote 0', 'You voted for #0 - opt1')
- test.answer_should_match('20:13:50 <x> #vote 0', 'You voted for #0 - opt1')
- test.answer_should_match('20:13:50 <x> #nextitem', 'Voting is currently ' +\
- 'open so I didn\'t change item. Please #endvote first')
- test.answer_should_match('20:13:50 <x> #previtem', 'Voting is currently ' +\
- 'open so I didn\'t change item. Please #endvote first')
+ test.answer_should_match('20:13:50 <x> #vote 1', 'You voted for #1 - opt2')
+ test.answer_should_match('20:13:50 <z> #vote 0', 'You voted for #0 - opt1')
+ test.answer_should_match('20:13:50 <x> #option list', 'Available voting options ' +\
+ 'are:\n0. opt1\n1. opt2\n')
test.answer_should_match('20:13:50 <x> #endvote', 'Voting closed.')
test.answer_should_match('20:13:50 <x> #endvote', 'Voting is already closed. ' +\
'You can start it with #startvote.')
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [gentoo-commits] proj/council-webapp:master commit in: bot/tests/, bot/ircmeeting/
@ 2011-06-18 15:46 Petteri Räty
0 siblings, 0 replies; 12+ messages in thread
From: Petteri Räty @ 2011-06-18 15:46 UTC (permalink / raw
To: gentoo-commits
commit: 9ccab32b9a8bd934555158115db64a25a266fb53
Author: Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
AuthorDate: Tue Jun 14 14:21:31 2011 +0000
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Tue Jun 14 16:45:39 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=9ccab32b
Improve Supybot tests, fix bugs found in the process
---
bot/ircmeeting/agenda.py | 12 ++++----
bot/tests/run_test.py | 68 +++++++++++++++++++++++---------------------
bot/tests/test_meeting.py | 16 ++++++----
3 files changed, 51 insertions(+), 45 deletions(-)
diff --git a/bot/ircmeeting/agenda.py b/bot/ircmeeting/agenda.py
index 247907b..cfecc61 100644
--- a/bot/ircmeeting/agenda.py
+++ b/bot/ircmeeting/agenda.py
@@ -7,8 +7,8 @@ class Agenda(object):
empty_agenda_msg = "Agenda is empty so I can't help you manage meeting (and voting)."
current_item_msg = "Current agenda item is {}."
voting_already_open_msg = "Voting is already open. You can end it with #endvote."
- voting_open_msg = "Voting started. Your choices are: {} Vote #vote <option number>.\n End voting with #endvote."
- voting_close_msg = "Voting is closed."
+ voting_open_msg = "Voting started. Your choices are:{}Vote #vote <option number>.\nEnd voting with #endvote."
+ voting_close_msg = "Voting closed."
voting_already_closed_msg = "Voting is already closed. You can start it with #startvote."
voting_open_so_item_not_changed_msg = "Voting is currently open so I didn't change item. Please #endvote first"
can_not_vote_msg = "You can not vote. Only {} can vote"
@@ -38,7 +38,7 @@ class Agenda(object):
if not self.conf.manage_agenda:
return('')
if self._vote_open:
- return voting_open_so_item_not_changed_msg
+ return self.voting_open_so_item_not_changed_msg
else:
if (self._current_item + 1) < len(self._agenda):
self._current_item += 1
@@ -48,7 +48,7 @@ class Agenda(object):
if not self.conf.manage_agenda:
return('')
if self._vote_open:
- return voting_open_so_item_not_changed_msg
+ return self.voting_open_so_item_not_changed_msg
else:
if self._current_item > 0:
self._current_item -= 1
@@ -70,8 +70,8 @@ class Agenda(object):
return('')
if self._vote_open:
self._vote_open = False
- return self.voting_already_closed_msg
- return voting_close_msg
+ return self.voting_close_msg
+ return self.voting_already_closed_msg
def get_data(self):
if not self.conf.manage_agenda:
diff --git a/bot/tests/run_test.py b/bot/tests/run_test.py
index f4e6e49..2b6c6f3 100644
--- a/bot/tests/run_test.py
+++ b/bot/tests/run_test.py
@@ -344,40 +344,44 @@ class MeetBotTest(unittest.TestCase):
"""
test = test_meeting.TestMeeting()
- test.M.config.manage_agenda = True
test.set_voters(['x', 'z'])
test.set_agenda([['first item', ['opt1', 'opt2']], ['second item', []]])
- test.process("""
- 20:13:50 <x> #startmeeting
- 20:13:50 <x> #nextitem
- 20:13:50 <x> #nextitem
- 20:13:50 <x> #previtem
- 20:13:50 <x> #previtem
- 20:13:50 <x> #startvote
- 20:13:50 <x> #vote 10
- 20:13:50 <x> #vote 1
- 20:13:50 <y> #vote 0
- 20:13:50 <z> #vote 0
- 20:13:50 <x> #endvote
- 20:13:50 <x> #endmeeting""")
-
-
- answers = ['Current agenda item is second item.',
- 'Current agenda item is second item.',
- 'Current agenda item is first item.',
- 'Current agenda item is first item.',
- 'Voting started. Your choices are: ',
- '0. first item',
- "1. ['opt1', 'opt2']",
- ' Vote #vote <option number>.',
- ' End voting with #endvote.',
- 'Your vote was out of range!',
- "You voted for #1 - ['opt1', 'opt2']",
- 'You can not vote. Only x, z can vote',
- 'You voted for #0 - first item']
-
- self.assert_(test.votes == {'first item': {u'x': 'opt2', u'z': 'opt1'}, 'second item': {}})
- self.assert_(test.log[0:len(answers)] == answers)
+
+
+ # Test starting meeting. Enable agenda management after that
+ test.answer_should_match("20:13:50 <x> #startmeeting",
+ "Meeting started .*\nUseful Commands: #action #agreed #help #info #idea #link #topic.\n")
+ test.M.config.manage_agenda = True
+
+ # Test moving through items
+ test.answer_should_match('20:13:50 <x> #nextitem', 'Current agenda item is second item.')
+ test.answer_should_match('20:13:50 <x> #nextitem', 'Current agenda item is second item.')
+ test.answer_should_match('20:13:50 <x> #previtem', 'Current agenda item is first item.')
+ test.answer_should_match('20:13:50 <x> #previtem', 'Current agenda item is first item.')
+
+ # Test voting
+ test.answer_should_match('20:13:50 <x> #startvote', 'Voting started\. ' +\
+ 'Your choices are:\n0. opt1\n1. opt2\nVote ' +\
+ '#vote <option number>.\nEnd voting with #endvote.')
+ test.answer_should_match('20:13:50 <x> #startvote', 'Voting is already open. ' +\
+ 'You can end it with #endvote.')
+ test.answer_should_match('20:13:50 <x> #vote 10', 'Your vote was out of range\!')
+ test.answer_should_match('20:13:50 <x> #vote 1', 'You voted for #1 - opt2')
+ test.answer_should_match('20:13:50 <x> #vote 0', 'You voted for #0 - opt1')
+ test.answer_should_match('20:13:50 <x> #vote 0', 'You voted for #0 - opt1')
+ test.answer_should_match('20:13:50 <x> #nextitem', 'Voting is currently ' +\
+ 'open so I didn\'t change item. Please #endvote first')
+ test.answer_should_match('20:13:50 <x> #previtem', 'Voting is currently ' +\
+ 'open so I didn\'t change item. Please #endvote first')
+ test.answer_should_match('20:13:50 <x> #endvote', 'Voting closed.')
+ test.answer_should_match('20:13:50 <x> #endvote', 'Voting is already closed. ' +\
+ 'You can start it with #startvote.')
+
+ test.M.config.manage_agenda = False
+ test.answer_should_match('20:13:50 <x> #endmeeting', 'Meeting ended ' +\
+ '.*\nMinutes:.*\nMinutes \(text\):.*\nLog:.*')
+
+ assert(test.votes() == {'first item': {u'x': 'opt2', u'z': 'opt1'}, 'second item': {}})
if __name__ == '__main__':
os.chdir(os.path.join(os.path.dirname(__file__), '.'))
diff --git a/bot/tests/test_meeting.py b/bot/tests/test_meeting.py
index 9315b63..78bd2dc 100644
--- a/bot/tests/test_meeting.py
+++ b/bot/tests/test_meeting.py
@@ -2,13 +2,6 @@ import ircmeeting.meeting as meeting
import ircmeeting.writers as writers
import re
import time
-def process_meeting(contents, extraConfig={}, dontSave=True,
- filename='/dev/null'):
- """Take a test script, return Meeting object of that meeting.
-
- To access the results (a dict keyed by extensions), use M.save(),
- with M being the return of this function.
- """
class TestMeeting:
logline_re = re.compile(r'\[?([0-9: ]*)\]? *<[@+]?([^>]+)> *(.*)')
loglineAction_re = re.compile(r'\[?([0-9: ]*)\]? *\* *([^ ]+) *(.*)')
@@ -57,5 +50,14 @@ class TestMeeting:
line = m.group(3).strip()
self.M.addline(nick, "ACTION "+line, time_=time_)
+ def answer_should_match(self, line, answer_regexp):
+ self.log = []
+ self.process(line)
+ answer = '\n'.join(self.log)
+ error_msg = "Answer for:\n\t'" + line + "'\n was \n\t'" + answer +\
+ "'\ndid not match regexp\n\t'" + answer_regexp + "'"
+ answer_matches = re.match(answer_regexp, answer)
+ assert answer_matches, error_msg
+
def votes(self):
return(self.M.config.agenda._votes)
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [gentoo-commits] proj/council-webapp:master commit in: bot/tests/, bot/ircmeeting/
@ 2011-06-18 15:46 Petteri Räty
0 siblings, 0 replies; 12+ messages in thread
From: Petteri Räty @ 2011-06-18 15:46 UTC (permalink / raw
To: gentoo-commits
commit: 758c16c3424aa59c173ccad7ca2c311f1d817001
Author: Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
AuthorDate: Tue Jun 14 12:13:03 2011 +0000
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Tue Jun 14 12:13:03 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=758c16c3
Disable agenda management by default
Reasons:
* Users may not want it, so they should be able to turn it off
* Tests don't fail when localhost:3000 is unreachable
* Make tests faster.
---
bot/ircmeeting/agenda.py | 16 ++++++++++++++++
bot/ircmeeting/meeting.py | 1 +
bot/tests/run_test.py | 1 +
3 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/bot/ircmeeting/agenda.py b/bot/ircmeeting/agenda.py
index e3f456c..247907b 100644
--- a/bot/ircmeeting/agenda.py
+++ b/bot/ircmeeting/agenda.py
@@ -27,12 +27,16 @@ class Agenda(object):
self.conf = conf
def get_agenda_item(self):
+ if not self.conf.manage_agenda:
+ return('')
if self._current_item < len(self._agenda):
return str.format(self.current_item_msg, self._agenda[self._current_item][0])
else:
return self.empty_agenda_msg
def next_agenda_item(self):
+ if not self.conf.manage_agenda:
+ return('')
if self._vote_open:
return voting_open_so_item_not_changed_msg
else:
@@ -41,6 +45,8 @@ class Agenda(object):
return(self.get_agenda_item())
def prev_agenda_item(self):
+ if not self.conf.manage_agenda:
+ return('')
if self._vote_open:
return voting_open_so_item_not_changed_msg
else:
@@ -49,6 +55,8 @@ class Agenda(object):
return(self.get_agenda_item())
def start_vote(self):
+ if not self.conf.manage_agenda:
+ return('')
if self._vote_open:
return self.voting_already_open_msg
self._vote_open = True
@@ -58,12 +66,16 @@ class Agenda(object):
return str.format(self.voting_open_msg, options)
def end_vote(self):
+ if not self.conf.manage_agenda:
+ return('')
if self._vote_open:
self._vote_open = False
return self.voting_already_closed_msg
return voting_close_msg
def get_data(self):
+ if not self.conf.manage_agenda:
+ return('')
self._voters = self._get_json(self.conf.voters_url)
self._agenda = self._get_json(self.conf.agenda_url)
self._votes = { }
@@ -71,6 +83,8 @@ class Agenda(object):
self._votes[i[0]] = { }
def vote(self, nick, line):
+ if not self.conf.manage_agenda:
+ return('')
if not nick in self._voters:
return str.format(self.can_not_vote_msg, ", ".join(self._voters))
if not line.isdigit():
@@ -91,6 +105,8 @@ class Agenda(object):
return result
def post_result(self):
+ if not self.conf.manage_agenda:
+ return('')
data = urllib.quote(json.dumps([self._votes]))
result_url = str.format(self.conf.result_url,
self.conf.voting_results_user,
diff --git a/bot/ircmeeting/meeting.py b/bot/ircmeeting/meeting.py
index 108ae1d..26138a2 100644
--- a/bot/ircmeeting/meeting.py
+++ b/bot/ircmeeting/meeting.py
@@ -105,6 +105,7 @@ class Config(object):
# Credentials for posting voting results
voting_results_user = 'user'
voting_results_password = 'password'
+ manage_agenda = False
def enc(self, text):
return text.encode(self.output_codec, 'replace')
diff --git a/bot/tests/run_test.py b/bot/tests/run_test.py
index 79bb9d7..f4e6e49 100644
--- a/bot/tests/run_test.py
+++ b/bot/tests/run_test.py
@@ -344,6 +344,7 @@ class MeetBotTest(unittest.TestCase):
"""
test = test_meeting.TestMeeting()
+ test.M.config.manage_agenda = True
test.set_voters(['x', 'z'])
test.set_agenda([['first item', ['opt1', 'opt2']], ['second item', []]])
test.process("""
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [gentoo-commits] proj/council-webapp:master commit in: bot/tests/, bot/ircmeeting/
@ 2011-06-18 15:46 Petteri Räty
0 siblings, 0 replies; 12+ messages in thread
From: Petteri Räty @ 2011-06-18 15:46 UTC (permalink / raw
To: gentoo-commits
commit: 55cfc31254373f2618a17f73e2923b2503514ecb
Author: Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
AuthorDate: Thu Jun 16 15:36:01 2011 +0000
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Thu Jun 16 15:36:01 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=55cfc312
Add '#option add' command to MeetBot
---
bot/ircmeeting/agenda.py | 15 ++++++++++++++-
bot/ircmeeting/meeting.py | 2 ++
bot/tests/run_test.py | 10 ++++++++++
3 files changed, 26 insertions(+), 1 deletions(-)
diff --git a/bot/ircmeeting/agenda.py b/bot/ircmeeting/agenda.py
index 32ddb9f..97bcfcf 100644
--- a/bot/ircmeeting/agenda.py
+++ b/bot/ircmeeting/agenda.py
@@ -1,9 +1,11 @@
import json
import urllib
+import re
class Agenda(object):
# Messages
+ added_option_msg = "You added new voting option: {}"
empty_agenda_msg = "Agenda is empty so I can't help you manage meeting (and voting)."
current_item_msg = "Current agenda item is {}."
voting_already_open_msg = "Voting is already open. You can end it with #endvote."
@@ -11,7 +13,7 @@ class Agenda(object):
voting_close_msg = "Voting closed."
voting_already_closed_msg = "Voting is already closed. You can start it with #startvote."
voting_open_so_item_not_changed_msg = "Voting is currently open so I didn't change item. Please #endvote first"
- can_not_vote_msg = "You can not vote. Only {} can vote"
+ can_not_vote_msg = "You can not vote or change agenda. Only {} can."
not_a_number_msg = "Your vote was not recognized as a number. Please retry."
out_of_range_msg = "Your vote was out of range!"
vote_confirm_msg = "You voted for #{} - {}"
@@ -111,6 +113,17 @@ class Agenda(object):
for i in range(n):
options += str.format("{}. {}\n", i, options_list[i])
return options
+ def add_option(self, nick, line):
+ if not self.conf.manage_agenda:
+ return('')
+ if not nick in self._voters:
+ return str.format(self.can_not_vote_msg, ", ".join(self._voters))
+ options_list = self._agenda[self._current_item][1]
+ option_text = re.match( ' *?add (.*)', line).group(1)
+ options_list.append(option_text)
+ return str.format(self.added_option_msg, option_text)
+
+
def post_result(self):
if not self.conf.manage_agenda:
diff --git a/bot/ircmeeting/meeting.py b/bot/ircmeeting/meeting.py
index d8589c4..f9c907b 100644
--- a/bot/ircmeeting/meeting.py
+++ b/bot/ircmeeting/meeting.py
@@ -343,6 +343,8 @@ class MeetingCommands(object):
def do_option(self, nick, time_, line, **kwargs):
if re.match( ' *?list', line):
result = self.config.agenda.options()
+ elif re.match( ' *?add .*', line):
+ result = self.config.agenda.add_option(nick, line)
for messageline in result.split('\n'):
self.reply(messageline)
diff --git a/bot/tests/run_test.py b/bot/tests/run_test.py
index c28f1ae..a80e6ec 100644
--- a/bot/tests/run_test.py
+++ b/bot/tests/run_test.py
@@ -385,6 +385,16 @@ class MeetBotTest(unittest.TestCase):
test.answer_should_match('20:13:50 <x> #option list', 'Available voting options ' +\
'are:\n0. opt1\n1. opt2\n')
+ def test_agenda_option_adding(self):
+ test = self.get_simple_agenda_test()
+ test.process('20:13:50 <x> #nextitem')
+ test.answer_should_match('20:13:50 <not_allowed> #option add first option',
+ 'You can not vote or change agenda. Only x, z can.')
+ test.answer_should_match('20:13:50 <x> #option add first option',
+ 'You added new voting option: first option')
+ test.answer_should_match('20:13:50 <x> #option list', 'Available voting options ' +\
+ 'are:\n0. first option')
+
def test_agenda_voting(self):
test = self.get_simple_agenda_test()
test.answer_should_match('20:13:50 <x> #startvote', 'Voting started\. ' +\
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [gentoo-commits] proj/council-webapp:master commit in: bot/tests/, bot/ircmeeting/
@ 2011-06-18 15:46 Petteri Räty
0 siblings, 0 replies; 12+ messages in thread
From: Petteri Räty @ 2011-06-18 15:46 UTC (permalink / raw
To: gentoo-commits
commit: d7fcb9289fb9403db1c646b4205117d1ba66acfe
Author: Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
AuthorDate: Fri Jun 17 12:06:25 2011 +0000
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Fri Jun 17 12:06:25 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=d7fcb928
Add '#option remove' command to MeetBot
---
bot/ircmeeting/agenda.py | 31 +++++++++++++++++++++++++------
bot/ircmeeting/meeting.py | 2 ++
bot/tests/run_test.py | 9 +++++++++
3 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/bot/ircmeeting/agenda.py b/bot/ircmeeting/agenda.py
index 97bcfcf..928ff5f 100644
--- a/bot/ircmeeting/agenda.py
+++ b/bot/ircmeeting/agenda.py
@@ -8,6 +8,7 @@ class Agenda(object):
added_option_msg = "You added new voting option: {}"
empty_agenda_msg = "Agenda is empty so I can't help you manage meeting (and voting)."
current_item_msg = "Current agenda item is {}."
+ removed_option_msg = "You removed voting option {}: {}"
voting_already_open_msg = "Voting is already open. You can end it with #endvote."
voting_open_msg = "Voting started. {}Vote #vote <option number>.\nEnd voting with #endvote."
voting_close_msg = "Voting closed."
@@ -86,13 +87,10 @@ class Agenda(object):
return('')
if not nick in self._voters:
return str.format(self.can_not_vote_msg, ", ".join(self._voters))
- if not line.isdigit():
- return self.not_a_number_msg
- opt = int(line)
-
- if opt < 0 or opt >= len(self._agenda[self._current_item][1]):
- return self.out_of_range_msg
+ opt = self._to_voting_option_number(line)
+ if opt.__class__ is not int:
+ return(opt)
self._votes[self._agenda[self._current_item][0]][nick] = self._agenda[self._current_item][1][opt]
return str.format(self.vote_confirm_msg, opt, self._agenda[self._current_item][1][opt])
@@ -103,6 +101,14 @@ class Agenda(object):
result = json.loads(str)
return result
+ def _to_voting_option_number(self, line):
+ if not line.isdigit():
+ return self.not_a_number_msg
+ opt = int(line)
+ if opt < 0 or opt >= len(self._agenda[self._current_item][1]):
+ return self.out_of_range_msg
+ return(opt)
+
def options(self):
options_list = self._agenda[self._current_item][1]
n = len(options_list)
@@ -113,6 +119,7 @@ class Agenda(object):
for i in range(n):
options += str.format("{}. {}\n", i, options_list[i])
return options
+
def add_option(self, nick, line):
if not self.conf.manage_agenda:
return('')
@@ -123,7 +130,19 @@ class Agenda(object):
options_list.append(option_text)
return str.format(self.added_option_msg, option_text)
+ def remove_option(self, nick, line):
+ if not self.conf.manage_agenda:
+ return('')
+ if not nick in self._voters:
+ return str.format(self.can_not_vote_msg, ", ".join(self._voters))
+
+ opt_str = re.match( ' *?remove (.*)', line).group(1)
+ opt = self._to_voting_option_number(opt_str)
+ if opt.__class__ is not int:
+ return(opt)
+ option = self._agenda[self._current_item][1].pop(opt)
+ return str.format(self.removed_option_msg, str(opt), option)
def post_result(self):
if not self.conf.manage_agenda:
diff --git a/bot/ircmeeting/meeting.py b/bot/ircmeeting/meeting.py
index f9c907b..84949ed 100644
--- a/bot/ircmeeting/meeting.py
+++ b/bot/ircmeeting/meeting.py
@@ -345,6 +345,8 @@ class MeetingCommands(object):
result = self.config.agenda.options()
elif re.match( ' *?add .*', line):
result = self.config.agenda.add_option(nick, line)
+ elif re.match( ' *?remove .*', line):
+ result = self.config.agenda.remove_option(nick, line)
for messageline in result.split('\n'):
self.reply(messageline)
diff --git a/bot/tests/run_test.py b/bot/tests/run_test.py
index a80e6ec..9808ee6 100644
--- a/bot/tests/run_test.py
+++ b/bot/tests/run_test.py
@@ -395,6 +395,15 @@ class MeetBotTest(unittest.TestCase):
test.answer_should_match('20:13:50 <x> #option list', 'Available voting options ' +\
'are:\n0. first option')
+ def test_agenda_option_removing(self):
+ test = self.get_simple_agenda_test()
+ test.answer_should_match('20:13:50 <not_allowed> #option remove 1',
+ 'You can not vote or change agenda. Only x, z can.')
+ test.answer_should_match('20:13:50 <x> #option remove 1',
+ 'You removed voting option 1: opt2')
+ test.answer_should_match('20:13:50 <x> #option list', 'Available voting options ' +\
+ 'are:\n0. opt1')
+
def test_agenda_voting(self):
test = self.get_simple_agenda_test()
test.answer_should_match('20:13:50 <x> #startvote', 'Voting started\. ' +\
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [gentoo-commits] proj/council-webapp:master commit in: bot/tests/, bot/ircmeeting/
@ 2011-06-22 7:59 Petteri Räty
0 siblings, 0 replies; 12+ messages in thread
From: Petteri Räty @ 2011-06-22 7:59 UTC (permalink / raw
To: gentoo-commits
commit: bc787b2518ac4fedcffaaf24e14f04839c3d7d3a
Author: Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
AuthorDate: Mon Jun 20 16:58:30 2011 +0000
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Wed Jun 22 07:22:05 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=bc787b25
Add #changeitem <no> command to MeetBot
---
bot/ircmeeting/agenda.py | 25 +++++++++++++++++++++----
bot/ircmeeting/meeting.py | 3 +++
bot/tests/run_test.py | 20 ++++++++++++++------
3 files changed, 38 insertions(+), 10 deletions(-)
diff --git a/bot/ircmeeting/agenda.py b/bot/ircmeeting/agenda.py
index 775dfd9..af03c3a 100644
--- a/bot/ircmeeting/agenda.py
+++ b/bot/ircmeeting/agenda.py
@@ -15,8 +15,8 @@ class Agenda(object):
voting_already_closed_msg = "Voting is already closed. You can start it with #startvote."
voting_open_so_item_not_changed_msg = "Voting is currently open so I didn't change item. Please #endvote first"
can_not_vote_msg = "You can not vote or change agenda. Only {} can."
- not_a_number_msg = "Your vote was not recognized as a number. Please retry."
- out_of_range_msg = "Your vote was out of range!"
+ not_a_number_msg = "Your choice was not recognized as a number. Please retry."
+ out_of_range_msg = "Your choice was out of range!"
vote_confirm_msg = "You voted for #{} - {}"
# Internal
@@ -109,14 +109,20 @@ class Agenda(object):
result = json.loads(str)
return result
- def _to_voting_option_number(self, line):
+ def _to_number(self, line, upper_limit):
if not line.isdigit():
return self.not_a_number_msg
opt = int(line)
- if opt < 0 or opt >= len(self._agenda[self._current_item][1]):
+ if opt < 0 or opt >= upper_limit:
return self.out_of_range_msg
return(opt)
+ def _to_voting_option_number(self, line):
+ return(self._to_number(line, len(self._agenda[self._current_item][1])))
+
+ def _to_agenda_item_number(self, line):
+ return(self._to_number(line, len(self._agenda)))
+
def options(self):
options_list = self._agenda[self._current_item][1]
n = len(options_list)
@@ -138,6 +144,17 @@ class Agenda(object):
options_list.append(option_text)
return str.format(self.added_option_msg, option_text)
+ def change_agenda_item(self, line):
+ if not self.conf.manage_agenda:
+ return('')
+ if self._vote_open:
+ return self.voting_open_so_item_not_changed_msg
+ opt = self._to_agenda_item_number(line)
+ if opt.__class__ is not int:
+ return(opt)
+ self._current_item = opt
+ return(self.get_agenda_item())
+
def remove_option(self, nick, line):
if not self.conf.manage_agenda:
return('')
diff --git a/bot/ircmeeting/meeting.py b/bot/ircmeeting/meeting.py
index 84949ed..c01176a 100644
--- a/bot/ircmeeting/meeting.py
+++ b/bot/ircmeeting/meeting.py
@@ -328,6 +328,9 @@ class MeetingCommands(object):
def do_previtem(self, nick, time_, line, **kwargs):
self.reply(self.config.agenda.prev_agenda_item())
+ def do_changeitem(self, nick, time_, line, **kwargs):
+ self.reply(self.config.agenda.change_agenda_item(line))
+
def do_startvote(self, nick, time_, line, **kwargs):
for messageline in self.config.agenda.start_vote().split('\n'):
self.reply(messageline)
diff --git a/bot/tests/run_test.py b/bot/tests/run_test.py
index 3c43fef..1358d47 100644
--- a/bot/tests/run_test.py
+++ b/bot/tests/run_test.py
@@ -342,7 +342,7 @@ class MeetBotTest(unittest.TestCase):
def get_simple_agenda_test(self):
test = test_meeting.TestMeeting()
test.set_voters(['x', 'z'])
- test.set_agenda([['first item', ['opt1', 'opt2']], ['second item', []]])
+ test.set_agenda([['first item', ['opt1', 'opt2']], ['second item', []], ['third item', []]])
test.M.config.manage_agenda = False
test.answer_should_match("20:13:50 <x> #startmeeting",
@@ -356,9 +356,16 @@ class MeetBotTest(unittest.TestCase):
# Test changing item before vote
test.answer_should_match('20:13:50 <x> #nextitem', 'Current agenda item is second item.')
- test.answer_should_match('20:13:50 <x> #nextitem', 'Current agenda item is second item.')
+ test.answer_should_match('20:13:50 <x> #nextitem', 'Current agenda item is third item.')
+ test.answer_should_match('20:13:50 <x> #nextitem', 'Current agenda item is third item.')
+ test.answer_should_match('20:13:50 <x> #previtem', 'Current agenda item is second item.')
test.answer_should_match('20:13:50 <x> #previtem', 'Current agenda item is first item.')
test.answer_should_match('20:13:50 <x> #previtem', 'Current agenda item is first item.')
+ test.answer_should_match('20:13:50 <x> #changeitem 2', 'Current agenda item is third item.')
+ test.answer_should_match('20:13:50 <x> #changeitem 1', 'Current agenda item is second item.')
+ test.answer_should_match('20:13:50 <x> #changeitem 0', 'Current agenda item is first item.')
+ test.answer_should_match('20:13:50 <x> #changeitem 10', 'Your choice was out of range!')
+ test.answer_should_match('20:13:50 <x> #changeitem puppy', 'Your choice was not recognized as a number. Please retry.')
# Test changing item during vote
test.process('20:13:50 <x> #startvote')
@@ -366,13 +373,14 @@ class MeetBotTest(unittest.TestCase):
'open so I didn\'t change item. Please #endvote first')
test.answer_should_match('20:13:50 <x> #previtem', 'Voting is currently ' +\
'open so I didn\'t change item. Please #endvote first')
+ test.answer_should_match('20:13:50 <x> #changeitem 2', 'Voting is currently ' +\
+ 'open so I didn\'t change item. Please #endvote first')
# Test changing item after vote
test.process('20:13:50 <x> #endvote')
test.answer_should_match('20:13:50 <x> #nextitem', 'Current agenda item is second item.')
- test.answer_should_match('20:13:50 <x> #nextitem', 'Current agenda item is second item.')
- test.answer_should_match('20:13:50 <x> #previtem', 'Current agenda item is first item.')
test.answer_should_match('20:13:50 <x> #previtem', 'Current agenda item is first item.')
+ test.answer_should_match('20:13:50 <x> #changeitem 2', 'Current agenda item is third item.')
def test_agenda_option_listing(self):
test = self.get_simple_agenda_test()
@@ -412,7 +420,7 @@ class MeetBotTest(unittest.TestCase):
'#vote <option number>.\nEnd voting with #endvote.')
test.answer_should_match('20:13:50 <x> #startvote', 'Voting is already open. ' +\
'You can end it with #endvote.')
- test.answer_should_match('20:13:50 <x> #vote 10', 'Your vote was out of range\!')
+ test.answer_should_match('20:13:50 <x> #vote 10', 'Your choice was out of range\!')
test.answer_should_match('20:13:50 <x> #vote 0', 'You voted for #0 - opt1')
test.answer_should_match('20:13:50 <x> #vote 1', 'You voted for #1 - opt2')
test.answer_should_match('20:13:50 <z> #vote 0', 'You voted for #0 - opt1')
@@ -426,7 +434,7 @@ class MeetBotTest(unittest.TestCase):
test.answer_should_match('20:13:50 <x> #endmeeting', 'Meeting ended ' +\
'.*\nMinutes:.*\nMinutes \(text\):.*\nLog:.*')
- assert(test.votes() == {'first item': {u'x': 'opt2', u'z': 'opt1'}, 'second item': {}})
+ assert(test.votes() == {'first item': {u'x': 'opt2', u'z': 'opt1'}, 'second item': {}, 'third item': {}})
def test_agenda_close_voting_after_last_vote(self):
test = self.get_simple_agenda_test()
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [gentoo-commits] proj/council-webapp:master commit in: bot/tests/, bot/ircmeeting/
@ 2011-06-22 7:59 Petteri Räty
0 siblings, 0 replies; 12+ messages in thread
From: Petteri Räty @ 2011-06-22 7:59 UTC (permalink / raw
To: gentoo-commits
commit: 1a137e470619a11e14ed9c0be48f24a062890d1b
Author: Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
AuthorDate: Tue Jun 21 15:29:09 2011 +0000
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Wed Jun 22 07:22:05 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=1a137e47
Close voting when last user allowed to vote voted.
---
bot/ircmeeting/agenda.py | 10 +++++++++-
bot/tests/run_test.py | 11 +++++++++++
2 files changed, 20 insertions(+), 1 deletions(-)
diff --git a/bot/ircmeeting/agenda.py b/bot/ircmeeting/agenda.py
index 928ff5f..775dfd9 100644
--- a/bot/ircmeeting/agenda.py
+++ b/bot/ircmeeting/agenda.py
@@ -79,6 +79,7 @@ class Agenda(object):
self._voters = self._get_json(self.conf.voters_url)
self._agenda = self._get_json(self.conf.agenda_url)
self._votes = { }
+ self._voters.sort()
for i in self._agenda:
self._votes[i[0]] = { }
@@ -93,7 +94,14 @@ class Agenda(object):
return(opt)
self._votes[self._agenda[self._current_item][0]][nick] = self._agenda[self._current_item][1][opt]
- return str.format(self.vote_confirm_msg, opt, self._agenda[self._current_item][1][opt])
+
+ users_who_voted = self._votes[self._agenda[self._current_item][0]].keys()
+ users_who_voted.sort()
+
+ reply = str.format(self.vote_confirm_msg, opt, self._agenda[self._current_item][1][opt])
+ if users_who_voted == self._voters:
+ reply += '. ' + self.end_vote()
+ return(reply)
def _get_json(self, url):
str = urllib.urlopen(url).read()
diff --git a/bot/tests/run_test.py b/bot/tests/run_test.py
index 9808ee6..3c43fef 100644
--- a/bot/tests/run_test.py
+++ b/bot/tests/run_test.py
@@ -406,6 +406,7 @@ class MeetBotTest(unittest.TestCase):
def test_agenda_voting(self):
test = self.get_simple_agenda_test()
+ test.M.config.agenda._voters.append('t')
test.answer_should_match('20:13:50 <x> #startvote', 'Voting started\. ' +\
'Available voting options are:\n0. opt1\n1. opt2\nVote ' +\
'#vote <option number>.\nEnd voting with #endvote.')
@@ -427,6 +428,16 @@ class MeetBotTest(unittest.TestCase):
assert(test.votes() == {'first item': {u'x': 'opt2', u'z': 'opt1'}, 'second item': {}})
+ def test_agenda_close_voting_after_last_vote(self):
+ test = self.get_simple_agenda_test()
+ test.answer_should_match('20:13:50 <x> #startvote', 'Voting started\. ' +\
+ 'Available voting options are:\n0. opt1\n1. opt2\nVote ' +\
+ '#vote <option number>.\nEnd voting with #endvote.')
+ test.answer_should_match('20:13:50 <x> #startvote', 'Voting is already open. ' +\
+ 'You can end it with #endvote.')
+ test.answer_should_match('20:13:50 <x> #vote 0', 'You voted for #0 - opt1')
+ test.answer_should_match('20:13:50 <z> #vote 0', 'You voted for #0 - opt1. Voting closed.')
+
if __name__ == '__main__':
os.chdir(os.path.join(os.path.dirname(__file__), '.'))
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [gentoo-commits] proj/council-webapp:master commit in: bot/tests/, bot/ircmeeting/
@ 2011-06-25 11:55 Petteri Räty
0 siblings, 0 replies; 12+ messages in thread
From: Petteri Räty @ 2011-06-25 11:55 UTC (permalink / raw
To: gentoo-commits
commit: 62b3ba6efe4ac1de77f24527e844c9a70ed94b1b
Author: Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
AuthorDate: Wed Jun 22 07:28:20 2011 +0000
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Wed Jun 22 18:31:35 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=62b3ba6e
Add support for #timelimit (add|list|remove) commands
---
bot/ircmeeting/agenda.py | 46 +++++++++++++++++++++++++++++++++++-
bot/ircmeeting/meeting.py | 17 +++++++++++++-
bot/tests/run_test.py | 56 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 116 insertions(+), 3 deletions(-)
diff --git a/bot/ircmeeting/agenda.py b/bot/ircmeeting/agenda.py
index 928ff5f..220acf9 100644
--- a/bot/ircmeeting/agenda.py
+++ b/bot/ircmeeting/agenda.py
@@ -1,7 +1,15 @@
import json
+import threading
import urllib
import re
+class MessageSender:
+ def __init__(self, irc, message):
+ self.irc = irc
+ self.message = message
+ def send_message(self):
+ self.irc.reply(self.message)
+
class Agenda(object):
# Messages
@@ -18,6 +26,10 @@ class Agenda(object):
not_a_number_msg = "Your vote was not recognized as a number. Please retry."
out_of_range_msg = "Your vote was out of range!"
vote_confirm_msg = "You voted for #{} - {}"
+ timelimit_added_msg = 'Added "{}" reminder in {}:{}'
+ timelimit_list_msg = 'Set reminders: "{}"'
+ timelimit_removed_msg = 'Reminder "{}" removed'
+ timelimit_missing_msg = 'No such reminder "{}"'
# Internal
_voters = []
@@ -28,6 +40,7 @@ class Agenda(object):
def __init__(self, conf):
self.conf = conf
+ self.reminders = {}
def get_agenda_item(self):
if not self.conf.manage_agenda:
@@ -37,6 +50,12 @@ class Agenda(object):
else:
return self.empty_agenda_msg
+ def _swich_agenda_item_to(self, new_item):
+ self._current_item = new_item
+ for reminder in self.reminders.values():
+ reminder.cancel()
+ self.reminders = {}
+
def next_agenda_item(self):
if not self.conf.manage_agenda:
return('')
@@ -44,7 +63,7 @@ class Agenda(object):
return self.voting_open_so_item_not_changed_msg
else:
if (self._current_item + 1) < len(self._agenda):
- self._current_item += 1
+ self._swich_agenda_item_to(self._current_item + 1)
return(self.get_agenda_item())
def prev_agenda_item(self):
@@ -54,7 +73,7 @@ class Agenda(object):
return self.voting_open_so_item_not_changed_msg
else:
if self._current_item > 0:
- self._current_item -= 1
+ self._swich_agenda_item_to(self._current_item - 1)
return(self.get_agenda_item())
def start_vote(self):
@@ -144,6 +163,29 @@ class Agenda(object):
option = self._agenda[self._current_item][1].pop(opt)
return str.format(self.removed_option_msg, str(opt), option)
+ def add_timelimit(self, minutes, seconds, message, irc):
+ sender = MessageSender(irc, message)
+ reminder = (threading.Timer(60*minutes + seconds, sender.send_message))
+ self.reminders[message] = reminder
+ reminder.start()
+ result = str.format(self.timelimit_added_msg, message, minutes, seconds)
+ return(result)
+
+ def list_timielimits(self):
+ keys = self.reminders.keys()
+ keys_str = '", "'.join(keys)
+ result = str.format(self.timelimit_list_msg, keys_str)
+ return(result)
+
+ def remove_timelimit(self, message):
+ if message in self.reminders:
+ timer = self.reminders.pop(message)
+ timer.cancel()
+ result = str.format(self.timelimit_removed_msg, message)
+ else:
+ result = str.format(self.timelimit_missing_msg, message)
+ return(result)
+
def post_result(self):
if not self.conf.manage_agenda:
return('')
diff --git a/bot/ircmeeting/meeting.py b/bot/ircmeeting/meeting.py
index 84949ed..4bd3221 100644
--- a/bot/ircmeeting/meeting.py
+++ b/bot/ircmeeting/meeting.py
@@ -33,6 +33,7 @@ import time
import os
import re
import stat
+import threading
import writers
import items
@@ -301,7 +302,6 @@ else:
# Subclass Config and LocalConfig, new type overrides Config.
Config = type('Config', (LocalConfig, Config), {})
-
class MeetingCommands(object):
# Command Definitions
# generic parameters to these functions:
@@ -328,6 +328,21 @@ class MeetingCommands(object):
def do_previtem(self, nick, time_, line, **kwargs):
self.reply(self.config.agenda.prev_agenda_item())
+ def do_timelimit(self, nick, time_, line, **kwargs):
+ reply = 'Usage "#timelimit add <minutes>:<seconds> <message>" or ' +\
+ '"#timelimit list" or "#timelimit remove <message>"'
+ match = re.match( ' *?add ([0-9]+):([0-9]+) (.*)', line)
+ if match:
+ reply = self.config.agenda.add_timelimit(int(match.group(1)),
+ int(match.group(2)), match.group(3), self)
+ elif re.match( ' *?list', line):
+ reply = self.config.agenda.list_timielimits()
+ else:
+ match = re.match( ' *?remove (.*)', line)
+ if(match):
+ reply = self.config.agenda.remove_timelimit(match.group(1))
+ self.reply(reply)
+
def do_startvote(self, nick, time_, line, **kwargs):
for messageline in self.config.agenda.start_vote().split('\n'):
self.reply(messageline)
diff --git a/bot/tests/run_test.py b/bot/tests/run_test.py
index 9808ee6..e3a9030 100644
--- a/bot/tests/run_test.py
+++ b/bot/tests/run_test.py
@@ -6,6 +6,8 @@ import re
import shutil
import sys
import tempfile
+import time
+import threading
import unittest
os.environ['MEETBOT_RUNNING_TESTS'] = '1'
@@ -427,6 +429,60 @@ class MeetBotTest(unittest.TestCase):
assert(test.votes() == {'first item': {u'x': 'opt2', u'z': 'opt1'}, 'second item': {}})
+ def test_agenda_time_limit_adding(self):
+ test = self.get_simple_agenda_test()
+ test.answer_should_match('20:13:50 <x> #timelimit', 'Usage "#timelimit ' +\
+ 'add <minutes>:<seconds> <message>" or "' +\
+ '#timelimit list" or "#timelimit remove ' +\
+ '<message>"')
+ test.answer_should_match('20:13:50 <x> #timelimit add 0:1 some other message',
+ 'Added "some other message" reminder in 0:1')
+ test.answer_should_match('20:13:50 <x> #timelimit add 1:0 some message',
+ 'Added "some message" reminder in 1:0')
+ time.sleep(2)
+ last_message = test.log[-1]
+ assert(last_message == 'some other message')
+ reminders = test.M.config.agenda.reminders
+ assert(len(reminders) == 2)
+ for reminder in reminders.values():
+ assert(reminder.__class__ == threading._Timer)
+
+ test.process('20:13:50 <x> #nextitem')
+
+ def test_agenda_time_limit_removing_when_changing_item(self):
+ test = self.get_simple_agenda_test()
+
+ test.process('20:13:50 <x> #timelimit add 0:1 message')
+ assert(len(test.M.config.agenda.reminders) == 1)
+ test.process('20:13:50 <x> #nextitem')
+ assert(len(test.M.config.agenda.reminders) == 0)
+ test.process('20:13:50 <x> #timelimit add 0:1 message')
+ assert(len(test.M.config.agenda.reminders) == 1)
+ test.process('20:13:50 <x> #previtem')
+ assert(len(test.M.config.agenda.reminders) == 0)
+
+ def test_agenda_time_limit_manual_removing(self):
+ test = self.get_simple_agenda_test()
+
+ test.process('20:13:50 <x> #timelimit add 0:1 message')
+ test.process('20:13:50 <x> #timelimit add 0:1 other message')
+ keys = test.M.config.agenda.reminders.keys()
+ keys.sort()
+ assert(keys == ['message', 'other message'])
+
+ test.answer_should_match('20:13:50 <x> #timelimit remove other message', 'Reminder "other message" removed')
+ keys = test.M.config.agenda.reminders.keys()
+ assert(keys == ['message'])
+
+ def test_agenda_time_limit_listing(self):
+ test = self.get_simple_agenda_test()
+ test.process('20:13:50 <x> #timelimit add 0:1 message')
+ test.process('20:13:50 <x> #timelimit add 0:1 other message')
+ test.process('20:13:50 <x> #timelimit add 0:1 yet another message')
+ keys = test.M.config.agenda.reminders.keys()
+ test.answer_should_match('20:13:50 <x> #timelimit list',
+ 'Set reminders: "' + '", "'.join(keys) + '"')
+
if __name__ == '__main__':
os.chdir(os.path.join(os.path.dirname(__file__), '.'))
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [gentoo-commits] proj/council-webapp:master commit in: bot/tests/, bot/ircmeeting/
@ 2011-06-25 11:55 Petteri Räty
0 siblings, 0 replies; 12+ messages in thread
From: Petteri Räty @ 2011-06-25 11:55 UTC (permalink / raw
To: gentoo-commits
commit: 4430af0e8a05b3424b88ee9803034959b5e46dec
Author: Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
AuthorDate: Fri Jun 24 17:37:23 2011 +0000
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Fri Jun 24 17:37:23 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=4430af0e
Bot receives reminders from webapp
---
bot/ircmeeting/agenda.py | 16 +++++++++++-----
bot/ircmeeting/meeting.py | 4 ++--
bot/tests/run_test.py | 19 ++++++++++++++++++-
3 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/bot/ircmeeting/agenda.py b/bot/ircmeeting/agenda.py
index 220acf9..101c73c 100644
--- a/bot/ircmeeting/agenda.py
+++ b/bot/ircmeeting/agenda.py
@@ -50,30 +50,36 @@ class Agenda(object):
else:
return self.empty_agenda_msg
- def _swich_agenda_item_to(self, new_item):
+ def _swich_agenda_item_to(self, new_item, irc):
self._current_item = new_item
for reminder in self.reminders.values():
reminder.cancel()
self.reminders = {}
-
- def next_agenda_item(self):
+ for line in self._agenda[self._current_item][2].split('\n'):
+ match = re.match( '([0-9]+):([0-9]+) (.*)', line)
+ if match:
+ self.add_timelimit(int(match.group(1)), int(match.group(2)),
+ match.group(3), irc)
+ self._agenda[self._current_item][2] = ''
+
+ def next_agenda_item(self, irc):
if not self.conf.manage_agenda:
return('')
if self._vote_open:
return self.voting_open_so_item_not_changed_msg
else:
if (self._current_item + 1) < len(self._agenda):
- self._swich_agenda_item_to(self._current_item + 1)
+ self._swich_agenda_item_to(self._current_item + 1, irc)
return(self.get_agenda_item())
- def prev_agenda_item(self):
+ def prev_agenda_item(self, irc):
if not self.conf.manage_agenda:
return('')
if self._vote_open:
return self.voting_open_so_item_not_changed_msg
else:
if self._current_item > 0:
- self._swich_agenda_item_to(self._current_item - 1)
+ self._swich_agenda_item_to(self._current_item - 1, irc)
return(self.get_agenda_item())
def start_vote(self):
diff --git a/bot/ircmeeting/meeting.py b/bot/ircmeeting/meeting.py
index 4bd3221..e3cf38d 100644
--- a/bot/ircmeeting/meeting.py
+++ b/bot/ircmeeting/meeting.py
@@ -323,10 +323,10 @@ class MeetingCommands(object):
self.reply(self.config.agenda.get_agenda_item())
def do_nextitem(self, nick, time_, line, **kwargs):
- self.reply(self.config.agenda.next_agenda_item())
+ self.reply(self.config.agenda.next_agenda_item(self))
def do_previtem(self, nick, time_, line, **kwargs):
- self.reply(self.config.agenda.prev_agenda_item())
+ self.reply(self.config.agenda.prev_agenda_item(self))
def do_timelimit(self, nick, time_, line, **kwargs):
reply = 'Usage "#timelimit add <minutes>:<seconds> <message>" or ' +\
diff --git a/bot/tests/run_test.py b/bot/tests/run_test.py
index e3a9030..e22516b 100644
--- a/bot/tests/run_test.py
+++ b/bot/tests/run_test.py
@@ -344,7 +344,7 @@ class MeetBotTest(unittest.TestCase):
def get_simple_agenda_test(self):
test = test_meeting.TestMeeting()
test.set_voters(['x', 'z'])
- test.set_agenda([['first item', ['opt1', 'opt2']], ['second item', []]])
+ test.set_agenda([['first item', ['opt1', 'opt2'], ''], ['second item', [], '']])
test.M.config.manage_agenda = False
test.answer_should_match("20:13:50 <x> #startmeeting",
@@ -483,6 +483,23 @@ class MeetBotTest(unittest.TestCase):
test.answer_should_match('20:13:50 <x> #timelimit list',
'Set reminders: "' + '", "'.join(keys) + '"')
+ def test_preset_agenda_time_limits(self):
+ test = self.get_simple_agenda_test()
+ test.M.config.agenda._agenda[0][2] = '1:0 message'
+ test.M.config.agenda._agenda[1][2] = '1:0 another message\n0:10 some other message'
+
+ test.process('20:13:50 <x> #nextitem')
+ keys = test.M.config.agenda.reminders.keys()
+ keys.sort()
+ assert(keys == ['another message', 'some other message'])
+
+ test.process('20:13:50 <x> #previtem')
+ keys = test.M.config.agenda.reminders.keys()
+ keys.sort()
+ assert(keys == ['message'])
+
+ test.process('20:13:50 <x> #nextitem')
+
if __name__ == '__main__':
os.chdir(os.path.join(os.path.dirname(__file__), '.'))
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [gentoo-commits] proj/council-webapp:master commit in: bot/tests/, bot/ircmeeting/
@ 2011-07-18 7:41 Petteri Räty
0 siblings, 0 replies; 12+ messages in thread
From: Petteri Räty @ 2011-07-18 7:41 UTC (permalink / raw
To: gentoo-commits
commit: 6fd62e887e49accc1d3189279f0e007fed3f3bd1
Author: Joachim Filip Ignacy Bartosik <jbartosik <AT> gmail <DOT> com>
AuthorDate: Sat Jul 16 18:21:26 2011 +0000
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Sat Jul 16 18:21:26 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/council-webapp.git;a=commit;h=6fd62e88
Add #command command to MeetBot - shows documentation for other commands
---
bot/ircmeeting/meeting.py | 31 ++++++++++++++++++++++++++++---
bot/tests/run_test.py | 15 +++++++++++----
2 files changed, 39 insertions(+), 7 deletions(-)
diff --git a/bot/ircmeeting/meeting.py b/bot/ircmeeting/meeting.py
index a15b674..c20fd6d 100644
--- a/bot/ircmeeting/meeting.py
+++ b/bot/ircmeeting/meeting.py
@@ -323,14 +323,20 @@ class MeetingCommands(object):
self.reply(self.config.agenda.get_agenda_item())
def do_nextitem(self, nick, time_, line, **kwargs):
+ """Go to next agenda item"""
self.reply(self.config.agenda.next_agenda_item(self))
def do_previtem(self, nick, time_, line, **kwargs):
+ """Go to previous agenda item"""
self.reply(self.config.agenda.prev_agenda_item(self))
def do_timelimit(self, nick, time_, line, **kwargs):
- reply = 'Usage "#timelimit add <minutes>:<seconds> <message>" or ' +\
- '"#timelimit list" or "#timelimit remove <message>"'
+ """ Manage reminders:
+ #timelimit list - list all active reminders
+ #timelimit add <minutes>:<seconds> <message> - add a new reminder
+ #timelimit remove <message> - remove reminder with message"""
+
+ reply = self.do_timelimit.__doc__
match = re.match( ' *?add ([0-9]+):([0-9]+) (.*)', line)
if match:
reply = self.config.agenda.add_timelimit(int(match.group(1)),
@@ -341,24 +347,33 @@ class MeetingCommands(object):
match = re.match( ' *?remove (.*)', line)
if(match):
reply = self.config.agenda.remove_timelimit(match.group(1))
- self.reply(reply)
+ for line in reply.split("\n"):
+ self.reply(line)
def do_changeitem(self, nick, time_, line, **kwargs):
+ """Change agenda item. Usage: #chengeitem <item number>"""
self.reply(self.config.agenda.change_agenda_item(line))
def do_startvote(self, nick, time_, line, **kwargs):
+ """Start vote on current item"""
for messageline in self.config.agenda.start_vote().split('\n'):
self.reply(messageline)
def do_endvote(self, nick, time_, line, **kwargs):
+ """Close voting for current agenda item. You can resume voting later with #startvote"""
for messageline in self.config.agenda.end_vote().split('\n'):
self.reply(messageline)
def do_vote(self, nick, time_, line, **kwargs):
+ """Make a vote. Usage: vote <option number>. Remember to #startvote before voting."""
for messageline in self.config.agenda.vote(nick, line).split('\n'):
self.reply(messageline)
def do_option(self, nick, time_, line, **kwargs):
+ """Manage voting options:
+ #option list - lists all available votin options for current item
+ #option add <option text> - adds new voting option
+ #option remove <option number> - removes existing option"""
if re.match( ' *?list', line):
result = self.config.agenda.options()
elif re.match( ' *?add .*', line):
@@ -515,6 +530,16 @@ class MeetingCommands(object):
commands = [ "#"+x[3:] for x in dir(self) if x[:3]=="do_" ]
commands.sort()
self.reply("Available commands: "+(" ".join(commands)))
+ def do_command(self, nick, line, **kwargs):
+ name = "do_" + line.strip()
+ attr = getattr(self, name)
+ if attr is None:
+ return
+ doc = attr.__doc__
+ if doc is None:
+ return
+ for line in doc.split("\n"):
+ self.reply(line)
diff --git a/bot/tests/run_test.py b/bot/tests/run_test.py
index 0d18cce..136e135 100644
--- a/bot/tests/run_test.py
+++ b/bot/tests/run_test.py
@@ -450,10 +450,7 @@ class MeetBotTest(unittest.TestCase):
def test_agenda_time_limit_adding(self):
test = self.get_simple_agenda_test()
- test.answer_should_match('20:13:50 <x> #timelimit', 'Usage "#timelimit ' +\
- 'add <minutes>:<seconds> <message>" or "' +\
- '#timelimit list" or "#timelimit remove ' +\
- '<message>"')
+ test.answer_should_match('20:13:50 <x> #timelimit', test.M.do_timelimit.__doc__)
test.answer_should_match('20:13:50 <x> #timelimit add 0:1 some other message',
'Added "some other message" reminder in 0:1')
test.answer_should_match('20:13:50 <x> #timelimit add 1:0 some message',
@@ -531,6 +528,16 @@ class MeetBotTest(unittest.TestCase):
error_msg = 'Received messages ' + str(test.log) + \
' didn\'t match expected ' + str(expected_messages)
assert messages_match, error_msg
+ def test_command_help(self):
+ test = self.get_simple_agenda_test()
+ commands = ['startmeeting', 'startvote', 'vote', 'endvote',
+ 'nextitem', 'previtem', 'changeitem', 'option',
+ 'timelimit', 'endmeeting']
+ for command in commands:
+ desc = getattr(test.M, 'do_' + command).__doc__
+ if desc is None:
+ desc = ''
+ test.answer_should_match('20:13:50 <x> #command ' + command, desc)
if __name__ == '__main__':
os.chdir(os.path.join(os.path.dirname(__file__), '.'))
^ permalink raw reply related [flat|nested] 12+ messages in thread
end of thread, other threads:[~2011-07-18 7:41 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-05 20:37 [gentoo-commits] proj/council-webapp:master commit in: bot/tests/, bot/ircmeeting/ Petteri Räty
-- strict thread matches above, loose matches on Subject: below --
2011-06-18 15:46 Petteri Räty
2011-06-18 15:46 Petteri Räty
2011-06-18 15:46 Petteri Räty
2011-06-18 15:46 Petteri Räty
2011-06-18 15:46 Petteri Räty
2011-06-18 15:46 Petteri Räty
2011-06-22 7:59 Petteri Räty
2011-06-22 7:59 Petteri Räty
2011-06-25 11:55 Petteri Räty
2011-06-25 11:55 Petteri Räty
2011-07-18 7:41 Petteri Räty
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox