mirror of
https://github.com/Mikaela/Limnoria.git
synced 2025-01-11 12:42:34 +01:00
* Fixed searchtodo
* Wrote tests for Todo.py
This commit is contained in:
parent
1e8de55ff8
commit
9f2352fbea
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
###
|
###
|
||||||
# Copyright (c) 2002, Jeremiah Fincher
|
# Copyright (c) 2003, Daniel DiPaolo
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
@ -30,18 +30,22 @@
|
|||||||
###
|
###
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Add the module docstring here. This will be used by the setup.py script.
|
The Todo module allows registered users to keep their own personal list of
|
||||||
|
tasks to do, with an optional priority for each.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import plugins
|
import plugins
|
||||||
|
|
||||||
|
import glob
|
||||||
import time
|
import time
|
||||||
import getopt
|
import getopt
|
||||||
|
import string
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
import sqlite
|
import sqlite
|
||||||
|
|
||||||
import conf
|
import conf
|
||||||
|
import debug
|
||||||
import ircdb
|
import ircdb
|
||||||
import utils
|
import utils
|
||||||
import privmsgs
|
import privmsgs
|
||||||
@ -124,16 +128,14 @@ class Todo(callbacks.Privmsg):
|
|||||||
irc.reply(msg, s)
|
irc.reply(msg, s)
|
||||||
else:
|
else:
|
||||||
cursor = self.db.cursor()
|
cursor = self.db.cursor()
|
||||||
cursor.execute("""SELECT id FROM todo WHERE userid = %s""", id)
|
cursor.execute("""SELECT id, task FROM todo
|
||||||
|
WHERE userid = %s""", id)
|
||||||
if cursor.rowcount == 0:
|
if cursor.rowcount == 0:
|
||||||
irc.reply(msg, 'You have no tasks in your todo list.')
|
irc.reply(msg, 'You have no tasks in your todo list.')
|
||||||
else:
|
|
||||||
ids = []
|
|
||||||
for (id,) in cursor.fetchall():
|
|
||||||
ids.append(str(id))
|
|
||||||
s = 'Task ids: %s' % ', '.join(ids)
|
|
||||||
irc.reply(msg, s)
|
|
||||||
return
|
return
|
||||||
|
s = ['#%s: %s' % (item[0], utils.ellipsisify(item[1], 50)) \
|
||||||
|
for item in cursor.fetchall()]
|
||||||
|
irc.reply(msg, utils.commaAndify(s))
|
||||||
|
|
||||||
def addtodo(self, irc, msg, args):
|
def addtodo(self, irc, msg, args):
|
||||||
"""[--priority=<num>] <text>
|
"""[--priority=<num>] <text>
|
||||||
@ -156,9 +158,10 @@ class Todo(callbacks.Privmsg):
|
|||||||
except ValueError, e:
|
except ValueError, e:
|
||||||
irc.error(msg, 'Invalid priority: %s' % e)
|
irc.error(msg, 'Invalid priority: %s' % e)
|
||||||
return
|
return
|
||||||
|
text = privmsgs.getArgs(rest, needed=1)
|
||||||
cursor = self.db.cursor()
|
cursor = self.db.cursor()
|
||||||
cursor.execute("""INSERT INTO todo VALUES (NULL, %s, %s, %s, %s)""",
|
cursor.execute("""INSERT INTO todo VALUES (NULL, %s, %s, %s, %s)""",
|
||||||
priority, int(time.time()), id, ' '.join(rest))
|
priority, int(time.time()), id, text)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
irc.reply(msg, conf.replySuccess)
|
irc.reply(msg, conf.replySuccess)
|
||||||
|
|
||||||
@ -184,6 +187,55 @@ class Todo(callbacks.Privmsg):
|
|||||||
self.db.commit()
|
self.db.commit()
|
||||||
irc.reply(msg, conf.replySuccess)
|
irc.reply(msg, conf.replySuccess)
|
||||||
|
|
||||||
|
_sqlTrans = string.maketrans('*?', '%_')
|
||||||
|
def searchtodo(self, irc, msg, args):
|
||||||
|
"""[--{regexp,exact}=<value>] [<glob>]
|
||||||
|
|
||||||
|
Searches the keyspace for tasks matching <glob>. If --regexp is given,
|
||||||
|
it associated value is taken as a regexp and matched against the tasks;
|
||||||
|
if --exact is given, its associated value is taken as an exact string
|
||||||
|
to match against the task.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
id = ircdb.users.getUserId(msg.prefix)
|
||||||
|
except KeyError:
|
||||||
|
irc.error(msg, conf.replyNotRegistered)
|
||||||
|
return
|
||||||
|
|
||||||
|
(optlist, rest) = getopt.getopt(args, '', ['regexp=', 'exact='])
|
||||||
|
if not optlist and not rest:
|
||||||
|
raise callbacks.ArgumentError
|
||||||
|
criteria = ['userid = %s' % id]
|
||||||
|
formats = []
|
||||||
|
predicateName = 'p'
|
||||||
|
for (option, arg) in optlist:
|
||||||
|
if option == '--exact':
|
||||||
|
criteria.append('task LIKE %s')
|
||||||
|
formats.append('%' + arg + '%')
|
||||||
|
elif option == '--regexp':
|
||||||
|
criteria.append('%s(task)' % predicateName)
|
||||||
|
try:
|
||||||
|
r = utils.perlReToPythonRe(arg)
|
||||||
|
except ValueError, e:
|
||||||
|
irc.error(msg, 'Invalid regexp: %s' % e)
|
||||||
|
return
|
||||||
|
def p(s, r=r):
|
||||||
|
return int(bool(r.search(s)))
|
||||||
|
self.db.create_function(predicateName, 1, p)
|
||||||
|
predicateName += 'p'
|
||||||
|
for glob in rest:
|
||||||
|
criteria.append('task LIKE %s')
|
||||||
|
formats.append(glob.translate(self._sqlTrans))
|
||||||
|
cursor = self.db.cursor()
|
||||||
|
sql = """SELECT id, task FROM todo WHERE %s""" % ' AND '.join(criteria)
|
||||||
|
cursor.execute(sql, formats)
|
||||||
|
if cursor.rowcount == 0:
|
||||||
|
irc.reply(msg, 'No tasks matched that query.')
|
||||||
|
else:
|
||||||
|
tasks = ['#%s: %s' % (item[0], utils.ellipsisify(item[1], 50)) \
|
||||||
|
for item in cursor.fetchall()]
|
||||||
|
irc.reply(msg, utils.commaAndify(tasks))
|
||||||
|
|
||||||
Class = Todo
|
Class = Todo
|
||||||
|
|
||||||
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|
||||||
|
82
test/test_Todo.py
Normal file
82
test/test_Todo.py
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
###
|
||||||
|
# Copyright (c) 2003, Daniel DiPaolo
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions, and the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions, and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
# * Neither the name of the author of this software nor the name of
|
||||||
|
# contributors to this software may be used to endorse or promote products
|
||||||
|
# derived from this software without specific prior written consent.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
###
|
||||||
|
|
||||||
|
from test import *
|
||||||
|
|
||||||
|
try:
|
||||||
|
import sqlite
|
||||||
|
except ImportError:
|
||||||
|
sqlite = None
|
||||||
|
|
||||||
|
if sqlite is not None:
|
||||||
|
class TodoTestCase(PluginTestCase, PluginDocumentation):
|
||||||
|
plugins = ('Todo', 'UserCommands')
|
||||||
|
def setUp(self):
|
||||||
|
PluginTestCase.setUp(self)
|
||||||
|
# Create a valid user to use
|
||||||
|
self.prefix = 'foo!bar@baz'
|
||||||
|
self.assertNotError('register tester moo')
|
||||||
|
|
||||||
|
def testTodo(self):
|
||||||
|
# Should not error, but no tasks yet.
|
||||||
|
self.assertNotError('todo')
|
||||||
|
self.assertRegexp('todo', 'You have no tasks in your todo list.')
|
||||||
|
# Add a task
|
||||||
|
self.assertNotError('addtodo wash my car')
|
||||||
|
self.assertRegexp('todo', '#1: wash my car')
|
||||||
|
# Check that task
|
||||||
|
self.assertNotError('todo 1')
|
||||||
|
|
||||||
|
def testAddtodo(self):
|
||||||
|
self.assertNotError('addtodo code a new plugin')
|
||||||
|
self.assertNotError('addtodo --priority=1000 fix all bugs')
|
||||||
|
|
||||||
|
def testRemovetodo(self):
|
||||||
|
self.assertNotError('addtodo do something else')
|
||||||
|
self.assertNotError('removetodo 1')
|
||||||
|
|
||||||
|
def testSearchtodo(self):
|
||||||
|
self.assertNotError('addtodo task number one')
|
||||||
|
self.assertRegexp('searchtodo task*', '#1: task number one')
|
||||||
|
self.assertNotError('addtodo task number two is much longer than'
|
||||||
|
' task number one')
|
||||||
|
self.assertRegexp('searchtodo task*', '#1: task number one and #2:'
|
||||||
|
' task number two is much longer than task '
|
||||||
|
'number...')
|
||||||
|
self.assertRegexp('searchtodo --exact "task number one"',
|
||||||
|
'#1: task number one')
|
||||||
|
self.assertError('searchtodo --regexp s/bustedregex')
|
||||||
|
self.assertRegexp('searchtodo --regexp m/task/', '#1: task number'
|
||||||
|
' one and #2: task number two is much longer '
|
||||||
|
'than task number...')
|
||||||
|
|
||||||
|
# vim:set shiftwidth=4 tabstop=8 expandtab textwidth=78:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user