Commit 09584282 authored by Bram Schoenmakers's avatar Bram Schoenmakers

Let functions in TodoList accept a Todo instead of a number.

parent e3301ee6
......@@ -45,13 +45,15 @@ class AddCommand(Command.Command):
for raw_value in self.todo.tag_values(p_tag):
try:
value = int(raw_value)
dep = self.todolist.todo(value)
except ValueError:
continue
if p_tag == 'after':
self.todolist.add_dependency(self.todolist.number(self.todo), value)
elif p_tag == 'before' or p_tag == 'partof':
self.todolist.add_dependency(value, self.todolist.number(self.todo))
if dep:
if p_tag == 'after':
self.todolist.add_dependency(self.todo, dep)
elif p_tag == 'before' or p_tag == 'partof':
self.todolist.add_dependency(dep, self.todo)
self.todo.remove_tag(p_tag, raw_value)
......
......@@ -18,7 +18,7 @@ class AppendCommand(Command.Command):
if number and text:
todo = self.todolist.todo(number)
if todo:
self.todolist.append(number, text)
self.todolist.append(todo, text)
self.out(pretty_print(todo, [self.todolist.pp_number()]))
else:
self.error("Invalid todo number given.")
......
......@@ -39,7 +39,9 @@ class DepCommand(Command.Command):
todos = []
if arg2 == 'to':
# dep ls 1 to ...
todos = self.todolist.children(convert_todo_number(arg1))
number = convert_todo_number(arg1)
todo = self.todolist.todo(number)
todos = self.todolist.children(todo)
elif arg1 == 'to':
# dep ls ... to 1
todos = self.todolist.parents(convert_todo_number(arg2))
......
......@@ -15,7 +15,7 @@ class DoCommand(Command.Command):
self.todo = self.todolist.todo(self.number)
def _complete_children(self):
children = [t for t in self.todolist.children(self.number) if not t.is_completed()]
children = [t for t in self.todolist.children(self.todo) if not t.is_completed()]
if children:
self.out("\n".join(pretty_print_list(children, [self.todolist.pp_number()])))
......
......@@ -69,8 +69,7 @@ class DependencyFilter(Filter):
"""
Returns True when there are no children that are uncompleted yet.
"""
number = self.todolist.number(p_todo)
children = self.todolist.children(number)
children = self.todolist.children(p_todo)
uncompleted = [todo for todo in children if not todo.is_completed()]
return not uncompleted
......@@ -122,38 +122,34 @@ class TodoList(object):
self._update_parent_cache()
self.dirty = True
def delete(self, p_number):
def delete(self, p_todo):
""" Deletes a todo item from the list. """
todo = self.todo(p_number)
number = self.number(p_todo)
if todo:
for child in self.children(p_number):
self.remove_dependency(self.number(todo), self.number(child))
for child in self.children(p_todo):
self.remove_dependency(p_todo, child)
for parent in self.parents(p_number):
self.remove_dependency(self.number(parent), self.number(todo))
for parent in self.parents(p_todo):
self.remove_dependency(parent, p_todo)
del self._todos[p_number - 1]
del self._todos[number - 1]
self.dirty = True
self.dirty = True
def count(self):
""" Returns the number of todos on this list. """
return len(self._todos)
def append(self, p_number, p_string):
def append(self, p_todo, p_string):
"""
Appends a text to the todo, specified by its number.
The todo will be parsed again, such that tags and projects in de
appended string are processed.
"""
if len(p_string) > 0:
todo = self.todo(p_number)
if todo:
new_text = todo.source() + ' ' + p_string
todo.set_source_text(new_text)
self.dirty = True
new_text = p_todo.source() + ' ' + p_string
p_todo.set_source_text(new_text)
self.dirty = True
def projects(self):
""" Returns a set of all projects in this list. """
......@@ -183,7 +179,7 @@ class TodoList(object):
"""
return View.View(p_sorter, p_filters, self)
def add_dependency(self, p_number1, p_number2):
def add_dependency(self, p_from_todo, p_to_todo):
""" Adds a dependency from task 1 to task 2. """
def find_next_id():
"""
......@@ -198,61 +194,48 @@ class TodoList(object):
return '%d' % new_id
from_todo = self.todo(p_number1)
to_todo = self.todo(p_number2)
if p_number1 != p_number2 and not self._depgraph.has_edge(hash(from_todo), hash(to_todo)):
if not from_todo or not to_todo:
return
if p_from_todo != p_to_todo and not self._depgraph.has_edge(hash(p_from_todo), hash(p_to_todo)):
dep_id = None
if from_todo.has_tag('id'):
dep_id = from_todo.tag_value('id')
if p_from_todo.has_tag('id'):
dep_id = p_from_todo.tag_value('id')
else:
dep_id = find_next_id()
from_todo.set_tag('id', dep_id)
p_from_todo.set_tag('id', dep_id)
to_todo.add_tag('p', dep_id)
self._depgraph.add_edge(hash(from_todo), hash(to_todo), dep_id)
p_to_todo.add_tag('p', dep_id)
self._depgraph.add_edge(hash(p_from_todo), hash(p_to_todo), dep_id)
self._update_parent_cache()
self.dirty = True
def remove_dependency(self, p_number1, p_number2):
def remove_dependency(self, p_from_todo, p_to_todo):
""" Removes a dependency between two todos. """
from_todo = self.todo(p_number1)
to_todo = self.todo(p_number2)
if not from_todo or not to_todo:
return
dep_id = from_todo.tag_value('id')
dep_id = p_from_todo.tag_value('id')
if dep_id:
to_todo.remove_tag('p', dep_id)
self._depgraph.remove_edge(hash(from_todo), hash(to_todo))
p_to_todo.remove_tag('p', dep_id)
self._depgraph.remove_edge(hash(p_from_todo), hash(p_to_todo))
self._update_parent_cache()
if not self.children(p_number1, True):
from_todo.remove_tag('id')
if not self.children(p_from_todo, True):
p_from_todo.remove_tag('id')
self.dirty = True
def parents(self, p_number, p_only_direct=False):
def parents(self, p_todo, p_only_direct=False):
"""
Returns a list of parent todos that (in)directly depend on the
given todo.
"""
todo = self.todo(p_number)
parents = self._depgraph.incoming_neighbors(hash(todo), not p_only_direct)
parents = self._depgraph.incoming_neighbors(hash(p_todo), not p_only_direct)
return [self.todo_by_hash(parent) for parent in parents]
def children(self, p_number, p_only_direct=False):
def children(self, p_todo, p_only_direct=False):
"""
Returns a list of child todos that the given todo (in)directly depends
on.
"""
todo = self.todo(p_number)
children = \
self._depgraph.outgoing_neighbors(hash(todo), not p_only_direct)
self._depgraph.outgoing_neighbors(hash(p_todo), not p_only_direct)
return [self.todo_by_hash(child) for child in children]
def clean_dependencies(self):
......@@ -284,7 +267,7 @@ class TodoList(object):
"""
for todo in self._todos:
todo.attributes['parents'] = self.parents(self.number(todo))
todo.attributes['parents'] = self.parents(todo)
def is_dirty(self):
return self.dirty
......@@ -292,14 +275,12 @@ class TodoList(object):
def todos(self):
return self._todos
def set_todo_completed(self, p_number):
todo = self.todo(p_number)
todo.set_completed()
def set_todo_completed(self, p_todo):
p_todo.set_completed()
self.dirty = True
def set_priority(self, p_number, p_priority):
todo = self.todo(p_number)
todo.set_priority(p_priority)
def set_priority(self, p_todo, p_priority):
p_todo.set_priority(p_priority)
self.dirty = True
def number(self, p_todo):
......
......@@ -72,7 +72,7 @@ class TodoListTester(unittest.TestCase):
def test_delete1(self):
count = self.todolist.count()
todo = self.todolist.todo(2)
self.todolist.delete(2)
self.todolist.delete(todo)
self.assertEquals(self.todolist.todo(2).source(), \
"(C) Baz @Context1 +Project1 key:value")
......@@ -80,39 +80,31 @@ class TodoListTester(unittest.TestCase):
self.assertTrue(self.todolist.is_dirty())
self.assertRaises(ValueError, self.todolist.number, todo)
def test_delete2(self):
count = self.todolist.count()
self.todolist.delete(count + 1)
self.assertEquals(self.todolist.count(), count)
self.assertFalse(self.todolist.is_dirty())
def test_append1(self):
self.todolist.append(3, "@Context3")
todo = self.todolist.todo(3)
self.todolist.append(todo, "@Context3")
self.assertEquals(self.todolist.todo(3).source(), \
self.assertEquals(todo.source(), \
"(C) Baz @Context1 +Project1 key:value @Context3")
self.assertEquals(set(['Context1', 'Context2', 'Context3']), \
self.todolist.contexts())
self.assertTrue(self.todolist.is_dirty())
def test_append2(self):
text = self.todolist.todo(3).text()
self.todolist.append(3, "foo:bar")
todo = self.todolist.todo(3)
text = todo.text()
self.todolist.append(todo, "foo:bar")
self.assertEquals(self.todolist.todo(3).text(), text)
self.assertEquals(self.todolist.todo(3).source(), \
self.assertEquals(todo.text(), text)
self.assertEquals(todo.source(), \
"(C) Baz @Context1 +Project1 key:value foo:bar")
def test_append3(self):
text = self.todolist.todo(3).text()
self.todolist.append(3, '')
todo = self.todolist.todo(3)
text = todo.text()
self.todolist.append(todo, '')
self.assertEquals(self.todolist.todo(3).text(), text)
def test_append4(self):
self.todolist.append(999, 'foo')
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(todo.text(), text)
def test_todo(self):
count = self.todolist.count()
......@@ -137,7 +129,7 @@ class TodoListTester(unittest.TestCase):
self.assertTrue(self.todolist.todo_by_dep_id('1'))
self.assertFalse(self.todolist.todo_by_dep_id('2'))
def test_todo_number(self):
def test_todo_number1(self):
todo = Todo.Todo("No number")
self.todolist.add_todo(todo)
......@@ -145,13 +137,20 @@ class TodoListTester(unittest.TestCase):
self.assertIsInstance(todo, Todo.Todo)
self.assertEquals(todo.text(), "No number")
def test_todo_number2(self):
todo = Todo.Todo("Non-existent")
self.assertRaises(ValueError, self.todolist.number, todo)
def test_todo_complete(self):
self.todolist.set_todo_completed(1)
todo = self.todolist.todo(1)
self.todolist.set_todo_completed(todo)
self.assertTrue(self.todolist.todo(1).is_completed())
self.assertTrue(self.todolist.is_dirty())
def test_todo_priority(self):
self.todolist.set_priority(1, 'F')
todo = self.todolist.todo(1)
self.todolist.set_priority(todo, 'F')
self.assertEquals(self.todolist.todo(1).priority(), 'F')
self.assertTrue(self.todolist.is_dirty())
......@@ -165,34 +164,36 @@ class TodoListDependencyTester(unittest.TestCase):
self.todolist.add("Fnord")
def test_check_dep(self):
children = self.todolist.children(1)
children = self.todolist.children(self.todolist.todo(1))
self.assertEqual(sorted([todo.source() for todo in children]), \
sorted(['Bar p:1', 'Baz p:1 id:2', 'Buzz p:2']))
children = self.todolist.children(1, True)
children = self.todolist.children(self.todolist.todo(1), True)
self.assertEqual(sorted([todo.source() for todo in children]), \
sorted(['Bar p:1', 'Baz p:1 id:2']))
children = self.todolist.children(3)
children = self.todolist.children(self.todolist.todo(3))
self.assertEqual(sorted([todo.source() for todo in children]), \
['Buzz p:2'])
parents = self.todolist.parents(4)
parents = self.todolist.parents(self.todolist.todo(4))
self.assertEqual(sorted([todo.source() for todo in parents]), \
sorted(['Foo id:1', 'Baz p:1 id:2']))
parents = self.todolist.parents(4, True)
parents = self.todolist.parents(self.todolist.todo(4), True)
self.assertEqual(sorted([todo.source() for todo in parents]), \
['Baz p:1 id:2'])
self.assertEqual(self.todolist.children(2), [])
self.assertEqual(self.todolist.parents(1), [])
self.assertEqual(self.todolist.children(self.todolist.todo(2)), [])
self.assertEqual(self.todolist.parents(self.todolist.todo(1)), [])
def test_add_dep1(self):
self.todolist.add_dependency(5, 4)
todo4 = self.todolist.todo(4)
todo5 = self.todolist.todo(5)
self.todolist.add_dependency(todo5, todo4)
self.assertTrue(self.todolist.todo(5).has_tag('id', '3'))
self.assertTrue(self.todolist.todo(4).has_tag('p', '3'))
self.assertTrue(todo5.has_tag('id', '3'))
self.assertTrue(todo4.has_tag('p', '3'))
def test_add_dep2(self):
"""
......@@ -200,41 +201,55 @@ class TodoListDependencyTester(unittest.TestCase):
edge_id properly.
"""
self.todolist.add_dependency(5, 4)
self.todolist.add_dependency(4, 1)
todo1 = self.todolist.todo(1)
todo4 = self.todolist.todo(4)
todo5 = self.todolist.todo(5)
self.todolist.add_dependency(todo5, todo4)
self.todolist.add_dependency(todo4, todo1)
self.assertTrue(self.todolist.todo(4).has_tag('id', '4'))
self.assertTrue(self.todolist.todo(1).has_tag('p', '4'))
self.assertTrue(todo4.has_tag('id', '4'))
self.assertTrue(todo1.has_tag('p', '4'))
def test_remove_dep1(self):
self.todolist.remove_dependency(3, 4)
from_todo = self.todolist.todo(3)
to_todo = self.todolist.todo(4)
self.todolist.remove_dependency(from_todo, to_todo)
self.assertFalse(self.todolist.todo(3).has_tag('id'))
self.assertFalse(self.todolist.todo(4).has_tag('p'))
self.assertFalse(from_todo.has_tag('id'))
self.assertFalse(to_todo.has_tag('p'))
def test_remove_dep2(self):
old = str(self.todolist)
self.todolist.remove_dependency(1, 4)
from_todo = self.todolist.todo(1)
to_todo = self.todolist.todo(4)
self.todolist.remove_dependency(from_todo, to_todo)
self.assertEquals(str(self.todolist), old)
def test_remove_todo_check_children(self):
self.todolist.delete(2)
self.assertTrue(self.todolist.children(2))
todo = self.todolist.todo(2)
self.todolist.delete(todo)
todo = self.todolist.todo(2)
self.assertTrue(self.todolist.children(todo))
def test_remove_task(self):
self.todolist.delete(3)
self.assertFalse(self.todolist.todo(3).has_tag('p', '2'))
todo = self.todolist.todo(3)
self.todolist.delete(todo)
self.assertFalse(todo.has_tag('p', '2'))
children = self.todolist.children(1)
self.assertEqual([todo.source() for todo in children], \
['Bar p:1'])
todo = self.todolist.todo(1)
children = self.todolist.children(todo)
self.assertEqual([t.source() for t in children], ['Bar p:1'])
def test_add_double_dep(self):
self.todolist.add_dependency(1, 2)
todo1 = self.todolist.todo(1)
todo2 = self.todolist.todo(2)
self.todolist.add_dependency(todo1, todo2)
self.assertEqual(self.todolist.todo(1).source(), 'Foo id:1')
self.assertEqual(self.todolist.todo(2).source(), 'Bar p:1')
self.assertEqual(todo1.source(), 'Foo id:1')
self.assertEqual(todo2.source(), 'Bar p:1')
class TodoListCleanDependencyTester(unittest.TestCase):
def setUp(self):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment