Commit ed237733 authored by Bram Schoenmakers's avatar Bram Schoenmakers

Make a base class for DoCommand and DeleteCommand since they're alike.

parent 28532694
......@@ -28,21 +28,39 @@ class DeleteCommandTest(CommandTest.CommandTest):
self.todolist = TodoList.TodoList(todos)
def test_del1(self):
command = DeleteCommand.DeleteCommand(["1"], self.todolist, self.out, self.error)
command = DeleteCommand.DeleteCommand(["1"], self.todolist, self.out, self.error, lambda p: "n")
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.todolist.todo(1).source(), "Bar")
self.assertEquals(self.output, " 1 Foo id:1\nRemoved.\n")
self.assertEquals(self.output, " 2 Bar p:1\nRemoved: Foo id:1\n")
self.assertEquals(self.errors, "")
def test_del2(self):
command = DeleteCommand.DeleteCommand(["1"], self.todolist, self.out, self.error, lambda p: "y")
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.todolist.count(), 0)
self.assertEquals(self.output, " 2 Bar p:1\nRemoved: Bar\nRemoved: Foo\n")
self.assertEquals(self.errors, "")
def test_del3(self):
command = DeleteCommand.DeleteCommand(["-f", "1"], self.todolist, self.out, self.error, lambda p: "n")
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.todolist.count(), 0)
self.assertEquals(self.output, " 2 Bar p:1\nRemoved: Foo\n")
self.assertEquals(self.errors, "")
def test_del4(self):
command = DeleteCommand.DeleteCommand(["2"], self.todolist, self.out, self.error)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.todolist.todo(1).source(), "Foo")
self.assertEquals(self.output, " 2 Bar p:1\nRemoved.\n")
self.assertEquals(self.output, "Removed: Bar p:1")
self.assertEquals(self.errors, "")
def test_del3(self):
......
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
......@@ -50,14 +50,14 @@ class DoCommandTest(CommandTest.CommandTest):
self.assertTrue(self.todolist.is_dirty())
self.assertTrue(self.todolist.todo(3).is_completed())
self.assertEquals(self.output, "x %s Baz p:1\n" % self.today)
self.assertEquals(self.output, "Completed: x %s Baz p:1\n" % self.today)
self.assertEquals(self.errors, "")
def test_do_children1(self):
def test_do_subtasks1(self):
command = DoCommand.DoCommand(["1"], self.todolist, self.out, self.error, _yes_prompt)
command.execute()
result = " 2 Bar p:1\n 3 Baz p:1\nx %s Bar p:1\nx %s Baz p:1\nx %s Foo id:1\n" % (self.today, self.today, self.today)
result = " 2 Bar p:1\n 3 Baz p:1\nCompleted: x %s Bar p:1\nCompleted: x %s Baz p:1\nCompleted: x %s Foo id:1\n" % (self.today, self.today, self.today)
for number in [1, 2, 3]:
self.assertTrue(self.todolist.todo(number).is_completed())
......@@ -67,11 +67,11 @@ class DoCommandTest(CommandTest.CommandTest):
self.assertEquals(self.output, result)
self.assertEquals(self.errors, "")
def test_do_children2(self):
def test_do_subtasks2(self):
command = DoCommand.DoCommand(["1"], self.todolist, self.out, self.error, _no_prompt)
command.execute()
result = " 2 Bar p:1\n 3 Baz p:1\nx %s Foo id:1\n" % self.today
result = " 2 Bar p:1\n 3 Baz p:1\nCompleted: x %s Foo id:1\n" % self.today
self.assertTrue(self.todolist.is_dirty())
self.assertTrue(self.todolist.todo(1).is_completed())
......@@ -80,7 +80,7 @@ class DoCommandTest(CommandTest.CommandTest):
self.assertEquals(self.output, result)
self.assertEquals(self.errors, "")
def test_do_children_force1(self):
def test_do_subtasks_force1(self):
prompt_shown = False
def prompt(p_prompt):
......@@ -93,7 +93,7 @@ class DoCommandTest(CommandTest.CommandTest):
self.assertEquals(self.errors, "")
self.assertFalse(self.todolist.todo(2).is_completed())
def test_do_children_force2(self):
def test_do_subtasks_force2(self):
prompt_shown = False
def prompt(p_prompt):
......@@ -114,7 +114,7 @@ class DoCommandTest(CommandTest.CommandTest):
command.execute()
todo = self.todolist.todo(8)
result = " 8 %s Recurring! rec:1d due:%s\nx %s Recurring! rec:1d\n" % (self.today, self.tomorrow, self.today)
result = " 8 %s Recurring! rec:1d due:%s\nCompleted: x %s Recurring! rec:1d\n" % (self.today, self.tomorrow, self.today)
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, result)
......@@ -144,7 +144,7 @@ class DoCommandTest(CommandTest.CommandTest):
command = DoCommand.DoCommand(["2"], self.todolist, self.out, self.error)
command.execute()
first_output = "x %s Bar p:1\n" % self.today
first_output = "Completed: x %s Bar p:1\n" % self.today
self.assertEquals(self.output, first_output)
self.assertEquals(self.errors, "")
......@@ -152,14 +152,14 @@ class DoCommandTest(CommandTest.CommandTest):
command = DoCommand.DoCommand(["3"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output, first_output + "x %s Baz p:1\nThe following todo item(s) became active:\nFoo id:1\n" % self.today)
self.assertEquals(self.output, first_output + "Completed: x %s Baz p:1\nThe following todo item(s) became active:\nFoo id:1\n" % self.today)
self.assertEquals(self.errors, "")
def test_activated_todos2(self):
command = DoCommand.DoCommand(["7"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output, "x %s Subtodo of inactive p:2\n" % self.today)
self.assertEquals(self.output, "Completed: x %s Subtodo of inactive p:2\n" % self.today)
self.assertEquals(self.errors, "")
def test_already_complete(self):
......
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from Command import *
from PrettyPrinter import *
from TodoList import InvalidTodoException
from Utils import convert_todo_number, InvalidTodoNumberException
class DCommand(Command):
"""
A common class for the 'do' and 'del' operations, because they're quite
alike.
"""
def __init__(self, p_args, p_todolist,
p_out=lambda a: None,
p_err=lambda a: None,
p_prompt=lambda a: None):
super(DCommand, self).__init__(p_args, p_todolist, p_out, p_err, p_prompt)
self.number = None
self.force = self.argument_shift("--force") or self.argument_shift("-f")
try:
self.number = convert_todo_number(self.argument(0))
self.todo = self.todolist.todo(self.number)
except (InvalidCommandArgument, InvalidTodoNumberException, InvalidTodoException):
self.todo = None
def _uncompleted_children(self, p_todo):
return sorted([t for t in self.todolist.children(p_todo) if not t.is_completed()])
def _print_list(self, p_todos, p_print_numbers=True):
filters = []
if p_print_numbers:
filters = [self.todolist.pp_number()]
self.out("\n".join(pretty_print_list(p_todos, filters)))
def prompt_text(self):
return "Yes or no? [n] "
def prefix(self):
""" Prefix to use when printing a todo. """
return ""
def _process_subtasks(self):
children = self._uncompleted_children(self.todo)
if children:
self._print_list(children)
if not self.force:
confirmation = self.prompt(self.prompt_text())
if not self.force and re.match('^y(es)?$', confirmation, re.I):
for child in children:
self.execute_specific_core(child)
self.out(self.prefix() + pretty_print(child))
def _print_unlocked_todos(self):
"""
Print the items that became unlocked by marking this subitem
(self.todo) as complete.
"""
parents = [parent for parent in self.todolist.parents(self.todo) if not self._uncompleted_children(parent) and parent.is_active()]
if parents:
self.out("The following todo item(s) became active:")
self._print_list(parents, False)
def condition(self):
""" An additional condition whether execute_specific should be executed. """
return True
def conditionFailedText(self):
return ""
def execute_specific(self):
pass
def execute_specific_core(self, p_todo):
"""
The core operation on the todo itself. Also used to operate on
child/parent tasks.
"""
pass
def execute(self):
if not super(DCommand, self).execute():
return False
if not self.number:
self.error(self.usage())
elif self.todo and self.condition():
self._process_subtasks()
self.execute_specific()
self._print_unlocked_todos()
elif not self.todo:
self.error("Invalid todo number given.")
else:
self.error(self.conditionFailedText())
......@@ -14,41 +14,31 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from Command import *
from DCommand import DCommand
from PrettyPrinter import pretty_print
from TodoList import InvalidTodoException
from Utils import convert_todo_number, InvalidTodoNumberException
class DeleteCommand(Command):
class DeleteCommand(DCommand):
def __init__(self, p_args, p_todolist,
p_out=lambda a: None,
p_err=lambda a: None,
p_prompt=lambda a: None):
super(DeleteCommand, self).__init__(p_args, p_todolist, p_out, p_err, p_prompt)
self.number = None
def prompt_text(self):
return "Also remove subtasks? [n] "
try:
self.number = convert_todo_number(self.argument(0))
self.todo = self.todolist.todo(self.number)
except (InvalidCommandArgument, InvalidTodoNumberException, InvalidTodoException):
self.todo = None
def prefix(self):
return "Removed: "
def execute(self):
if not super(DeleteCommand, self).execute():
return False
def execute_specific_core(self, p_todo):
self.todolist.delete(p_todo)
if not self.number:
self.error(self.usage())
elif self.todo:
self.out(pretty_print(self.todo, [self.todolist.pp_number()]))
self.todolist.delete(self.todo)
self.out("Removed.")
else:
self.error("Invalid todo number given.")
def execute_specific(self):
self.out(self.prefix() + pretty_print(self.todo))
self.execute_specific_core(self.todo)
def usage(self):
return """Synopsis: del <NUMBER>"""
return """Synopsis: del [-f] <NUMBER>"""
def help(self):
return """Deletes the todo item with the given number from the list."""
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
from Command import *
from PrettyPrinter import *
from DCommand import DCommand
from PrettyPrinter import pretty_print
from Recurrence import advance_recurring_todo
from TodoList import InvalidTodoException
from Utils import convert_todo_number, InvalidTodoNumberException
class DoCommand(Command):
class DoCommand(DCommand):
def __init__(self, p_args, p_todolist,
p_out=lambda a: None,
p_err=lambda a: None,
p_prompt=lambda a: None):
super(DoCommand, self).__init__(p_args, p_todolist, p_out, p_err, p_prompt)
self.number = None
self.force = self.argument_shift("--force") or self.argument_shift("-f")
try:
self.number = convert_todo_number(self.argument(0))
self.todo = self.todolist.todo(self.number)
except (InvalidCommandArgument, InvalidTodoNumberException, InvalidTodoException):
self.todo = None
def _uncompleted_children(self, p_todo):
return sorted([t for t in self.todolist.children(p_todo) if not t.is_completed()])
def _print_list(self, p_todos, p_print_numbers=True):
filters = []
if p_print_numbers:
filters = [self.todolist.pp_number()]
self.out("\n".join(pretty_print_list(p_todos, filters)))
def _complete_children(self):
children = self._uncompleted_children(self.todo)
if children:
self._print_list(children)
if not self.force:
confirmation = self.prompt("Also mark subtasks as done? [n] ")
if not self.force and re.match('^y(es)?$', confirmation, re.I):
for child in children:
self.todolist.set_todo_completed(child)
self.out(pretty_print(child))
def _handle_recurrence(self):
if self.todo.has_tag('rec'):
new_todo = advance_recurring_todo(self.todo)
self.todolist.add_todo(new_todo)
self.out(pretty_print(new_todo, [self.todolist.pp_number()]))
def _print_unlocked_todos(self):
"""
Print the items that became unlocked by marking this subitem
(self.todo) as complete.
"""
parents = [parent for parent in self.todolist.parents(self.todo) if not self._uncompleted_children(parent) and parent.is_active()]
def prompt_text(self):
return "Also mark subtasks as done? [n] "
def prefix(self):
return "Completed: "
if parents:
self.out("The following todo item(s) became active:")
self._print_list(parents, False)
def condition(self):
""" An additional condition whether execute_specific should be executed. """
return not self.todo.is_completed()
def execute(self):
if not super(DoCommand, self).execute():
return False
def conditionFailedText(self):
return "Todo has already been completed."
if not self.number:
self.error(self.usage())
elif self.todo and not self.todo.is_completed():
self._complete_children()
self._handle_recurrence()
self.todolist.set_todo_completed(self.todo)
self.out(pretty_print(self.todo))
self._print_unlocked_todos()
elif not self.todo:
self.error("Invalid todo number given.")
else:
self.error("Todo has already been completed.")
def execute_specific(self):
""" Actions specific to this command. """
self._handle_recurrence()
self.execute_specific_core(self.todo)
self.out(self.prefix() + pretty_print(self.todo))
def execute_specific_core(self, p_todo):
"""
The core operation on the todo itself. Also used to operate on
child/parent tasks.
"""
self.todolist.set_todo_completed(p_todo)
def usage(self):
return """Synopsis: do [--force] <NUMBER>"""
......
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