Commit 8bf0fbb7 authored by Bram Schoenmakers's avatar Bram Schoenmakers

Merge branch 'master' into ls-format

Conflicts:
	setup.py
parents 9a9dda8d f3ae3f46
[run] [run]
source = topydo source = topydo
branch = True
[report] [report]
exclude_lines = exclude_lines =
...@@ -11,5 +12,5 @@ exclude_lines = ...@@ -11,5 +12,5 @@ exclude_lines =
if __name__ == .__main__.: if __name__ == .__main__.:
omit = omit =
topydo/lib/ExitCommand.py topydo/commands/ExitCommand.py
topydo/lib/Version.py topydo/lib/Version.py
...@@ -18,18 +18,13 @@ install: ...@@ -18,18 +18,13 @@ install:
- "pip install ." - "pip install ."
- "pip install .[ical]" - "pip install .[ical]"
- "pip install .[test]" - "pip install .[test]"
- "pip install coveralls" - "pip install codecov"
script: script:
- "green -vvr" - "green -vvr"
- "python -m pylint --errors-only topydo test" - "python -m pylint --errors-only topydo test"
# Cache Dependencies # Cache Dependencies
after_script: after_script:
- if [[ $TRAVIS_PYTHON_VERSION == 3.4 ]]; then - codecov
coveralls;
fi
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then
coveralls;
fi
cache: cache:
directories: directories:
- $HOME/travis/.cache/pip - $HOME/travis/.cache/pip
......
Main author / maintainer: Bram Schoenmakers (@bram85)
For a list of contributors, please refer to the Contributors page on
[Github](https://github.com/bram85/topydo/graphs/contributors).
0.7
---
* New subcommand: `revert`. Revert the last executed command(s). The number of
revisions can be tuned in the configuration file:
[topydo]
backup_count = 25
* New feature: aliases. Aliases can be defined in the configuration file:
[aliases]
showall = ls -x
(thanks to @mruwek)
* Filter based on priorities (thanks to @mruwek)
ls (A)
ls (<A)
* `ls` has a `-n` flag to limit the number of todo items (similar to the
list_limit option in the configuration file:
ls -n 5
* Prompt mode no longer warns about background modifications to todo.txt when a
read-only command is entered (e.g. `ls`).
* Removed restriction in `edit` mode that requires keeping the same amount of
lines in the todo.txt file.
* `edit` only processes the todo items when edits were actually made in the
editor.
* Bugfix: not all tags were properly hidden with the `hide_tags` configuration
option.
* Better PEP8 compliance (thanks to @MinchinWeb)
* Various test/CI improvements (thanks to @MinchinWeb)
* Support for Python 3.2 removed.
* Many other minor improvements (a.o. thanks to @MinchinWeb)
0.6 0.6
--- ---
...@@ -16,7 +54,9 @@ ...@@ -16,7 +54,9 @@
--- ---
* Remove 'ical' subcommand in favor of 'topydo ls -f ical' * Remove 'ical' subcommand in favor of 'topydo ls -f ical'
* Remove options highlight_projects_colors in favor of colorscheme options. In case you wish to disable the project/context colors, assign an empty value in the configuration file: * Remove options highlight_projects_colors in favor of colorscheme options. In
case you wish to disable the project/context colors, assign an empty value in
the configuration file:
[colorscheme] [colorscheme]
project_color = project_color =
......
topydo topydo
====== ======
[![Build Status](https://travis-ci.org/bram85/topydo.svg?branch=master)](https://travis-ci.org/bram85/topydo) [![Coverage Status](https://coveralls.io/repos/bram85/topydo/badge.svg?branch=master&service=github)](https://coveralls.io/github/bram85/topydo?branch=master) [![Join the chat at https://gitter.im/bram85/topydo](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bram85/topydo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=bram85&url=https://github.com/bram85/topydo&title=topydo&language=&tags=github&category=software) [![Build Status](https://travis-ci.org/bram85/topydo.svg?branch=master)](https://travis-ci.org/bram85/topydo) [![codecov.io](https://codecov.io/github/bram85/topydo/coverage.svg?branch=master)](https://codecov.io/github/bram85/topydo?branch=master) [![Join the chat at https://gitter.im/bram85/topydo](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bram85/topydo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=bram85&url=https://github.com/bram85/topydo&title=topydo&language=&tags=github&category=software)
topydo is a todo list application using the [todo.txt format][1]. It is heavily topydo is a todo list application using the [todo.txt format][1]. It is heavily
inspired by the [todo.txt CLI][2] by Gina Trapani. This tool is actually a inspired by the [todo.txt CLI][2] by Gina Trapani. This tool is actually a
......
...@@ -43,8 +43,8 @@ setup( ...@@ -43,8 +43,8 @@ setup(
':python_version=="3.2"': ['backports.shutil_get_terminal_size>=1.0.0'], ':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'],
'edit-cmd-tests': ['mock'],
'test': ['coverage', 'freezegun', 'green', ], 'test': ['coverage', 'freezegun', 'green', ],
'test:python_version=="2.7"': ['mock'],
'test:python_version!="3.2"': ['pylint'], 'test:python_version!="3.2"': ['pylint'],
}, },
entry_points= { entry_points= {
......
[topydo]
colors = junk
[add]
auto_creation_date = junk
[ls]
indent = junk
list_limit = junk
human_readable_dates = junk
[sort]
keep_sorted = junk
ignore_weekends = junk
[dep]
append_parent_projects = junk
append_parent_contexts = junk
[colorscheme]
priority_colors = junk
project_color = junk
context_color = junk
metadata_color = junk
link_color = junk
[colorscheme]
; priority_colors = junk
; project_color = junk
; context_color = junk
; metadata_color = junk
; link_color = junk
Todo item with +project3 @context1
Todo item with +Project2 @Context2
Todo item with +project1 @context3
Todo item with +project1 @context3
Todo item with +Project2 @Context2
Todo item with +project3 @context1
Todo item with +Project2 @Context2
Todo item with +project1 @context3
Todo item with +project3 @context1
...@@ -15,28 +15,130 @@ ...@@ -15,28 +15,130 @@
# 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 unittest import skip
from test.topydo_testcase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib.Config import config from topydo.lib.Config import config
class ConfigTest(TopydoTest): class ConfigTest(TopydoTest):
def test_config1(self): def test_config01(self):
self.assertEqual(config("test/data/config1").default_command(), 'do') self.assertEqual(config("test/data/ConfigTest1.conf").default_command(), 'do')
def test_config2(self): def test_config02(self):
self.assertNotEqual(config("").default_command(), 'do') self.assertNotEqual(config("").default_command(), 'do')
def test_config3(self): def test_config03(self):
self.assertTrue(config("test/data/config2").ignore_weekends()) self.assertTrue(config("test/data/ConfigTest2.conf").ignore_weekends())
def test_config4(self): def test_config04(self):
""" Test that value in file is overridden by parameter. """ """ Test that value in file is overridden by parameter. """
overrides = { overrides = {
('topydo', 'default_command'): 'edit' ('topydo', 'default_command'): 'edit'
} }
self.assertEqual(config("test/data/config1", p_overrides=overrides).default_command(), 'edit') self.assertEqual(config("test/data/ConfigTest1.conf",
p_overrides=overrides).default_command(),
'edit')
def test_config05(self):
""" Bad colour switch value. """
# boolean settings must first be typecast to integers, because all
# strings evaulate to 'True'
self.assertEqual(config("test/data/ConfigTest4.conf").colors(),
bool(int(config().defaults["topydo"]["colors"])))
def test_config06(self):
""" Bad auto creation date switch value. """
self.assertEqual(config("test/data/ConfigTest4.conf").auto_creation_date(),
bool(int(config().defaults["add"]["auto_creation_date"])))
def test_config07(self):
""" Bad indent value. """
self.assertEqual(config("test/data/ConfigTest4.conf").list_indent(),
int(config().defaults["ls"]["indent"]))
def test_config08(self):
""" Bad list limit value. """
self.assertEqual(config("test/data/ConfigTest4.conf").list_limit(),
int(config().defaults["ls"]["list_limit"]))
def test_config10(self):
""" Bad keep sorted switch value. """
self.assertEqual(config("test/data/ConfigTest4.conf").keep_sorted(),
bool(int(config().defaults["sort"]["keep_sorted"])))
def test_config11(self):
""" Bad ignore weekends switch value. """
self.assertEqual(config("test/data/ConfigTest4.conf").ignore_weekends(),
bool(int(config().defaults["sort"]["ignore_weekends"])))
def test_config12(self):
""" Bad append parent projects switch value. """
self.assertEqual(config("test/data/ConfigTest4.conf").append_parent_projects(),
bool(int(config().defaults["dep"]["append_parent_projects"])))
def test_config13(self):
""" Bad append parent project contexts switch value. """
self.assertEqual(config("test/data/ConfigTest4.conf").append_parent_contexts(),
bool(int(config().defaults["dep"]["append_parent_contexts"])))
@skip("Error checking not yet implemented")
def test_config14(self):
""" Bad priority color value. """
self.assertEqual(config("test/data/ConfigTest4.conf").priority_colors(),
config().defaults["colorscheme"]["priority_colors"])
@skip("Error checking not yet implemented")
def test_config15(self):
""" Bad project color value. """
self.assertEqual(config("test/data/ConfigTest4.conf").project_color(),
config().defaults["colorscheme"]["project_color"])
@skip("Error checking not yet implemented")
def test_config16(self):
""" Bad context color value. """
self.assertEqual(config("test/data/ConfigTest4.conf").context_color(),
config().defaults["colorscheme"]["context_color"])
@skip("Error checking not yet implemented")
def test_config17(self):
""" Bad metadata color value. """
self.assertEqual(config("test/data/ConfigTest4.conf").metadata_color(),
config().defaults["colorscheme"]["metadata_color"])
@skip("Error checking not yet implemented")
def test_config18(self):
""" Bad link color value. """
self.assertEqual(config("test/data/ConfigTest4.conf").link_color(),
config().defaults["colorscheme"]["link_color"])
@skip("Test not yet implemented")
# the test needs to be of the internal function _str_to_dict
def test_config19(self):
""" No priority color value. """
self.assertEqual(config("test/data/ConfigTest4.conf").priority_colors(),
config().defaults["colorscheme"]["priority_colors"])
def test_config20(self):
""" No project color value. """
self.assertEqual(config("test/data/ConfigTest5.conf").project_color(),
config().defaults["colorscheme"]["project_color"])
def test_config21(self):
""" No context color value. """
self.assertEqual(config("test/data/ConfigTest5.conf").context_color(),
config().defaults["colorscheme"]["context_color"])
def test_config22(self):
""" No metadata color value. """
self.assertEqual(config("test/data/ConfigTest5.conf").metadata_color(),
config().defaults["colorscheme"]["metadata_color"])
def test_config23(self):
""" No link color value. """
self.assertEqual(config("test/data/ConfigTest5.conf").link_color(),
config().defaults["colorscheme"]["link_color"])
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -198,5 +198,14 @@ class EditCommandTest(CommandTest): ...@@ -198,5 +198,14 @@ class EditCommandTest(CommandTest):
self.assertEqual(self.todolist.print_todos(), result) self.assertEqual(self.todolist.print_todos(), result)
mock_call.assert_called_once_with([editor, todotxt]) mock_call.assert_called_once_with([editor, todotxt])
def test_help(self):
command = EditCommand(["help"], self.todolist, self.out, self.error,
None)
command.execute()
self.assertEqual(self.output, "")
self.assertEqual(self.errors,
command.usage() + "\n\n" + command.help() + "\n")
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -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 os import os
import tempfile
import unittest import unittest
from datetime import date from datetime import date
...@@ -47,8 +48,8 @@ class RevertCommandTest(CommandTest): ...@@ -47,8 +48,8 @@ class RevertCommandTest(CommandTest):
self.tmp_name = str(uuid4().hex.upper()[0:6]) self.tmp_name = str(uuid4().hex.upper()[0:6])
archive_filename = '/tmp/' + self.tmp_name + '_archive' archive_filename = tempfile.gettempdir() + os.sep + self.tmp_name + '_archive'
todo_filename = '/tmp/' + self.tmp_name + '_todo' todo_filename = tempfile.gettempdir() + os.sep + self.tmp_name + '_todo'
config(p_overrides={('topydo', 'archive_filename'): archive_filename, config(p_overrides={('topydo', 'archive_filename'): archive_filename,
('topydo', 'filename'): todo_filename, ('topydo', 'backup_count'): '5'}) ('topydo', 'filename'): todo_filename, ('topydo', 'backup_count'): '5'})
......
...@@ -170,5 +170,24 @@ class SorterTest(TopydoTest): ...@@ -170,5 +170,24 @@ class SorterTest(TopydoTest):
self.assertEqual(print_view(view), todolist_to_string(result)) self.assertEqual(print_view(view), todolist_to_string(result))
def test_sort17(self):
"""
Check sorting by project.
"""
sorter = Sorter('project')
self.sort_file('test/data/SorterTest13.txt',
'test/data/SorterTest13-result-project.txt', sorter)
def test_sort18(self):
"""
Check sorting by context.
"""
sorter = Sorter('context')
self.sort_file('test/data/SorterTest13.txt',
'test/data/SorterTest13-result-context.txt', sorter)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -5,7 +5,8 @@ default_command = ls ...@@ -5,7 +5,8 @@ default_command = ls
; filename = todo.txt ; filename = todo.txt
; archive_filename = done.txt ; archive_filename = done.txt
colors = 1 colors = 1
identifiers = linenumber ; or: text ; identifiers can be 'linenumber' or 'text'
identifiers = linenumber
backup_count = 5 backup_count = 5
[add] [add]
......
...@@ -38,6 +38,8 @@ def get_field_function(p_field): ...@@ -38,6 +38,8 @@ def get_field_function(p_field):
if is_priority_field(p_field): if is_priority_field(p_field):
# assign dummy priority when a todo has no priority # assign dummy priority when a todo has no priority
result = lambda a: a.priority() or 'ZZ' result = lambda a: a.priority() or 'ZZ'
elif p_field == 'context' or p_field == 'contexts':
result = lambda a: sorted([c.lower() for c in a.contexts()])
elif p_field == 'creationdate' or p_field == 'creation': elif p_field == 'creationdate' or p_field == 'creation':
# when a task has no creation date, push it to the end by assigning it # when a task has no creation date, push it to the end by assigning it
# the maximum possible date. # the maximum possible date.
...@@ -50,6 +52,8 @@ def get_field_function(p_field): ...@@ -50,6 +52,8 @@ def get_field_function(p_field):
result = importance result = importance
elif p_field == 'importance-avg' or p_field == 'importance-average': elif p_field == 'importance-avg' or p_field == 'importance-average':
result = average_importance result = average_importance
elif p_field == 'project' or p_field == 'projects':
result = lambda a: sorted([c.lower() for c in a.projects()])
elif p_field == 'text': elif p_field == 'text':
result = lambda a: a.text() result = lambda a: a.text()
else: else:
......
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