Commit 851e2cdd authored by Bram Schoenmakers's avatar Bram Schoenmakers

Merge branch 'master' into dot

Revived the dot subcommand and the dot printer for 'ls'.
parents f2072530 798ed50b
...@@ -14,3 +14,4 @@ exclude_lines = ...@@ -14,3 +14,4 @@ exclude_lines =
omit = omit =
topydo/commands/ExitCommand.py topydo/commands/ExitCommand.py
topydo/lib/Version.py topydo/lib/Version.py
topydo/ui/*
...@@ -8,8 +8,9 @@ python: ...@@ -8,8 +8,9 @@ python:
install: install:
- "python -m pip install pip --upgrade" - "python -m pip install pip --upgrade"
- "pip install ." - "pip install ."
- "pip install .[columns]"
- "pip install .[ical]" - "pip install .[ical]"
- "pip install .[prompt-toolkit]" - "pip install .[prompt]"
- "pip install .[test]" - "pip install .[test]"
- "pip install pylint" - "pip install pylint"
- "pip install codecov" - "pip install codecov"
......
0.10
----
A major release, introducing a new user interface (TUI). Special thanks go to
@mruwek for helping out to get this UI in its current shape.
* New: A column-based user interface. Each column has its own filters and sort
order, allowing you to build a dashboard with your todo items. Launch with
`topydo columns`.
* New: color blocks that change from green to red (overdue) as time passes by.
Use the %z placeholder to add color blocks to the `ls` output.
* New: color option can be set to 0, 1, 16 or 256 and if needed overridden by
-C on the commandline.
* New: recurrence based on business days. Skips Saturdays and Sundays when
calculating the next date (thanks to @mruwek).
* New: items can be sorted by length (use 'length' as sort field).
* New: parents-of and children-of operators with `add`, `dep` and `append`
subcommands. The todo item receives the same parents/children from the
specified todo item.
* New: `append` understands relative dates and other tags that are special to
`add` (thanks to @rameshg87).
* Fix: dependency ID creation with orphan todo items.
* Fix: crash after completing/deleting an edited item.
* Fix: crash after completing an item that got a new dependency with `dep add`
* Change: a new tag value with an existing key can be added with the tag
subcommand (thanks to @MinchinWeb)
* Change: ~/.config/topydo/config can be used as a configuration file.
* Change: No backups are written for read-only commands (e.g. lsprj)
* Change: topydo is more scalable for large todo.txt files.
* Known issue: color blocks are not shown in `ls` output in the column UI.
0.9
---
* Dropped support for Python 2.7.
* Add ability to filter on creation/completion dates:
topydo ls created:today
topydo ls completed:today
topydo -t done.txt completed:today # if auto-archiving is set
* `ls -F` supports `%P` that expands to a single space when no priority is set,
in contrast to `%p` which expands to an empty string (thanks to @MinchinWeb).
* `ls -N` prints enough todo items such that it fits on one screen (thanks to
@MinchinWeb).
* Aliases can have a `{}` placeholder which is substituted with the alias'
arguments (thanks to @mruwek).
* `pri` accepts priorities in lowercase (thanks to @MinchinWeb).
* Several bugfixes for `dep gc`.
* Various test/CI improvements.
0.8 0.8
--- ---
......
...@@ -43,10 +43,6 @@ smoothly into topydo. ...@@ -43,10 +43,6 @@ smoothly into topydo.
exit 1 exit 1
fi fi
if ! python2 -m pylint --errors-only topydo test; then
exit 1
fi
if ! python3 -m pylint --errors-only topydo test; then if ! python3 -m pylint --errors-only topydo test; then
exit 1 exit 1
fi fi
......
...@@ -26,12 +26,26 @@ Simply install with: ...@@ -26,12 +26,26 @@ Simply install with:
pip install topydo pip install topydo
### Optional dependencies ### Dependencies
* [arrow][8] : Used to turn dates into a human readable version.
#### Optional dependencies:
* [icalendar][7] : To print your todo.txt file as an iCalendar file * [icalendar][7] : To print your todo.txt file as an iCalendar file
(not supported for Python 3.2). (not supported for PyPy3).
* [prompt-toolkit][6] : For topydo's _prompt_ mode, which offers a shell-like * [prompt-toolkit][6] : For topydo's _prompt_ mode, which offers a shell-like
interface with auto-completion. interface with auto-completion.
* [arrow][8] : Used to turn dates into a human readable version.
* [urwid][12] : For topydo's _columns_ mode, a TUI with columns for
your todo items.
* [backports.shutil_get_terminal_size][9] : Used to determine your terminal
window size. This function was
added to the standard library in
Python 3.3 and so is only
required for PyPy3.
* [mock][11] : Used for testing. This was added to the standard
library in Python 3.3.
Demo Demo
---- ----
...@@ -46,3 +60,8 @@ Demo ...@@ -46,3 +60,8 @@ Demo
[5]: https://raw.githubusercontent.com/bram85/topydo/master/doc/topydo.gif [5]: https://raw.githubusercontent.com/bram85/topydo/master/doc/topydo.gif
[6]: https://github.com/jonathanslenders/python-prompt-toolkit [6]: https://github.com/jonathanslenders/python-prompt-toolkit
[7]: https://github.com/collective/icalendar [7]: https://github.com/collective/icalendar
[8]: https://github.com/crsmithdev/arrow
[9]: https://github.com/chrippa/backports.shutil_get_terminal_size
[10]: https://dateutil.readthedocs.org/
[11]: https://github.com/testing-cabal/mock
[12]: https://github.com/urwid/urwid
...@@ -33,12 +33,15 @@ setup( ...@@ -33,12 +33,15 @@ setup(
], ],
extras_require = { extras_require = {
':sys_platform=="win32"': ['colorama>=0.2.5'], ':sys_platform=="win32"': ['colorama>=0.2.5'],
':python_version=="3.2"': ['backports.shutil_get_terminal_size>=1.0.0'],
'columns': ['urwid >= 1.3.0'],
'ical': ['icalendar'], 'ical': ['icalendar'],
'prompt-toolkit': ['prompt-toolkit >= 0.53'], 'prompt': ['prompt_toolkit >= 0.53'],
'test': ['coverage', 'freezegun', 'green', ], 'test': ['coverage', 'freezegun', 'green', ],
'test:python_version=="3.2"': ['mock'],
}, },
entry_points= { entry_points= {
'console_scripts': ['topydo = topydo.cli.UILoader:main'], 'console_scripts': ['topydo = topydo.ui.UILoader:main'],
}, },
classifiers = [ classifiers = [
"Development Status :: 5 - Production/Stable", "Development Status :: 5 - Production/Stable",
......
...@@ -20,14 +20,19 @@ from topydo.lib.Utils import escape_ansi ...@@ -20,14 +20,19 @@ from topydo.lib.Utils import escape_ansi
class CommandTest(TopydoTest): class CommandTest(TopydoTest):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(CommandTest, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.output = "" self.output = ""
self.errors = "" self.errors = ""
def out(self, p_output): def out(self, p_output):
if p_output: if isinstance(p_output, list) and p_output:
self.output += escape_ansi(p_output + "\n") self.output += escape_ansi(
"\n".join([str(s) for s in p_output]) + "\n")
elif p_output:
self.output += str(p_output) + "\n"
def error(self, p_error): def error(self, p_error):
if p_error: if isinstance(p_error, list) and p_error:
self.errors += escape_ansi(p_error + "\n") self.errors += escape_ansi(p_error + "\n") + "\n"
elif p_error:
self.errors += str(p_error) + "\n"
[column_keymap]
up = up
<Left> = prev_column
<Esc>d = delete_column
(A) item 1
(B) item 2
(C) item 3
(D) item 4
(E) item 5
(F) item 6
(G) item 7
(H) item 8
(I) item 9
(J) item 10
(K) item 11
(L) item 12
(M) item 13
(N) item 14
(O) item 15
(P) item 16
(Q) item 17
(R) item 18
(S) item 19
(T) item 20
(U) item 21
(V) item 22
(W) item 23
(X) item 24
(Y) item 25
(Z) item 26
(A) item 27
(B) item 28
(C) item 29
(D) item 30
(E) item 31
(F) item 32
(G) item 33
(H) item 34
(I) item 35
(J) item 36
(K) item 37
(L) item 38
(M) item 39
(N) item 40
(O) item 41
(P) item 42
(Q) item 43
(R) item 44
(S) item 45
(T) item 46
(U) item 47
(V) item 48
(W) item 49
(X) item 50
1 No length (zero)
2016-04-25 2 No length (zero)
3 Length of 0 days t:2016-04-25 due:2016-04-25
4 Length of 0 days t:2016-04-25 due:2016-04-25
5 Length of 0 days tomorrow t:2016-04-26 due:2016-04-26
2016-04-25 1 Length of 1 day with creation due:2016-04-26
2 Length of 1 day t:2016-04-25 due:2016-04-26
2016-04-25 Length of 2 days with creation due:2016-04-27
4 Length of 0 days t:2016-04-25 due:2016-04-25
2016-04-25 2 No length (zero)
3 Length of 0 days t:2016-04-25 due:2016-04-25
5 Length of 0 days tomorrow t:2016-04-26 due:2016-04-26
2 Length of 1 day t:2016-04-25 due:2016-04-26
2016-04-25 Length of 2 days with creation due:2016-04-27
2016-04-25 1 Length of 1 day with creation due:2016-04-26
1 No length (zero)
...@@ -3,3 +3,5 @@ foo = rm -f test ...@@ -3,3 +3,5 @@ foo = rm -f test
baz = FooBar baz = FooBar
format = ls -F "|I| x c d {(}p{)} s k" -n 25 format = ls -F "|I| x c d {(}p{)} s k" -n 25
smile = ls smile = ls
star = tag {} star 1
quot = lol'd
...@@ -52,4 +52,4 @@ def todolist_to_string(p_list): ...@@ -52,4 +52,4 @@ def todolist_to_string(p_list):
def print_view(p_view): def print_view(p_view):
printer = PrettyPrinter() printer = PrettyPrinter()
return printer.print_list(p_view.todos) return "\n".join([str(s) for s in printer.print_list(p_view.todos)])
...@@ -33,7 +33,7 @@ except ImportError: ...@@ -33,7 +33,7 @@ except ImportError:
class AddCommandTest(CommandTest): class AddCommandTest(CommandTest):
def setUp(self): def setUp(self):
super(AddCommandTest, self).setUp() super().setUp()
self.todolist = TodoList.TodoList([]) self.todolist = TodoList.TodoList([])
self.today = date.today().isoformat() self.today = date.today().isoformat()
...@@ -268,6 +268,61 @@ class AddCommandTest(CommandTest): ...@@ -268,6 +268,61 @@ class AddCommandTest(CommandTest):
self.assertEqual(self.output, "|wb3| {today} Bar p:1 @Context\n|wb3| {today} Bar @Context\n".format(today=self.today)) self.assertEqual(self.output, "|wb3| {today} Bar p:1 @Context\n|wb3| {today} Bar @Context\n".format(today=self.today))
def add_parentsof_helper(self, p_tag):
command = AddCommand.AddCommand(["Foo"], self.todolist, self.out,
self.error)
command.execute()
command = AddCommand.AddCommand(["Bar before:1"], self.todolist,
self.out, self.error)
command.execute()
command = AddCommand.AddCommand(["Baz {}:2".format(p_tag)],
self.todolist, self.out, self.error)
command.execute()
self.assertTrue(self.todolist.todo(3).has_tag('p', '1'))
def test_add_dep_parentsof01(self):
self.add_parentsof_helper('parentsof')
def test_add_dep_parentsof02(self):
self.add_parentsof_helper('parentof')
def test_add_dep_parentsof03(self):
self.add_parentsof_helper('parents-of')
def test_add_dep_parentsof04(self):
self.add_parentsof_helper('parent-of')
def add_childrenof_helper(self, p_tag):
command = AddCommand.AddCommand(["Foo"], self.todolist, self.out,
self.error)
command.execute()
command = AddCommand.AddCommand(["Bar before:1"], self.todolist,
self.out, self.error)
command.execute()
command = AddCommand.AddCommand(["Baz {}:1".format(p_tag)],
self.todolist, self.out, self.error)
command.execute()
self.assertTrue(self.todolist.todo(3).has_tag('id', '2'))
self.assertTrue(self.todolist.todo(2).has_tag('p', '2'))
def test_add_dep_childrenof01(self):
self.add_childrenof_helper('childrenof')
def test_add_dep_childrenof02(self):
self.add_childrenof_helper('childof')
def test_add_dep_childrenof03(self):
self.add_childrenof_helper('children-of')
def test_add_dep_childrenof04(self):
self.add_childrenof_helper('child-of')
def test_add_reldate1(self): def test_add_reldate1(self):
command = AddCommand.AddCommand(["Foo due:today"], self.todolist, command = AddCommand.AddCommand(["Foo due:today"], self.todolist,
self.out, self.error) self.out, self.error)
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest import unittest
from datetime import date
from test.command_testcase import CommandTest from test.command_testcase import CommandTest
from topydo.commands.AppendCommand import AppendCommand from topydo.commands.AppendCommand import AppendCommand
...@@ -23,9 +24,10 @@ from topydo.lib.TodoList import TodoList ...@@ -23,9 +24,10 @@ from topydo.lib.TodoList import TodoList
class AppendCommandTest(CommandTest): class AppendCommandTest(CommandTest):
def setUp(self): def setUp(self):
super(AppendCommandTest, self).setUp() super().setUp()
self.todolist = TodoList([]) self.todolist = TodoList([])
self.todolist.add("Foo") self.todolist.add("Foo")
self.today = date.today().isoformat()
def test_append1(self): def test_append1(self):
command = AppendCommand([1, "Bar"], self.todolist, self.out, command = AppendCommand([1, "Bar"], self.todolist, self.out,
...@@ -79,6 +81,27 @@ class AppendCommandTest(CommandTest): ...@@ -79,6 +81,27 @@ class AppendCommandTest(CommandTest):
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n") self.assertEqual(self.errors, command.usage() + "\n")
def test_append8(self):
command = AppendCommand([1, "due:today t:today"], self.todolist,
self.out, self.error)
command.execute()
self.assertEqual(self.output,
"| 1| Foo due:%s t:%s\n" % (self.today, self.today))
self.assertEqual(self.errors, "")
def test_append9(self):
self.todolist.add("Qux due:2015-12-21 t:2015-12-21 before:1")
self.todolist.add("Baz")
command = AppendCommand([2, "due:today t:today before:3"], self.todolist,
self.out, self.error)
command.execute()
self.assertEqual(
self.output,
"| 2| Qux due:%s t:%s p:1 p:2\n" % (self.today, self.today))
self.assertEqual(self.errors, "")
def test_help(self): def test_help(self):
command = AppendCommand(["help"], self.todolist, self.out, self.error) command = AppendCommand(["help"], self.todolist, self.out, self.error)
command.execute() command.execute()
......
...@@ -30,8 +30,8 @@ class ArchiveCommandTest(CommandTest): ...@@ -30,8 +30,8 @@ class ArchiveCommandTest(CommandTest):
command = ArchiveCommand(todolist, archive) command = ArchiveCommand(todolist, archive)
command.execute() command.execute()
self.assertTrue(todolist.is_dirty()) self.assertTrue(todolist.dirty)
self.assertTrue(archive.is_dirty()) self.assertTrue(archive.dirty)
self.assertEqual(todolist.print_todos(), "x Not complete\n(C) Active") self.assertEqual(todolist.print_todos(), "x Not complete\n(C) Active")
self.assertEqual(archive.print_todos(), "x 2014-10-19 Complete\nx 2014-10-20 Another one complete") self.assertEqual(archive.print_todos(), "x 2014-10-19 Complete\nx 2014-10-20 Another one complete")
......
This diff is collapsed.
...@@ -45,8 +45,7 @@ class ConfigTest(TopydoTest): ...@@ -45,8 +45,7 @@ class ConfigTest(TopydoTest):
""" Bad colour switch value. """ """ Bad colour switch value. """
# boolean settings must first be typecast to integers, because all # boolean settings must first be typecast to integers, because all
# strings evaulate to 'True' # strings evaulate to 'True'
self.assertEqual(config("test/data/ConfigTest4.conf").colors(), self.assertEqual(config("test/data/ConfigTest4.conf").colors(), 16)
bool(int(config().defaults["topydo"]["colors"])))
def test_config06(self): def test_config06(self):
""" Bad auto creation date switch value. """ """ Bad auto creation date switch value. """
...@@ -83,62 +82,76 @@ class ConfigTest(TopydoTest): ...@@ -83,62 +82,76 @@ class ConfigTest(TopydoTest):
self.assertEqual(config("test/data/ConfigTest4.conf").append_parent_contexts(), self.assertEqual(config("test/data/ConfigTest4.conf").append_parent_contexts(),
bool(int(config().defaults["dep"]["append_parent_contexts"]))) bool(int(config().defaults["dep"]["append_parent_contexts"])))
@skip("Error checking not yet implemented")
def test_config14(self): def test_config14(self):
""" Bad priority color value. """ """ Bad priority color value. """
self.assertEqual(config("test/data/ConfigTest4.conf").priority_colors(), self.assertEqual(config("test/data/ConfigTest4.conf").priority_color('A').color, 6)
config().defaults["colorscheme"]["priority_colors"]) self.assertEqual(config("test/data/ConfigTest4.conf").priority_color('B').color, 3)
self.assertEqual(config("test/data/ConfigTest4.conf").priority_color('C').color, 4)
@skip("Error checking not yet implemented")
def test_config15(self): def test_config15(self):
""" Bad project color value. """ """ Bad project color value. """
self.assertEqual(config("test/data/ConfigTest4.conf").project_color(), self.assertTrue(config("test/data/ConfigTest4.conf").project_color().is_neutral())
config().defaults["colorscheme"]["project_color"])
@skip("Error checking not yet implemented")
def test_config16(self): def test_config16(self):
""" Bad context color value. """ """ Bad context color value. """
self.assertEqual(config("test/data/ConfigTest4.conf").context_color(), self.assertTrue(config("test/data/ConfigTest4.conf").context_color().is_neutral())
config().defaults["colorscheme"]["context_color"])
@skip("Error checking not yet implemented")
def test_config17(self): def test_config17(self):
""" Bad metadata color value. """ """ Bad metadata color value. """
self.assertEqual(config("test/data/ConfigTest4.conf").metadata_color(), self.assertTrue(config("test/data/ConfigTest4.conf").metadata_color().is_neutral())
config().defaults["colorscheme"]["metadata_color"])
@skip("Error checking not yet implemented")
def test_config18(self): def test_config18(self):
""" Bad link color value. """ """ Bad link color value. """
self.assertEqual(config("test/data/ConfigTest4.conf").link_color(), self.assertTrue(config("test/data/ConfigTest4.conf").link_color().is_neutral())
config().defaults["colorscheme"]["link_color"])
@skip("Test not yet implemented")
# the test needs to be of the internal function _str_to_dict # the test needs to be of the internal function _str_to_dict
def test_config19(self): def test_config19(self):
""" No priority color value. """ """ No priority color value. """
self.assertEqual(config("test/data/ConfigTest4.conf").priority_colors(), self.assertEqual(config("test/data/ConfigTest4.conf").priority_color('A').color, 6)
config().defaults["colorscheme"]["priority_colors"]) self.assertEqual(config("test/data/ConfigTest4.conf").priority_color('B').color, 3)
self.assertEqual(config("test/data/ConfigTest4.conf").priority_color('C').color, 4)
def test_config20(self): def test_config20(self):
""" No project color value. """ """ No project color value. """
self.assertEqual(config("test/data/ConfigTest5.conf").project_color(), self.assertEqual(config("test/data/ConfigTest5.conf").project_color().color, 1)
config().defaults["colorscheme"]["project_color"])
def test_config21(self): def test_config21(self):
""" No context color value. """ """ No context color value. """
self.assertEqual(config("test/data/ConfigTest5.conf").context_color(), self.assertEqual(config("test/data/ConfigTest5.conf").context_color().color, 5)
config().defaults["colorscheme"]["context_color"])
def test_config22(self): def test_config22(self):
""" No metadata color value. """ """ No metadata color value. """
self.assertEqual(config("test/data/ConfigTest5.conf").metadata_color(), self.assertEqual(config("test/data/ConfigTest5.conf").metadata_color().color, 2)
config().defaults["colorscheme"]["metadata_color"])
def test_config23(self): def test_config23(self):
""" No link color value. """ """ No link color value. """
self.assertEqual(config("test/data/ConfigTest5.conf").link_color(), self.assertEqual(config("test/data/ConfigTest5.conf").link_color().color, 6)
config().defaults["colorscheme"]["link_color"])
def test_config24(self):
""" column_keymap test. """
keymap, keystates = config("test/data/ConfigTest6.conf").column_keymap()
self.assertEqual(keymap['pp'], 'postpone')
self.assertEqual(keymap['ps'], 'postpone_s')
self.assertEqual(keymap['pr'], 'pri')
self.assertEqual(keymap['pra'], 'cmd pri {} a')
self.assertIn('p', keystates)
self.assertIn('g', keystates)
self.assertIn('pp', keystates)
self.assertIn('ps', keystates)
self.assertIn('pr', keystates)
self.assertEqual(keymap['up'], 'up')
self.assertIn('u', keystates)
self.assertEqual(keymap['<Left>'], 'prev_column')
self.assertNotIn('<Lef', keystates)
self.assertEqual(keymap['<Esc>d'], 'delete_column')
self.assertNotIn('<Esc', keystates)
self.assertIn('<Esc>', keystates)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -33,7 +33,7 @@ def _no_prompt(self): ...@@ -33,7 +33,7 @@ def _no_prompt(self):
class DeleteCommandTest(CommandTest): class DeleteCommandTest(CommandTest):
def setUp(self): def setUp(self):
super(DeleteCommandTest, self).setUp() super().setUp()
todos = [ todos = [
"Foo id:1", "Foo id:1",
"Bar p:1", "Bar p:1",
...@@ -48,7 +48,7 @@ class DeleteCommandTest(CommandTest): ...@@ -48,7 +48,7 @@ class DeleteCommandTest(CommandTest):
_no_prompt) _no_prompt)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.todo(1).source(), "Bar") self.assertEqual(self.todolist.todo(1).source(), "Bar")
self.assertEqual(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n") self.assertEqual(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -58,7 +58,7 @@ class DeleteCommandTest(CommandTest): ...@@ -58,7 +58,7 @@ class DeleteCommandTest(CommandTest):
_no_prompt) _no_prompt)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.todo(1).source(), "Bar") self.assertEqual(self.todolist.todo(1).source(), "Bar")
self.assertEqual(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n") self.assertEqual(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -68,7 +68,7 @@ class DeleteCommandTest(CommandTest): ...@@ -68,7 +68,7 @@ class DeleteCommandTest(CommandTest):
_yes_prompt) _yes_prompt)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.count(), 2) self.assertEqual(self.todolist.count(), 2)
self.assertEqual(self.output, self.assertEqual(self.output,
"| 2| Bar p:1\nRemoved: Bar\nRemoved: Foo\n") "| 2| Bar p:1\nRemoved: Bar\nRemoved: Foo\n")
...@@ -79,7 +79,7 @@ class DeleteCommandTest(CommandTest): ...@@ -79,7 +79,7 @@ class DeleteCommandTest(CommandTest):
self.error, _yes_prompt) self.error, _yes_prompt)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.count(), 3) # force won't delete subtasks self.assertEqual(self.todolist.count(), 3) # force won't delete subtasks
self.assertEqual(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n") self.assertEqual(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -89,7 +89,7 @@ class DeleteCommandTest(CommandTest): ...@@ -89,7 +89,7 @@ class DeleteCommandTest(CommandTest):
self.error, _yes_prompt) self.error, _yes_prompt)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.count(), 3) # force won't delete subtasks self.assertEqual(self.todolist.count(), 3) # force won't delete subtasks
self.assertEqual(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n") self.assertEqual(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -98,7 +98,7 @@ class DeleteCommandTest(CommandTest): ...@@ -98,7 +98,7 @@ class DeleteCommandTest(CommandTest):
command = DeleteCommand(["2"], self.todolist, self.out, self.error) command = DeleteCommand(["2"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.todo(1).source(), "Foo") self.assertEqual(self.todolist.todo(1).source(), "Foo")
self.assertEqual(self.output, "Removed: Bar p:1\nThe following todo item(s) became active:\n| 1| Foo\n") self.assertEqual(self.output, "Removed: Bar p:1\nThe following todo item(s) became active:\n| 1| Foo\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -107,7 +107,7 @@ class DeleteCommandTest(CommandTest): ...@@ -107,7 +107,7 @@ class DeleteCommandTest(CommandTest):
command = DeleteCommand(["99"], self.todolist, self.out, self.error) command = DeleteCommand(["99"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given.\n") self.assertEqual(self.errors, "Invalid todo number given.\n")
...@@ -115,7 +115,7 @@ class DeleteCommandTest(CommandTest): ...@@ -115,7 +115,7 @@ class DeleteCommandTest(CommandTest):
command = DeleteCommand(["A"], self.todolist, self.out, self.error) command = DeleteCommand(["A"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given.\n") self.assertEqual(self.errors, "Invalid todo number given.\n")
...@@ -159,7 +159,7 @@ class DeleteCommandTest(CommandTest): ...@@ -159,7 +159,7 @@ class DeleteCommandTest(CommandTest):
self.error, _yes_prompt) self.error, _yes_prompt)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given: 99.\n") self.assertEqual(self.errors, "Invalid todo number given: 99.\n")
...@@ -169,7 +169,7 @@ class DeleteCommandTest(CommandTest): ...@@ -169,7 +169,7 @@ class DeleteCommandTest(CommandTest):
self.error, _yes_prompt) self.error, _yes_prompt)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given: 99.\nInvalid todo number given: A.\n") self.assertEqual(self.errors, "Invalid todo number given: 99.\nInvalid todo number given: A.\n")
...@@ -181,7 +181,7 @@ class DeleteCommandTest(CommandTest): ...@@ -181,7 +181,7 @@ class DeleteCommandTest(CommandTest):
self.out, self.error, None) self.out, self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, self.assertEqual(self.errors,
u"Invalid todo number given: Fo\u00d3B\u0105r.\n") u"Invalid todo number given: Fo\u00d3B\u0105r.\n")
...@@ -193,7 +193,7 @@ class DeleteCommandTest(CommandTest): ...@@ -193,7 +193,7 @@ class DeleteCommandTest(CommandTest):
result = "Removed: a @test with due:2015-06-03\nRemoved: a @test with +project\n" result = "Removed: a @test with due:2015-06-03\nRemoved: a @test with +project\n"
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.count(), 2) self.assertEqual(self.todolist.count(), 2)
self.assertEqual(self.output, result) self.assertEqual(self.output, result)
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -203,7 +203,7 @@ class DeleteCommandTest(CommandTest): ...@@ -203,7 +203,7 @@ class DeleteCommandTest(CommandTest):
self.todolist, self.out, self.error, None) self.todolist, self.out, self.error, None)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "Removed: a @test with due:2015-06-03\n") self.assertEqual(self.output, "Removed: a @test with due:2015-06-03\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -212,7 +212,7 @@ class DeleteCommandTest(CommandTest): ...@@ -212,7 +212,7 @@ class DeleteCommandTest(CommandTest):
self.todolist, self.out, self.error, None) self.todolist, self.out, self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
def test_expr_del4(self): def test_expr_del4(self):
""" Remove only relevant todo items. """ """ Remove only relevant todo items. """
...@@ -222,7 +222,7 @@ class DeleteCommandTest(CommandTest): ...@@ -222,7 +222,7 @@ class DeleteCommandTest(CommandTest):
result = "Foo" result = "Foo"
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.count(), 1) self.assertEqual(self.todolist.count(), 1)
self.assertEqual(self.todolist.print_todos(), result) self.assertEqual(self.todolist.print_todos(), result)
...@@ -232,14 +232,14 @@ class DeleteCommandTest(CommandTest): ...@@ -232,14 +232,14 @@ class DeleteCommandTest(CommandTest):
self.error, _yes_prompt) self.error, _yes_prompt)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.count(), 0) self.assertEqual(self.todolist.count(), 0)
def test_empty(self): def test_empty(self):
command = DeleteCommand([], self.todolist, self.out, self.error) command = DeleteCommand([], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, command.usage() + "\n") self.assertEqual(self.errors, command.usage() + "\n")
......
This diff is collapsed.
...@@ -23,7 +23,7 @@ from topydo.lib.TodoList import TodoList ...@@ -23,7 +23,7 @@ from topydo.lib.TodoList import TodoList
class DepriCommandTest(CommandTest): class DepriCommandTest(CommandTest):
def setUp(self): def setUp(self):
super(DepriCommandTest, self).setUp() super().setUp()
todos = [ todos = [
"(A) Foo", "(A) Foo",
"Bar", "Bar",
...@@ -39,7 +39,7 @@ class DepriCommandTest(CommandTest): ...@@ -39,7 +39,7 @@ class DepriCommandTest(CommandTest):
command = DepriCommand(["1"], self.todolist, self.out, self.error) command = DepriCommand(["1"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.todo(1).priority(), None) self.assertEqual(self.todolist.todo(1).priority(), None)
self.assertEqual(self.output, "Priority removed.\n| 1| Foo\n") self.assertEqual(self.output, "Priority removed.\n| 1| Foo\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -48,7 +48,7 @@ class DepriCommandTest(CommandTest): ...@@ -48,7 +48,7 @@ class DepriCommandTest(CommandTest):
command = DepriCommand(["2"], self.todolist, self.out, self.error) command = DepriCommand(["2"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.todolist.todo(2).priority(), None) self.assertEqual(self.todolist.todo(2).priority(), None)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -57,7 +57,7 @@ class DepriCommandTest(CommandTest): ...@@ -57,7 +57,7 @@ class DepriCommandTest(CommandTest):
command = DepriCommand(["Foo"], self.todolist, self.out, self.error) command = DepriCommand(["Foo"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.todo(1).priority(), None) self.assertEqual(self.todolist.todo(1).priority(), None)
self.assertEqual(self.output, "Priority removed.\n| 1| Foo\n") self.assertEqual(self.output, "Priority removed.\n| 1| Foo\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -67,7 +67,7 @@ class DepriCommandTest(CommandTest): ...@@ -67,7 +67,7 @@ class DepriCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.todo(1).priority(), None) self.assertEqual(self.todolist.todo(1).priority(), None)
self.assertEqual(self.todolist.todo(3).priority(), None) self.assertEqual(self.todolist.todo(3).priority(), None)
self.assertEqual(self.output, "Priority removed.\n| 1| Foo\nPriority removed.\n| 3| Baz\n") self.assertEqual(self.output, "Priority removed.\n| 1| Foo\nPriority removed.\n| 3| Baz\n")
...@@ -80,7 +80,7 @@ class DepriCommandTest(CommandTest): ...@@ -80,7 +80,7 @@ class DepriCommandTest(CommandTest):
result = "Priority removed.\n| 4| a @test with due:2015-06-03\nPriority removed.\n| 5| a @test with +project p:1\n" result = "Priority removed.\n| 4| a @test with due:2015-06-03\nPriority removed.\n| 5| a @test with +project p:1\n"
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, result) self.assertEqual(self.output, result)
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -91,7 +91,7 @@ class DepriCommandTest(CommandTest): ...@@ -91,7 +91,7 @@ class DepriCommandTest(CommandTest):
result = "Priority removed.\n| 4| a @test with due:2015-06-03\n" result = "Priority removed.\n| 4| a @test with due:2015-06-03\n"
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, result) self.assertEqual(self.output, result)
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -100,7 +100,7 @@ class DepriCommandTest(CommandTest): ...@@ -100,7 +100,7 @@ class DepriCommandTest(CommandTest):
self.todolist, self.out, self.error, None) self.todolist, self.out, self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
def test_expr_depri4(self): def test_expr_depri4(self):
""" Don't remove priority from unrelevant todo items. """ """ Don't remove priority from unrelevant todo items. """
...@@ -108,7 +108,7 @@ class DepriCommandTest(CommandTest): ...@@ -108,7 +108,7 @@ class DepriCommandTest(CommandTest):
self.error, None) self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
def test_expr_depri5(self): def test_expr_depri5(self):
""" Force unprioritizing unrelevant items with additional -x flag. """ """ Force unprioritizing unrelevant items with additional -x flag. """
...@@ -116,7 +116,7 @@ class DepriCommandTest(CommandTest): ...@@ -116,7 +116,7 @@ class DepriCommandTest(CommandTest):
self.error, None) self.error, None)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "Priority removed.\n| 6| Bax id:1\n") self.assertEqual(self.output, "Priority removed.\n| 6| Bax id:1\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -124,7 +124,7 @@ class DepriCommandTest(CommandTest): ...@@ -124,7 +124,7 @@ class DepriCommandTest(CommandTest):
command = DepriCommand(["99"], self.todolist, self.out, self.error) command = DepriCommand(["99"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, "Invalid todo number given.\n") self.assertEqual(self.errors, "Invalid todo number given.\n")
...@@ -133,7 +133,7 @@ class DepriCommandTest(CommandTest): ...@@ -133,7 +133,7 @@ class DepriCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, "Invalid todo number given: 99.\n") self.assertEqual(self.errors, "Invalid todo number given: 99.\n")
...@@ -142,7 +142,7 @@ class DepriCommandTest(CommandTest): ...@@ -142,7 +142,7 @@ class DepriCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, "Invalid todo number given: 99.\nInvalid todo number given: FooBar.\n") self.assertEqual(self.errors, "Invalid todo number given: 99.\nInvalid todo number given: FooBar.\n")
...@@ -154,7 +154,7 @@ class DepriCommandTest(CommandTest): ...@@ -154,7 +154,7 @@ class DepriCommandTest(CommandTest):
self.out, self.error, None) self.out, self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, self.assertEqual(self.errors,
u"Invalid todo number given: Fo\u00d3B\u0105r.\n") u"Invalid todo number given: Fo\u00d3B\u0105r.\n")
...@@ -163,7 +163,7 @@ class DepriCommandTest(CommandTest): ...@@ -163,7 +163,7 @@ class DepriCommandTest(CommandTest):
command = DepriCommand([], self.todolist, self.out, self.error) command = DepriCommand([], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, command.usage() + "\n") self.assertEqual(self.errors, command.usage() + "\n")
......
...@@ -32,7 +32,7 @@ def _no_prompt(self): ...@@ -32,7 +32,7 @@ def _no_prompt(self):
class DoCommandTest(CommandTest): class DoCommandTest(CommandTest):
def setUp(self): def setUp(self):
super(DoCommandTest, self).setUp() super().setUp()
todos = [ todos = [
"Foo id:1", "Foo id:1",
"Bar p:1", "Bar p:1",
...@@ -61,7 +61,7 @@ class DoCommandTest(CommandTest): ...@@ -61,7 +61,7 @@ class DoCommandTest(CommandTest):
_no_prompt) _no_prompt)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertTrue(self.todolist.todo(3).is_completed()) self.assertTrue(self.todolist.todo(3).is_completed())
self.assertEqual(self.output, self.assertEqual(self.output,
"Completed: x {} Baz p:1\n".format(self.today)) "Completed: x {} Baz p:1\n".format(self.today))
...@@ -77,7 +77,7 @@ class DoCommandTest(CommandTest): ...@@ -77,7 +77,7 @@ class DoCommandTest(CommandTest):
for number in [1, 2, 3]: for number in [1, 2, 3]:
self.assertTrue(self.todolist.todo(number).is_completed()) self.assertTrue(self.todolist.todo(number).is_completed())
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertFalse(self.todolist.todo(4).is_completed()) self.assertFalse(self.todolist.todo(4).is_completed())
self.assertEqual(self.output, result) self.assertEqual(self.output, result)
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -89,7 +89,7 @@ class DoCommandTest(CommandTest): ...@@ -89,7 +89,7 @@ class DoCommandTest(CommandTest):
result = "| 2| Bar p:1\n| 3| Baz p:1\nCompleted: x {} Foo id:1\n".format(self.today) result = "| 2| Bar p:1\n| 3| Baz p:1\nCompleted: x {} Foo id:1\n".format(self.today)
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertTrue(self.todolist.todo(1).is_completed()) self.assertTrue(self.todolist.todo(1).is_completed())
self.assertFalse(self.todolist.todo(2).is_completed()) self.assertFalse(self.todolist.todo(2).is_completed())
self.assertFalse(self.todolist.todo(3).is_completed()) self.assertFalse(self.todolist.todo(3).is_completed())
...@@ -130,7 +130,7 @@ class DoCommandTest(CommandTest): ...@@ -130,7 +130,7 @@ class DoCommandTest(CommandTest):
command = DoCommand(p_flags, self.todolist, self.out, self.error) command = DoCommand(p_flags, self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
self.assertEqual(self.todolist.count(), 12) self.assertEqual(self.todolist.count(), 12)
...@@ -162,7 +162,7 @@ class DoCommandTest(CommandTest): ...@@ -162,7 +162,7 @@ class DoCommandTest(CommandTest):
command = DoCommand(["99"], self.todolist, self.out, self.error) command = DoCommand(["99"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, "Invalid todo number given.\n") self.assertEqual(self.errors, "Invalid todo number given.\n")
...@@ -170,7 +170,7 @@ class DoCommandTest(CommandTest): ...@@ -170,7 +170,7 @@ class DoCommandTest(CommandTest):
command = DoCommand(["AAA"], self.todolist, self.out, self.error) command = DoCommand(["AAA"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, "Invalid todo number given.\n") self.assertEqual(self.errors, "Invalid todo number given.\n")
...@@ -179,7 +179,7 @@ class DoCommandTest(CommandTest): ...@@ -179,7 +179,7 @@ class DoCommandTest(CommandTest):
_yes_prompt) _yes_prompt)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, "Invalid todo number given.\n") self.assertEqual(self.errors, "Invalid todo number given.\n")
...@@ -209,7 +209,7 @@ class DoCommandTest(CommandTest): ...@@ -209,7 +209,7 @@ class DoCommandTest(CommandTest):
command = DoCommand(["5"], self.todolist, self.out, self.error) command = DoCommand(["5"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.todolist.todo(5).completion_date(), self.assertEqual(self.todolist.todo(5).completion_date(),
date(2014, 10, 18)) date(2014, 10, 18))
self.assertFalse(self.output) self.assertFalse(self.output)
...@@ -219,7 +219,7 @@ class DoCommandTest(CommandTest): ...@@ -219,7 +219,7 @@ class DoCommandTest(CommandTest):
command = DoCommand(["baz"], self.todolist, self.out, self.error) command = DoCommand(["baz"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertTrue(self.todolist.todo(3).is_completed()) self.assertTrue(self.todolist.todo(3).is_completed())
self.assertEqual(self.output, self.assertEqual(self.output,
"Completed: x {} Baz p:1\n".format(self.today)) "Completed: x {} Baz p:1\n".format(self.today))
...@@ -230,7 +230,7 @@ class DoCommandTest(CommandTest): ...@@ -230,7 +230,7 @@ class DoCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "Completed: x 2014-11-18 Baz p:1\n") self.assertEqual(self.output, "Completed: x 2014-11-18 Baz p:1\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -239,7 +239,7 @@ class DoCommandTest(CommandTest): ...@@ -239,7 +239,7 @@ class DoCommandTest(CommandTest):
self.error, _yes_prompt) self.error, _yes_prompt)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "| 2| Bar p:1\n| 3| Baz p:1\nCompleted: x 2014-11-18 Bar p:1\nCompleted: x 2014-11-18 Baz p:1\nCompleted: x 2014-11-18 Foo id:1\n") self.assertEqual(self.output, "| 2| Bar p:1\n| 3| Baz p:1\nCompleted: x 2014-11-18 Bar p:1\nCompleted: x 2014-11-18 Baz p:1\nCompleted: x 2014-11-18 Foo id:1\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -248,7 +248,7 @@ class DoCommandTest(CommandTest): ...@@ -248,7 +248,7 @@ class DoCommandTest(CommandTest):
self.out, self.error) self.out, self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "Completed: x 2014-11-18 Baz p:1\n") self.assertEqual(self.output, "Completed: x 2014-11-18 Baz p:1\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -257,7 +257,7 @@ class DoCommandTest(CommandTest): ...@@ -257,7 +257,7 @@ class DoCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, self.assertEqual(self.output,
"Completed: x {} Baz p:1\n".format(self.today)) "Completed: x {} Baz p:1\n".format(self.today))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -271,7 +271,7 @@ class DoCommandTest(CommandTest): ...@@ -271,7 +271,7 @@ class DoCommandTest(CommandTest):
self.out, self.error) self.out, self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "| 12| {today} Recurring! rec:1d due:{today}\nCompleted: x {yesterday} Recurring! rec:1d\n".format(today=self.today, yesterday=self.yesterday)) self.assertEqual(self.output, "| 12| {today} Recurring! rec:1d due:{today}\nCompleted: x {yesterday} Recurring! rec:1d\n".format(today=self.today, yesterday=self.yesterday))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -285,7 +285,7 @@ class DoCommandTest(CommandTest): ...@@ -285,7 +285,7 @@ class DoCommandTest(CommandTest):
self.out, self.error) self.out, self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "| 12| {today} Recurring! rec:1d due:{today}\nCompleted: x {yesterday} Recurring! rec:1d\n".format(today=self.today, yesterday=self.yesterday)) self.assertEqual(self.output, "| 12| {today} Recurring! rec:1d due:{today}\nCompleted: x {yesterday} Recurring! rec:1d\n".format(today=self.today, yesterday=self.yesterday))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -298,7 +298,7 @@ class DoCommandTest(CommandTest): ...@@ -298,7 +298,7 @@ class DoCommandTest(CommandTest):
self.out, self.error) self.out, self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "| 12| {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.assertEqual(self.output, "| 12| {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.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -310,7 +310,7 @@ class DoCommandTest(CommandTest): ...@@ -310,7 +310,7 @@ class DoCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, self.assertEqual(self.output,
"Completed: x {} Baz p:1\n".format(self.yesterday)) "Completed: x {} Baz p:1\n".format(self.yesterday))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -323,7 +323,7 @@ class DoCommandTest(CommandTest): ...@@ -323,7 +323,7 @@ class DoCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, self.assertEqual(self.output,
"Completed: x {} Baz p:1\n".format(self.yesterday)) "Completed: x {} Baz p:1\n".format(self.yesterday))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -385,7 +385,7 @@ class DoCommandTest(CommandTest): ...@@ -385,7 +385,7 @@ class DoCommandTest(CommandTest):
self.out, self.error, None) self.out, self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.errors, self.assertEqual(self.errors,
u"Invalid todo number given: Fo\u00d3B\u0105r.\n") u"Invalid todo number given: Fo\u00d3B\u0105r.\n")
...@@ -394,7 +394,7 @@ class DoCommandTest(CommandTest): ...@@ -394,7 +394,7 @@ class DoCommandTest(CommandTest):
self.error, None) self.error, None)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "Completed: x {t} a @test with due:2015-06-03\nCompleted: x {t} a @test with +project\n".format(t=self.today)) self.assertEqual(self.output, "Completed: x {t} a @test with due:2015-06-03\nCompleted: x {t} a @test with +project\n".format(t=self.today))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -403,7 +403,7 @@ class DoCommandTest(CommandTest): ...@@ -403,7 +403,7 @@ class DoCommandTest(CommandTest):
self.out, self.error, None) self.out, self.error, None)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "Completed: x {} a @test with due:2015-06-03\n".format(self.today)) self.assertEqual(self.output, "Completed: x {} a @test with due:2015-06-03\n".format(self.today))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -412,7 +412,7 @@ class DoCommandTest(CommandTest): ...@@ -412,7 +412,7 @@ class DoCommandTest(CommandTest):
self.todolist, self.out, self.error, None) self.todolist, self.out, self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
def test_expr_do4(self): def test_expr_do4(self):
""" Don't do anything with unrelevant todo items. """ """ Don't do anything with unrelevant todo items. """
...@@ -420,7 +420,7 @@ class DoCommandTest(CommandTest): ...@@ -420,7 +420,7 @@ class DoCommandTest(CommandTest):
None) None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
def test_expr_do5(self): def test_expr_do5(self):
""" Force marking unrelevant items as done with additional -x flag. """ """ Force marking unrelevant items as done with additional -x flag. """
...@@ -430,7 +430,7 @@ class DoCommandTest(CommandTest): ...@@ -430,7 +430,7 @@ class DoCommandTest(CommandTest):
result = "| 2| Bar p:1\n| 3| Baz p:1\nCompleted: x {t} Bar p:1\nCompleted: x {t} Baz p:1\nCompleted: x {t} Foo id:1\n".format(t=self.today) result = "| 2| Bar p:1\n| 3| Baz p:1\nCompleted: x {t} Bar p:1\nCompleted: x {t} Baz p:1\nCompleted: x {t} Foo id:1\n".format(t=self.today)
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, result) self.assertEqual(self.output, result)
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -450,7 +450,7 @@ class DoCommandTest(CommandTest): ...@@ -450,7 +450,7 @@ class DoCommandTest(CommandTest):
command = DoCommand([], self.todolist, self.out, self.error) command = DoCommand([], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, command.usage() + "\n") self.assertEqual(self.errors, command.usage() + "\n")
......
...@@ -33,7 +33,7 @@ except ImportError: ...@@ -33,7 +33,7 @@ except ImportError:
class EditCommandTest(CommandTest): class EditCommandTest(CommandTest):
def setUp(self): def setUp(self):
super(EditCommandTest, self).setUp() super().setUp()
todos = [ todos = [
"Foo id:1", "Foo id:1",
"Bar p:1 @test", "Bar p:1 @test",
...@@ -56,7 +56,7 @@ class EditCommandTest(CommandTest): ...@@ -56,7 +56,7 @@ class EditCommandTest(CommandTest):
command.execute() command.execute()
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.print_todos(), u"Bar p:1 @test\nBaz @test\nFo\u00f3B\u0105\u017a\nFoo id:1") self.assertEqual(self.todolist.print_todos(), u"Bar p:1 @test\nBaz @test\nFo\u00f3B\u0105\u017a\nFoo id:1")
@mock.patch('topydo.commands.EditCommand._is_edited') @mock.patch('topydo.commands.EditCommand._is_edited')
...@@ -72,7 +72,7 @@ class EditCommandTest(CommandTest): ...@@ -72,7 +72,7 @@ class EditCommandTest(CommandTest):
None) None)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
self.assertEqual(self.todolist.print_todos(), u"Foo id:1\nBaz @test\nFo\u00f3B\u0105\u017a\nLazy Cat") self.assertEqual(self.todolist.print_todos(), u"Foo id:1\nBaz @test\nFo\u00f3B\u0105\u017a\nLazy Cat")
...@@ -82,7 +82,7 @@ class EditCommandTest(CommandTest): ...@@ -82,7 +82,7 @@ class EditCommandTest(CommandTest):
None) None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.errors, "Invalid todo number given.\n") self.assertEqual(self.errors, "Invalid todo number given.\n")
def test_edit04(self): def test_edit04(self):
...@@ -91,7 +91,7 @@ class EditCommandTest(CommandTest): ...@@ -91,7 +91,7 @@ class EditCommandTest(CommandTest):
self.error, None) self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.errors, "Invalid todo number given: 5.\n") self.assertEqual(self.errors, "Invalid todo number given: 5.\n")
def test_edit05(self): def test_edit05(self):
...@@ -102,7 +102,7 @@ class EditCommandTest(CommandTest): ...@@ -102,7 +102,7 @@ class EditCommandTest(CommandTest):
self.out, self.error, None) self.out, self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.errors, self.assertEqual(self.errors,
u"Invalid todo number given: Fo\u00d3B\u0105r.\n") u"Invalid todo number given: Fo\u00d3B\u0105r.\n")
...@@ -119,7 +119,7 @@ class EditCommandTest(CommandTest): ...@@ -119,7 +119,7 @@ class EditCommandTest(CommandTest):
self.out, self.error, None) self.out, self.error, None)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
self.assertEqual(self.todolist.print_todos(), self.assertEqual(self.todolist.print_todos(),
u"Foo id:1\nBar p:1 @test\nBaz @test\nLazy Cat") u"Foo id:1\nBar p:1 @test\nBaz @test\nLazy Cat")
...@@ -137,7 +137,7 @@ class EditCommandTest(CommandTest): ...@@ -137,7 +137,7 @@ class EditCommandTest(CommandTest):
self.error, None) self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.errors, "Editing aborted. Nothing to do.\n") self.assertEqual(self.errors, "Editing aborted. Nothing to do.\n")
self.assertEqual(self.todolist.print_todos(), u"Foo id:1\nBar p:1 @test\nBaz @test\nFo\u00f3B\u0105\u017a") self.assertEqual(self.todolist.print_todos(), u"Foo id:1\nBar p:1 @test\nBaz @test\nFo\u00f3B\u0105\u017a")
...@@ -158,7 +158,7 @@ class EditCommandTest(CommandTest): ...@@ -158,7 +158,7 @@ class EditCommandTest(CommandTest):
expected = u"| 3| Lazy Cat\n| 4| Lazy Dog\n" expected = u"| 3| Lazy Cat\n| 4| Lazy Dog\n"
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, expected) self.assertEqual(self.output, expected)
self.assertEqual(self.todolist.print_todos(), u"Foo id:1\nFo\u00f3B\u0105\u017a\nLazy Cat\nLazy Dog") self.assertEqual(self.todolist.print_todos(), u"Foo id:1\nFo\u00f3B\u0105\u017a\nLazy Cat\nLazy Dog")
......
...@@ -301,7 +301,7 @@ class FilterTest(TopydoTest): ...@@ -301,7 +301,7 @@ class FilterTest(TopydoTest):
class OrdinalTagFilterTest(TopydoTest): class OrdinalTagFilterTest(TopydoTest):
def setUp(self): def setUp(self):
super(OrdinalTagFilterTest, self).setUp() super().setUp()
today = date.today() today = date.today()
tomorrow = today + timedelta(1) tomorrow = today + timedelta(1)
...@@ -379,9 +379,87 @@ class OrdinalTagFilterTest(TopydoTest): ...@@ -379,9 +379,87 @@ class OrdinalTagFilterTest(TopydoTest):
self.assertEqual(result[0].source(), self.todo3) self.assertEqual(result[0].source(), self.todo3)
class CreationFilterTest(TopydoTest):
def setUp(self):
super().setUp()
self.todo1 = "2015-12-19 With creation date."
self.todo2 = "Without creation date."
self.todos = [Todo(self.todo1), Todo(self.todo2)]
def test_filter1(self):
cf = Filter.CreationFilter('create:2015-12-19')
result = cf.filter(self.todos)
self.assertEqual(len(result), 1)
self.assertEqual(result[0].source(), self.todo1)
def test_filter2(self):
cf = Filter.CreationFilter('creation:2015-12-19')
result = cf.filter(self.todos)
self.assertEqual(len(result), 1)
self.assertEqual(result[0].source(), self.todo1)
def test_filter3(self):
cf = Filter.CreationFilter('created:2015-12-19')
result = cf.filter(self.todos)
self.assertEqual(len(result), 1)
self.assertEqual(result[0].source(), self.todo1)
class CompletionFilterTest(TopydoTest):
def setUp(self):
super().setUp()
self.todo1 = "2015-12-19 With creation date."
self.todo2 = "x 2015-12-19 2015-12-18 Without creation date."
self.todo3 = "x 2015-12-18 Without creation date."
self.todos = [Todo(self.todo1), Todo(self.todo2), Todo(self.todo3)]
def test_filter1(self):
cf = Filter.CompletionFilter('complete:2015-12-19')
result = cf.filter(self.todos)
self.assertEqual(len(result), 1)
self.assertEqual(result[0].source(), self.todo2)
def test_filter2(self):
cf = Filter.CompletionFilter('completed:2015-12-19')
result = cf.filter(self.todos)
self.assertEqual(len(result), 1)
self.assertEqual(result[0].source(), self.todo2)
def test_filter3(self):
cf = Filter.CompletionFilter('completion:2015-12-19')
result = cf.filter(self.todos)
self.assertEqual(len(result), 1)
self.assertEqual(result[0].source(), self.todo2)
def test_filter4(self):
cf = Filter.CompletionFilter('completion:<=2015-12-19')
result = cf.filter(self.todos)
self.assertEqual(len(result), 2)
self.assertEqual(result[0].source(), self.todo2)
self.assertEqual(result[1].source(), self.todo3)
class PriorityFilterTest(TopydoTest): class PriorityFilterTest(TopydoTest):
def setUp(self): def setUp(self):
super(PriorityFilterTest, self).setUp() super().setUp()
self.todo1 = "(A) Foo" self.todo1 = "(A) Foo"
self.todo2 = "(B) Bar" self.todo2 = "(B) Bar"
......
...@@ -21,8 +21,8 @@ from topydo.Commands import get_subcommand ...@@ -21,8 +21,8 @@ from topydo.Commands import get_subcommand
from topydo.commands.AddCommand import AddCommand from topydo.commands.AddCommand import AddCommand
from topydo.commands.DeleteCommand import DeleteCommand from topydo.commands.DeleteCommand import DeleteCommand
from topydo.commands.ListCommand import ListCommand from topydo.commands.ListCommand import ListCommand
from topydo.commands.ListProjectCommand import ListProjectCommand from topydo.commands.TagCommand import TagCommand
from topydo.lib.Config import config from topydo.lib.Config import config, ConfigError
class GetSubcommandTest(TopydoTest): class GetSubcommandTest(TopydoTest):
def test_normal_cmd(self): def test_normal_cmd(self):
...@@ -60,6 +60,14 @@ class GetSubcommandTest(TopydoTest): ...@@ -60,6 +60,14 @@ class GetSubcommandTest(TopydoTest):
self.assertTrue(issubclass(real_cmd, ListCommand)) self.assertTrue(issubclass(real_cmd, ListCommand))
self.assertEqual(final_args, [u"\u263b"]) self.assertEqual(final_args, [u"\u263b"])
def test_alias04(self):
config("test/data/aliases.conf")
args = ["star", "foo"]
real_cmd, final_args = get_subcommand(args)
self.assertTrue(issubclass(real_cmd, TagCommand))
self.assertEqual(final_args, ["foo", "star", "1"])
def test_default_cmd01(self): def test_default_cmd01(self):
args = ["bar"] args = ["bar"]
real_cmd, final_args = get_subcommand(args) real_cmd, final_args = get_subcommand(args)
...@@ -111,6 +119,15 @@ class GetSubcommandTest(TopydoTest): ...@@ -111,6 +119,15 @@ class GetSubcommandTest(TopydoTest):
real_cmd, final_args = get_subcommand(args) real_cmd, final_args = get_subcommand(args)
self.assertEqual(real_cmd, None) self.assertEqual(real_cmd, None)
def test_alias_quotation(self):
config("test/data/aliases.conf")
args = ["quot"]
with self.assertRaises(ConfigError) as ce:
get_subcommand(args)
self.assertEqual(str(ce.exception), 'No closing quotation')
def test_help(self): def test_help(self):
real_cmd, final_args = get_subcommand(['help', 'nonexisting']) real_cmd, final_args = get_subcommand(['help', 'nonexisting'])
self.assertFalse(real_cmd) self.assertFalse(real_cmd)
......
...@@ -22,7 +22,7 @@ from topydo.lib.Graph import DirectedGraph ...@@ -22,7 +22,7 @@ from topydo.lib.Graph import DirectedGraph
class GraphTest(TopydoTest): class GraphTest(TopydoTest):
def setUp(self): def setUp(self):
super(GraphTest, self).setUp() super().setUp()
self.graph = DirectedGraph() self.graph = DirectedGraph()
......
This diff is collapsed.
This diff is collapsed.
...@@ -24,7 +24,7 @@ from topydo.lib.TodoList import TodoList ...@@ -24,7 +24,7 @@ from topydo.lib.TodoList import TodoList
class PostponeCommandTest(CommandTest): class PostponeCommandTest(CommandTest):
def setUp(self): def setUp(self):
super(PostponeCommandTest, self).setUp() super().setUp()
self.today = date.today() self.today = date.today()
self.past = date.today() - timedelta(1) self.past = date.today() - timedelta(1)
self.future = date.today() + timedelta(1) self.future = date.today() + timedelta(1)
...@@ -49,7 +49,7 @@ class PostponeCommandTest(CommandTest): ...@@ -49,7 +49,7 @@ class PostponeCommandTest(CommandTest):
due = self.today + timedelta(7) due = self.today + timedelta(7)
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, self.assertEqual(self.output,
"| 1| Foo due:{}\n".format(due.isoformat())) "| 1| Foo due:{}\n".format(due.isoformat()))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -61,7 +61,7 @@ class PostponeCommandTest(CommandTest): ...@@ -61,7 +61,7 @@ class PostponeCommandTest(CommandTest):
due = self.today + timedelta(7) due = self.today + timedelta(7)
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, self.assertEqual(self.output,
"| 2| Bar due:{}\n".format(due.isoformat())) "| 2| Bar due:{}\n".format(due.isoformat()))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -73,7 +73,7 @@ class PostponeCommandTest(CommandTest): ...@@ -73,7 +73,7 @@ class PostponeCommandTest(CommandTest):
due = self.today + timedelta(7) due = self.today + timedelta(7)
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, self.assertEqual(self.output,
"| 2| Bar due:{}\n".format(due.isoformat())) "| 2| Bar due:{}\n".format(due.isoformat()))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -85,7 +85,7 @@ class PostponeCommandTest(CommandTest): ...@@ -85,7 +85,7 @@ class PostponeCommandTest(CommandTest):
due = self.today + timedelta(7) due = self.today + timedelta(7)
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "| 3| Baz due:{} t:{}\n".format(due.isoformat(), self.start.isoformat())) self.assertEqual(self.output, "| 3| Baz due:{} t:{}\n".format(due.isoformat(), self.start.isoformat()))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -97,7 +97,7 @@ class PostponeCommandTest(CommandTest): ...@@ -97,7 +97,7 @@ class PostponeCommandTest(CommandTest):
due = self.today + timedelta(7) due = self.today + timedelta(7)
start = self.start + timedelta(7) start = self.start + timedelta(7)
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
# pylint: disable=E1103 # pylint: disable=E1103
self.assertEqual(self.output, "| 3| Baz due:{} t:{}\n".format(due.isoformat(), start.isoformat())) self.assertEqual(self.output, "| 3| Baz due:{} t:{}\n".format(due.isoformat(), start.isoformat()))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -109,7 +109,7 @@ class PostponeCommandTest(CommandTest): ...@@ -109,7 +109,7 @@ class PostponeCommandTest(CommandTest):
due = self.today + timedelta(7) due = self.today + timedelta(7)
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, self.assertEqual(self.output,
"| 4| Past due:{}\n".format(due.isoformat())) "| 4| Past due:{}\n".format(due.isoformat()))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -121,7 +121,7 @@ class PostponeCommandTest(CommandTest): ...@@ -121,7 +121,7 @@ class PostponeCommandTest(CommandTest):
due = self.future + timedelta(7) due = self.future + timedelta(7)
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
# pylint: disable=E1103 # pylint: disable=E1103
self.assertEqual(self.output, "| 5| Future due:{} t:{}\n".format(due.isoformat(), self.future_start.isoformat())) self.assertEqual(self.output, "| 5| Future due:{} t:{}\n".format(due.isoformat(), self.future_start.isoformat()))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -134,7 +134,7 @@ class PostponeCommandTest(CommandTest): ...@@ -134,7 +134,7 @@ class PostponeCommandTest(CommandTest):
due = self.future + timedelta(7) due = self.future + timedelta(7)
start = self.future_start + timedelta(7) start = self.future_start + timedelta(7)
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
# pylint: disable=E1103 # pylint: disable=E1103
self.assertEqual(self.output, "| 5| Future due:{} t:{}\n".format(due.isoformat(), start.isoformat())) self.assertEqual(self.output, "| 5| Future due:{} t:{}\n".format(due.isoformat(), start.isoformat()))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -144,7 +144,7 @@ class PostponeCommandTest(CommandTest): ...@@ -144,7 +144,7 @@ class PostponeCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid date pattern given.\n") self.assertEqual(self.errors, "Invalid date pattern given.\n")
...@@ -153,7 +153,7 @@ class PostponeCommandTest(CommandTest): ...@@ -153,7 +153,7 @@ class PostponeCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given.\n") self.assertEqual(self.errors, "Invalid todo number given.\n")
...@@ -162,7 +162,7 @@ class PostponeCommandTest(CommandTest): ...@@ -162,7 +162,7 @@ class PostponeCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given.\n") self.assertEqual(self.errors, "Invalid todo number given.\n")
...@@ -170,7 +170,7 @@ class PostponeCommandTest(CommandTest): ...@@ -170,7 +170,7 @@ class PostponeCommandTest(CommandTest):
command = PostponeCommand(["1"], self.todolist, self.out, self.error) command = PostponeCommand(["1"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n") self.assertEqual(self.errors, command.usage() + "\n")
...@@ -181,7 +181,7 @@ class PostponeCommandTest(CommandTest): ...@@ -181,7 +181,7 @@ class PostponeCommandTest(CommandTest):
due = self.today + timedelta(7) due = self.today + timedelta(7)
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, self.assertEqual(self.output,
"| 1| Foo due:{}\n".format(due.isoformat())) "| 1| Foo due:{}\n".format(due.isoformat()))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -193,7 +193,7 @@ class PostponeCommandTest(CommandTest): ...@@ -193,7 +193,7 @@ class PostponeCommandTest(CommandTest):
due = self.today + timedelta(7) due = self.today + timedelta(7)
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "| 1| Foo due:{}\n| 2| Bar due:{}\n".format(due.isoformat(), due.isoformat())) self.assertEqual(self.output, "| 1| Foo due:{}\n| 2| Bar due:{}\n".format(due.isoformat(), due.isoformat()))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -204,7 +204,7 @@ class PostponeCommandTest(CommandTest): ...@@ -204,7 +204,7 @@ class PostponeCommandTest(CommandTest):
due = self.today + timedelta(7) due = self.today + timedelta(7)
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "| 1| Foo due:{}\n| 2| Bar due:{}\n".format(due.isoformat(), due.isoformat())) self.assertEqual(self.output, "| 1| Foo due:{}\n| 2| Bar due:{}\n".format(due.isoformat(), due.isoformat()))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -216,7 +216,7 @@ class PostponeCommandTest(CommandTest): ...@@ -216,7 +216,7 @@ class PostponeCommandTest(CommandTest):
due = self.today + timedelta(7) due = self.today + timedelta(7)
start = self.start + timedelta(7) start = self.start + timedelta(7)
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
# pylint: disable=E1103 # pylint: disable=E1103
self.assertEqual(self.output, "| 2| Bar due:{}\n| 3| Baz due:{} t:{}\n".format(due.isoformat(), due.isoformat(), start.isoformat())) self.assertEqual(self.output, "| 2| Bar due:{}\n| 3| Baz due:{} t:{}\n".format(due.isoformat(), due.isoformat(), start.isoformat()))
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -226,7 +226,7 @@ class PostponeCommandTest(CommandTest): ...@@ -226,7 +226,7 @@ class PostponeCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid date pattern given.\n") self.assertEqual(self.errors, "Invalid date pattern given.\n")
...@@ -235,7 +235,7 @@ class PostponeCommandTest(CommandTest): ...@@ -235,7 +235,7 @@ class PostponeCommandTest(CommandTest):
self.out, self.error) self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given: 99.\nInvalid todo number given: 123.\n") self.assertEqual(self.errors, "Invalid todo number given: 99.\nInvalid todo number given: 123.\n")
...@@ -244,7 +244,7 @@ class PostponeCommandTest(CommandTest): ...@@ -244,7 +244,7 @@ class PostponeCommandTest(CommandTest):
self.out, self.error) self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given: Zoo.\nInvalid todo number given: 99.\nInvalid todo number given: 123.\n") self.assertEqual(self.errors, "Invalid todo number given: Zoo.\nInvalid todo number given: 99.\nInvalid todo number given: 123.\n")
...@@ -254,7 +254,7 @@ class PostponeCommandTest(CommandTest): ...@@ -254,7 +254,7 @@ class PostponeCommandTest(CommandTest):
self.todolist, self.out, self.error, None) self.todolist, self.out, self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, self.assertEqual(self.errors,
u"Invalid todo number given: Fo\u00d3B\u0105r.\n") u"Invalid todo number given: Fo\u00d3B\u0105r.\n")
...@@ -267,7 +267,7 @@ class PostponeCommandTest(CommandTest): ...@@ -267,7 +267,7 @@ class PostponeCommandTest(CommandTest):
due = self.today + timedelta(14) due = self.today + timedelta(14)
result = "| 2| Bar due:{d}\n| 3| Baz due:{d} t:{s}\n".format(d=due.isoformat(), s=self.start.isoformat()) result = "| 2| Bar due:{d}\n| 3| Baz due:{d} t:{s}\n".format(d=due.isoformat(), s=self.start.isoformat())
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, result) self.assertEqual(self.output, result)
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -282,7 +282,7 @@ class PostponeCommandTest(CommandTest): ...@@ -282,7 +282,7 @@ class PostponeCommandTest(CommandTest):
result = "| 3| Baz due:{} t:{}\n".format(due.isoformat(), result = "| 3| Baz due:{} t:{}\n".format(due.isoformat(),
self.start.isoformat()) self.start.isoformat())
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, result) self.assertEqual(self.output, result)
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -291,7 +291,7 @@ class PostponeCommandTest(CommandTest): ...@@ -291,7 +291,7 @@ class PostponeCommandTest(CommandTest):
self.todolist, self.out, self.error, None) self.todolist, self.out, self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
def test_expr_postpone4(self): def test_expr_postpone4(self):
""" Don't postpone unrelevant todo items. """ """ Don't postpone unrelevant todo items. """
...@@ -299,7 +299,7 @@ class PostponeCommandTest(CommandTest): ...@@ -299,7 +299,7 @@ class PostponeCommandTest(CommandTest):
self.out, self.error, None) self.out, self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
def test_expr_postpone5(self): def test_expr_postpone5(self):
""" Force postponing unrelevant items with additional -x flag. """ """ Force postponing unrelevant items with additional -x flag. """
...@@ -310,7 +310,7 @@ class PostponeCommandTest(CommandTest): ...@@ -310,7 +310,7 @@ class PostponeCommandTest(CommandTest):
due = self.today + timedelta(7) due = self.today + timedelta(7)
result = "| 6| FutureStart t:{} due:{}\n".format(self.future.isoformat(), due.isoformat()) result = "| 6| FutureStart t:{} due:{}\n".format(self.future.isoformat(), due.isoformat())
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, result) self.assertEqual(self.output, result)
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
......
...@@ -23,7 +23,7 @@ from topydo.lib.TodoList import TodoList ...@@ -23,7 +23,7 @@ from topydo.lib.TodoList import TodoList
class PriorityCommandTest(CommandTest): class PriorityCommandTest(CommandTest):
def setUp(self): def setUp(self):
super(PriorityCommandTest, self).setUp() super().setUp()
todos = [ todos = [
"(A) Foo", "(A) Foo",
"Bar", "Bar",
...@@ -39,7 +39,7 @@ class PriorityCommandTest(CommandTest): ...@@ -39,7 +39,7 @@ class PriorityCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, self.assertEqual(self.output,
"Priority changed from A to B\n| 1| (B) Foo\n") "Priority changed from A to B\n| 1| (B) Foo\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -49,7 +49,7 @@ class PriorityCommandTest(CommandTest): ...@@ -49,7 +49,7 @@ class PriorityCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "Priority set to Z.\n| 2| (Z) Bar\n") self.assertEqual(self.output, "Priority set to Z.\n| 2| (Z) Bar\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -58,7 +58,7 @@ class PriorityCommandTest(CommandTest): ...@@ -58,7 +58,7 @@ class PriorityCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, self.assertEqual(self.output,
"Priority changed from A to B\n| 1| (B) Foo\n") "Priority changed from A to B\n| 1| (B) Foo\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -68,7 +68,7 @@ class PriorityCommandTest(CommandTest): ...@@ -68,7 +68,7 @@ class PriorityCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "| 1| (A) Foo\n") self.assertEqual(self.output, "| 1| (A) Foo\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -77,7 +77,7 @@ class PriorityCommandTest(CommandTest): ...@@ -77,7 +77,7 @@ class PriorityCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "Priority changed from A to C\n| 1| (C) Foo\nPriority set to C.\n| 2| (C) Bar\n") self.assertEqual(self.output, "Priority changed from A to C\n| 1| (C) Foo\nPriority set to C.\n| 2| (C) Bar\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -87,7 +87,17 @@ class PriorityCommandTest(CommandTest): ...@@ -87,7 +87,17 @@ class PriorityCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "Priority changed from A to C\n| 1| (C) Foo\nPriority set to C.\n| 2| (C) Bar\n")
self.assertEqual(self.errors, "")
def test_set_prio7(self):
""" Allow lowercase priority to be set. """
command = PriorityCommand(["Foo", "2", "c"], self.todolist, self.out,
self.error)
command.execute()
self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "Priority changed from A to C\n| 1| (C) Foo\nPriority set to C.\n| 2| (C) Bar\n") self.assertEqual(self.output, "Priority changed from A to C\n| 1| (C) Foo\nPriority set to C.\n| 2| (C) Bar\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -98,7 +108,7 @@ class PriorityCommandTest(CommandTest): ...@@ -98,7 +108,7 @@ class PriorityCommandTest(CommandTest):
result = "Priority changed from B to C\n| 3| (C) a @test with due:2015-06-03\nPriority set to C.\n| 4| (C) a @test with +project p:1\n" result = "Priority changed from B to C\n| 3| (C) a @test with due:2015-06-03\nPriority set to C.\n| 4| (C) a @test with +project p:1\n"
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, result) self.assertEqual(self.output, result)
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -109,7 +119,7 @@ class PriorityCommandTest(CommandTest): ...@@ -109,7 +119,7 @@ class PriorityCommandTest(CommandTest):
result = "Priority changed from B to C\n| 3| (C) a @test with due:2015-06-03\n" result = "Priority changed from B to C\n| 3| (C) a @test with due:2015-06-03\n"
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, result) self.assertEqual(self.output, result)
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -119,7 +129,7 @@ class PriorityCommandTest(CommandTest): ...@@ -119,7 +129,7 @@ class PriorityCommandTest(CommandTest):
None) None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
def test_expr_prio4(self): def test_expr_prio4(self):
""" Don't prioritize unrelevant todo items. """ """ Don't prioritize unrelevant todo items. """
...@@ -127,7 +137,7 @@ class PriorityCommandTest(CommandTest): ...@@ -127,7 +137,7 @@ class PriorityCommandTest(CommandTest):
self.error, None) self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
def test_expr_prio5(self): def test_expr_prio5(self):
""" Force prioritizing unrelevant items with additional -x flag. """ """ Force prioritizing unrelevant items with additional -x flag. """
...@@ -135,7 +145,7 @@ class PriorityCommandTest(CommandTest): ...@@ -135,7 +145,7 @@ class PriorityCommandTest(CommandTest):
self.error, None) self.error, None)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, self.assertEqual(self.output,
"Priority set to D.\n| 5| (D) Baz id:1\n") "Priority set to D.\n| 5| (D) Baz id:1\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -145,7 +155,7 @@ class PriorityCommandTest(CommandTest): ...@@ -145,7 +155,7 @@ class PriorityCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, "Invalid todo number given.\n") self.assertEqual(self.errors, "Invalid todo number given.\n")
...@@ -154,7 +164,7 @@ class PriorityCommandTest(CommandTest): ...@@ -154,7 +164,7 @@ class PriorityCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, "Invalid todo number given: 99.\n") self.assertEqual(self.errors, "Invalid todo number given: 99.\n")
...@@ -163,7 +173,7 @@ class PriorityCommandTest(CommandTest): ...@@ -163,7 +173,7 @@ class PriorityCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, "Invalid todo number given: 98.\nInvalid todo number given: 99.\n") self.assertEqual(self.errors, "Invalid todo number given: 98.\nInvalid todo number given: 99.\n")
...@@ -172,7 +182,7 @@ class PriorityCommandTest(CommandTest): ...@@ -172,7 +182,7 @@ class PriorityCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, "Invalid priority given.\n") self.assertEqual(self.errors, "Invalid priority given.\n")
...@@ -180,7 +190,7 @@ class PriorityCommandTest(CommandTest): ...@@ -180,7 +190,7 @@ class PriorityCommandTest(CommandTest):
command = PriorityCommand(["A"], self.todolist, self.out, self.error) command = PriorityCommand(["A"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, command.usage() + "\n") self.assertEqual(self.errors, command.usage() + "\n")
...@@ -188,7 +198,7 @@ class PriorityCommandTest(CommandTest): ...@@ -188,7 +198,7 @@ class PriorityCommandTest(CommandTest):
command = PriorityCommand(["1"], self.todolist, self.out, self.error) command = PriorityCommand(["1"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, command.usage() + "\n") self.assertEqual(self.errors, command.usage() + "\n")
...@@ -200,7 +210,7 @@ class PriorityCommandTest(CommandTest): ...@@ -200,7 +210,7 @@ class PriorityCommandTest(CommandTest):
self.todolist, self.out, self.error, None) self.todolist, self.out, self.error, None)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, self.assertEqual(self.errors,
u"Invalid todo number given: Fo\u00d3B\u0105r.\n") u"Invalid todo number given: Fo\u00d3B\u0105r.\n")
...@@ -214,7 +224,7 @@ class PriorityCommandTest(CommandTest): ...@@ -214,7 +224,7 @@ class PriorityCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid priority given.\n") self.assertEqual(self.errors, "Invalid priority given.\n")
...@@ -227,7 +237,7 @@ class PriorityCommandTest(CommandTest): ...@@ -227,7 +237,7 @@ class PriorityCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid priority given.\n") self.assertEqual(self.errors, "Invalid priority given.\n")
...@@ -235,7 +245,7 @@ class PriorityCommandTest(CommandTest): ...@@ -235,7 +245,7 @@ class PriorityCommandTest(CommandTest):
command = PriorityCommand([], self.todolist, self.out, self.error) command = PriorityCommand([], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, command.usage() + "\n") self.assertEqual(self.errors, command.usage() + "\n")
......
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2016 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 freezegun import freeze_time
import unittest
from test.topydo_testcase import TopydoTest
from topydo.lib.Config import config
from topydo.lib.ProgressColor import progress_color
from topydo.lib.Todo import Todo
def set_256_colors():
config(p_overrides={('topydo', 'colors'): '256'})
@freeze_time('2016, 01, 01')
class ProgressColorTest(TopydoTest):
def test_progress1(self):
""" Test progress of task with no length """
color = progress_color(Todo('Foo'))
self.assertEqual(color.color, 2)
def test_progress2(self):
""" Test progress of task with no length (but with creation date). """
color = progress_color(Todo('2016-02-11 Foo'))
self.assertEqual(color.color, 2)
def test_progress3(self):
""" Test progress of task with no length """
set_256_colors()
color = progress_color(Todo('Foo'))
self.assertEqual(color.color, 22)
def test_progress4(self):
""" Test progress of task with no length (but with creation date). """
set_256_colors()
color = progress_color(Todo('2016-02-11 Foo'))
self.assertEqual(color.color, 22)
def test_progress5(self):
""" Test overdue tasks """
color = progress_color(Todo('Foo due:2015-12-31'))
self.assertEqual(color.color, 1)
def test_progress6(self):
""" Test overdue tasks """
set_256_colors()
color = progress_color(Todo('Foo due:2015-12-31'))
self.assertEqual(color.color, 196)
def test_progress7(self):
""" Due today """
color = progress_color(Todo('Foo due:2016-01-01'))
self.assertEqual(color.color, 3)
def test_progress8(self):
""" Due today (256) """
set_256_colors()
color = progress_color(Todo('Foo due:2016-01-01'))
self.assertEqual(color.color, 202)
def test_progress9(self):
""" Due tomorrow """
color = progress_color(Todo('Foo due:2016-01-02'))
# a length of 14 days is assumed
self.assertEqual(color.color, 3)
def test_progress10(self):
set_256_colors()
color = progress_color(Todo('Foo due:2016-01-02'))
# a length of 14 days is assumed
self.assertEqual(color.color, 208)
def test_progress11(self):
""" Due tomorrow (creation date) """
color = progress_color(Todo('2016-01-01 Foo due:2016-01-02'))
# a length of 14 days is assumed
self.assertEqual(color.color, 2)
def test_progress12(self):
""" Due tomorrow (creation date) """
set_256_colors()
color = progress_color(Todo('2016-01-01 Foo due:2016-01-02'))
self.assertEqual(color.color, 22)
def test_progress13(self):
""" Due tomorrow (recurrence) """
color = progress_color(Todo('Foo due:2016-01-02 rec:1d'))
self.assertEqual(color.color, 2)
def test_progress14(self):
""" Due tomorrow (recurrence) """
set_256_colors()
color = progress_color(Todo('Foo due:2016-01-02 rec:1d'))
self.assertEqual(color.color, 22)
def test_progress15(self):
""" Due tomorrow (creation date + recurrence) """
color = progress_color(Todo('2016-12-01 Foo due:2016-01-02 rec:1d'))
self.assertEqual(color.color, 2)
def test_progress16(self):
""" Due tomorrow (creation date + recurrence) """
set_256_colors()
color = progress_color(Todo('2015-12-01 Foo due:2016-01-02 rec:1d'))
self.assertEqual(color.color, 22)
def test_progress17(self):
""" Due tomorrow (creation date + recurrence + start date) """
color = progress_color(Todo('2016-12-01 Foo due:2016-01-02 rec:1d t:2016-01-02'))
self.assertEqual(color.color, 2)
def test_progress18(self):
""" Due tomorrow (creation date + recurrence + start date) """
set_256_colors()
color = progress_color(Todo('2015-12-01 Foo due:2016-01-02 rec:1d t:2016-01-02'))
self.assertEqual(color.color, 22)
def test_progress19(self):
""" Due tomorrow (creation date + strict recurrence + start date) """
color = progress_color(Todo('2016-12-01 Foo due:2016-01-02 rec:+1d t:2016-01-02'))
self.assertEqual(color.color, 2)
def test_progress20(self):
""" Due tomorrow (creation date + strict recurrence + start date) """
set_256_colors()
color = progress_color(Todo('2015-12-01 Foo due:2016-01-02 rec:+1d t:2016-01-02'))
self.assertEqual(color.color, 22)
def test_progress21(self):
""" Due tomorrow (creation date + start date) """
color = progress_color(Todo('2016-12-01 Foo due:2016-01-02 t:2016-01-02'))
self.assertEqual(color.color, 2)
def test_progress22(self):
""" Due tomorrow (creation date + start date) """
set_256_colors()
color = progress_color(Todo('2015-12-01 Foo due:2016-01-02 t:2016-01-02'))
self.assertEqual(color.color, 22)
def test_progress23(self):
""" Due tomorrow (creation date + start date) """
color = progress_color(Todo('2016-12-01 Foo due:2016-01-02 t:2015-12-31'))
self.assertEqual(color.color, 10)
def test_progress24(self):
""" Due tomorrow (creation date + start date) """
set_256_colors()
color = progress_color(Todo('2015-12-01 Foo due:2016-01-02 t:2015-12-31'))
self.assertEqual(color.color, 118)
def test_progress25(self):
""" Start date after due date """
color = progress_color(Todo('Foo due:2016-01-02 t:2016-01-03'))
# a length of 14 days is assumed
self.assertEqual(color.color, 3)
def test_progress26(self):
""" Start date after due date """
set_256_colors()
color = progress_color(Todo('Foo due:2016-01-02 t:2016-01-03'))
# a length of 14 days is assumed
self.assertEqual(color.color, 208)
def test_progress27(self):
""" Creation date after due date """
set_256_colors()
color = progress_color(Todo('2016-01-03 Foo due:2016-01-02'))
# a length of 14 days is assumed
self.assertEqual(color.color, 208)
if __name__ == '__main__':
unittest.main()
...@@ -25,7 +25,7 @@ from topydo.lib.Todo import Todo ...@@ -25,7 +25,7 @@ from topydo.lib.Todo import Todo
class RecurrenceTest(TopydoTest): class RecurrenceTest(TopydoTest):
def setUp(self): def setUp(self):
super(RecurrenceTest, self).setUp() super().setUp()
self.todo = Todo("Test rec:1w") self.todo = Todo("Test rec:1w")
self.stricttodo = Todo("Test rec:+1w") self.stricttodo = Todo("Test rec:+1w")
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest import unittest
from datetime import date, timedelta from datetime import date
from freezegun import freeze_time from freezegun import freeze_time
from test.topydo_testcase import TopydoTest from test.topydo_testcase import TopydoTest
...@@ -25,7 +25,7 @@ from topydo.lib.RelativeDate import relative_date_to_date ...@@ -25,7 +25,7 @@ from topydo.lib.RelativeDate import relative_date_to_date
@freeze_time('2015, 11, 06') @freeze_time('2015, 11, 06')
class RelativeDateTester(TopydoTest): class RelativeDateTester(TopydoTest):
def setUp(self): def setUp(self):
super(RelativeDateTester, self).setUp() super().setUp()
self.yesterday = date(2015, 11, 5) self.yesterday = date(2015, 11, 5)
self.today = date(2015, 11, 6) self.today = date(2015, 11, 6)
self.tomorrow = date(2015, 11, 7) self.tomorrow = date(2015, 11, 7)
...@@ -40,6 +40,18 @@ class RelativeDateTester(TopydoTest): ...@@ -40,6 +40,18 @@ class RelativeDateTester(TopydoTest):
result = relative_date_to_date('1d') result = relative_date_to_date('1d')
self.assertEqual(result, self.tomorrow) self.assertEqual(result, self.tomorrow)
def test_zero_bdays(self):
result = relative_date_to_date('0b')
self.assertEqual(result, self.today)
def test_one_bday(self):
result = relative_date_to_date('1b')
self.assertEqual(result, self.monday)
def test_one_bweek(self):
result = relative_date_to_date('5b')
self.assertEqual(result, self.friday)
def test_one_week(self): def test_one_week(self):
result = relative_date_to_date('1w') result = relative_date_to_date('1w')
self.assertEqual(result, date(2015, 11, 13)) self.assertEqual(result, date(2015, 11, 13))
...@@ -152,6 +164,14 @@ class RelativeDateTester(TopydoTest): ...@@ -152,6 +164,14 @@ class RelativeDateTester(TopydoTest):
result = relative_date_to_date('-0d') result = relative_date_to_date('-0d')
self.assertTrue(result, self.today) self.assertTrue(result, self.today)
def test_negative_period3(self):
result = relative_date_to_date('-1b')
self.assertEqual(result, date(2015, 11, 5))
def test_negative_period4(self):
result = relative_date_to_date('-5b')
self.assertEqual(result, date(2015, 10, 30))
def test_weekday_next_week(self): def test_weekday_next_week(self):
""" """
When entering "Friday" on a Friday, return next week Friday instead of When entering "Friday" on a Friday, return next week Friday instead of
......
...@@ -35,7 +35,7 @@ from topydo.lib.TodoList import TodoList ...@@ -35,7 +35,7 @@ from topydo.lib.TodoList import TodoList
class RevertCommandTest(CommandTest): class RevertCommandTest(CommandTest):
def setUp(self): def setUp(self):
super(RevertCommandTest, self).setUp() super().setUp()
todos = [ todos = [
"Foo", "Foo",
"Bar", "Bar",
......
...@@ -24,7 +24,7 @@ from topydo.lib.Config import config ...@@ -24,7 +24,7 @@ from topydo.lib.Config import config
class SortCommandTest(CommandTest): class SortCommandTest(CommandTest):
def setUp(self): def setUp(self):
super(SortCommandTest, self).setUp() super().setUp()
self.todolist = load_file_to_todolist("test/data/SorterTest1.txt") self.todolist = load_file_to_todolist("test/data/SorterTest1.txt")
def test_sort1(self): def test_sort1(self):
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from freezegun import freeze_time
import unittest import unittest
from test.facilities import (load_file, load_file_to_todolist, print_view, from test.facilities import (load_file, load_file_to_todolist, print_view,
...@@ -23,6 +24,7 @@ from topydo.lib.Config import config ...@@ -23,6 +24,7 @@ from topydo.lib.Config import config
from topydo.lib.Sorter import Sorter from topydo.lib.Sorter import Sorter
@freeze_time("2016, 04, 25")
class SorterTest(TopydoTest): class SorterTest(TopydoTest):
def sort_file(self, p_filename, p_filename_ref, p_sorter): def sort_file(self, p_filename, p_filename_ref, p_sorter):
""" """
...@@ -189,5 +191,14 @@ class SorterTest(TopydoTest): ...@@ -189,5 +191,14 @@ class SorterTest(TopydoTest):
'test/data/SorterTest13-result-context.txt', sorter) 'test/data/SorterTest13-result-context.txt', sorter)
def test_sort19(self):
"""
Check sorting by length.
"""
sorter = Sorter('length,text')
self.sort_file('test/data/SorterTest14.txt',
'test/data/SorterTest14-result.txt', sorter)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -24,7 +24,7 @@ from topydo.lib.TodoList import TodoList ...@@ -24,7 +24,7 @@ from topydo.lib.TodoList import TodoList
class TagCommandTest(CommandTest): class TagCommandTest(CommandTest):
def setUp(self): def setUp(self):
super(TagCommandTest, self).setUp() super().setUp()
todos = [ todos = [
"Foo", "Foo",
"Bar due:2014-10-22", "Bar due:2014-10-22",
...@@ -42,7 +42,7 @@ class TagCommandTest(CommandTest): ...@@ -42,7 +42,7 @@ class TagCommandTest(CommandTest):
self.assertEqual(self.todolist.todo(1).source(), "Foo due:2014-10-22") self.assertEqual(self.todolist.todo(1).source(), "Foo due:2014-10-22")
self.assertEqual(self.output, "| 1| Foo due:2014-10-22\n") self.assertEqual(self.output, "| 1| Foo due:2014-10-22\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
def test_add_tag2(self): def test_add_tag2(self):
command = TagCommand(["Foo", "due", "2014-10-22"], self.todolist, command = TagCommand(["Foo", "due", "2014-10-22"], self.todolist,
...@@ -52,7 +52,7 @@ class TagCommandTest(CommandTest): ...@@ -52,7 +52,7 @@ class TagCommandTest(CommandTest):
self.assertEqual(self.todolist.todo(1).source(), "Foo due:2014-10-22") self.assertEqual(self.todolist.todo(1).source(), "Foo due:2014-10-22")
self.assertEqual(self.output, "| 1| Foo due:2014-10-22\n") self.assertEqual(self.output, "| 1| Foo due:2014-10-22\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
def test_add_tag3(self): def test_add_tag3(self):
command = TagCommand(["-a", "2", "due", "2014-10-19"], self.todolist, command = TagCommand(["-a", "2", "due", "2014-10-19"], self.todolist,
...@@ -64,23 +64,34 @@ class TagCommandTest(CommandTest): ...@@ -64,23 +64,34 @@ class TagCommandTest(CommandTest):
self.assertEqual(self.output, self.assertEqual(self.output,
"| 2| Bar due:2014-10-22 due:2014-10-19\n") "| 2| Bar due:2014-10-22 due:2014-10-19\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
def test_add_tag4(self): def test_add_tag4(self):
command = TagCommand(["Foox", "due", "2014-10-22"], self.todolist, command = TagCommand(["Foox", "due", "2014-10-22"], self.todolist,
self.out, self.error) self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertFalse(self.output) self.assertFalse(self.output)
self.assertEqual(self.errors, "Invalid todo number.\n") self.assertEqual(self.errors, "Invalid todo number.\n")
def test_force_add_tag01(self):
'''Tries to different values to a tag for the same name 3 times.'''
for letter in ['a', 'b', 'c']:
command = TagCommand(['-a', '1', 'k', letter], self.todolist,
self.out, self.error)
command.execute()
self.assertEqual(self.errors, "")
self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.todo(1).source(), "Foo k:a k:b k:c")
def test_set_tag04(self): def test_set_tag04(self):
command = TagCommand(["3", "due", "2014-10-20"], self.todolist, command = TagCommand(["3", "due", "2014-10-20"], self.todolist,
self.out, self.error) self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "| 3| Baz due:2014-10-20\n") self.assertEqual(self.output, "| 3| Baz due:2014-10-20\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -89,7 +100,7 @@ class TagCommandTest(CommandTest): ...@@ -89,7 +100,7 @@ class TagCommandTest(CommandTest):
self.out, self.error, lambda t: "all") self.out, self.error, lambda t: "all")
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-20 due:2014-10-20\n") self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-20 due:2014-10-20\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -98,7 +109,7 @@ class TagCommandTest(CommandTest): ...@@ -98,7 +109,7 @@ class TagCommandTest(CommandTest):
self.out, self.error, lambda t: "1") self.out, self.error, lambda t: "1")
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-20 due:2014-10-22\n") self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-20 due:2014-10-22\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -107,7 +118,7 @@ class TagCommandTest(CommandTest): ...@@ -107,7 +118,7 @@ class TagCommandTest(CommandTest):
self.out, self.error, lambda t: "2") self.out, self.error, lambda t: "2")
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-20 due:2014-10-20\n") self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-20 due:2014-10-20\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -116,7 +127,7 @@ class TagCommandTest(CommandTest): ...@@ -116,7 +127,7 @@ class TagCommandTest(CommandTest):
self.out, self.error, lambda t: "") self.out, self.error, lambda t: "")
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-20 due:2014-10-22\n") self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-20 due:2014-10-22\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -125,7 +136,7 @@ class TagCommandTest(CommandTest): ...@@ -125,7 +136,7 @@ class TagCommandTest(CommandTest):
self.out, self.error, lambda t: "99") self.out, self.error, lambda t: "99")
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-20 due:2014-10-22\n") self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-20 due:2014-10-22\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -134,7 +145,7 @@ class TagCommandTest(CommandTest): ...@@ -134,7 +145,7 @@ class TagCommandTest(CommandTest):
self.out, self.error, lambda t: "99") self.out, self.error, lambda t: "99")
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, self.assertEqual(self.output,
"| 4| Fnord due:2014-10-20 due:2014-10-20\n") "| 4| Fnord due:2014-10-20 due:2014-10-20\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -145,7 +156,7 @@ class TagCommandTest(CommandTest): ...@@ -145,7 +156,7 @@ class TagCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "| 3| Baz due:2015-11-19\n") self.assertEqual(self.output, "| 3| Baz due:2015-11-19\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -158,7 +169,7 @@ class TagCommandTest(CommandTest): ...@@ -158,7 +169,7 @@ class TagCommandTest(CommandTest):
self.error) self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "| 3| Baz due:2014-10-20 foo:today\n") self.assertEqual(self.output, "| 3| Baz due:2014-10-20 foo:today\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -166,7 +177,7 @@ class TagCommandTest(CommandTest): ...@@ -166,7 +177,7 @@ class TagCommandTest(CommandTest):
command = TagCommand(["1", "due"], self.todolist, self.out, self.error) command = TagCommand(["1", "due"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "| 1| Foo\n") self.assertEqual(self.output, "| 1| Foo\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -174,7 +185,7 @@ class TagCommandTest(CommandTest): ...@@ -174,7 +185,7 @@ class TagCommandTest(CommandTest):
command = TagCommand(["2", "due"], self.todolist, self.out, self.error) command = TagCommand(["2", "due"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "| 2| Bar\n") self.assertEqual(self.output, "| 2| Bar\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -183,7 +194,7 @@ class TagCommandTest(CommandTest): ...@@ -183,7 +194,7 @@ class TagCommandTest(CommandTest):
self.error, lambda t: "all") self.error, lambda t: "all")
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, self.assertEqual(self.output,
" 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord\n") " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -193,7 +204,7 @@ class TagCommandTest(CommandTest): ...@@ -193,7 +204,7 @@ class TagCommandTest(CommandTest):
lambda t: "1") lambda t: "1")
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-22\n") self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-22\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -202,7 +213,7 @@ class TagCommandTest(CommandTest): ...@@ -202,7 +213,7 @@ class TagCommandTest(CommandTest):
lambda t: "99") lambda t: "99")
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-20 due:2014-10-22\n") self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-20 due:2014-10-22\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -211,7 +222,7 @@ class TagCommandTest(CommandTest): ...@@ -211,7 +222,7 @@ class TagCommandTest(CommandTest):
lambda t: "A") lambda t: "A")
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-20 due:2014-10-22\n") self.assertEqual(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n| 4| Fnord due:2014-10-20 due:2014-10-22\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -219,7 +230,7 @@ class TagCommandTest(CommandTest): ...@@ -219,7 +230,7 @@ class TagCommandTest(CommandTest):
command = TagCommand(["5", "due"], self.todolist, self.out, self.error) command = TagCommand(["5", "due"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number.\n") self.assertEqual(self.errors, "Invalid todo number.\n")
...@@ -227,7 +238,7 @@ class TagCommandTest(CommandTest): ...@@ -227,7 +238,7 @@ class TagCommandTest(CommandTest):
command = TagCommand(["A", "due"], self.todolist, self.out, self.error) command = TagCommand(["A", "due"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number.\n") self.assertEqual(self.errors, "Invalid todo number.\n")
...@@ -236,7 +247,7 @@ class TagCommandTest(CommandTest): ...@@ -236,7 +247,7 @@ class TagCommandTest(CommandTest):
self.error, lambda t: "A") self.error, lambda t: "A")
command.execute() command.execute()
self.assertTrue(self.todolist.is_dirty()) self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, "| 4| Fnord\n") self.assertEqual(self.output, "| 4| Fnord\n")
self.assertEqual(self.errors, "") self.assertEqual(self.errors, "")
...@@ -244,7 +255,7 @@ class TagCommandTest(CommandTest): ...@@ -244,7 +255,7 @@ class TagCommandTest(CommandTest):
command = TagCommand(["4"], self.todolist, self.out, self.error) command = TagCommand(["4"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.dirty)
self.assertEqual(self.output, "") self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n") self.assertEqual(self.errors, command.usage() + "\n")
......
This diff is collapsed.
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 - 2015 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 unittest
from test.topydo_testcase import TopydoTest
from topydo.lib.Utils import translate_key_to_config
class UtilsTest(TopydoTest):
def test_key_to_cfg(self):
ctrl_s = translate_key_to_config('ctrl s')
meta_d = translate_key_to_config('meta d')
esc = translate_key_to_config('esc')
f4 = translate_key_to_config('f4')
self.assertEqual(ctrl_s, '<C-s>')
self.assertEqual(meta_d, '<M-d>')
self.assertEqual(esc, '<Esc>')
self.assertEqual(f4, '<F4>')
if __name__ == '__main__':
unittest.main()
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
default_command = ls default_command = ls
; filename = todo.txt ; filename = todo.txt
; archive_filename = done.txt ; archive_filename = done.txt
colors = 1 colors = auto
; identifiers can be 'linenumber' or 'text' ; identifiers can be 'linenumber' or 'text'
identifiers = linenumber identifiers = linenumber
backup_count = 5 backup_count = 5
...@@ -42,6 +42,8 @@ append_parent_contexts = 0 ...@@ -42,6 +42,8 @@ append_parent_contexts = 0
; [light-]gray, darkgray or numbers from 0 to 255. When number is specified color ; [light-]gray, darkgray or numbers from 0 to 255. When number is specified color
; is matched from Xterm color chart available here: ; is matched from Xterm color chart available here:
; http://en.wikipedia.org/wiki/File:Xterm_256color_chart.svg ; http://en.wikipedia.org/wiki/File:Xterm_256color_chart.svg
; When using values between 16 and 256, make sure to set colors = 256 in the
; [topydo] section.
; priority_colors = A:cyan,B:yellow,C:blue ; priority_colors = A:cyan,B:yellow,C:blue
; project_color = red ; project_color = red
...@@ -52,7 +54,9 @@ append_parent_contexts = 0 ...@@ -52,7 +54,9 @@ append_parent_contexts = 0
[aliases] [aliases]
;showall = ls -x ;showall = ls -x
;next = ls -n 1 ;next = ls -n 1
;top = ls -F '|%I| %x %p %S %k %{(}H{)}' ;top = ls -F '%I %x %P %S %k %{(}H{)}' -N
;star = tag {} star 1
;unstar = tag {} star
;lsproj = lsprj ;lsproj = lsprj
;listprj = lsprj ;listprj = lsprj
;listproj = lsprj ;listproj = lsprj
...@@ -61,3 +65,35 @@ append_parent_contexts = 0 ...@@ -61,3 +65,35 @@ append_parent_contexts = 0
;listcon = lscon ;listcon = lscon
;listcontext = lscon ;listcontext = lscon
;listcontexts = lscon ;listcontexts = lscon
[columns]
column_width = 40
[column_keymap]
; Keymap configuration for column-mode
gg = home
G = end
j = down
k = up
d = cmd del {}
e = cmd edit {}
u = cmd revert
x = cmd do {}
pp = postpone
ps = postpone_s
pr = pri
m = mark
0 = first_column
$ = last_column
h = prev_column
l = next_column
A = append_column
I = insert_column
E = edit_column
D = delete_column
Y = copy_column
L = swap_left
R = swap_right
<Left> = prev_column
<Right> = next_column
<Esc> = reset
...@@ -21,7 +21,7 @@ instance based on an argument list. ...@@ -21,7 +21,7 @@ instance based on an argument list.
import sys import sys
from topydo.lib.Config import config from topydo.lib.Config import config, ConfigError
_SUBCOMMAND_MAP = { _SUBCOMMAND_MAP = {
'add': 'AddCommand', 'add': 'AddCommand',
...@@ -71,6 +71,18 @@ def get_subcommand(p_args): ...@@ -71,6 +71,18 @@ def get_subcommand(p_args):
__import__(modulename, globals(), locals(), [classname], 0) __import__(modulename, globals(), locals(), [classname], 0)
return getattr(sys.modules[modulename], classname) return getattr(sys.modules[modulename], classname)
def join_args(p_cli_args, p_alias_args):
"""
Returns properly joined args from alias definition and from user input.
"""
if '{}' in p_alias_args:
pos = p_alias_args.index('{}')
args = p_alias_args[:pos] + p_cli_args + p_alias_args[pos+1:]
else:
args = p_alias_args + p_cli_args
return args
def resolve_alias(p_alias, p_args): def resolve_alias(p_alias, p_args):
""" """
Resolves a subcommand alias and returns a tuple (Command, args). Resolves a subcommand alias and returns a tuple (Command, args).
...@@ -78,10 +90,14 @@ def get_subcommand(p_args): ...@@ -78,10 +90,14 @@ def get_subcommand(p_args):
If alias resolves to non-existent command, main help message is If alias resolves to non-existent command, main help message is
returned. returned.
""" """
try:
real_subcommand, alias_args = alias_map[p_alias] real_subcommand, alias_args = alias_map[p_alias]
except ValueError as ve:
raise ConfigError(alias_map[p_alias]) from ve
try: try:
result = import_subcommand(real_subcommand) result = import_subcommand(real_subcommand)
args = alias_args + p_args args = join_args(p_args, alias_args)
return (result, args) return (result, args)
except KeyError: except KeyError:
return get_subcommand(['help']) return get_subcommand(['help'])
......
...@@ -22,19 +22,17 @@ from datetime import date ...@@ -22,19 +22,17 @@ from datetime import date
from os.path import expanduser from os.path import expanduser
from sys import stdin from sys import stdin
from topydo.lib.Command import Command from topydo.lib.WriteCommand import WriteCommand
from topydo.lib.Config import config from topydo.lib.Config import config
from topydo.lib.prettyprinters.Numbers import PrettyPrinterNumbers from topydo.lib.prettyprinters.Numbers import PrettyPrinterNumbers
from topydo.lib.RelativeDate import relative_date_to_date
from topydo.lib.TodoListBase import InvalidTodoException
class AddCommand(Command): class AddCommand(WriteCommand):
def __init__(self, p_args, p_todolist, # pragma: no branch def __init__(self, p_args, p_todolist, # pragma: no branch
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(AddCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
self.text = ' '.join(p_args) self.text = ' '.join(p_args)
self.from_file = None self.from_file = None
...@@ -70,56 +68,18 @@ class AddCommand(Command): ...@@ -70,56 +68,18 @@ class AddCommand(Command):
return todo_text return todo_text
def _postprocess_input_todo(p_todo):
"""
Post-processes a parsed todo when adding it to the list.
* It converts relative dates to absolute ones.
* Automatically inserts a creation date if not present.
* Handles more user-friendly dependencies with before:, partof: and
after: tags
"""
def convert_date(p_tag):
value = p_todo.tag_value(p_tag)
if value:
dateobj = relative_date_to_date(value)
if dateobj:
p_todo.set_tag(p_tag, dateobj.isoformat())
def add_dependencies(p_tag):
for value in p_todo.tag_values(p_tag):
try:
dep = self.todolist.todo(value)
if p_tag == 'after':
self.todolist.add_dependency(p_todo, dep)
elif p_tag == 'before' or p_tag == 'partof':
self.todolist.add_dependency(dep, p_todo)
except InvalidTodoException:
pass
p_todo.remove_tag(p_tag, value)
convert_date(config().tag_start())
convert_date(config().tag_due())
add_dependencies('partof')
add_dependencies('before')
add_dependencies('after')
if config().auto_creation_date():
p_todo.set_creation_date(date.today())
todo_text = _preprocess_input_todo(p_todo_text) todo_text = _preprocess_input_todo(p_todo_text)
todo = self.todolist.add(todo_text) todo = self.todolist.add(todo_text)
_postprocess_input_todo(todo) self.postprocess_input_todo(todo)
if config().auto_creation_date():
todo.set_creation_date(date.today())
self.out(self.printer.print_todo(todo)) self.out(self.printer.print_todo(todo))
def execute(self): def execute(self):
""" Adds a todo item to the list. """ """ Adds a todo item to the list. """
if not super(AddCommand, self).execute(): if not super().execute():
return False return False
self.printer.add_filter(PrettyPrinterNumbers(self.todolist)) self.printer.add_filter(PrettyPrinterNumbers(self.todolist))
...@@ -138,23 +98,22 @@ class AddCommand(Command): ...@@ -138,23 +98,22 @@ class AddCommand(Command):
def usage(self): def usage(self):
return """Synopsis: return """Synopsis:
add <text> add <TEXT>
add -f <file> add -f <FILE> | -"""
add -f -"""
def help(self): def help(self):
return """\ return """\
This subcommand automatically adds the creation date to the added item. This subcommand automatically adds the creation date to the added item.
<text> may contain: TEXT may contain:
* Priorities mid-sentence. Example: add "Water flowers (C)" * Priorities mid-sentence. Example: add "Water flowers (C)"
* Dependencies using before, after and partof tags. They are translated to the * Dependencies using before, after, partof, parents-of and children-of tags.
corresponding 'id' and 'p' tags. The values of these tags correspond to the These are translated to the corresponding 'id' and 'p' tags. The values of
todo number (not the dependency number). these tags correspond to the todo number (not the dependency number).
Example: add "Subtask partof:1" Example: add "Subtask partof:1"
-f : Add todo items from specified <file> or from standard input. -f : Add todo items from specified FILE or from standard input.\
""" """
...@@ -14,21 +14,23 @@ ...@@ -14,21 +14,23 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from topydo.lib.Command import Command, InvalidCommandArgument from topydo.lib.Config import config
from topydo.lib.Command import InvalidCommandArgument
from topydo.lib.WriteCommand import WriteCommand
from topydo.lib.prettyprinters.Numbers import PrettyPrinterNumbers from topydo.lib.prettyprinters.Numbers import PrettyPrinterNumbers
from topydo.lib.TodoListBase import InvalidTodoException from topydo.lib.TodoListBase import InvalidTodoException
from topydo.lib.TodoParser import parse_line
class AppendCommand(WriteCommand):
class AppendCommand(Command):
def __init__(self, p_args, p_todolist, #pragma: no branch def __init__(self, p_args, p_todolist, #pragma: no branch
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(AppendCommand, self).__init__(p_args, p_todolist, p_out, p_err, super().__init__(p_args, p_todolist, p_out, p_err,
p_prompt) p_prompt)
def execute(self): def execute(self):
if not super(AppendCommand, self).execute(): if not super().execute():
return False return False
try: try:
...@@ -37,7 +39,13 @@ class AppendCommand(Command): ...@@ -37,7 +39,13 @@ class AppendCommand(Command):
if text: if text:
todo = self.todolist.todo(number) todo = self.todolist.todo(number)
new_text_parsed = parse_line(text)
new_tags = new_text_parsed['tags']
for tag in (config().tag_start(), config().tag_due()):
if tag in new_tags:
todo.remove_tag(tag)
self.todolist.append(todo, text) self.todolist.append(todo, text)
self.postprocess_input_todo(todo)
self.printer.add_filter(PrettyPrinterNumbers(self.todolist)) self.printer.add_filter(PrettyPrinterNumbers(self.todolist))
self.out(self.printer.print_todo(todo)) self.out(self.printer.print_todo(todo))
...@@ -49,9 +57,9 @@ class AppendCommand(Command): ...@@ -49,9 +57,9 @@ class AppendCommand(Command):
self.error("Invalid todo number given.") self.error("Invalid todo number given.")
def usage(self): def usage(self):
return """Synopsis: append <number> <text>""" return """Synopsis: append <NUMBER> <TEXT>"""
def help(self): def help(self):
return """\ return """\
Adds the given <text> to the end of the todo indicated by <number>. Adds the given TEXT to the end of the todo indicated by NUMBER.\
""" """
...@@ -27,7 +27,7 @@ class ArchiveCommand(Command): ...@@ -27,7 +27,7 @@ class ArchiveCommand(Command):
TodoListBase class which does no dependency checking, so a better TodoListBase class which does no dependency checking, so a better
choice for huge done.txt files. choice for huge done.txt files.
""" """
super(ArchiveCommand, self).__init__([], p_todolist) super().__init__([], p_todolist)
self.archive = p_archive_list self.archive = p_archive_list
def execute(self): def execute(self):
......
...@@ -22,7 +22,7 @@ class DeleteCommand(DCommand): ...@@ -22,7 +22,7 @@ class DeleteCommand(DCommand):
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(DeleteCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
def prompt_text(self): def prompt_text(self):
...@@ -40,15 +40,15 @@ class DeleteCommand(DCommand): ...@@ -40,15 +40,15 @@ class DeleteCommand(DCommand):
def usage(self): def usage(self):
return """\ return """\
Synopsis: del [-f] <NUMBER1> [<NUMBER2> ...] Synopsis: del [-f] <NUMBER 1> [<NUMBER 2> ...]
del [-x] -e <EXPRESSION> del [-x] -e <EXPRESSION>\
""" """
def help(self): def help(self):
return """\ return """\
Deletes the todo item(s) with the given number(s) from the list. Deletes the todo item(s) with the given number(s) from the list.
It is also possible to delete items as complete with an expression using It is also possible to delete items that match EXPRESSION using the -e flag.
the -e flag. Use -x to also process todo items that are normally invisible Use -x to also process todo items that are normally invisible (as with the 'ls'
(with the 'ls' subcommand). subcommand).\
""" """
...@@ -29,7 +29,7 @@ class DepCommand(Command): ...@@ -29,7 +29,7 @@ class DepCommand(Command):
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(DepCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
try: try:
...@@ -40,44 +40,66 @@ class DepCommand(Command): ...@@ -40,44 +40,66 @@ class DepCommand(Command):
self.printer = pretty_printer_factory(self.todolist) self.printer = pretty_printer_factory(self.todolist)
def _handle_add(self): def _handle_add(self):
(from_todo, to_todo) = self._get_todos() for from_todo, to_todo in self._get_todos():
if from_todo and to_todo:
self.todolist.add_dependency(from_todo, to_todo) self.todolist.add_dependency(from_todo, to_todo)
def _handle_rm(self): def _handle_rm(self):
(from_todo, to_todo) = self._get_todos() for from_todo, to_todo in self._get_todos():
if from_todo and to_todo:
self.todolist.remove_dependency(from_todo, to_todo) self.todolist.remove_dependency(from_todo, to_todo)
def _get_todos(self): def _get_todos(self):
from_todo = None result = []
to_todo = None
def get_parent_dependencies():
child_todo = first_todo
sibling_todo = second_todo
return [(parent, child_todo) for parent in self.todolist.parents(sibling_todo)]
def get_child_dependencies():
parent_todo = first_todo
sibling_todo = second_todo
return [(parent_todo, child) for child in self.todolist.children(sibling_todo)]
get_before_dependency = lambda: [(second_todo, first_todo)]
get_after_dependency = lambda: [(first_todo, second_todo)]
operators = {
"after": get_after_dependency,
"before": get_before_dependency,
"child-of": get_child_dependencies,
"childof": get_child_dependencies,
"children-of": get_child_dependencies,
"childrenof": get_child_dependencies,
"parent-of": get_parent_dependencies,
"parentof": get_parent_dependencies,
"parents-of": get_parent_dependencies,
"parentsof": get_parent_dependencies,
"partof": get_before_dependency,
"to": get_after_dependency,
}
try: try:
first_todo_nr = self.argument(1)
operator = self.argument(2) operator = self.argument(2)
if operator == 'before' or operator == 'partof': if operator in operators:
from_todo_nr = self.argument(3) second_todo_nr = self.argument(3)
to_todo_nr = self.argument(1)
elif operator == 'to' or operator == 'after':
from_todo_nr = self.argument(1)
to_todo_nr = self.argument(3)
else: else:
# the operator was omitted, assume 2nd argument is target task second_todo_nr = self.argument(2)
# default to 'to' behavior operator = "to"
from_todo_nr = self.argument(1)
to_todo_nr = self.argument(2) first_todo = self.todolist.todo(first_todo_nr)
second_todo = self.todolist.todo(second_todo_nr)
from_todo = self.todolist.todo(from_todo_nr) result = operators[operator]()
to_todo = self.todolist.todo(to_todo_nr)
except (InvalidTodoException): except (InvalidTodoException):
self.error("Invalid todo number given.") self.error("Invalid todo number given.")
except InvalidCommandArgument: except InvalidCommandArgument:
self.error(self.usage()) self.error(self.usage())
return (from_todo, to_todo) return result
def _handle_ls(self): def _handle_ls(self):
""" Handles the ls subsubcommand. """ """ Handles the ls subsubcommand. """
...@@ -127,7 +149,7 @@ class DepCommand(Command): ...@@ -127,7 +149,7 @@ class DepCommand(Command):
def execute(self): def execute(self):
if not super(DepCommand, self).execute(): if not super().execute():
return False return False
dispatch = { dispatch = {
...@@ -148,7 +170,7 @@ class DepCommand(Command): ...@@ -148,7 +170,7 @@ class DepCommand(Command):
def usage(self): def usage(self):
return """Synopsis: return """Synopsis:
dep <add|rm> <NUMBER> [to] <NUMBER> dep <add|rm> <NUMBER> [to] <NUMBER>
dep add <NUMBER> <before|partof|after> <NUMBER> dep add <NUMBER> <before|partof|after|parents-of|children-of> <NUMBER>
dep ls <NUMBER> to dep ls <NUMBER> to
dep ls to <NUMBER> dep ls to <NUMBER>
dep dot <NUMBER> dep dot <NUMBER>
...@@ -156,10 +178,11 @@ class DepCommand(Command): ...@@ -156,10 +178,11 @@ class DepCommand(Command):
def help(self): def help(self):
return """\ return """\
* add : Adds a dependency. Using 1 before 2 creates a dependency * add : Adds a dependency. `dep add 1 2` denotes that todo item 1
from todo item 2 to 1. is dependant on todo item 2, i.e. item 2 is a subitem of
item 1.
* rm (alias: del) : Removes a dependency. * rm (alias: del) : Removes a dependency.
* ls : Lists all dependencies to or from a certain todo. * ls : Lists all dependencies to or from a certain todo.
* dot : Prints a dependency tree as a Dot graph. * dot : Prints a dependency tree as a Dot graph.
* clean (alias: gc) : Removes redundant id or p tags. * clean (alias: gc) : Removes redundant id or p tags.\
""" """
...@@ -23,7 +23,7 @@ class DepriCommand(MultiCommand): ...@@ -23,7 +23,7 @@ class DepriCommand(MultiCommand):
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(DepriCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
def _execute_multi_specific(self): def _execute_multi_specific(self):
...@@ -37,14 +37,14 @@ class DepriCommand(MultiCommand): ...@@ -37,14 +37,14 @@ class DepriCommand(MultiCommand):
def usage(self): def usage(self):
return """\ return """\
Synopsis: depri <NUMBER1> [<NUMBER2> ...] Synopsis: depri <NUMBER 1> [<NUMBER 2> ...]
depri [-x] -e <EXPRESSION> depri [-x] -e <EXPRESSION>\
""" """
def help(self): def help(self):
return """Removes the priority of the given todo item(s). return """Removes the priority of the given todo item(s).
It is also possible to deprioritize items as complete with an expression using It is also possible to deprioritize items as complete with an EXPRESSION using
the -e flag. Use -x to also process todo items that are normally invisible the -e flag. Use -x to also process todo items that are normally invisible (as
(with the 'ls' subcommand). with the 'ls' subcommand).\
""" """
...@@ -33,17 +33,17 @@ class DoCommand(DCommand): ...@@ -33,17 +33,17 @@ class DoCommand(DCommand):
self.strict_recurrence = False self.strict_recurrence = False
self.completion_date = date.today() self.completion_date = date.today()
super(DoCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
def get_flags(self): def get_flags(self):
""" Additional flags. """ """ Additional flags. """
opts, long_opts = super(DoCommand, self).get_flags() opts, long_opts = super().get_flags()
return ("d:s" + opts, ["date=", "strict"] + long_opts) return ("d:s" + opts, ["date=", "strict"] + long_opts)
def process_flag(self, p_opt, p_value): def process_flag(self, p_opt, p_value):
super(DoCommand, self).process_flag(p_opt, p_value) super().process_flag(p_opt, p_value)
if p_opt == "-s" or p_opt == "--strict": if p_opt == "-s" or p_opt == "--strict":
self.strict_recurrence = True self.strict_recurrence = True
...@@ -105,28 +105,28 @@ class DoCommand(DCommand): ...@@ -105,28 +105,28 @@ class DoCommand(DCommand):
def usage(self): def usage(self):
return """\ return """\
Synopsis: do [--date] [--force] [--strict] <NUMBER1> [<NUMBER2> ...] Synopsis: do [--date <DATE>] [--force] [--strict] <NUMBER 1> [<NUMBER 2> ...]
do [-x] -e <EXPRESSION> do [-x] -e <EXPRESSION>\
""" """
def help(self): def help(self):
return """Marks the todo(s) with given number(s) as complete. return """Marks the todo(s) with given NUMBER(s) as complete.
It is also possible to mark todo items as complete with an expression using the It is also possible to mark todo items as complete with an EXPRESSION using the
-e flag. Use -x to also process todo items that are normally invisible (with -e flag. Use -x to also process todo items that are normally invisible (as with
the 'ls' subcommand). the 'ls' subcommand).
In case a todo has subitems, a question is asked whether the subitems should be In case a todo has subitems (dependencies), a question is asked whether the
marked as completed as well. When --force is given, no interaction is required subitems should be marked as completed as well. When --force is given, no
and the subitems are not marked completed. interaction is required and the subitems are not marked completed.
In case a completed todo is recurring, a new todo will be added to the list, In case a completed todo is recurring, a new todo will be added to the list,
while the given todo item is marked as complete. The new date is calculated while the given todo item is marked as complete. The new date is calculated
based on the todo item's due date. If the due date is in the past, today's date based on the todo item's due date. If the due date is in the past, today's date
is used to calculate the new recurrence date. Using --strict prevents this, is used to calculate the new recurrence date. Using --strict prevents this, and
then the actual due date of the todo item is used to calculate the new then the actual due date of the todo item is used to calculate the new
recurrence date. Note that a future due date is always used as such to recurrence date. Note that a future due date is always used as such to
calculate the new due date. calculate the new due date.
Use --date to set a custom completion date. Use --date to set a custom completion date.\
""" """
...@@ -27,10 +27,6 @@ from topydo.lib.TodoList import TodoList ...@@ -27,10 +27,6 @@ from topydo.lib.TodoList import TodoList
# the true and only editor # the true and only editor
DEFAULT_EDITOR = 'vi' DEFAULT_EDITOR = 'vi'
# Access the base class of the TodoList instance kept inside EditCommand. We
# cannot use super() inside the class itself
BASE_TODOLIST = lambda tl: super(TodoList, tl)
def _get_file_mtime(p_file): def _get_file_mtime(p_file):
return os.stat(p_file.name).st_mtime return os.stat(p_file.name).st_mtime
...@@ -39,7 +35,7 @@ def _is_edited(p_orig_mtime, p_file): ...@@ -39,7 +35,7 @@ def _is_edited(p_orig_mtime, p_file):
class EditCommand(MultiCommand): class EditCommand(MultiCommand):
def __init__(self, p_args, p_todolist, p_output, p_error, p_input): def __init__(self, p_args, p_todolist, p_output, p_error, p_input):
super(EditCommand, self).__init__(p_args, p_todolist, p_output, super().__init__(p_args, p_todolist, p_output,
p_error, p_input) p_error, p_input)
if len(self.args) == 0: if len(self.args) == 0:
...@@ -115,7 +111,7 @@ class EditCommand(MultiCommand): ...@@ -115,7 +111,7 @@ class EditCommand(MultiCommand):
if _is_edited(orig_mtime, temp_todos): if _is_edited(orig_mtime, temp_todos):
for todo in self.todos: for todo in self.todos:
BASE_TODOLIST(self.todolist).delete(todo) self.todolist.delete(todo, p_leave_tags=True)
for todo in new_todos: for todo in new_todos:
self.todolist.add_todo(todo) self.todolist.add_todo(todo)
...@@ -138,8 +134,8 @@ class EditCommand(MultiCommand): ...@@ -138,8 +134,8 @@ class EditCommand(MultiCommand):
def usage(self): def usage(self):
return """Synopsis: return """Synopsis:
edit edit
edit <NUMBER1> [<NUMBER2> ...] edit <NUMBER 1> [<NUMBER 2> ...]
edit -e [-x] [expression] edit -e [-x] [EXPRESSION]
edit -d""" edit -d"""
def help(self): def help(self):
...@@ -147,15 +143,15 @@ class EditCommand(MultiCommand): ...@@ -147,15 +143,15 @@ class EditCommand(MultiCommand):
Launches a text editor to edit todos. Launches a text editor to edit todos.
Without any arguments it will just open the todo.txt file. Alternatively it can Without any arguments it will just open the todo.txt file. Alternatively it can
edit todo item(s) with the given number(s) or edit relevant todos matching edit todo item(s) with the given NUMBER(s) or edit relevant todos matching
the given expression. See `topydo help ls` for more information on relevant the given EXPRESSION. See `topydo help ls` for more information on relevant
todo items. It is also possible to open the archive file. todo items. It is also possible to open the archive file.
By default it will use $EDITOR in your environment, otherwise it will fall back By default it will look to your environment variable $EDITOR, otherwise it will
to 'vi'. fall back to 'vi'.
-e : Treat the subsequent arguments as an expression. -e : Treat the subsequent arguments as an EXPRESSION.
-x : Edit *all* todos matching the expression (i.e. do not filter on -x : Edit *all* todos matching the EXPRESSION (i.e. do not filter on
dependencies or relevance). dependencies or relevance).
-d : Open the archive file. -d : Open the archive file.\
""" """
...@@ -26,11 +26,11 @@ class ExitCommand(Command): ...@@ -26,11 +26,11 @@ class ExitCommand(Command):
""" """
def __init__(self, p_args, p_todolist, p_output, p_error, p_input): def __init__(self, p_args, p_todolist, p_output, p_error, p_input):
super(ExitCommand, self).__init__(p_args, p_todolist, p_output, p_error, super().__init__(p_args, p_todolist, p_output, p_error,
p_input) p_input)
def execute(self): def execute(self):
if not super(ExitCommand, self).execute(): if not super().execute():
return False return False
sys.exit(0) sys.exit(0)
...@@ -20,6 +20,7 @@ from topydo.lib.Filter import InstanceFilter ...@@ -20,6 +20,7 @@ from topydo.lib.Filter import InstanceFilter
from topydo.lib.printers.PrettyPrinter import pretty_printer_factory from topydo.lib.printers.PrettyPrinter import pretty_printer_factory
from topydo.lib.prettyprinters.Format import PrettyPrinterFormatFilter from topydo.lib.prettyprinters.Format import PrettyPrinterFormatFilter
from topydo.lib.TodoListBase import InvalidTodoException from topydo.lib.TodoListBase import InvalidTodoException
from topydo.lib.Utils import get_terminal_size
class ListCommand(ExpressionCommand): class ListCommand(ExpressionCommand):
...@@ -27,7 +28,7 @@ class ListCommand(ExpressionCommand): ...@@ -27,7 +28,7 @@ class ListCommand(ExpressionCommand):
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(ListCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
self.printer = None self.printer = None
...@@ -50,7 +51,7 @@ class ListCommand(ExpressionCommand): ...@@ -50,7 +51,7 @@ class ListCommand(ExpressionCommand):
return True return True
def _process_flags(self): def _process_flags(self):
opts, args = self.getopt('f:F:i:n:s:x') opts, args = self.getopt('f:F:i:n:Ns:x')
for opt, value in opts: for opt, value in opts:
if opt == '-x': if opt == '-x':
...@@ -65,17 +66,21 @@ class ListCommand(ExpressionCommand): ...@@ -65,17 +66,21 @@ class ListCommand(ExpressionCommand):
if self._poke_icalendar(): if self._poke_icalendar():
from topydo.lib.printers.Ical import IcalPrinter from topydo.lib.printers.Ical import IcalPrinter
self.printer = IcalPrinter(self.todolist) self.printer = IcalPrinter(self.todolist)
elif value == 'dot':
from topydo.lib.printers.Dot import DotPrinter
self.printer = DotPrinter(self.todolist)
# a graph without dependencies is not so useful, hence # a graph without dependencies is not so useful, hence
# show all # show all
self.show_all = True self.show_all = True
elif value == 'dot':
from topydo.lib.printers.Dot import DotPrinter
self.printer = DotPrinter(self.todolist)
else: else:
self.printer = None self.printer = None
elif opt == '-F': elif opt == '-F':
self.format = value self.format = value
elif opt == '-N':
# 2 lines are assumed to be taken up by printing the next prompt
# display at least one item
self.limit = max(get_terminal_size().lines - 2, 1)
elif opt == '-n': elif opt == '-n':
try: try:
self.limit = int(value) self.limit = int(value)
...@@ -94,7 +99,7 @@ class ListCommand(ExpressionCommand): ...@@ -94,7 +99,7 @@ class ListCommand(ExpressionCommand):
Additional filters to select particular todo items given with the -i Additional filters to select particular todo items given with the -i
flag. flag.
""" """
filters = super(ListCommand, self)._filters() filters = super()._filters()
if self.ids: if self.ids:
def get_todo(p_id): def get_todo(p_id):
...@@ -124,7 +129,6 @@ class ListCommand(ExpressionCommand): ...@@ -124,7 +129,6 @@ class ListCommand(ExpressionCommand):
# create a standard printer with some filters # create a standard printer with some filters
indent = config().list_indent() indent = config().list_indent()
final_format = ' ' * indent + self.format final_format = ' ' * indent + self.format
hidden_tags = config().hidden_tags()
filters = [] filters = []
filters.append(PrettyPrinterFormatFilter(self.todolist, final_format)) filters.append(PrettyPrinterFormatFilter(self.todolist, final_format))
...@@ -134,7 +138,7 @@ class ListCommand(ExpressionCommand): ...@@ -134,7 +138,7 @@ class ListCommand(ExpressionCommand):
self.out(self.printer.print_list(self._view().todos)) self.out(self.printer.print_list(self._view().todos))
def execute(self): def execute(self):
if not super(ListCommand, self).execute(): if not super().execute():
return False return False
try: try:
...@@ -148,20 +152,21 @@ class ListCommand(ExpressionCommand): ...@@ -148,20 +152,21 @@ class ListCommand(ExpressionCommand):
return True return True
def usage(self): def usage(self):
return """Synopsis: ls [-x] [-s <sort_expression>] [-f <output format>] return """Synopsis: ls [-x] [-s <SORT EXPRESSION>] [-f <OUTPUT FORMAT>]
[-F <format string>] [expression]""" [-F <FORMAT STRING>] [-i <NUMBER 1>[,<NUMBER 2> ...]] [-N | -n <INTEGER>]
[EXPRESSION]"""
def help(self): def help(self):
return """\ return """\
Lists all relevant todos. A todo is relevant when: Lists all relevant todos. A todo is relevant when:
* has not been completed yet; * has not been completed yet,
* the start date (if present) has passed; * the start date (if present) has passed, and
* there are no subitems that need to be completed. * there are no subitems that need to be completed.
When an expression is given, only the todos matching that expression are shown. When an EXPRESSION is given, only the todos matching that EXPRESSION are shown.
-f : Specify the output format, being 'text' (default), 'dot' or 'ical' or -f : Specify the OUTPUT format, being 'text' (default), 'dot' or 'ical' or
'json'. 'json'.
* 'text' - Text output with colors and indentation if applicable. * 'text' - Text output with colors and indentation if applicable.
...@@ -172,6 +177,7 @@ When an expression is given, only the todos matching that expression are shown. ...@@ -172,6 +177,7 @@ When an expression is given, only the todos matching that expression are shown.
an 'ical' tag with a unique ID. Completed todo items may be an 'ical' tag with a unique ID. Completed todo items may be
archived. archived.
* 'json' - Javascript Object Notation (JSON) * 'json' - Javascript Object Notation (JSON)
-F : Specify the format of the text ('text' format), which may contain -F : Specify the format of the text ('text' format), which may contain
placeholders that may be expanded if the todo has such attribute. If such placeholders that may be expanded if the todo has such attribute. If such
attribute does not exist, then it expands to an empty string. attribute does not exist, then it expands to an empty string.
...@@ -187,6 +193,7 @@ When an expression is given, only the todos matching that expression are shown. ...@@ -187,6 +193,7 @@ When an expression is given, only the todos matching that expression are shown.
%k: List of tags separated by spaces (excluding hidden tags). %k: List of tags separated by spaces (excluding hidden tags).
%K: List of all tags separated by spaces. %K: List of all tags separated by spaces.
%p: Priority. %p: Priority.
%P: Priority or placeholder space if no priority.
%s: Todo text. %s: Todo text.
%S: Todo text, truncated such that an item fits on one line. %S: Todo text, truncated such that an item fits on one line.
%t: Absolute creation date. %t: Absolute creation date.
...@@ -198,12 +205,14 @@ When an expression is given, only the todos matching that expression are shown. ...@@ -198,12 +205,14 @@ When an expression is given, only the todos matching that expression are shown.
Conditional characters can be added with blocks surrounded by curly Conditional characters can be added with blocks surrounded by curly
braces, they will only appear when a placeholder expanded to a value. braces, they will only appear when a placeholder expanded to a value.
E.g. %{(}p{)} will print (C) when the todo item has priority C, or '' E.g. %{(}p{)} will print '(C)' when the todo item has priority C, or ''
(empty string) when an item has no priority set. (empty string) when an item has no priority set.
A tab character serves as a marker to start right alignment. A tab character serves as a marker to start right alignment.
-i : Comma separated list of todo IDs to print. -i : Comma separated list of todo IDs to print.
-s : Sort the list according to a sort expression. Defaults to the expression -n : Number of items to display. Defaults to the value in the configuration.
-N : Limit number of items displayed such that they fit on the terminal.
-s : Sort the list according to a SORT EXPRESSION. Defaults to the expression
in the configuration. in the configuration.
-x : Show all todos (i.e. do not filter on dependencies or relevance). -x : Show all todos (i.e. do not filter on dependencies or relevance).\
""" """
...@@ -22,11 +22,11 @@ class ListContextCommand(Command): ...@@ -22,11 +22,11 @@ class ListContextCommand(Command):
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(ListContextCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
def execute(self): def execute(self):
if not super(ListContextCommand, self).execute(): if not super().execute():
return False return False
for context in sorted(self.todolist.contexts(), key=lambda s: s.lower()): for context in sorted(self.todolist.contexts(), key=lambda s: s.lower()):
......
...@@ -22,11 +22,11 @@ class ListProjectCommand(Command): ...@@ -22,11 +22,11 @@ class ListProjectCommand(Command):
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(ListProjectCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
def execute(self): def execute(self):
if not super(ListProjectCommand, self).execute(): if not super().execute():
return False return False
for project in sorted(self.todolist.projects(), key=lambda s: s.lower()): for project in sorted(self.todolist.projects(), key=lambda s: s.lower()):
......
...@@ -28,7 +28,7 @@ class PostponeCommand(MultiCommand): ...@@ -28,7 +28,7 @@ class PostponeCommand(MultiCommand):
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(PostponeCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
self.move_start_date = False self.move_start_date = False
...@@ -69,7 +69,7 @@ class PostponeCommand(MultiCommand): ...@@ -69,7 +69,7 @@ class PostponeCommand(MultiCommand):
# pylint: disable=E1103 # pylint: disable=E1103
todo.set_tag(config().tag_due(), new_due.isoformat()) todo.set_tag(config().tag_due(), new_due.isoformat())
self.todolist.set_dirty() self.todolist.dirty = True
self.out(self.printer.print_todo(todo)) self.out(self.printer.print_todo(todo))
else: else:
self.error("Invalid date pattern given.") self.error("Invalid date pattern given.")
...@@ -77,23 +77,23 @@ class PostponeCommand(MultiCommand): ...@@ -77,23 +77,23 @@ class PostponeCommand(MultiCommand):
def usage(self): def usage(self):
return """\ return """\
Synopsis: postpone [-s] <NUMBER> [<NUMBER2> ...] <PATTERN>" Synopsis: postpone [-s] <NUMBER> [<NUMBER2> ...] <PATTERN>
postpone [-x] -e <EXPRESSION> postpone [-x] -e <EXPRESSION>\
""" """
def help(self): def help(self):
return """\ return """\
Postpone the todo item(s) with the given number(s) and the given pattern. Postpone the todo item(s) with the given NUMBER(s) and the given PATTERN.
Postponing is done by adjusting the due date(s) of the todo(s), and if the -s Postponing is done by adjusting the due date(s) of the todo(s), and if the -s
flag is given, the start date accordingly. flag is given, the start date accordingly.
It is also possible to postpone items as complete with an expression using It is also possible to postpone items as complete with an EXPRESSION using
the -e flag. Use -x to also process todo items that are normally invisible the -e flag. Use -x to also process todo items that are normally invisible (as
(with the 'ls' subcommand). with the 'ls' subcommand).
The pattern is a relative date, written in the format <COUNT><PERIOD> where The PATTERN is a relative date, written in the format <COUNT> <PERIOD> where
count is a number and <PERIOD> is either 'd', 'w', 'm' or 'y', which stands for COUNT is a number and PERIOD is either 'd', 'w', 'm' or 'y', which stands for
days, weeks, months and years respectively. Example: 'postpone 1 1w' postpones days, weeks, months and years respectively. Example: 'postpone 1 2w' postpones
todo number 1 for 1 week. todo number 1 for 2 weeks.\
""" """
...@@ -22,18 +22,18 @@ from topydo.lib.Utils import is_valid_priority ...@@ -22,18 +22,18 @@ from topydo.lib.Utils import is_valid_priority
class PriorityCommand(MultiCommand): class PriorityCommand(MultiCommand):
def __init__(self, p_args, p_todolist, #pragma: no branch def __init__(self, p_args, p_todolist, # pragma: no branch
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(PriorityCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
self.last_argument = True self.last_argument = True
def _execute_multi_specific(self): def _execute_multi_specific(self):
def normalize_priority(p_priority): def normalize_priority(p_priority):
match = re.search(r'\b([A-Z])\b', p_priority) match = re.search(r'\b([A-Z])\b', p_priority.upper())
return match.group(1) if match else p_priority return match.group(1) if match else p_priority
priority = normalize_priority(self.args[-1]) priority = normalize_priority(self.args[-1])
...@@ -56,15 +56,15 @@ class PriorityCommand(MultiCommand): ...@@ -56,15 +56,15 @@ class PriorityCommand(MultiCommand):
def usage(self): def usage(self):
return """\ return """\
Synopsis: pri <NUMBER1> [<NUMBER2> ...] <PRIORITY> Synopsis: pri <NUMBER 1> [<NUMBER 2> ...] <PRIORITY>
pri [-x] -e <EXPRESSION> pri [-x] -e <EXPRESSION>\
""" """
def help(self): def help(self):
return """\ return """\
Sets the priority of todo(s) the given number(s) to the given priority. Sets the priority of todo(s) the given NUMBER(s) to the given PRIORITY.
It is also possible to prioritize items as complete with an expression using It is also possible to prioritize items with an EXPRESSION using the -e flag.
the -e flag. Use -x to also process todo items that are normally invisible Use -x to also process todo items that are normally invisible (as with the 'ls'
(with the 'ls' subcommand). subcommand).\
""" """
...@@ -25,11 +25,11 @@ class RevertCommand(Command): ...@@ -25,11 +25,11 @@ class RevertCommand(Command):
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(RevertCommand, self).__init__(p_args, p_todolist, p_out, p_err, super().__init__(p_args, p_todolist, p_out, p_err,
p_prompt) p_prompt)
def execute(self): def execute(self):
if not super(RevertCommand, self).execute(): if not super().execute():
return False return False
archive_file = TodoFile.TodoFile(config().archive()) archive_file = TodoFile.TodoFile(config().archive())
...@@ -54,6 +54,4 @@ class RevertCommand(Command): ...@@ -54,6 +54,4 @@ class RevertCommand(Command):
return """Synopsis: revert""" return """Synopsis: revert"""
def help(self): def help(self):
return """\ return """Reverts the last command."""
Reverts the last command.
"""
...@@ -24,11 +24,11 @@ class SortCommand(Command): ...@@ -24,11 +24,11 @@ class SortCommand(Command):
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(SortCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
def execute(self): def execute(self):
if not super(SortCommand, self).execute(): if not super().execute():
return False return False
try: try:
...@@ -42,14 +42,14 @@ class SortCommand(Command): ...@@ -42,14 +42,14 @@ class SortCommand(Command):
self.todolist.replace(sorted_todos) self.todolist.replace(sorted_todos)
def usage(self): def usage(self):
return """Synopsis: sort [expression]""" return """Synopsis: sort [<EXPRESSION>]"""
def help(self): def help(self):
return """\ return """\
Sorts the file according to the expression. If no expression is given, the Sorts the todo file according to the EXPRESSION. If no EXPRESSION is given, the
expression in the configuration is used. expression in the configuration is used.
The expression is a comma separated list of attributes to sort on. The list is The EXPRESSION is a comma separated list of attributes to sort on. The list is
evaluated in order, which means that the first attribute takes higher evaluated in order, which means that the first attribute takes higher
precedence, then the second, etc. precedence, then the second, etc.
...@@ -61,12 +61,12 @@ The following sort attributes are supported: ...@@ -61,12 +61,12 @@ The following sort attributes are supported:
* importance - Sort by importance * importance - Sort by importance
* importance-avg - Sort by average importance (based on parent items) * importance-avg - Sort by average importance (based on parent items)
* text - Sort by text * text - Sort by text
* <tag> - Sort by values of the given tag * <TAG> - Sort by values of the given TAG
Each item can optionally be prefixed with asc: and desc: to specify ascending Each item can optionally be prefixed with asc: and desc: to specify ascending
or descending sort respectively. If not specified, ascending sort is assumed. or descending sort respectively. If not specified, ascending sort is assumed.
Example: Example:
desc:importance,due,desc:priority desc:importance,due,desc:priority\
""" """
...@@ -26,7 +26,7 @@ class TagCommand(Command): ...@@ -26,7 +26,7 @@ class TagCommand(Command):
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(TagCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
self.force = False self.force = False
...@@ -106,10 +106,10 @@ class TagCommand(Command): ...@@ -106,10 +106,10 @@ class TagCommand(Command):
self.todo.set_tag(self.tag, self.value, self.force_add, p_old_value) self.todo.set_tag(self.tag, self.value, self.force_add, p_old_value)
if old_src != self.todo.source(): if old_src != self.todo.source():
self.todolist.set_dirty() self.todolist.dirty = True
def _set(self): def _set(self):
if len(self.current_values) > 1: if len(self.current_values) > 1 and not self.force_add:
answer = self._choose() answer = self._choose()
if answer == "all": if answer == "all":
...@@ -124,7 +124,7 @@ class TagCommand(Command): ...@@ -124,7 +124,7 @@ class TagCommand(Command):
self._print() self._print()
def execute(self): def execute(self):
if not super(TagCommand, self).execute(): if not super().execute():
return False return False
self._process_args() self._process_args()
...@@ -133,15 +133,15 @@ class TagCommand(Command): ...@@ -133,15 +133,15 @@ class TagCommand(Command):
self._set() self._set()
def usage(self): def usage(self):
return """Synopsis: tag [-a] [-f] <NUMBER> <tag> [<value>]""" return """Synopsis: tag [-a] [-f] <NUMBER> <TAG> [<VALUE>]"""
def help(self): def help(self):
return """\ return """\
Sets the given tag to the given todo number with the given value. If the value Sets the given TAG on the given todo NUMBER with the given VALUE. If the VALUE
is omitted, the tag is removed from the todo item. is omitted, the TAG is removed from the todo item.
-a : Do not change the current value of the tag if it exists, but add a new -a : Do not change the current value of the TAG if it exists, but add a new
value. VALUE for the given TAG.
-f : Force setting/removing all values of the tag. Prevents interaction with -f : Force setting/removing all values of the TAG. Prevents interaction with
the user. the user.\
""" """
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2016 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/>.
""" This module provides a class that represents a color. """
class AbstractColor:
NEUTRAL = 0
PROJECT = 1
CONTEXT = 2
META = 3
LINK = 4
class Color:
color_names_dict = {
'black': 0,
'red': 1,
'green': 2,
'yellow': 3,
'blue': 4,
'magenta': 5,
'cyan': 6,
'gray': 7,
'darkgray': 8,
'light-red': 9,
'light-green': 10,
'light-yellow': 11,
'light-blue': 12,
'light-magenta': 13,
'light-cyan': 14,
'white': 15,
}
# Source: https://gist.github.com/jasonm23/2868981
html_color_dict = {
0: "#000000", 1: "#800000", 2: "#008000", 3: "#808000", 4: "#000080",
5: "#800080", 6: "#008080", 7: "#c0c0c0", 8: "#808080", 9: "#ff0000",
10: "#00ff00", 11: "#ffff00", 12: "#0000ff", 13: "#ff00ff", 14: "#00ffff",
15: "#ffffff", 16: "#000000", 17: "#00005f", 18: "#000087", 19: "#0000af",
20: "#0000d7", 21: "#0000ff", 22: "#005f00", 23: "#005f5f", 24: "#005f87",
25: "#005faf", 26: "#005fd7", 27: "#005fff", 28: "#008700", 29: "#00875f",
30: "#008787", 31: "#0087af", 32: "#0087d7", 33: "#0087ff", 34: "#00af00",
35: "#00af5f", 36: "#00af87", 37: "#00afaf", 38: "#00afd7", 39: "#00afff",
40: "#00d700", 41: "#00d75f", 42: "#00d787", 43: "#00d7af", 44: "#00d7d7",
45: "#00d7ff", 46: "#00ff00", 47: "#00ff5f", 48: "#00ff87", 49: "#00ffaf",
50: "#00ffd7", 51: "#00ffff", 52: "#5f0000", 53: "#5f005f", 54: "#5f0087",
55: "#5f00af", 56: "#5f00d7", 57: "#5f00ff", 58: "#5f5f00", 59: "#5f5f5f",
60: "#5f5f87", 61: "#5f5faf", 62: "#5f5fd7", 63: "#5f5fff", 64: "#5f8700",
65: "#5f875f", 66: "#5f8787", 67: "#5f87af", 68: "#5f87d7", 69: "#5f87ff",
70: "#5faf00", 71: "#5faf5f", 72: "#5faf87", 73: "#5fafaf", 74: "#5fafd7",
75: "#5fafff", 76: "#5fd700", 77: "#5fd75f", 78: "#5fd787", 79: "#5fd7af",
80: "#5fd7d7", 81: "#5fd7ff", 82: "#5fff00", 83: "#5fff5f", 84: "#5fff87",
85: "#5fffaf", 86: "#5fffd7", 87: "#5fffff", 88: "#870000", 89: "#87005f",
90: "#870087", 91: "#8700af", 92: "#8700d7", 93: "#8700ff", 94: "#875f00",
95: "#875f5f", 96: "#875f87", 97: "#875faf", 98: "#875fd7", 99: "#875fff",
100: "#878700", 101: "#87875f", 102: "#878787", 103: "#8787af", 104: "#8787d7",
105: "#8787ff", 106: "#87af00", 107: "#87af5f", 108: "#87af87", 109: "#87afaf",
110: "#87afd7", 111: "#87afff", 112: "#87d700", 113: "#87d75f", 114: "#87d787",
115: "#87d7af", 116: "#87d7d7", 117: "#87d7ff", 118: "#87ff00", 119: "#87ff5f",
120: "#87ff87", 121: "#87ffaf", 122: "#87ffd7", 123: "#87ffff", 124: "#af0000",
125: "#af005f", 126: "#af0087", 127: "#af00af", 128: "#af00d7", 129: "#af00ff",
130: "#af5f00", 131: "#af5f5f", 132: "#af5f87", 133: "#af5faf", 134: "#af5fd7",
135: "#af5fff", 136: "#af8700", 137: "#af875f", 138: "#af8787", 139: "#af87af",
140: "#af87d7", 141: "#af87ff", 142: "#afaf00", 143: "#afaf5f", 144: "#afaf87",
145: "#afafaf", 146: "#afafd7", 147: "#afafff", 148: "#afd700", 149: "#afd75f",
150: "#afd787", 151: "#afd7af", 152: "#afd7d7", 153: "#afd7ff", 154: "#afff00",
155: "#afff5f", 156: "#afff87", 157: "#afffaf", 158: "#afffd7", 159: "#afffff",
160: "#d70000", 161: "#d7005f", 162: "#d70087", 163: "#d700af", 164: "#d700d7",
165: "#d700ff", 166: "#d75f00", 167: "#d75f5f", 168: "#d75f87", 169: "#d75faf",
170: "#d75fd7", 171: "#d75fff", 172: "#d78700", 173: "#d7875f", 174: "#d78787",
175: "#d787af", 176: "#d787d7", 177: "#d787ff", 178: "#dfaf00", 179: "#dfaf5f",
180: "#dfaf87", 181: "#dfafaf", 182: "#dfafdf", 183: "#dfafff", 184: "#dfdf00",
185: "#dfdf5f", 186: "#dfdf87", 187: "#dfdfaf", 188: "#dfdfdf", 189: "#dfdfff",
190: "#dfff00", 191: "#dfff5f", 192: "#dfff87", 193: "#dfffaf", 194: "#dfffdf",
195: "#dfffff", 196: "#ff0000", 197: "#ff005f", 198: "#ff0087", 199: "#ff00af",
200: "#ff00df", 201: "#ff00ff", 202: "#ff5f00", 203: "#ff5f5f", 204: "#ff5f87",
205: "#ff5faf", 206: "#ff5fdf", 207: "#ff5fff", 208: "#ff8700", 209: "#ff875f",
210: "#ff8787", 211: "#ff87af", 212: "#ff87df", 213: "#ff87ff", 214: "#ffaf00",
215: "#ffaf5f", 216: "#ffaf87", 217: "#ffafaf", 218: "#ffafdf", 219: "#ffafff",
220: "#ffdf00", 221: "#ffdf5f", 222: "#ffdf87", 223: "#ffdfaf", 224: "#ffdfdf",
225: "#ffdfff", 226: "#ffff00", 227: "#ffff5f", 228: "#ffff87", 229: "#ffffaf",
230: "#ffffdf", 231: "#ffffff", 232: "#080808", 233: "#121212", 234: "#1c1c1c",
235: "#262626", 236: "#303030", 237: "#3a3a3a", 238: "#444444", 239: "#4e4e4e",
240: "#585858", 241: "#626262", 242: "#6c6c6c", 243: "#767676", 244: "#808080",
245: "#8a8a8a", 246: "#949494", 247: "#9e9e9e", 248: "#a8a8a8", 249: "#b2b2b2",
250: "#bcbcbc", 251: "#c6c6c6", 252: "#d0d0d0", 253: "#dadada", 254: "#e4e4e4",
255: "#eeeeee",
}
def __init__(self, p_value=None):
""" p_value is user input, be it a word color or an xterm code """
self._value = None
self.color = p_value
@property
def color(self):
return self._value
@color.setter
def color(self, p_value):
try:
if not p_value:
self._value = None
elif p_value in Color.color_names_dict:
self._value = Color.color_names_dict[p_value]
else:
self._value = int(p_value)
# values not in the 256 range are normalized to be neutral
if not 0 <= self._value < 256:
raise ValueError
except ValueError:
# garbage was entered, make it neutral, so at least some
# highlighting may take place
self._value = -1
def is_neutral(self):
"""
A neutral color is the default color on the shell, setting this color
will reset all other attributes (background, foreground, decoration).
"""
return self._value == -1
def is_valid(self):
"""
Whether the color is a valid color.
"""
return self._value is not None
def as_ansi(self, p_decoration='normal', p_background=False):
if not self.is_valid():
return ''
elif self.is_neutral():
return '\033[0m'
is_high_color = 8 <= self._value < 16
is_256 = 16 <= self._value < 255
decoration_dict = {
'normal': '0',
'bold': '1',
'faint': '2',
'italic': '3',
'underline': '4',
}
decoration = decoration_dict[p_decoration]
base = 40 if p_background else 30
if is_high_color:
color = '1;{}'.format(base + self._value - 8)
elif is_256:
color = '{};5;{}'.format(base + 8, self._value)
else:
# it's a low color
color = str(base + self._value)
return '\033[{};{}m'.format(
decoration,
color
)
def as_html(self):
try:
return Color.html_color_dict[self.color]
except KeyError:
return '#ffffff'
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 - 2015 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/>.
""" This module serves for managing output colors. """
from topydo.lib.Config import config
NEUTRAL_COLOR = '\033[0m'
def int_to_ansi(p_int, p_decorator='normal', p_safe=True, p_background=''):
"""
Returns ansi code for color based on xterm color id (0-255) and
decoration, where decoration can be one of: normal, bold, faint,
italic, or underline. When p_safe is True, resulting ansi code is
constructed in most compatible way, but with support for only base 16
colors.
"""
decoration_dict = {
'normal': '0',
'bold': '1',
'faint': '2',
'italic': '3',
'underline': '4'
}
decoration = decoration_dict[p_decorator]
try:
if p_safe:
if p_background:
p_background = ';4{}'.format(p_background)
if 8 > int(p_int) >= 0:
return '\033[{};3{}{}m'.format(decoration, str(p_int), p_background)
elif 16 > int(p_int):
p_int = int(p_int) - 8
return '\033[{};1;3{}{}m'.format(decoration, str(p_int), p_background)
if 256 > int(p_int) >= 0:
if p_background:
p_background = ';48;5;{}'.format(str(p_int))
return '\033[{};38;5;{}{}m'.format(decoration, str(p_int), p_background)
else:
return NEUTRAL_COLOR
except ValueError:
return None
def _name_to_int(p_color_name):
""" Returns xterm color id from color name. """
color_names_dict = {
'black': 0,
'red': 1,
'green': 2,
'yellow': 3,
'blue': 4,
'magenta': 5,
'cyan': 6,
'gray': 7,
'darkgray': 8,
'light-red': 9,
'light-green': 10,
'light-yellow': 11,
'light-blue': 12,
'light-magenta': 13,
'light-cyan': 14,
'white': 15,
}
try:
return color_names_dict[p_color_name]
except KeyError:
return 404
def _name_to_ansi(p_color_name, p_decorator):
""" Returns ansi color code from color name. """
number = _name_to_int(p_color_name)
return int_to_ansi(number, p_decorator)
def _get_ansi(p_color, p_decorator):
""" Returns ansi color code from color name or xterm color id. """
if p_color == '':
ansi = ''
else:
ansi = int_to_ansi(p_color, p_decorator, False)
if not ansi:
ansi = _name_to_ansi(p_color, p_decorator)
return ansi
def _get_priority_colors():
pri_ansi_colors = dict()
pri_colors = config().priority_colors()
for pri in pri_colors:
color = _get_ansi(pri_colors[pri], 'normal')
if color == '':
color = NEUTRAL_COLOR
pri_ansi_colors[pri] = color
return pri_ansi_colors
class Colors(object):
def __init__(self):
self.priority_colors = _get_priority_colors()
self.project_color = config().project_color()
self.context_color = config().context_color()
self.metadata_color = config().metadata_color()
self.link_color = config().link_color()
def get_project_color(self):
return _get_ansi(self.project_color, 'bold')
def get_context_color(self):
return _get_ansi(self.context_color, 'bold')
def get_metadata_color(self):
return _get_ansi(self.metadata_color, 'bold')
def get_link_color(self):
return _get_ansi(self.link_color, 'underline')
def get_priority_color(self, p_priority):
try:
priority_color = self.priority_colors[p_priority]
except KeyError:
priority_color = NEUTRAL_COLOR
return priority_color
...@@ -71,8 +71,8 @@ class Command(object): ...@@ -71,8 +71,8 @@ class Command(object):
""" Retrieves a value from the argument list at the given position. """ """ Retrieves a value from the argument list at the given position. """
try: try:
return self.args[p_number] return self.args[p_number]
except IndexError: except IndexError as ie:
raise InvalidCommandArgument raise InvalidCommandArgument from ie
def getopt(self, p_flags, p_long=None): def getopt(self, p_flags, p_long=None):
p_long = p_long or [] p_long = p_long or []
......
This diff is collapsed.
...@@ -31,7 +31,7 @@ class DCommand(MultiCommand): ...@@ -31,7 +31,7 @@ class DCommand(MultiCommand):
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(DCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
self.force = False self.force = False
......
...@@ -32,7 +32,7 @@ class ExpressionCommand(Command): ...@@ -32,7 +32,7 @@ class ExpressionCommand(Command):
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(ExpressionCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
self.sort_expression = config().sort_string() self.sort_expression = config().sort_string()
...@@ -45,38 +45,12 @@ class ExpressionCommand(Command): ...@@ -45,38 +45,12 @@ class ExpressionCommand(Command):
def _filters(self): def _filters(self):
filters = [] filters = []
def arg_filters():
result = []
if self.last_argument:
args = self.args[:-1]
else:
args = self.args
for arg in args:
# when a word starts with -, it should be negated
is_negated = len(arg) > 1 and arg[0] == '-'
arg = arg[1:] if is_negated else arg
if re.match(Filter.ORDINAL_TAG_MATCH, arg):
argfilter = Filter.OrdinalTagFilter(arg)
elif re.match(Filter.PRIORITY_MATCH, arg):
argfilter = Filter.PriorityFilter(arg)
else:
argfilter = Filter.GrepFilter(arg)
if is_negated:
argfilter = Filter.NegationFilter(argfilter)
result.append(argfilter)
return result
if not self.show_all: if not self.show_all:
filters.append(Filter.DependencyFilter(self.todolist)) filters.append(Filter.DependencyFilter(self.todolist))
filters.append(Filter.RelevanceFilter()) filters.append(Filter.RelevanceFilter())
filters += arg_filters() args = self.args[:-1] if self.last_argument else self.args
filters += Filter.get_filter_list(args)
if not self.show_all: if not self.show_all:
filters.append(Filter.LimitFilter(self.limit)) filters.append(Filter.LimitFilter(self.limit))
......
This diff is collapsed.
...@@ -83,12 +83,14 @@ def average_importance(p_todo, p_ignore_weekend=config().ignore_weekends()): ...@@ -83,12 +83,14 @@ def average_importance(p_todo, p_ignore_weekend=config().ignore_weekends()):
average = 0 average = 0
parents = [] parents = []
if 'parents' in p_todo.attributes: try:
sum_importance = own_importance sum_importance = own_importance
parents = p_todo.attributes['parents'] parents = p_todo.parents()
for parent in parents: for parent in parents:
sum_importance += importance(parent, p_ignore_weekend) sum_importance += importance(parent, p_ignore_weekend)
average = float(sum_importance) / float(1 + len(parents)) average = float(sum_importance) / float(1 + len(parents))
except AttributeError:
pass
return max(own_importance, average) return max(own_importance, average)
This diff is collapsed.
...@@ -27,7 +27,7 @@ class MultiCommand(ExpressionCommand): ...@@ -27,7 +27,7 @@ class MultiCommand(ExpressionCommand):
p_out=lambda a: None, p_out=lambda a: None,
p_err=lambda a: None, p_err=lambda a: None,
p_prompt=lambda a: None): p_prompt=lambda a: None):
super(MultiCommand, self).__init__( super().__init__(
p_args, p_todolist, p_out, p_err, p_prompt) p_args, p_todolist, p_out, p_err, p_prompt)
self.todos = [] self.todos = []
...@@ -114,7 +114,7 @@ class MultiCommand(ExpressionCommand): ...@@ -114,7 +114,7 @@ class MultiCommand(ExpressionCommand):
raise NotImplementedError raise NotImplementedError
def execute(self): def execute(self):
if not super(MultiCommand, self).execute(): if not super().execute():
return False return False
self._process_flags() self._process_flags()
......
...@@ -29,4 +29,3 @@ class PrettyPrinterFilter(object): ...@@ -29,4 +29,3 @@ class PrettyPrinterFilter(object):
Applies a filter to p_todo_str and returns a modified version of it. Applies a filter to p_todo_str and returns a modified version of it.
""" """
raise NotImplementedError raise NotImplementedError
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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