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