Commit 13b748ac authored by Bram Schoenmakers's avatar Bram Schoenmakers

Merge remote-tracking branch 'origin/master'

parents 34653821 19b5623a
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
--- ---
......
...@@ -29,9 +29,18 @@ Simply install with: ...@@ -29,9 +29,18 @@ Simply install with:
### Optional dependencies ### 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.
* [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.
* [python-dateutil][10]: A dependency of *arrow*.
* [mock][11] : Used for testing. This was added to the standard
library in Python 3.3.
Demo Demo
---- ----
...@@ -46,3 +55,7 @@ Demo ...@@ -46,3 +55,7 @@ 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
...@@ -33,9 +33,11 @@ setup( ...@@ -33,9 +33,11 @@ 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'],
'ical': ['icalendar'], 'ical': ['icalendar'],
'prompt-toolkit': ['prompt-toolkit >= 0.53'], 'prompt-toolkit': ['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.cli.UILoader:main'],
......
...@@ -20,7 +20,7 @@ from topydo.lib.Utils import escape_ansi ...@@ -20,7 +20,7 @@ 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 = ""
......
(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
...@@ -3,3 +3,4 @@ foo = rm -f test ...@@ -3,3 +3,4 @@ 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
...@@ -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()
......
...@@ -23,7 +23,7 @@ from topydo.lib.TodoList import TodoList ...@@ -23,7 +23,7 @@ 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")
......
...@@ -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",
......
...@@ -23,7 +23,7 @@ from topydo.lib.TodoList import TodoList ...@@ -23,7 +23,7 @@ from topydo.lib.TodoList import TodoList
class DepCommandTest(CommandTest): class DepCommandTest(CommandTest):
def setUp(self): def setUp(self):
super(DepCommandTest, self).setUp() super().setUp()
todos = [ todos = [
"Foo id:1", "Foo id:1",
"Bar p:1", "Bar p:1",
......
...@@ -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",
......
...@@ -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",
......
...@@ -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",
......
...@@ -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"
......
...@@ -22,6 +22,7 @@ from topydo.commands.AddCommand import AddCommand ...@@ -22,6 +22,7 @@ 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.ListProjectCommand import ListProjectCommand
from topydo.commands.TagCommand import TagCommand
from topydo.lib.Config import config from topydo.lib.Config import config
class GetSubcommandTest(TopydoTest): class GetSubcommandTest(TopydoTest):
...@@ -60,6 +61,14 @@ class GetSubcommandTest(TopydoTest): ...@@ -60,6 +61,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)
......
...@@ -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()
......
...@@ -17,17 +17,27 @@ ...@@ -17,17 +17,27 @@
import codecs import codecs
import re import re
import unittest import unittest
from collections import namedtuple
from test.command_testcase import CommandTest from test.command_testcase import CommandTest
from test.facilities import load_file_to_todolist from test.facilities import load_file_to_todolist
from topydo.commands.ListCommand import ListCommand from topydo.commands.ListCommand import ListCommand
from topydo.lib.Config import config from topydo.lib.Config import config
# We're searching for 'mock'
# 'mock' was added as 'unittest.mock' in Python 3.3, but PyPy 3 is based on Python 3.2
# pylint: disable=no-name-in-module
try:
from unittest import mock
except ImportError:
import mock
class ListCommandTest(CommandTest): class ListCommandTest(CommandTest):
def setUp(self): def setUp(self):
super(ListCommandTest, self).setUp() super().setUp()
self.todolist = load_file_to_todolist("test/data/ListCommandTest.txt") self.todolist = load_file_to_todolist("test/data/ListCommandTest.txt")
self.terminal_size = namedtuple('terminal_size', ['columns', 'lines'])
def test_list01(self): def test_list01(self):
command = ListCommand([""], self.todolist, self.out, self.error) command = ListCommand([""], self.todolist, self.out, self.error)
...@@ -313,8 +323,64 @@ class ListCommandTest(CommandTest): ...@@ -313,8 +323,64 @@ class ListCommandTest(CommandTest):
self.assertEqual(self.errors, "option -z not recognized\n") self.assertEqual(self.errors, "option -z not recognized\n")
def test_list42(self): def test_list42(self):
command = ListCommand(["-x", "+Project1", "-id:1"], self.todolist, self.out, command = ListCommand(["-x", "+Project1", "-id:1"], self.todolist,
self.error) self.out, self.error)
command.execute()
self.assertEqual(self.output, "| 1| (C) 2015-11-05 Foo @Context2 Not@Context +Project1 Not+Project\n")
self.assertEqual(self.errors, "")
def test_list43(self):
"""Test basic 'N' parameter."""
command = ListCommand(["-N"], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(self.output, "| 1| (C) 2015-11-05 Foo @Context2 Not@Context +Project1 Not+Project\n| 4| (C) Drink beer @ home\n| 5| (C) 13 + 29 = 42\n| 2| (D) Bar @Context1 +Project2\n")
self.assertEqual(self.errors, "")
@mock.patch('topydo.commands.ListCommand.get_terminal_size')
def test_list44(self, mock_terminal_size):
"""
Test 'N' parameter with output longer than available terminal lines.
"""
self.todolist = load_file_to_todolist("test/data/ListCommand_50_items.txt")
mock_terminal_size.return_value = self.terminal_size(80, 23)
command = ListCommand(["-N"], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(self.output, "| 1| (A) item 1\n| 27| (A) item 27\n| 2| (B) item 2\n| 28| (B) item 28\n| 3| (C) item 3\n| 29| (C) item 29\n| 4| (D) item 4\n| 30| (D) item 30\n| 5| (E) item 5\n| 31| (E) item 31\n| 6| (F) item 6\n| 32| (F) item 32\n| 7| (G) item 7\n| 33| (G) item 33\n| 8| (H) item 8\n| 34| (H) item 34\n| 9| (I) item 9\n| 35| (I) item 35\n| 10| (J) item 10\n| 36| (J) item 36\n| 11| (K) item 11\n")
self.assertEqual(self.errors, "")
@mock.patch('topydo.commands.ListCommand.get_terminal_size')
def test_list45(self, mock_terminal_size):
"""Test basic 'N' parameter with nine line terminal."""
# have 9 lines on the terminal will print 7 items and leave 2 lines
# for the next prompt
mock_terminal_size.return_value = self.terminal_size(100, 9)
self.todolist = load_file_to_todolist("test/data/ListCommand_50_items.txt")
command = ListCommand(["-N"], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(self.output, "| 1| (A) item 1\n| 27| (A) item 27\n| 2| (B) item 2\n| 28| (B) item 28\n| 3| (C) item 3\n| 29| (C) item 29\n| 4| (D) item 4\n")
self.assertEqual(self.errors, "")
@mock.patch('topydo.commands.ListCommand.get_terminal_size')
def test_list46(self, mock_terminal_size):
"""Test basic 'N' parameter with zero height terminal."""
# we still print at least 1 item
mock_terminal_size.return_value = self.terminal_size(100, 0)
self.todolist = load_file_to_todolist("test/data/ListCommand_50_items.txt")
command = ListCommand(["-N"], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(self.output, "| 1| (A) item 1\n")
self.assertEqual(self.errors, "")
def test_list47(self):
command = ListCommand(["created:2015-11-05"], self.todolist, self.out, self.error)
command.execute() command.execute()
self.assertEqual(self.output, "| 1| (C) 2015-11-05 Foo @Context2 Not@Context +Project1 Not+Project\n") self.assertEqual(self.output, "| 1| (C) 2015-11-05 Foo @Context2 Not@Context +Project1 Not+Project\n")
...@@ -331,7 +397,7 @@ class ListCommandTest(CommandTest): ...@@ -331,7 +397,7 @@ class ListCommandTest(CommandTest):
class ListCommandUnicodeTest(CommandTest): class ListCommandUnicodeTest(CommandTest):
def setUp(self): def setUp(self):
super(ListCommandUnicodeTest, self).setUp() super().setUp()
self.todolist = load_file_to_todolist("test/data/ListCommandUnicodeTest.txt") self.todolist = load_file_to_todolist("test/data/ListCommandUnicodeTest.txt")
def test_list_unicode1(self): def test_list_unicode1(self):
......
...@@ -25,16 +25,18 @@ from topydo.commands.ListCommand import ListCommand ...@@ -25,16 +25,18 @@ from topydo.commands.ListCommand import ListCommand
from topydo.lib.Config import config from topydo.lib.Config import config
# We're searching for 'mock' # We're searching for 'mock'
# 'mock' was added as 'unittest.mock' in Python 3.3, but PyPy 3 is based on Python 3.2
# pylint: disable=no-name-in-module # pylint: disable=no-name-in-module
try: try:
from unittest import mock from unittest import mock
except ImportError: except ImportError:
import mock import mock
@freeze_time("2015, 11, 06") @freeze_time("2015, 11, 06")
class ListFormatTest(CommandTest): class ListFormatTest(CommandTest):
def setUp(self): def setUp(self):
super(ListFormatTest, self).setUp() super().setUp()
self.todolist = load_file_to_todolist("test/data/ListFormat.txt") self.todolist = load_file_to_todolist("test/data/ListFormat.txt")
self.terminal_size = namedtuple('terminal_size', ['columns', 'lines']) self.terminal_size = namedtuple('terminal_size', ['columns', 'lines'])
...@@ -43,7 +45,7 @@ class ListFormatTest(CommandTest): ...@@ -43,7 +45,7 @@ class ListFormatTest(CommandTest):
command = ListCommand(["-x"], self.todolist, self.out, self.error) command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29 result = """| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29
| 2| (Z) 2015-11-06 Lorem ipsum dolorem sit amet. Red @fox +jumped over the and jar due:2015-11-08 lazy:bar t:2015-11-07 | 2| (Z) 2015-11-06 Lorem ipsum dolorem sit amet. Red @fox +jumped over the and jar due:2015-11-08 lazy:bar t:2015-11-07
| 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project | 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project
| 4| (C) Baz @Context1 +Project1 key:value | 4| (C) Baz @Context1 +Project1 key:value
...@@ -60,7 +62,7 @@ class ListFormatTest(CommandTest): ...@@ -60,7 +62,7 @@ class ListFormatTest(CommandTest):
command = ListCommand(["-x"], self.todolist, self.out, self.error) command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29 result = """| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29
| 2| (Z) 2015-11-06 Lorem ipsum dolore... due:2015-11-08 lazy:bar t:2015-11-07 | 2| (Z) 2015-11-06 Lorem ipsum dolore... due:2015-11-08 lazy:bar t:2015-11-07
| 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project | 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project
| 4| (C) Baz @Context1 +Project1 key:value | 4| (C) Baz @Context1 +Project1 key:value
...@@ -77,7 +79,7 @@ class ListFormatTest(CommandTest): ...@@ -77,7 +79,7 @@ class ListFormatTest(CommandTest):
command = ListCommand(["-x"], self.todolist, self.out, self.error) command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29 result = """| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29
| 2| (Z) 2015-11-06 Lorem ipsum dolorem sit amet. Red @fox... due:2015-11-08 lazy:bar t:2015-11-07 | 2| (Z) 2015-11-06 Lorem ipsum dolorem sit amet. Red @fox... due:2015-11-08 lazy:bar t:2015-11-07
| 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project | 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project
| 4| (C) Baz @Context1 +Project1 key:value | 4| (C) Baz @Context1 +Project1 key:value
...@@ -94,7 +96,7 @@ class ListFormatTest(CommandTest): ...@@ -94,7 +96,7 @@ class ListFormatTest(CommandTest):
command = ListCommand(["-x"], self.todolist, self.out, self.error) command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29 result = """| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29
| 2| (Z) 2015-11-06 Lorem ipsum dolorem sit amet. Red @fox... due:2015-11-08 lazy:bar t:2015-11-07 | 2| (Z) 2015-11-06 Lorem ipsum dolorem sit amet. Red @fox... due:2015-11-08 lazy:bar t:2015-11-07
| 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project | 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project
| 4| (C) Baz @Context1 +Project1 key:value | 4| (C) Baz @Context1 +Project1 key:value
...@@ -111,7 +113,7 @@ class ListFormatTest(CommandTest): ...@@ -111,7 +113,7 @@ class ListFormatTest(CommandTest):
command = ListCommand(["-x"], self.todolist, self.out, self.error) command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29 result = """| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29
| 2| (Z) 2015-11-06 Lorem ipsum dolore... due:2015-11-08 lazy:bar t:2015-11-07 | 2| (Z) 2015-11-06 Lorem ipsum dolore... due:2015-11-08 lazy:bar t:2015-11-07
| 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project | 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project
| 4| (C) Baz @Context1 +Project1 key:value | 4| (C) Baz @Context1 +Project1 key:value
...@@ -119,6 +121,8 @@ class ListFormatTest(CommandTest): ...@@ -119,6 +121,8 @@ class ListFormatTest(CommandTest):
| 6| x 2014-12-12 Completed but with date:2014-12-12 | 6| x 2014-12-12 Completed but with date:2014-12-12
""" """
self.assertEqual(self.output, result)
@mock.patch('topydo.lib.ListFormat.get_terminal_size') @mock.patch('topydo.lib.ListFormat.get_terminal_size')
def test_list_format06(self, mock_terminal_size): def test_list_format06(self, mock_terminal_size):
mock_terminal_size.return_value = self.terminal_size(100, 25) mock_terminal_size.return_value = self.terminal_size(100, 25)
...@@ -127,7 +131,7 @@ class ListFormatTest(CommandTest): ...@@ -127,7 +131,7 @@ class ListFormatTest(CommandTest):
command = ListCommand(["-x"], self.todolist, self.out, self.error) command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""| 1| D Bar @Context1 +Project2 (3 months ago, due a month ago, started a month ago) result = """| 1| D Bar @Context1 +Project2 (3 months ago, due a month ago, started a month ago)
| 2| Z Lorem ipsum dolorem sit amet. Red @f... lazy:bar (just now, due in 2 days, starts in a day) | 2| Z Lorem ipsum dolorem sit amet. Red @f... lazy:bar (just now, due in 2 days, starts in a day)
| 3| C Foo @Context2 Not@Context +Project1 Not+Project (4 months ago) | 3| C Foo @Context2 Not@Context +Project1 Not+Project (4 months ago)
| 4| C Baz @Context1 +Project1 key:value | 4| C Baz @Context1 +Project1 key:value
...@@ -144,7 +148,7 @@ class ListFormatTest(CommandTest): ...@@ -144,7 +148,7 @@ class ListFormatTest(CommandTest):
command = ListCommand(["-x"], self.todolist, self.out, self.error) command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""| 1| D Bar @Context1 +Project2 (due a month ago, started a month ago) result = """| 1| D Bar @Context1 +Project2 (due a month ago, started a month ago)
| 2| Z Lorem ipsum dolorem sit amet. Red @fox +jumped... lazy:bar (due in 2 days, starts in a day) | 2| Z Lorem ipsum dolorem sit amet. Red @fox +jumped... lazy:bar (due in 2 days, starts in a day)
| 3| C Foo @Context2 Not@Context +Project1 Not+Project | 3| C Foo @Context2 Not@Context +Project1 Not+Project
| 4| C Baz @Context1 +Project1 key:value | 4| C Baz @Context1 +Project1 key:value
...@@ -161,7 +165,7 @@ class ListFormatTest(CommandTest): ...@@ -161,7 +165,7 @@ class ListFormatTest(CommandTest):
command = ListCommand(["-x"], self.todolist, self.out, self.error) command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""2015-08-31 2015-09-30 2015-09-29 result = """2015-08-31 2015-09-30 2015-09-29
2015-11-06 2015-11-08 2015-11-07 2015-11-06 2015-11-08 2015-11-07
2015-07-12 2015-07-12
...@@ -178,7 +182,7 @@ x 2014-12-12 ...@@ -178,7 +182,7 @@ x 2014-12-12
command = ListCommand(["-x"], self.todolist, self.out, self.error) command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""3 months ago | a month ago | a month ago | result = """3 months ago | a month ago | a month ago |
just now | in 2 days | in a day | just now | in 2 days | in a day |
4 months ago | | | 4 months ago | | |
| | | | | |
...@@ -192,7 +196,7 @@ just now | in 2 days | in a day | ...@@ -192,7 +196,7 @@ just now | in 2 days | in a day |
command = ListCommand(["-x"], self.todolist, self.out, self.error) command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""|1| result = """|1|
|2| lazy:bar |2| lazy:bar
|3| |3|
|4| key:value |4| key:value
...@@ -206,7 +210,7 @@ just now | in 2 days | in a day | ...@@ -206,7 +210,7 @@ just now | in 2 days | in a day |
command = ListCommand(["-x"], self.todolist, self.out, self.error) command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""| 1| due:2015-09-30 t:2015-09-29 result = """| 1| due:2015-09-30 t:2015-09-29
| 2| due:2015-11-08 lazy:bar t:2015-11-07 | 2| due:2015-11-08 lazy:bar t:2015-11-07
| 3| | 3|
| 4| key:value | 4| key:value
...@@ -220,7 +224,7 @@ just now | in 2 days | in a day | ...@@ -220,7 +224,7 @@ just now | in 2 days | in a day |
command = ListCommand(["-x"], self.todolist, self.out, self.error) command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""| 1| % result = """| 1| %
| 2| % | 2| %
| 3| % | 3| %
| 4| % | 4| %
...@@ -234,7 +238,7 @@ just now | in 2 days | in a day | ...@@ -234,7 +238,7 @@ just now | in 2 days | in a day |
self.todolist, self.out, self.error) self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29 result = """| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29
| 2| (Z) 2015-11-06 Lorem ipsum dolorem sit amet. Red @fox +jumped over the and jar due:2015-11-08 lazy:bar t:2015-11-07 | 2| (Z) 2015-11-06 Lorem ipsum dolorem sit amet. Red @fox +jumped over the and jar due:2015-11-08 lazy:bar t:2015-11-07
| 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project | 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project
| 4| (C) Baz @Context1 +Project1 key:value | 4| (C) Baz @Context1 +Project1 key:value
...@@ -250,7 +254,7 @@ just now | in 2 days | in a day | ...@@ -250,7 +254,7 @@ just now | in 2 days | in a day |
self.todolist, self.out, self.error) self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29 result = """| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29
| 4| (C) Baz @Context1 +Project1 key:value | 4| (C) Baz @Context1 +Project1 key:value
""" """
...@@ -260,7 +264,7 @@ just now | in 2 days | in a day | ...@@ -260,7 +264,7 @@ just now | in 2 days | in a day |
command = ListCommand(["-x", "-F", "%c"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%c"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""2015-08-31 result = """2015-08-31
2015-11-06 2015-11-06
2015-07-12 2015-07-12
...@@ -273,7 +277,7 @@ just now | in 2 days | in a day | ...@@ -273,7 +277,7 @@ just now | in 2 days | in a day |
command = ListCommand(["-x", "-F", "%C"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%C"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""3 months ago result = """3 months ago
just now just now
4 months ago 4 months ago
...@@ -286,7 +290,7 @@ just now ...@@ -286,7 +290,7 @@ just now
command = ListCommand(["-x", "-F", "%d"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%d"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""2015-09-30 result = """2015-09-30
2015-11-08 2015-11-08
...@@ -299,7 +303,7 @@ just now ...@@ -299,7 +303,7 @@ just now
command = ListCommand(["-x", "-F", "%D"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%D"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""a month ago result = """a month ago
in 2 days in 2 days
...@@ -312,7 +316,7 @@ in 2 days ...@@ -312,7 +316,7 @@ in 2 days
command = ListCommand(["-x", "-F", "%h"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%h"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""due a month ago, started a month ago result = """due a month ago, started a month ago
due in 2 days, starts in a day due in 2 days, starts in a day
...@@ -325,7 +329,7 @@ due in 2 days, starts in a day ...@@ -325,7 +329,7 @@ due in 2 days, starts in a day
command = ListCommand(["-x", "-F", "%H"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%H"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""3 months ago, due a month ago, started a month ago result = """3 months ago, due a month ago, started a month ago
just now, due in 2 days, starts in a day just now, due in 2 days, starts in a day
4 months ago 4 months ago
...@@ -338,7 +342,7 @@ just now, due in 2 days, starts in a day ...@@ -338,7 +342,7 @@ just now, due in 2 days, starts in a day
command = ListCommand(["-x", "-F", "%i"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%i"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""1 result = """1
2 2
3 3
4 4
...@@ -351,7 +355,7 @@ just now, due in 2 days, starts in a day ...@@ -351,7 +355,7 @@ just now, due in 2 days, starts in a day
command = ListCommand(["-x", "-F", "%I"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%I"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u""" 1 result = """ 1
2 2
3 3
4 4
...@@ -364,7 +368,7 @@ just now, due in 2 days, starts in a day ...@@ -364,7 +368,7 @@ just now, due in 2 days, starts in a day
command = ListCommand(["-x", "-F", "%k"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%k"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u""" result = """
lazy:bar lazy:bar
key:value key:value
...@@ -377,7 +381,7 @@ date:2014-12-12 ...@@ -377,7 +381,7 @@ date:2014-12-12
command = ListCommand(["-x", "-F", "%K"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%K"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""due:2015-09-30 t:2015-09-29 result = """due:2015-09-30 t:2015-09-29
due:2015-11-08 lazy:bar t:2015-11-07 due:2015-11-08 lazy:bar t:2015-11-07
key:value key:value
...@@ -390,7 +394,7 @@ date:2014-12-12 ...@@ -390,7 +394,7 @@ date:2014-12-12
command = ListCommand(["-x", "-F", "%p"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%p"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""D result = """D
Z Z
C C
C C
...@@ -419,7 +423,7 @@ Completed but with ...@@ -419,7 +423,7 @@ Completed but with
command = ListCommand(["-x", "-F", "%S"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%S"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""Bar @Context1 +Project2 result = """Bar @Context1 +Project2
Lorem ipsum dolorem sit amet. Red @fox +jumped... Lorem ipsum dolorem sit amet. Red @fox +jumped...
Foo @Context2 Not@Context +Project1 Not+Project Foo @Context2 Not@Context +Project1 Not+Project
Baz @Context1 +Project1 Baz @Context1 +Project1
...@@ -432,7 +436,7 @@ Completed but with ...@@ -432,7 +436,7 @@ Completed but with
command = ListCommand(["-x", "-F", "%t"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%t"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""2015-09-29 result = """2015-09-29
2015-11-07 2015-11-07
...@@ -445,7 +449,7 @@ Completed but with ...@@ -445,7 +449,7 @@ Completed but with
command = ListCommand(["-x", "-F", "%T"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%T"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""a month ago result = """a month ago
in a day in a day
...@@ -458,7 +462,7 @@ in a day ...@@ -458,7 +462,7 @@ in a day
command = ListCommand(["-x", "-F", "%x"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u""" result = """
...@@ -471,7 +475,7 @@ x 2014-12-12 ...@@ -471,7 +475,7 @@ x 2014-12-12
command = ListCommand(["-x", "-F", "%X"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "%X"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u""" result = """
...@@ -484,7 +488,7 @@ x 11 months ago ...@@ -484,7 +488,7 @@ x 11 months ago
command = ListCommand(["-x", "-s", "desc:priority", "-F", "%{{}p{}}"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-s", "desc:priority", "-F", "%{{}p{}}"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""{C} result = """{C}
{C} {C}
{D} {D}
{Z} {Z}
...@@ -497,7 +501,7 @@ x 11 months ago ...@@ -497,7 +501,7 @@ x 11 months ago
command = ListCommand(["-x", "-s", "desc:priority", "-F", "%{\%p}p{\%p}"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-s", "desc:priority", "-F", "%{\%p}p{\%p}"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""%pC%p result = """%pC%p
%pC%p %pC%p
%pD%p %pD%p
%pZ%p %pZ%p
...@@ -510,7 +514,7 @@ x 11 months ago ...@@ -510,7 +514,7 @@ x 11 months ago
command = ListCommand(["-x", "-s", "desc:priority", "-F", "%p%p"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-s", "desc:priority", "-F", "%p%p"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""CC result = """CC
CC CC
DD DD
ZZ ZZ
...@@ -525,7 +529,7 @@ ZZ ...@@ -525,7 +529,7 @@ ZZ
command = ListCommand(["-x", "-s", "desc:priority", "-F", "%p{ } %{ }p"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-s", "desc:priority", "-F", "%p{ } %{ }p"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""C C result = """C C
C C C C
D D D D
Z Z Z Z
...@@ -541,7 +545,7 @@ Z Z ...@@ -541,7 +545,7 @@ Z Z
command = ListCommand(["-x", "-s", "desc:priority", "-F", "%p{ } %{ }p"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-s", "desc:priority", "-F", "%p{ } %{ }p"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""C C result = """C C
C C C C
D D D D
Z Z Z Z
...@@ -556,7 +560,7 @@ Z Z ...@@ -556,7 +560,7 @@ Z Z
command = ListCommand(["-x", "-s", "desc:priority", "-F", " %{ }p"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-s", "desc:priority", "-F", " %{ }p"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u""" C result = """ C
C C
D D
Z Z
...@@ -572,7 +576,7 @@ Z Z ...@@ -572,7 +576,7 @@ Z Z
command = ListCommand(["-x", "-s", "desc:priority", "-F", "%&"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-s", "desc:priority", "-F", "%&"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u""" result = """
...@@ -589,7 +593,7 @@ Z Z ...@@ -589,7 +593,7 @@ Z Z
command = ListCommand(["-x", "-s", "desc:priority", "-F", "%"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-s", "desc:priority", "-F", "%"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u""" result = """
...@@ -606,7 +610,7 @@ Z Z ...@@ -606,7 +610,7 @@ Z Z
command = ListCommand(["-x"], self.todolist, self.out, self.error) command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29 result = """| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29
| 2| (Z) 2015-11-06 Lorem ipsum dolorem sit amet. Red @fox... due:2015-11-08 lazy:bar t:2015-11-07 | 2| (Z) 2015-11-06 Lorem ipsum dolorem sit amet. Red @fox... due:2015-11-08 lazy:bar t:2015-11-07
| 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project | 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project
| 4| (C) Baz @Context1 +Project1 key:value | 4| (C) Baz @Context1 +Project1 key:value
...@@ -622,7 +626,7 @@ Z Z ...@@ -622,7 +626,7 @@ Z Z
command = ListCommand(["-x", "-F", "|%I| %x %{(}p{)} %c %S\\t%K"], self.todolist, self.out, self.error) command = ListCommand(["-x", "-F", "|%I| %x %{(}p{)} %c %S\\t%K"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u"""| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29 result = """| 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29
| 2| (Z) 2015-11-06 Lorem ipsum dolorem sit amet. Red @fox... due:2015-11-08 lazy:bar t:2015-11-07 | 2| (Z) 2015-11-06 Lorem ipsum dolorem sit amet. Red @fox... due:2015-11-08 lazy:bar t:2015-11-07
| 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project | 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project
| 4| (C) Baz @Context1 +Project1 key:value | 4| (C) Baz @Context1 +Project1 key:value
...@@ -639,7 +643,7 @@ Z Z ...@@ -639,7 +643,7 @@ Z Z
command = ListCommand(["-x"], self.todolist, self.out, self.error) command = ListCommand(["-x"], self.todolist, self.out, self.error)
command.execute() command.execute()
result = u""" | 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29 result = """ | 1| (D) 2015-08-31 Bar @Context1 +Project2 due:2015-09-30 t:2015-09-29
| 2| (Z) 2015-11-06 Lorem ipsum dolorem sit amet. Red @... due:2015-11-08 lazy:bar t:2015-11-07 | 2| (Z) 2015-11-06 Lorem ipsum dolorem sit amet. Red @... due:2015-11-08 lazy:bar t:2015-11-07
| 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project | 3| (C) 2015-07-12 Foo @Context2 Not@Context +Project1 Not+Project
| 4| (C) Baz @Context1 +Project1 key:value | 4| (C) Baz @Context1 +Project1 key:value
...@@ -648,5 +652,32 @@ Z Z ...@@ -648,5 +652,32 @@ Z Z
""" """
self.assertEqual(self.output, result) self.assertEqual(self.output, result)
def test_list_format43(self):
command = ListCommand(["-x", "-F", "%P -"], self.todolist, self.out, self.error)
command.execute()
result = """D -
Z -
C -
C -
-
-
"""
self.assertEqual(self.output, result)
def test_list_format44(self):
command = ListCommand(["-x", "-F", "%i %{(}P{)}"], self.todolist, self.out, self.error)
command.execute()
result = """1 (D)
2 (Z)
3 (C)
4 (C)
5 ( )
6 ( )
"""
self.assertEqual(self.output, result)
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 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)
......
...@@ -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",
......
...@@ -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")
......
...@@ -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)
......
...@@ -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):
......
...@@ -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",
......
...@@ -29,7 +29,7 @@ from topydo.lib.TodoListBase import InvalidTodoException, TodoListBase ...@@ -29,7 +29,7 @@ from topydo.lib.TodoListBase import InvalidTodoException, TodoListBase
class TodoListTester(TopydoTest): class TodoListTester(TopydoTest):
def setUp(self): def setUp(self):
super(TodoListTester, self).setUp() super().setUp()
self.todofile = TodoFile('test/data/TodoListTest.txt') self.todofile = TodoFile('test/data/TodoListTest.txt')
lines = [line for line in self.todofile.read() lines = [line for line in self.todofile.read()
...@@ -237,7 +237,7 @@ class TodoListTester(TopydoTest): ...@@ -237,7 +237,7 @@ class TodoListTester(TopydoTest):
class TodoListDependencyTester(TopydoTest): class TodoListDependencyTester(TopydoTest):
def setUp(self): def setUp(self):
super(TodoListDependencyTester, self).setUp() super().setUp()
self.todolist = TodoList([]) self.todolist = TodoList([])
self.todolist.add("Foo id:1") self.todolist.add("Foo id:1")
...@@ -391,7 +391,7 @@ class TodoListCleanDependencyTester(TopydoTest): ...@@ -391,7 +391,7 @@ class TodoListCleanDependencyTester(TopydoTest):
""" """
def setUp(self): def setUp(self):
super(TodoListCleanDependencyTester, self).setUp() super().setUp()
self.todolist = TodoList([]) self.todolist = TodoList([])
def test_clean_dependencies1(self): def test_clean_dependencies1(self):
......
...@@ -52,7 +52,9 @@ append_parent_contexts = 0 ...@@ -52,7 +52,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
......
...@@ -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).
...@@ -81,7 +93,7 @@ def get_subcommand(p_args): ...@@ -81,7 +93,7 @@ def get_subcommand(p_args):
real_subcommand, alias_args = alias_map[p_alias] real_subcommand, alias_args = alias_map[p_alias]
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'])
......
...@@ -41,7 +41,7 @@ class CLIApplication(CLIApplicationBase): ...@@ -41,7 +41,7 @@ class CLIApplication(CLIApplicationBase):
""" """
def __init__(self): def __init__(self):
super(CLIApplication, self).__init__() super().__init__()
def run(self): def run(self):
""" Main entry function. """ """ Main entry function. """
......
...@@ -59,7 +59,7 @@ class PromptApplication(CLIApplicationBase): ...@@ -59,7 +59,7 @@ class PromptApplication(CLIApplicationBase):
""" """
def __init__(self): def __init__(self):
super(PromptApplication, self).__init__() super().__init__()
self._process_flags() self._process_flags()
self.mtime = None self.mtime = None
......
...@@ -34,7 +34,7 @@ class AddCommand(Command): ...@@ -34,7 +34,7 @@ class AddCommand(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(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
...@@ -119,7 +119,7 @@ class AddCommand(Command): ...@@ -119,7 +119,7 @@ class AddCommand(Command):
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))
......
...@@ -24,11 +24,11 @@ class AppendCommand(Command): ...@@ -24,11 +24,11 @@ class AppendCommand(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(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:
......
...@@ -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):
......
...@@ -28,7 +28,7 @@ class DepCommand(Command): ...@@ -28,7 +28,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:
...@@ -109,7 +109,7 @@ class DepCommand(Command): ...@@ -109,7 +109,7 @@ class DepCommand(Command):
self.error(self.usage()) self.error(self.usage())
def execute(self): def execute(self):
if not super(DepCommand, self).execute(): if not super().execute():
return False return False
dispatch = { dispatch = {
......
...@@ -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):
......
...@@ -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
......
...@@ -39,7 +39,7 @@ def _is_edited(p_orig_mtime, p_file): ...@@ -39,7 +39,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:
......
...@@ -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.PrettyPrinter import pretty_printer_factory from topydo.lib.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':
...@@ -69,6 +70,10 @@ class ListCommand(ExpressionCommand): ...@@ -69,6 +70,10 @@ class ListCommand(ExpressionCommand):
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)
...@@ -87,7 +92,7 @@ class ListCommand(ExpressionCommand): ...@@ -87,7 +92,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):
...@@ -127,7 +132,7 @@ class ListCommand(ExpressionCommand): ...@@ -127,7 +132,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:
...@@ -142,7 +147,7 @@ class ListCommand(ExpressionCommand): ...@@ -142,7 +147,7 @@ class ListCommand(ExpressionCommand):
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 <item numbers>] [-N | -n <integer>] [expression]"""
def help(self): def help(self):
return """\ return """\
...@@ -177,6 +182,7 @@ When an expression is given, only the todos matching that expression are shown. ...@@ -177,6 +182,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.
...@@ -193,6 +199,8 @@ When an expression is given, only the todos matching that expression are shown. ...@@ -193,6 +199,8 @@ When an expression is given, only the todos matching that expression are shown.
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.
-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 -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
......
...@@ -26,7 +26,7 @@ class PriorityCommand(MultiCommand): ...@@ -26,7 +26,7 @@ class PriorityCommand(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(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
......
...@@ -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())
......
...@@ -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:
......
...@@ -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
...@@ -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()
......
...@@ -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()
...@@ -58,11 +58,13 @@ class ExpressionCommand(Command): ...@@ -58,11 +58,13 @@ class ExpressionCommand(Command):
is_negated = len(arg) > 1 and arg[0] == '-' is_negated = len(arg) > 1 and arg[0] == '-'
arg = arg[1:] if is_negated else arg arg = arg[1:] if is_negated else arg
if re.match(Filter.ORDINAL_TAG_MATCH, arg): argfilter = None
argfilter = Filter.OrdinalTagFilter(arg) for match, _filter in Filter.MATCHES:
elif re.match(Filter.PRIORITY_MATCH, arg): if re.match(match, arg):
argfilter = Filter.PriorityFilter(arg) argfilter = _filter(arg)
else: break
if not argfilter:
argfilter = Filter.GrepFilter(arg) argfilter = Filter.GrepFilter(arg)
if is_negated: if is_negated:
......
...@@ -62,7 +62,7 @@ class GrepFilter(Filter): ...@@ -62,7 +62,7 @@ class GrepFilter(Filter):
""" Matches when the todo text contains a text. """ """ Matches when the todo text contains a text. """
def __init__(self, p_expression, p_case_sensitive=None): def __init__(self, p_expression, p_case_sensitive=None):
super(GrepFilter, self).__init__() super().__init__()
# convert to string in case we receive integers # convert to string in case we receive integers
self.expression = p_expression self.expression = p_expression
...@@ -115,7 +115,7 @@ class DependencyFilter(Filter): ...@@ -115,7 +115,7 @@ class DependencyFilter(Filter):
Pass on a TodoList instance such that the dependencies can be Pass on a TodoList instance such that the dependencies can be
looked up. looked up.
""" """
super(DependencyFilter, self).__init__() super().__init__()
self.todolist = p_todolist self.todolist = p_todolist
def match(self, p_todo): def match(self, p_todo):
...@@ -138,7 +138,7 @@ class InstanceFilter(Filter): ...@@ -138,7 +138,7 @@ class InstanceFilter(Filter):
This is handy for constructing a view given a plain list of Todo items. This is handy for constructing a view given a plain list of Todo items.
""" """
super(InstanceFilter, self).__init__() super().__init__()
self.todos = p_todos self.todos = p_todos
def match(self, p_todo): def match(self, p_todo):
...@@ -154,20 +154,20 @@ class InstanceFilter(Filter): ...@@ -154,20 +154,20 @@ class InstanceFilter(Filter):
class LimitFilter(Filter): class LimitFilter(Filter):
def __init__(self, p_limit): def __init__(self, p_limit):
super(LimitFilter, self).__init__() super().__init__()
self.limit = p_limit self.limit = p_limit
def filter(self, p_todos): def filter(self, p_todos):
return p_todos[:self.limit] if self.limit >= 0 else p_todos return p_todos[:self.limit] if self.limit >= 0 else p_todos
OPERATOR_MATCH = r"(?P<operator><=?|=|>=?|!)?" _OPERATOR_MATCH = r"(?P<operator><=?|=|>=?|!)?"
class OrdinalFilter(Filter): class OrdinalFilter(Filter):
""" Base class for ordinal filters. """ """ Base class for ordinal filters. """
def __init__(self, p_expression, p_pattern): def __init__(self, p_expression, p_pattern):
super(OrdinalFilter, self).__init__() super().__init__()
self.expression = p_expression self.expression = p_expression
...@@ -200,12 +200,13 @@ class OrdinalFilter(Filter): ...@@ -200,12 +200,13 @@ class OrdinalFilter(Filter):
return False return False
ORDINAL_TAG_MATCH = r"(?P<key>[^:]*):" + OPERATOR_MATCH + r"(?P<value>\S+)" _VALUE_MATCH = r"(?P<value>\S+)"
_ORDINAL_TAG_MATCH = r"(?P<key>[^:]*):" + _OPERATOR_MATCH + _VALUE_MATCH
class OrdinalTagFilter(OrdinalFilter): class OrdinalTagFilter(OrdinalFilter):
def __init__(self, p_expression): def __init__(self, p_expression):
super(OrdinalTagFilter, self).__init__(p_expression, ORDINAL_TAG_MATCH) super().__init__(p_expression, _ORDINAL_TAG_MATCH)
def match(self, p_todo): def match(self, p_todo):
""" """
...@@ -243,12 +244,55 @@ class OrdinalTagFilter(OrdinalFilter): ...@@ -243,12 +244,55 @@ class OrdinalTagFilter(OrdinalFilter):
return self.compare_operands(operand1, operand2) return self.compare_operands(operand1, operand2)
PRIORITY_MATCH = r"\(" + OPERATOR_MATCH + r"(?P<value>[A-Z]{1})\)"
class _DateAttributeFilter(OrdinalFilter):
def __init__(self, p_expression, p_match, p_getter):
super().__init__(p_expression, p_match)
self.getter = p_getter
def match(self, p_todo):
operand1 = self.getter(p_todo)
operand2 = relative_date_to_date(self.value)
if not operand2:
operand2 = date_string_to_date(self.value)
if operand1 and operand2:
return self.compare_operands(operand1, operand2)
else:
return False
_CREATED_MATCH = r'creat(ion|ed?):' + _OPERATOR_MATCH + _VALUE_MATCH
class CreationFilter(_DateAttributeFilter):
def __init__(self, p_expression):
super().__init__(
p_expression,
_CREATED_MATCH,
lambda t: t.creation_date() # pragma: no branch
)
_COMPLETED_MATCH = r'complet(ed?|ion):' + _OPERATOR_MATCH + _VALUE_MATCH
class CompletionFilter(_DateAttributeFilter):
def __init__(self, p_expression):
super().__init__(
p_expression,
_COMPLETED_MATCH,
lambda t: t.completion_date() # pragma: no branch
)
_PRIORITY_MATCH = r"\(" + _OPERATOR_MATCH + r"(?P<value>[A-Z]{1})\)"
class PriorityFilter(OrdinalFilter): class PriorityFilter(OrdinalFilter):
def __init__(self, p_expression): def __init__(self, p_expression):
super(PriorityFilter, self).__init__(p_expression, PRIORITY_MATCH) super().__init__(p_expression, _PRIORITY_MATCH)
def match(self, p_todo): def match(self, p_todo):
""" """
...@@ -265,3 +309,10 @@ class PriorityFilter(OrdinalFilter): ...@@ -265,3 +309,10 @@ class PriorityFilter(OrdinalFilter):
operand2 = p_todo.priority() or 'ZZ' operand2 = p_todo.priority() or 'ZZ'
return self.compare_operands(operand1, operand2) return self.compare_operands(operand1, operand2)
MATCHES = [
(_CREATED_MATCH, CreationFilter),
(_COMPLETED_MATCH, CompletionFilter),
(_ORDINAL_TAG_MATCH, OrdinalTagFilter),
(_PRIORITY_MATCH, PriorityFilter),
]
...@@ -66,7 +66,7 @@ class IcalPrinter(Printer): ...@@ -66,7 +66,7 @@ class IcalPrinter(Printer):
""" """
def __init__(self, p_todolist): def __init__(self, p_todolist):
super(IcalPrinter, self).__init__() super().__init__()
self.todolist = p_todolist self.todolist = p_todolist
try: try:
......
...@@ -52,7 +52,7 @@ class JsonPrinter(Printer): ...@@ -52,7 +52,7 @@ class JsonPrinter(Printer):
""" """
def __init__(self): def __init__(self):
super(JsonPrinter, self).__init__() super().__init__()
def print_todo(self, p_todo): def print_todo(self, p_todo):
return json.dumps(_convert_todo(p_todo), ensure_ascii=False, return json.dumps(_convert_todo(p_todo), ensure_ascii=False,
......
...@@ -152,6 +152,7 @@ class ListFormatParser(object): ...@@ -152,6 +152,7 @@ class ListFormatParser(object):
# relative dates in form: creation, due, start # relative dates in form: creation, due, start
'H': lambda t: humanize_dates(t.due_date(), t.start_date(), t.creation_date()), 'H': lambda t: humanize_dates(t.due_date(), t.start_date(), t.creation_date()),
# todo ID # todo ID
'i': lambda t: str(self.todolist.number(t)), 'i': lambda t: str(self.todolist.number(t)),
...@@ -172,6 +173,9 @@ class ListFormatParser(object): ...@@ -172,6 +173,9 @@ class ListFormatParser(object):
# priority # priority
'p': lambda t: t.priority() if t.priority() else '', 'p': lambda t: t.priority() if t.priority() else '',
# priority (or placeholder space)
'P': lambda t: t.priority() if t.priority() else ' ',
# text # text
's': lambda t: t.text(), 's': lambda t: t.text(),
......
...@@ -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()
......
...@@ -50,7 +50,7 @@ class PrettyPrinter(Printer): ...@@ -50,7 +50,7 @@ class PrettyPrinter(Printer):
""" """
Constructor. Constructor.
""" """
super(PrettyPrinter, self).__init__() super().__init__()
self.filters = [] self.filters = []
def add_filter(self, p_filter): def add_filter(self, p_filter):
......
...@@ -41,7 +41,7 @@ class TodoList(TodoListBase): ...@@ -41,7 +41,7 @@ class TodoList(TodoListBase):
self._tododict = {} # hash(todo) to todo lookup self._tododict = {} # hash(todo) to todo lookup
self._depgraph = DirectedGraph() self._depgraph = DirectedGraph()
super(TodoList, self).__init__(p_todostrings) super().__init__(p_todostrings)
def todo_by_dep_id(self, p_dep_id): def todo_by_dep_id(self, p_dep_id):
""" """
......
...@@ -23,6 +23,12 @@ import re ...@@ -23,6 +23,12 @@ import re
from collections import namedtuple from collections import namedtuple
from datetime import date from datetime import date
# shutil.get_terminal_size was added to the standard library in Python 3.3
try:
from shutil import get_terminal_size as _get_terminal_size # pylint: disable=no-name-in-module
except ImportError:
from backports.shutil_get_terminal_size import get_terminal_size as _get_terminal_size # pylint: disable=import-error
def date_string_to_date(p_date): def date_string_to_date(p_date):
""" """
...@@ -54,15 +60,14 @@ def escape_ansi(p_string): ...@@ -54,15 +60,14 @@ def escape_ansi(p_string):
escape_ansi.pattern = re.compile(r'\x1b[^m]*m') escape_ansi.pattern = re.compile(r'\x1b[^m]*m')
def get_terminal_size(): def get_terminal_size():
""" """
Try to determine terminal size at run time. If that is not possible, Try to determine terminal size at run time. If that is not possible,
returns the default size of 80x24. returns the default size of 80x24.
""" """
from shutil import get_terminal_size # pylint: disable=no-name-in-module
try: try:
sz = get_terminal_size() sz = _get_terminal_size()
except ValueError: except ValueError:
""" """
This can result from the 'underlying buffer being detached', which This can result from the 'underlying buffer being detached', which
......
""" Version of Topydo. """ """ Version of Topydo. """
VERSION = '0.8' VERSION = '0.9'
LICENSE = """Copyright (C) 2014-2015 Bram Schoenmakers LICENSE = """Copyright (C) 2014-2015 Bram Schoenmakers
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
......
...@@ -25,7 +25,7 @@ from topydo.lib.ListFormat import ListFormatParser ...@@ -25,7 +25,7 @@ from topydo.lib.ListFormat import ListFormatParser
class PrettyPrinterFormatFilter(PrettyPrinterFilter): class PrettyPrinterFormatFilter(PrettyPrinterFilter):
def __init__(self, p_todolist, p_format=None): def __init__(self, p_todolist, p_format=None):
super(PrettyPrinterFormatFilter, self).__init__() super().__init__()
self.parser = ListFormatParser(p_todolist, p_format) self.parser = ListFormatParser(p_todolist, p_format)
def filter(self, p_todo_str, p_todo): def filter(self, p_todo_str, p_todo):
......
...@@ -23,7 +23,7 @@ class PrettyPrinterNumbers(PrettyPrinterFilter): ...@@ -23,7 +23,7 @@ class PrettyPrinterNumbers(PrettyPrinterFilter):
""" Prepends the todo's number, retrieved from the todolist. """ """ Prepends the todo's number, retrieved from the todolist. """
def __init__(self, p_todolist): def __init__(self, p_todolist):
super(PrettyPrinterNumbers, self).__init__() super().__init__()
self.todolist = p_todolist self.todolist = p_todolist
def filter(self, p_todo_str, p_todo): def filter(self, p_todo_str, p_todo):
......
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