Commit 787bbeca authored by Bram Schoenmakers's avatar Bram Schoenmakers

Merge branch 'master' of bram85.nl:/home/bram/Projecten/todo.py

parents b46691b6 a8ae9225
...@@ -125,14 +125,8 @@ class DirectedGraph(object): ...@@ -125,14 +125,8 @@ class DirectedGraph(object):
""" """
Returns True if the client registered an edge with the given id. Returns True if the client registered an edge with the given id.
""" """
result = False l = [e for e in self._edge_numbers.itervalues() if e == p_id]
return len(l) > 0
for edge_id in self._edge_numbers.itervalues():
if edge_id == p_id:
result = True
break
return result
def edge_id(self, p_from, p_to): def edge_id(self, p_from, p_to):
""" """
......
""" """
Provides a function to calculate the importance value of a task. Provides functions to calculate the importance value of a task.
For those who are familiar with the Toodledo website, the importance value is a For those who are familiar with the Toodledo website, the importance value is a
combination of the priority and the todo's due date. Low priority tasks due combination of the priority and the todo's due date. Low priority tasks due
...@@ -57,3 +57,14 @@ def importance(p_todo, p_ignore_weekend=False): ...@@ -57,3 +57,14 @@ def importance(p_todo, p_ignore_weekend=False):
result += 1 result += 1
return result if not p_todo.is_completed() else 0 return result if not p_todo.is_completed() else 0
def average_importance(p_todo, p_ignore_weekend=False):
sum_importance = importance(p_todo, p_ignore_weekend)
parents = []
if 'parents' in p_todo.attributes:
parents = p_todo.attributes['parents']
for parent in parents:
sum_importance += importance(parent, p_ignore_weekend)
return float(sum_importance) / float(1 + len(parents))
...@@ -161,10 +161,25 @@ class Application(object): ...@@ -161,10 +161,25 @@ class Application(object):
usage() usage()
def do(self): def do(self):
def complete_children(p_number):
children = [t.number for t in self.todolist.children(p_number) if not t.is_completed()]
if children:
for child in children:
self.print_todo(child)
confirmation = raw_input("Also mark subtasks as done? [n] ");
if re.match('^y(es)?$', confirmation, re.I):
for child in children:
self.todolist.todo(child).set_completed()
self.print_todo(child)
number = convert_number(argument(2)) number = convert_number(argument(2))
todo = self.todolist.todo(number) todo = self.todolist.todo(number)
if todo: if todo and not todo.is_completed():
complete_children(number)
todo.set_completed() todo.set_completed()
self.print_todo(number) self.print_todo(number)
self.dirty = True self.dirty = True
......
...@@ -4,7 +4,7 @@ import datetime ...@@ -4,7 +4,7 @@ import datetime
import re import re
import Config import Config
from Importance import importance from Importance import importance, average_importance
def is_priority_field(p_field): def is_priority_field(p_field):
""" Returns True when the field name denotes the priority. """ """ Returns True when the field name denotes the priority. """
...@@ -30,6 +30,8 @@ def get_field_function(p_field): ...@@ -30,6 +30,8 @@ def get_field_function(p_field):
else datetime.date.max) else datetime.date.max)
elif p_field == 'importance': elif p_field == 'importance':
result = lambda a: importance(a, Config.IGNORE_WEEKENDS) result = lambda a: importance(a, Config.IGNORE_WEEKENDS)
elif p_field == 'importance-avg' or p_field == 'importance-average':
result = lambda a: average_importance(a, Config.IGNORE_WEEKENDS)
elif p_field == 'text': elif p_field == 'text':
result = lambda a: a.text() result = lambda a: a.text()
else: else:
......
...@@ -16,6 +16,7 @@ class Todo(TodoBase.TodoBase): ...@@ -16,6 +16,7 @@ class Todo(TodoBase.TodoBase):
def __init__(self, p_str, p_number=-1): def __init__(self, p_str, p_number=-1):
TodoBase.TodoBase.__init__(self, p_str, p_number) TodoBase.TodoBase.__init__(self, p_str, p_number)
self.attributes = {}
def get_date(self, p_tag): def get_date(self, p_tag):
""" Given a date tag, return a date object. """ """ Given a date tag, return a date object. """
......
...@@ -101,6 +101,7 @@ class TodoList(object): ...@@ -101,6 +101,7 @@ class TodoList(object):
self._todos.append(todo) self._todos.append(todo)
self._maintain_dep_graph(todo) self._maintain_dep_graph(todo)
self._update_parent_cache()
return todo return todo
...@@ -193,6 +194,7 @@ class TodoList(object): ...@@ -193,6 +194,7 @@ class TodoList(object):
to_todo.add_tag('p', dep_id) to_todo.add_tag('p', dep_id)
self._depgraph.add_edge(p_number1, p_number2, int(dep_id)) self._depgraph.add_edge(p_number1, p_number2, int(dep_id))
self._update_parent_cache()
def remove_dependency(self, p_number1, p_number2): def remove_dependency(self, p_number1, p_number2):
""" Removes a dependency between two todos. """ """ Removes a dependency between two todos. """
...@@ -207,6 +209,7 @@ class TodoList(object): ...@@ -207,6 +209,7 @@ class TodoList(object):
if dep_id: if dep_id:
to_todo.remove_tag('p', dep_id) to_todo.remove_tag('p', dep_id)
self._depgraph.remove_edge(p_number1, p_number2) self._depgraph.remove_edge(p_number1, p_number2)
self._update_parent_cache()
if not self.children(p_number1, True): if not self.children(p_number1, True):
from_todo.remove_tag('id') from_todo.remove_tag('id')
...@@ -247,6 +250,17 @@ class TodoList(object): ...@@ -247,6 +250,17 @@ class TodoList(object):
clean_by_tag('p') clean_by_tag('p')
clean_by_tag('id') clean_by_tag('id')
def _update_parent_cache(self):
"""
Sets the attribute to the list of parents, such that others may access
it outside this todo list.
This is used for calculating the average importance, that requires
access to a todo's parents.
"""
for todo in self._todos:
todo.attributes['parents'] = self.parents(todo.number)
def __str__(self): def __str__(self):
return '\n'.join(pretty_print(self._todos)) return '\n'.join(pretty_print(self._todos))
import unittest import unittest
import Sorter import Sorter
from TestFacilities import load_file, todolist_to_string import TodoList
import View
from TestFacilities import load_file, todolist_to_string, load_file_to_todolist
class SorterTest(unittest.TestCase): class SorterTest(unittest.TestCase):
def sort_file(self,p_filename, p_filename_ref, p_sorter): def sort_file(self,p_filename, p_filename_ref, p_sorter):
...@@ -87,3 +90,35 @@ class SorterTest(unittest.TestCase): ...@@ -87,3 +90,35 @@ class SorterTest(unittest.TestCase):
sorter = Sorter.Sorter('fnord') sorter = Sorter.Sorter('fnord')
self.sort_file('data/SorterTest9.txt', 'data/SorterTest9.txt', sorter) self.sort_file('data/SorterTest9.txt', 'data/SorterTest9.txt', sorter)
def test_sort12(self):
"""
Descendingly sorted by average importance.
Reusing input and output for normal importance test, since without
dependencies the average importance should be equal.
"""
sorter = Sorter.Sorter('desc:importance-avg')
self.sort_file('data/SorterTest9.txt', 'data/SorterTest9-result.txt', sorter)
def test_sort13(self):
sorter = Sorter.Sorter('desc:importance-average')
todolist = load_file_to_todolist('data/SorterTest10.txt')
view = todolist.view(sorter, [])
result = load_file('data/SorterTest10-result.txt')
self.assertEquals(str(view), todolist_to_string(result))
def test_sort14(self):
"""
Test that own importance is used when average turns out to be
lower.
"""
sorter = Sorter.Sorter('desc:importance-average')
todolist = load_file_to_todolist('data/SorterTest11.txt')
view = todolist.view(sorter, [])
result = load_file('data/SorterTest11-result.txt')
self.assertEquals(str(view), todolist_to_string(result))
import Todo import Todo
import TodoFile import TodoFile
import TodoList
def load_file(p_filename): def load_file(p_filename):
""" """
...@@ -16,6 +17,13 @@ def load_file_to_raw_list(p_filename): ...@@ -16,6 +17,13 @@ def load_file_to_raw_list(p_filename):
todofile = TodoFile.TodoFile(p_filename) todofile = TodoFile.TodoFile(p_filename)
return todofile.read() return todofile.read()
def load_file_to_todolist(p_filename):
"""
Loads a todo file to a TodoList instance.
"""
todolist = load_file_to_raw_list(p_filename)
return TodoList.TodoList(todolist)
def todolist_to_string(p_list): def todolist_to_string(p_list):
""" Converts a todo list to a single string. """ """ Converts a todo list to a single string. """
return '\n'.join([str(t) for t in p_list]) return '\n'.join([str(t) for t in p_list])
(A) Important parent task id:1 (5)
(A) Another important task id:2 (5)
(C) Less important child task p:1 p:2 ((3+5+5)/3=4.3)
(B) Normal task (4)
(B) Normal task (4)
(A) Important parent task id:1 (5)
(A) Another important task id:2 (5)
(C) Less important child task p:1 p:2 ((3+5+5)/3=4.3)
(B) Normal task (4)
(C) Less important child task p:1 p:2 ((3+0+0)/3=1 -> 3)
(D) Not-so important parent task id:1 (2)
(D) Another not-so important task id:2 (2)
(B) Normal task (4)
(D) Not-so important parent task id:1 (2)
(D) Another not-so important task id:2 (2)
(C) Less important child task p:1 p:2 ((3+0+0)/3=1 -> 3)
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