Commit e664ac52 authored by Bram Schoenmakers's avatar Bram Schoenmakers

Handle absence or invalid recurrence patterns more gracefully.

When completing a command, show a warning when a 'rec' tag has an
invalid recurrence pattern.

Fixes issue #6.

Conflicts:
	topydo/lib/DoCommand.py
parent ae56aa78
......@@ -39,6 +39,7 @@ class DoCommandTest(CommandTest.CommandTest):
"Inactive t:2030-12-31 id:2",
"Subtodo of inactive p:2",
"Strict due:2014-01-01 rec:1d",
"Invalid rec:1",
]
self.todolist = TodoList(todos)
......@@ -121,7 +122,7 @@ class DoCommandTest(CommandTest.CommandTest):
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.errors, "")
self.assertEquals(self.todolist.count(), 9)
self.assertEquals(self.todolist.count(), 10)
def test_recurrence(self):
self.assertFalse(self.todolist.todo(4).has_tag('due'))
......@@ -129,22 +130,22 @@ class DoCommandTest(CommandTest.CommandTest):
self._recurrence_helper(["4"])
self.assertTrue(self.todolist.todo(4).is_completed())
result = "| 9| {today} Recurring! rec:1d due:{tomorrow}\nCompleted: x {today} Recurring! rec:1d\n".format(today=self.today, tomorrow=self.tomorrow)
result = "| 10| {today} Recurring! rec:1d due:{tomorrow}\nCompleted: x {today} Recurring! rec:1d\n".format(today=self.today, tomorrow=self.tomorrow)
self.assertEquals(self.output, result)
todo = self.todolist.todo(8)
todo = self.todolist.todo(10)
self.assertFalse(todo.is_completed())
self.assertTrue(todo.has_tag('due'))
def test_strict_recurrence1(self):
self._recurrence_helper(["-s", "8"])
result = "| 9| {today} Strict due:2014-01-02 rec:1d\nCompleted: x {today} Strict due:2014-01-01 rec:1d\n".format(today=self.today)
result = "| 10| {today} Strict due:2014-01-02 rec:1d\nCompleted: x {today} Strict due:2014-01-01 rec:1d\n".format(today=self.today)
self.assertEquals(self.output, result)
def test_strict_recurrence2(self):
self._recurrence_helper(["--strict", "8"])
result = "| 9| {today} Strict due:2014-01-02 rec:1d\nCompleted: x {today} Strict due:2014-01-01 rec:1d\n".format(today=self.today)
result = "| 10| {today} Strict due:2014-01-02 rec:1d\nCompleted: x {today} Strict due:2014-01-01 rec:1d\n".format(today=self.today)
self.assertEquals(self.output, result)
def test_invalid1(self):
......@@ -252,7 +253,7 @@ class DoCommandTest(CommandTest.CommandTest):
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, "| 9| {today} Recurring! rec:1d due:{today}\nCompleted: x {yesterday} Recurring! rec:1d\n".format(today=self.today, yesterday=self.yesterday))
self.assertEquals(self.output, "| 10| {today} Recurring! rec:1d due:{today}\nCompleted: x {yesterday} Recurring! rec:1d\n".format(today=self.today, yesterday=self.yesterday))
self.assertEquals(self.errors, "")
def test_do_custom_date6(self):
......@@ -265,7 +266,7 @@ class DoCommandTest(CommandTest.CommandTest):
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, "| 9| {today} Recurring! rec:1d due:{today}\nCompleted: x {yesterday} Recurring! rec:1d\n".format(today=self.today, yesterday=self.yesterday))
self.assertEquals(self.output, "| 10| {today} Recurring! rec:1d due:{today}\nCompleted: x {yesterday} Recurring! rec:1d\n".format(today=self.today, yesterday=self.yesterday))
self.assertEquals(self.errors, "")
def test_do_custom_date7(self):
......@@ -277,7 +278,7 @@ class DoCommandTest(CommandTest.CommandTest):
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, "| 9| {today} Strict due:2014-01-02 rec:1d\nCompleted: x {yesterday} Strict due:2014-01-01 rec:1d\n".format(today=self.today, yesterday=self.yesterday))
self.assertEquals(self.output, "| 10| {today} Strict due:2014-01-02 rec:1d\nCompleted: x {yesterday} Strict due:2014-01-01 rec:1d\n".format(today=self.today, yesterday=self.yesterday))
self.assertEquals(self.errors, "")
def test_multi_do1(self):
......@@ -320,11 +321,19 @@ class DoCommandTest(CommandTest.CommandTest):
When a todo item was generated by a recurring todo item, make sure
it cannot be completed in the same invocation.
"""
command = DoCommand(["4", "9"], self.todolist, self.out, self.error, _no_prompt)
command = DoCommand(["4", "10"], self.todolist, self.out, self.error, _no_prompt)
command.execute()
self.assertTrue(self.todolist.todo(4).is_completed())
self.assertFalse(self.todolist.todo(9).is_completed())
self.assertFalse(self.todolist.todo(10).is_completed())
def test_invalid_recurrence(self):
""" Show error message when an item has an invalid recurrence pattern. """
command = DoCommand(["9"], self.todolist, self.out, self.error, _no_prompt)
command.execute()
self.assertEquals(self.output, "Completed: x {} Invalid rec:1\n".format(self.today))
self.assertEquals(self.errors, "Warning: todo item has an invalid recurrence pattern.\n")
def test_empty(self):
command = DoCommand([], self.todolist, self.out, self.error)
......
......@@ -136,7 +136,12 @@ class RecurrenceTest(TopydoTest):
def test_no_recurrence(self):
self.todo.remove_tag('rec')
self.assertRaises(NoRecurrenceException,advance_recurring_todo,self.todo)
self.assertRaises(NoRecurrenceException, advance_recurring_todo, self.todo)
def test_invalid_recurrence(self):
""" Throw exception when 'rec' tag has an invalid value. """
self.todo.set_tag('rec', '1')
self.assertRaises(NoRecurrenceException, advance_recurring_todo, self.todo)
if __name__ == '__main__':
unittest.main()
......@@ -19,7 +19,7 @@ from datetime import date
from topydo.lib.DCommand import DCommand
from topydo.lib.PrettyPrinter import PrettyPrinter
from topydo.lib.PrettyPrinterFilter import PrettyPrinterNumbers
from topydo.lib.Recurrence import advance_recurring_todo, strict_advance_recurring_todo
from topydo.lib.Recurrence import advance_recurring_todo, strict_advance_recurring_todo, NoRecurrenceException
from topydo.lib.Utils import date_string_to_date
class DoCommand(DCommand):
......@@ -49,18 +49,21 @@ class DoCommand(DCommand):
def _handle_recurrence(self, p_todo):
if p_todo.has_tag('rec'):
if self.strict_recurrence:
new_todo = strict_advance_recurring_todo(p_todo,
self.completion_date)
else:
new_todo = advance_recurring_todo(p_todo,
self.completion_date)
self.todolist.add_todo(new_todo)
printer = PrettyPrinter()
printer.add_filter(PrettyPrinterNumbers(self.todolist))
self.out(printer.print_todo(new_todo))
try:
if self.strict_recurrence:
new_todo = strict_advance_recurring_todo(p_todo,
self.completion_date)
else:
new_todo = advance_recurring_todo(p_todo,
self.completion_date)
self.todolist.add_todo(new_todo)
printer = PrettyPrinter()
printer.add_filter(PrettyPrinterNumbers(self.todolist))
self.out(printer.print_todo(new_todo))
except NoRecurrenceException:
self.error("Warning: todo item has an invalid recurrence pattern.")
def prompt_text(self):
return "Also mark subtasks as done? [y/N] "
......
......@@ -42,8 +42,11 @@ def _advance_recurring_todo_helper(p_todo, p_offset):
raise NoRecurrenceException()
length = todo.length()
new_due = relative_date_to_date(pattern, p_offset)
if not new_due:
raise NoRecurrenceException()
todo.set_tag(config().tag_due(), new_due.isoformat())
if todo.start_date():
......
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