Commit 68f9288d authored by Bram Schoenmakers's avatar Bram Schoenmakers

Merge branch 'master' into stable

parents 40b96592 41e534bf
language: python
python:
- "2.7"
- "3.2"
- "3.3"
- "3.4"
install:
- "pip install ."
- "pip install icalendar"
- "pip install pylint"
script: "python setup.py test && pylint --errors-only topydo test"
script: "./run-tests.sh"
notifications:
webhooks:
urls:
......
0.4
---
* A new prompt mode with autocompletion. To enable, run `pip install
prompt-toolkit`, then `topydo prompt`.
* Support for Python 3.2, 3.3 and 3.4 (note that iCalendar output does not
work in Python 3.2)
* Better Unicode support.
* `add` command has the `-f` flag to add todo items from a file (or use `-` to
read from standard input) (Jacek Sowiński - @mruwek)
* Customizable colors + additional highlighting of tags and URLs (Jacek
Sowiński (@mruwek) and @kidpixo).
* Make sure that the `edit` subcommand always uses the correct todo.txt file.
* `ls` subcommand has the `-f` flag to specify the output format. Currently,
three formats are supported:
* `text` - The default plain text format.
* `ical` - iCalendar (WARNING: this deprecates the `ical` subcommand)
* `json` - Javascript Object Notation (JSON)
* Resolve `~` to home directory if used in a configuration file
(@robertvanbregt).
* Various minor fixes.
Again, I'd like to thank Jacek (@mruwek) for his assistance and contributions
in this release.
0.3.2
-----
......@@ -27,7 +52,7 @@
* Fix assignment of dependency IDs: in some cases two distinct todos get the
same dependency ID.
Big thanks to Jacek for his contributions in this release.
Big thanks to Jacek (@mruwek) for his contributions in this release.
0.2
---
......
If you're reading this, you may have interest in enhancing topydo. Thank you!
Please read the following guidelines to get your enhancement / bug fixes smoothly into topydo:
Please read the following guidelines to get your enhancement / bug fixes
smoothly into topydo:
* This Github page defaults to the **stable** branch which is for **bug fixes only**. If you would like to add a new
feature, make sure to make a Pull Request on the `master` branch.
* This Github page defaults to the **stable** branch which is for **bug fixes
only**. If you would like to add a new feature, make sure to make a Pull
Request on the `master` branch.
* Run tests with:
python2 setup.py test
python3 setup.py test
Obviously, I won't accept anything that makes the tests fail. When you submit a Pull Request, Travis CI will
automatically run all tests for various Python versions, but it's better if you run the tests locally first.
Make sure you have the `mock` package installed if you test on a Python version older than 3.3.
./run-tests.sh [python2|python3]
Obviously, I won't accept anything that makes the tests fail. When you submit
a Pull Request, Travis CI will automatically run all tests for various Python
versions, but it's better if you run the tests locally first.
Make sure you have the `mock` package installed if you test on a Python
version older than 3.3.
* Add tests for your change(s):
* Bugfixes: add a testcase that covers your bugfix, so the bug won't happen ever again.
* Features: add testcases that checks various inputs and outputs of your feature. Be creative in trying to break the
feature you've just implemented.
* Bugfixes: add a testcase that covers your bugfix, so the bug won't happen
ever again.
* Features: add testcases that checks various inputs and outputs of your
feature. Be creative in trying to break the feature you've just implemented.
* Use descriptive commit messages.
### Coding style
* Please try to adhere to the coding style dictated by `pylint` as much possible. I won't be very picky about long lines,
but please try to avoid them.
* I strongly prefer simple and short functions, doing only one thing. I'll request you to refactor functions with
massive indentation or don't fit otherwise on a screen.
* Please try to adhere to the coding style dictated by `pylint` as much
possible. I won't be very picky about long lines, but please try to avoid
them.
* I strongly prefer simple and short functions, doing only one thing. I'll
request you to refactor functions with massive indentation or don't fit
otherwise on a screen.
#!/bin/bash
if [ "$1" = "python2" ] || [ "$1" = "python3" ]; then
PYTHON=$1
else
# run whatever is active
PYTHON=python
fi
# Run normal tests
if ! $PYTHON setup.py test; then
exit 1
fi
# pylint is not supported on 3.2, so skip the test there
if $PYTHON --version 2>&1 | grep 'Python 3\.2' > /dev/null; then
exit 0
fi
if ! $PYTHON -m pylint --errors-only topydo test; then
exit 1
fi
exit 0
[bdist_wheel]
universal = 1
from setuptools import setup
from setuptools import setup, find_packages
setup(
name = "topydo",
packages = ["topydo", "topydo.lib", "topydo.cli"],
version = "0.3.2",
packages = find_packages(exclude=["test"]),
version = "0.4",
description = "A command-line todo list application using the todo.txt format.",
author = "Bram Schoenmakers",
author_email = "me@bramschoenmakers.nl",
url = "https://github.com/bram85/topydo",
install_requires = [
'six >= 1.9.0',
],
extras_require = {
'ical': ['icalendar'],
'prompt-toolkit': ['prompt-toolkit >= 0.37'],
'edit-cmd-tests': ['mock'],
},
entry_points= {
'console_scripts': ['topydo = topydo.cli.Main:main'],
'console_scripts': ['topydo = topydo.cli.UILoader:main'],
},
classifiers = [
"Development Status :: 4 - Beta",
......@@ -22,6 +26,9 @@ setup(
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
"Natural Language :: English",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.2",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Topic :: Utilities",
],
long_description = """\
......
This diff is collapsed.
......@@ -16,11 +16,11 @@
import unittest
from topydo.lib.AppendCommand import AppendCommand
import CommandTest
from topydo.commands.AppendCommand import AppendCommand
from test.CommandTest import CommandTest
from topydo.lib.TodoList import TodoList
class AppendCommandTest(CommandTest.CommandTest):
class AppendCommandTest(CommandTest):
def setUp(self):
super(AppendCommandTest, self).setUp()
self.todolist = TodoList([])
......@@ -79,8 +79,8 @@ class AppendCommandTest(CommandTest.CommandTest):
command = AppendCommand(["help"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output, "")
self.assertEquals(self.errors, command.usage() + "\n\n" + command.help() + "\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n\n" + command.help() + "\n")
if __name__ == '__main__':
unittest.main()
......@@ -16,14 +16,14 @@
import unittest
from topydo.lib.ArchiveCommand import ArchiveCommand
import CommandTest
import TestFacilities
from topydo.commands.ArchiveCommand import ArchiveCommand
from test.CommandTest import CommandTest
from test.TestFacilities import load_file_to_todolist
from topydo.lib.TodoList import TodoList
class ArchiveCommandTest(CommandTest.CommandTest):
class ArchiveCommandTest(CommandTest):
def test_archive(self):
todolist = TestFacilities.load_file_to_todolist("test/data/ArchiveCommandTest.txt")
todolist = load_file_to_todolist("test/data/ArchiveCommandTest.txt")
archive = TodoList([])
command = ArchiveCommand(todolist, archive)
......@@ -31,8 +31,8 @@ class ArchiveCommandTest(CommandTest.CommandTest):
self.assertTrue(todolist.is_dirty())
self.assertTrue(archive.is_dirty())
self.assertEquals(str(todolist), "x Not complete\n(C) Active")
self.assertEquals(str(archive), "x 2014-10-19 Complete\nx 2014-10-20 Another one complete")
self.assertEqual(str(todolist), "x Not complete\n(C) Active")
self.assertEqual(str(archive), "x 2014-10-19 Complete\nx 2014-10-20 Another one complete")
if __name__ == '__main__':
unittest.main()
......
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
""" Tests for the colorscheme functionality. """
import unittest
from topydo.lib.Colors import Colors, NEUTRAL_COLOR
from topydo.lib.Config import config
from test.TopydoTest import TopydoTest
class ColorsTest(TopydoTest):
def test_project_color1(self):
config(p_overrides={('colorscheme', 'project_color'): '2'})
color = Colors().get_project_color()
self.assertEqual(color, '\033[1;38;5;2m')
def test_project_color2(self):
config(p_overrides={('colorscheme', 'project_color'): 'Foo'})
color = Colors().get_project_color()
self.assertEqual(color, NEUTRAL_COLOR)
def test_project_color3(self):
config(p_overrides={('colorscheme', 'project_color'): 'yellow'})
color = Colors().get_project_color()
self.assertEqual(color, '\033[1;33m')
def test_project_color4(self):
config(p_overrides={('colorscheme', 'project_color'): '686'})
color = Colors().get_project_color()
self.assertEqual(color, NEUTRAL_COLOR)
def test_context_color1(self):
config(p_overrides={('colorscheme', 'context_color'): '35'})
color = Colors().get_context_color()
self.assertEqual(color, '\033[1;38;5;35m')
def test_context_color2(self):
config(p_overrides={('colorscheme', 'context_color'): 'Bar'})
color = Colors().get_context_color()
self.assertEqual(color, NEUTRAL_COLOR)
def test_context_color3(self):
config(p_overrides={('colorscheme', 'context_color'): 'magenta'})
color = Colors().get_context_color()
self.assertEqual(color, '\033[1;35m')
def test_context_color4(self):
config(p_overrides={('colorscheme', 'context_color'): '392'})
color = Colors().get_context_color()
self.assertEqual(color, NEUTRAL_COLOR)
def test_metadata_color1(self):
config(p_overrides={('colorscheme', 'metadata_color'): '128'})
color = Colors().get_metadata_color()
self.assertEqual(color, '\033[1;38;5;128m')
def test_metadata_color2(self):
config(p_overrides={('colorscheme', 'metadata_color'): 'Baz'})
color = Colors().get_metadata_color()
self.assertEqual(color, NEUTRAL_COLOR)
def test_metadata_color3(self):
config(p_overrides={('colorscheme', 'metadata_color'): 'light-red'})
color = Colors().get_metadata_color()
self.assertEqual(color, '\033[1;1;31m')
def test_metadata_color4(self):
config(p_overrides={('colorscheme', 'metadata_color'): '777'})
color = Colors().get_metadata_color()
self.assertEqual(color, NEUTRAL_COLOR)
def test_link_color1(self):
config(p_overrides={('colorscheme', 'link_color'): '77'})
color = Colors().get_link_color()
self.assertEqual(color, '\033[4;38;5;77m')
def test_link_color2(self):
config(p_overrides={('colorscheme', 'link_color'): 'FooBar'})
color = Colors().get_link_color()
self.assertEqual(color, NEUTRAL_COLOR)
def test_link_color3(self):
config(p_overrides={('colorscheme', 'link_color'): 'red'})
color = Colors().get_link_color()
self.assertEqual(color, '\033[4;31m')
def test_link_color4(self):
config(p_overrides={('colorscheme', 'link_color'): '777'})
color = Colors().get_link_color()
self.assertEqual(color, NEUTRAL_COLOR)
def test_priority_color1(self):
config("test/data/ColorsTest1.conf")
color = Colors().get_priority_colors()
self.assertEqual(color['A'], '\033[0;38;5;1m')
self.assertEqual(color['B'], '\033[0;38;5;2m')
self.assertEqual(color['C'], '\033[0;38;5;3m')
def test_priority_color2(self):
config("test/data/ColorsTest2.conf")
color = Colors().get_priority_colors()
self.assertEqual(color['A'], '\033[0;35m')
self.assertEqual(color['B'], '\033[0;1;36m')
self.assertEqual(color['C'], '\033[0;37m')
def test_priority_color3(self):
config("test/data/ColorsTest3.conf")
color = Colors().get_priority_colors()
self.assertEqual(color['A'], '\033[0;35m')
self.assertEqual(color['B'], '\033[0;1;36m')
self.assertEqual(color['Z'], NEUTRAL_COLOR)
self.assertEqual(color['D'], '\033[0;31m')
self.assertEqual(color['C'], '\033[0;38;5;7m')
def test_priority_color4(self):
config("test/data/ColorsTest4.conf")
color = Colors().get_priority_colors()
self.assertEqual(color['A'], NEUTRAL_COLOR)
self.assertEqual(color['B'], NEUTRAL_COLOR)
self.assertEqual(color['C'], NEUTRAL_COLOR)
def test_empty_color_values(self):
config("test/data/ColorsTest5.conf")
pri_color = Colors().get_priority_colors()
project_color = Colors().get_project_color()
context_color = Colors().get_context_color()
link_color = Colors().get_link_color()
metadata_color = Colors().get_metadata_color()
self.assertEqual(pri_color['A'], NEUTRAL_COLOR)
self.assertEqual(pri_color['B'], NEUTRAL_COLOR)
self.assertEqual(pri_color['C'], NEUTRAL_COLOR)
self.assertEqual(project_color, '')
self.assertEqual(context_color, '')
self.assertEqual(link_color, '')
self.assertEqual(metadata_color, '')
def test_empty_colorscheme(self):
config("test/data/config1")
pri_color = Colors().get_priority_colors()
project_color = Colors().get_project_color()
context_color = Colors().get_context_color()
link_color = Colors().get_link_color()
metadata_color = Colors().get_metadata_color()
self.assertEqual(pri_color['A'], '\033[0;36m')
self.assertEqual(pri_color['B'], '\033[0;33m')
self.assertEqual(pri_color['C'], '\033[0;34m')
self.assertEqual(project_color, '\033[1;31m')
self.assertEqual(context_color, '\033[1;35m')
self.assertEqual(link_color, '\033[4;36m')
self.assertEqual(metadata_color, '\033[1;32m')
......@@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
from six import PY2
from topydo.lib.Utils import escape_ansi
from test.TopydoTest import TopydoTest
......@@ -33,5 +34,13 @@ class CommandTest(TopydoTest):
if p_error:
self.errors += escape_ansi(p_error + "\n")
# utility for several commands
def utf8(p_string):
""" Converts a Unicode string to UTF-8 in case of Python 2. """
if PY2:
p_string = p_string.encode('utf-8')
return p_string
if __name__ == '__main__':
unittest.main()
......@@ -21,13 +21,21 @@ from test.TopydoTest import TopydoTest
class ConfigTest(TopydoTest):
def test_config1(self):
self.assertEquals(config("test/data/config1").default_command(), 'do')
self.assertEqual(config("test/data/config1").default_command(), 'do')
def test_config2(self):
self.assertNotEquals(config("").default_command(), 'do')
self.assertNotEqual(config("").default_command(), 'do')
def test_config3(self):
self.assertTrue(config("test/data/config2").ignore_weekends())
def test_config4(self):
""" Test that value in file is overridden by parameter. """
overrides = {
('topydo', 'default_command'): 'edit'
}
self.assertEqual(config("test/data/config1", p_overrides=overrides).default_command(), 'edit')
if __name__ == '__main__':
unittest.main()
......@@ -15,10 +15,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
from six import u
import CommandTest
from test.CommandTest import CommandTest
from topydo.lib.Config import config
from topydo.lib.DeleteCommand import DeleteCommand
from topydo.commands.DeleteCommand import DeleteCommand
from topydo.lib.TodoList import TodoList
from topydo.lib.TodoListBase import InvalidTodoException
......@@ -28,7 +29,7 @@ def _yes_prompt(self):
def _no_prompt(self):
return "n"
class DeleteCommandTest(CommandTest.CommandTest):
class DeleteCommandTest(CommandTest):
def setUp(self):
super(DeleteCommandTest, self).setUp()
todos = [
......@@ -43,79 +44,79 @@ class DeleteCommandTest(CommandTest.CommandTest):
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.todolist.todo(1).source(), "Bar")
self.assertEquals(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n")
self.assertEquals(self.errors, "")
self.assertEqual(self.todolist.todo(1).source(), "Bar")
self.assertEqual(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n")
self.assertEqual(self.errors, "")
def test_del1_regex(self):
command = DeleteCommand(["Foo"], self.todolist, self.out, self.error, _no_prompt)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.todolist.todo(1).source(), "Bar")
self.assertEquals(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n")
self.assertEquals(self.errors, "")
self.assertEqual(self.todolist.todo(1).source(), "Bar")
self.assertEqual(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n")
self.assertEqual(self.errors, "")
def test_del2(self):
command = DeleteCommand(["1"], self.todolist, self.out, self.error, _yes_prompt)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.todolist.count(), 0)
self.assertEquals(self.output, "| 2| Bar p:1\nRemoved: Bar\nRemoved: Foo\n")
self.assertEquals(self.errors, "")
self.assertEqual(self.todolist.count(), 0)
self.assertEqual(self.output, "| 2| Bar p:1\nRemoved: Bar\nRemoved: Foo\n")
self.assertEqual(self.errors, "")
def test_del3(self):
command = DeleteCommand(["-f", "1"], self.todolist, self.out, self.error, _yes_prompt)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.todolist.count(), 1) # force won't delete subtasks
self.assertEquals(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n")
self.assertEquals(self.errors, "")
self.assertEqual(self.todolist.count(), 1) # force won't delete subtasks
self.assertEqual(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n")
self.assertEqual(self.errors, "")
def test_del4(self):
command = DeleteCommand(["--force", "1"], self.todolist, self.out, self.error, _yes_prompt)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.todolist.count(), 1) # force won't delete subtasks
self.assertEquals(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n")
self.assertEquals(self.errors, "")
self.assertEqual(self.todolist.count(), 1) # force won't delete subtasks
self.assertEqual(self.output, "| 2| Bar p:1\nRemoved: Foo id:1\n")
self.assertEqual(self.errors, "")
def test_del5(self):
command = DeleteCommand(["2"], self.todolist, self.out, self.error)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.todolist.todo(1).source(), "Foo")
self.assertEquals(self.output, "Removed: Bar p:1\nThe following todo item(s) became active:\n| 1| Foo\n")
self.assertEquals(self.errors, "")
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.errors, "")
def test_del7(self):
command = DeleteCommand(["99"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Invalid todo number given.\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given.\n")
def test_del8(self):
command = DeleteCommand(["A"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Invalid todo number given.\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given.\n")
def test_del9(self):
""" Test deletion with textual IDs. """
config("test/data/todolist-uid.conf")
command = DeleteCommand(["b0n"], self.todolist, self.out, self.error)
command = DeleteCommand(["8to"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(str(self.todolist), "Foo")
self.assertEqual(str(self.todolist), "Foo")
self.assertRaises(InvalidTodoException, self.todolist.todo, 'b0n')
def test_multi_del1(self):
......@@ -123,14 +124,14 @@ class DeleteCommandTest(CommandTest.CommandTest):
command = DeleteCommand(["1", "2"], self.todolist, self.out, self.error, _no_prompt)
command.execute()
self.assertEquals(self.todolist.count(), 0)
self.assertEqual(self.todolist.count(), 0)
def test_multi_del2(self):
""" Test deletion of multiple items. """
command = DeleteCommand(["1", "2"], self.todolist, self.out, self.error, _yes_prompt)
command.execute()
self.assertEquals(self.todolist.count(), 0)
self.assertEqual(self.todolist.count(), 0)
def test_multi_del3(self):
""" Fail if any of supplied todo numbers is invalid. """
......@@ -138,8 +139,8 @@ class DeleteCommandTest(CommandTest.CommandTest):
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Invalid todo number given: 99.\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given: 99.\n")
def test_multi_del4(self):
""" Check output when all supplied todo numbers are invalid. """
......@@ -147,8 +148,17 @@ class DeleteCommandTest(CommandTest.CommandTest):
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Invalid todo number given: 99.\nInvalid todo number given: A.\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given: 99.\nInvalid todo number given: A.\n")
def test_multi_del5(self):
""" Throw an error with invalid argument containing special characters. """
command = DeleteCommand([u("Fo\u00d3B\u0105r"), "Bar"], self.todolist, self.out, self.error, None)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEqual(self.output, "")
self.assertEqual(self.errors, u("Invalid todo number given: Fo\u00d3B\u0105r.\n"))
def test_empty(self):
command = DeleteCommand([], self.todolist, self.out, self.error)
......@@ -156,14 +166,14 @@ class DeleteCommandTest(CommandTest.CommandTest):
self.assertFalse(self.todolist.is_dirty())
self.assertFalse(self.output)
self.assertEquals(self.errors, command.usage() + "\n")
self.assertEqual(self.errors, command.usage() + "\n")
def test_help(self):
command = DeleteCommand(["help"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output, "")
self.assertEquals(self.errors, command.usage() + "\n\n" + command.help() + "\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n\n" + command.help() + "\n")
if __name__ == '__main__':
unittest.main()
......@@ -16,11 +16,11 @@
import unittest
import CommandTest
from topydo.lib.DepCommand import DepCommand
from topydo.commands.DepCommand import DepCommand
from test.CommandTest import CommandTest
from topydo.lib.TodoList import TodoList
class DepCommandTest(CommandTest.CommandTest):
class DepCommandTest(CommandTest):
def setUp(self):
super(DepCommandTest, self).setUp()
todos = [
......@@ -40,8 +40,8 @@ class DepCommandTest(CommandTest.CommandTest):
self.assertTrue(self.todolist.is_dirty())
self.assertTrue(self.todolist.todo(4).has_tag('p', '1'))
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "")
def test_add2(self):
command = DepCommand(["add", "1", "4"], self.todolist, self.out, self.error)
......@@ -49,32 +49,32 @@ class DepCommandTest(CommandTest.CommandTest):
self.assertTrue(self.todolist.is_dirty())
self.assertTrue(self.todolist.todo(4).has_tag('p', '1'))
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "")
def test_add3(self):
command = DepCommand(["add", "99", "3"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Invalid todo number given.\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given.\n")
def test_add4(self):
command = DepCommand(["add", "A", "3"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Invalid todo number given.\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given.\n")
def test_add5(self):
command = DepCommand(["add", "1"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, command.usage() + "\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n")
def test_add6(self):
command = DepCommand(["add", "1", "after", "4"], self.todolist, self.out, self.error)
......@@ -82,8 +82,8 @@ class DepCommandTest(CommandTest.CommandTest):
self.assertTrue(self.todolist.is_dirty())
self.assertTrue(self.todolist.todo(4).has_tag('p', '1'))
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "")
def test_add7(self):
command = DepCommand(["add", "1", "before", "4"], self.todolist, self.out, self.error)
......@@ -91,8 +91,8 @@ class DepCommandTest(CommandTest.CommandTest):
self.assertTrue(self.todolist.is_dirty())
self.assertTrue(self.todolist.todo(1).has_tag('p', '2'))
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "")
def test_add8(self):
command = DepCommand(["add", "1", "partof", "4"], self.todolist, self.out, self.error)
......@@ -100,8 +100,8 @@ class DepCommandTest(CommandTest.CommandTest):
self.assertTrue(self.todolist.is_dirty())
self.assertTrue(self.todolist.todo(1).has_tag('p', '2'))
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "")
def test_add9(self):
command = DepCommand(["add", "Foo", "to", "4"], self.todolist, self.out, self.error)
......@@ -109,8 +109,8 @@ class DepCommandTest(CommandTest.CommandTest):
self.assertTrue(self.todolist.is_dirty())
self.assertTrue(self.todolist.todo(4).has_tag('p', '1'))
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "")
def rm_helper(self, p_args):
"""
......@@ -124,8 +124,8 @@ class DepCommandTest(CommandTest.CommandTest):
self.assertTrue(self.todolist.is_dirty())
self.assertTrue(self.todolist.todo(1).has_tag('id', '1'))
self.assertFalse(self.todolist.todo(3).has_tag('p', '1'))
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "")
def test_rm1(self):
self.rm_helper(["rm", "1", "to", "3"])
......@@ -144,64 +144,64 @@ class DepCommandTest(CommandTest.CommandTest):
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Invalid todo number given.\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given.\n")
def test_rm4(self):
command = DepCommand(["rm", "A", "3"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Invalid todo number given.\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given.\n")
def test_rm5(self):
command = DepCommand(["rm", "1"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, command.usage() + "\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n")
def test_ls1(self):
command = DepCommand(["ls", "1", "to"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "| 2| Bar p:1\n| 3| Baz p:1\n")
self.assertEquals(self.errors, "")
self.assertEqual(self.output, "| 2| Bar p:1\n| 3| Baz p:1\n")
self.assertEqual(self.errors, "")
def test_ls2(self):
command = DepCommand(["ls", "99", "to"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Invalid todo number given.\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given.\n")
def test_ls3(self):
command = DepCommand(["ls", "to", "3"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "| 1| Foo id:1\n")
self.assertEquals(self.errors, "")
self.assertEqual(self.output, "| 1| Foo id:1\n")
self.assertEqual(self.errors, "")
def test_ls4(self):
command = DepCommand(["ls", "to", "99"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Invalid todo number given.\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "Invalid todo number given.\n")
def test_ls5(self):
command = DepCommand(["ls", "1"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, command.usage() + "\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n")
def test_ls6(self):
command = DepCommand(["ls"], self.todolist, self.out, self.error)
......@@ -209,7 +209,7 @@ class DepCommandTest(CommandTest.CommandTest):
self.assertFalse(self.todolist.is_dirty())
self.assertFalse(self.output)
self.assertEquals(self.errors, command.usage() + "\n")
self.assertEqual(self.errors, command.usage() + "\n")
def gc_helper(self, p_subcommand):
command = DepCommand([p_subcommand], self.todolist, self.out, self.error)
......@@ -246,8 +246,8 @@ class DepCommandTest(CommandTest.CommandTest):
command = DepCommand(["help"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output, "")
self.assertEquals(self.errors, command.usage() + "\n\n" + command.help() + "\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n\n" + command.help() + "\n")
if __name__ == '__main__':
unittest.main()
......@@ -15,12 +15,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
from six import u
import CommandTest
from topydo.lib.DepriCommand import DepriCommand
from topydo.commands.DepriCommand import DepriCommand
from test.CommandTest import CommandTest
from topydo.lib.TodoList import TodoList
class DepriCommandTest(CommandTest.CommandTest):
class DepriCommandTest(CommandTest):
def setUp(self):
super(DepriCommandTest, self).setUp()
todos = [
......@@ -36,37 +37,37 @@ class DepriCommandTest(CommandTest.CommandTest):
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.todolist.todo(1).priority(), None)
self.assertEquals(self.output, "Priority removed.\n| 1| Foo\n")
self.assertEquals(self.errors, "")
self.assertEqual(self.todolist.todo(1).priority(), None)
self.assertEqual(self.output, "Priority removed.\n| 1| Foo\n")
self.assertEqual(self.errors, "")
def test_depri2(self):
command = DepriCommand(["2"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.todolist.todo(2).priority(), None)
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "")
self.assertEqual(self.todolist.todo(2).priority(), None)
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "")
def test_depri3(self):
command = DepriCommand(["Foo"], self.todolist, self.out, self.error)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.todolist.todo(1).priority(), None)
self.assertEquals(self.output, "Priority removed.\n| 1| Foo\n")
self.assertEquals(self.errors, "")
self.assertEqual(self.todolist.todo(1).priority(), None)
self.assertEqual(self.output, "Priority removed.\n| 1| Foo\n")
self.assertEqual(self.errors, "")
def test_depri4(self):
command = DepriCommand(["1","Baz"], self.todolist, self.out, self.error)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.todolist.todo(1).priority(), None)
self.assertEquals(self.todolist.todo(3).priority(), None)
self.assertEquals(self.output, "Priority removed.\n| 1| Foo\nPriority removed.\n| 3| Baz\n")
self.assertEquals(self.errors, "")
self.assertEqual(self.todolist.todo(1).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.errors, "")
def test_invalid1(self):
......@@ -75,7 +76,7 @@ class DepriCommandTest(CommandTest.CommandTest):
self.assertFalse(self.todolist.is_dirty())
self.assertFalse(self.output)
self.assertEquals(self.errors, "Invalid todo number given.\n")
self.assertEqual(self.errors, "Invalid todo number given.\n")
def test_invalid2(self):
command = DepriCommand(["99", "1"], self.todolist, self.out, self.error)
......@@ -83,7 +84,7 @@ class DepriCommandTest(CommandTest.CommandTest):
self.assertFalse(self.todolist.is_dirty())
self.assertFalse(self.output)
self.assertEquals(self.errors, "Invalid todo number given: 99.\n")
self.assertEqual(self.errors, "Invalid todo number given: 99.\n")
def test_invalid3(self):
command = DepriCommand(["99", "FooBar"], self.todolist, self.out, self.error)
......@@ -91,7 +92,16 @@ class DepriCommandTest(CommandTest.CommandTest):
self.assertFalse(self.todolist.is_dirty())
self.assertFalse(self.output)
self.assertEquals(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")
def test_invalid4(self):
""" Throw an error with invalid argument containing special characters. """
command = DepriCommand([u("Fo\u00d3B\u0105r"), "Bar"], self.todolist, self.out, self.error, None)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertFalse(self.output)
self.assertEqual(self.errors, u("Invalid todo number given: Fo\u00d3B\u0105r.\n"))
def test_empty(self):
command = DepriCommand([], self.todolist, self.out, self.error)
......@@ -99,14 +109,14 @@ class DepriCommandTest(CommandTest.CommandTest):
self.assertFalse(self.todolist.is_dirty())
self.assertFalse(self.output)
self.assertEquals(self.errors, command.usage() + "\n")
self.assertEqual(self.errors, command.usage() + "\n")
def test_help(self):
command = DepriCommand(["help"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output, "")
self.assertEquals(self.errors, command.usage() + "\n\n" + command.help() + "\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n\n" + command.help() + "\n")
if __name__ == '__main__':
unittest.main()
This diff is collapsed.
......@@ -15,27 +15,37 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
import mock
# We're searching for 'mock'
# pylint: disable=no-name-in-module
try:
from unittest import mock
except ImportError:
import mock
from six import u
import os
import CommandTest
from topydo.lib.EditCommand import EditCommand
from topydo.commands.EditCommand import EditCommand
from test.CommandTest import CommandTest, utf8
from topydo.lib.TodoList import TodoList
from topydo.lib.Todo import Todo
from topydo.lib.Config import config
class EditCommandTest(CommandTest.CommandTest):
class EditCommandTest(CommandTest):
def setUp(self):
super(EditCommandTest, self).setUp()
todos = [
"Foo id:1",
"Bar p:1 @test",
"Baz @test",
u("Fo\u00f3B\u0105\u017a"),
]
self.todolist = TodoList(todos)
@mock.patch('topydo.lib.EditCommand.EditCommand._open_in_editor')
@mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor')
def test_edit1(self, mock_open_in_editor):
""" Preserve dependencies after editing. """
mock_open_in_editor.return_value = 0
......@@ -44,11 +54,11 @@ class EditCommandTest(CommandTest.CommandTest):
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.errors, "")
self.assertEquals(str(self.todolist), "Bar p:1 @test\nBaz @test\nFoo id:1")
self.assertEqual(self.errors, "")
self.assertEqual(str(self.todolist), utf8(u("Bar p:1 @test\nBaz @test\nFo\u00f3B\u0105\u017a\nFoo id:1")))
@mock.patch('topydo.lib.EditCommand.EditCommand._todos_from_temp')
@mock.patch('topydo.lib.EditCommand.EditCommand._open_in_editor')
@mock.patch('topydo.commands.EditCommand.EditCommand._todos_from_temp')
@mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor')
def test_edit2(self, mock_open_in_editor, mock_todos_from_temp):
""" Edit some todo. """
mock_open_in_editor.return_value = 0
......@@ -58,8 +68,8 @@ class EditCommandTest(CommandTest.CommandTest):
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.errors, "")
self.assertEquals(str(self.todolist), "Foo id:1\nBaz @test\nLazy Cat")
self.assertEqual(self.errors, "")
self.assertEqual(str(self.todolist), utf8(u("Foo id:1\nBaz @test\nFo\u00f3B\u0105\u017a\nLazy Cat")))
def test_edit3(self):
""" Throw an error after invalid todo number given as argument. """
......@@ -67,47 +77,70 @@ class EditCommandTest(CommandTest.CommandTest):
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.errors, "Invalid todo number given.\n")
self.assertEqual(self.errors, "Invalid todo number given.\n")
def test_edit4(self):
""" Throw an error with pointing invalid argument. """
command = EditCommand(["Bar","4"], self.todolist, self.out, self.error, None)
command = EditCommand(["Bar", "5"], self.todolist, self.out, self.error, None)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.errors, "Invalid todo number given: 4.\n")
self.assertEqual(self.errors, "Invalid todo number given: 5.\n")
@mock.patch('topydo.lib.EditCommand.EditCommand._todos_from_temp')
@mock.patch('topydo.lib.EditCommand.EditCommand._open_in_editor')
@mock.patch('topydo.commands.EditCommand.EditCommand._todos_from_temp')
@mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor')
def test_edit5(self, mock_open_in_editor, mock_todos_from_temp):
""" Don't let to delete todos acidentally while editing. """
mock_open_in_editor.return_value = 0
mock_todos_from_temp.return_value = [Todo('Only one line')]
command = EditCommand(["1","Bar"], self.todolist, self.out, self.error, None)
command = EditCommand(["1", "Bar"], self.todolist, self.out, self.error, None)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEqual(self.errors, "Number of edited todos is not equal to number of supplied todo IDs.\n")
self.assertEqual(str(self.todolist), utf8(u("Foo id:1\nBar p:1 @test\nBaz @test\nFo\u00f3B\u0105\u017a")))
def test_edit6(self):
""" Throw an error with invalid argument containing special characters. """
command = EditCommand([u("Fo\u00d3B\u0105r"), "Bar"], self.todolist, self.out, self.error, None)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.errors, "Number of edited todos is not equal to number of supplied todo IDs.\n")
self.assertEquals(str(self.todolist), "Foo id:1\nBar p:1 @test\nBaz @test")
self.assertEqual(self.errors, u("Invalid todo number given: Fo\u00d3B\u0105r.\n"))
@mock.patch('topydo.commands.EditCommand.EditCommand._todos_from_temp')
@mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor')
def test_edit7(self, mock_open_in_editor, mock_todos_from_temp):
""" Edit todo with special characters. """
mock_open_in_editor.return_value = 0
mock_todos_from_temp.return_value = [Todo('Lazy Cat')]
command = EditCommand([u("Fo\u00f3B\u0105\u017a")], self.todolist, self.out, self.error, None)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEqual(self.errors, "")
self.assertEqual(str(self.todolist), utf8(u("Foo id:1\nBar p:1 @test\nBaz @test\nLazy Cat")))
@mock.patch('topydo.lib.EditCommand.EditCommand._todos_from_temp')
@mock.patch('topydo.lib.EditCommand.EditCommand._open_in_editor')
@mock.patch('topydo.commands.EditCommand.EditCommand._todos_from_temp')
@mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor')
def test_edit_expr(self, mock_open_in_editor, mock_todos_from_temp):
""" Edit todos matching expression. """
mock_open_in_editor.return_value = 0
mock_todos_from_temp.return_value = [Todo('Lazy Cat'), Todo('Lazy Dog')]
command = EditCommand(["-e","@test"], self.todolist, self.out, self.error, None)
command = EditCommand(["-e", "@test"], self.todolist, self.out, self.error, None)
command.execute()
expected = "| 2| Lazy Cat\n| 3| Lazy Dog\n"
expected = utf8(u("| 3| Lazy Cat\n| 4| Lazy Dog\n"))
self.assertTrue(self.todolist.is_dirty())
self.assertEqual(self.errors, "")
self.assertEqual(self.output, expected)
self.assertEqual(str(self.todolist), utf8(u("Foo id:1\nFo\u00f3B\u0105\u017a\nLazy Cat\nLazy Dog")))
@mock.patch('topydo.lib.EditCommand.call')
@mock.patch('topydo.commands.EditCommand.call')
def test_edit_archive(self, mock_call):
""" Edit archive file. """
mock_call.return_value = 0
......@@ -116,7 +149,7 @@ class EditCommandTest(CommandTest.CommandTest):
os.environ['EDITOR'] = editor
archive = config().archive()
command = EditCommand(["-d"], self.todolist, self.out, self.error, None)
command = EditCommand([u("-d")], self.todolist, self.out, self.error, None)
command.execute()
self.assertEqual(self.errors, "")
......
This diff is collapsed.
......@@ -51,34 +51,34 @@ class GraphTest(TopydoTest):
self.assertFalse(self.graph.has_edge_id("1"))
def test_incoming_neighbors1(self):
self.assertEquals(self.graph.incoming_neighbors(1), set())
self.assertEqual(self.graph.incoming_neighbors(1), set())
def test_edge_id_of_nonexistent_edge(self):
self.assertFalse(self.graph.edge_id(1, 6))
def test_incoming_neighbors2(self):
self.assertEquals(self.graph.incoming_neighbors(2), set([1, 6]))
self.assertEqual(self.graph.incoming_neighbors(2), set([1, 6]))
def test_incoming_neighbors3(self):
self.assertEquals(self.graph.incoming_neighbors(1, True), set())
self.assertEqual(self.graph.incoming_neighbors(1, True), set())
def test_incoming_neighbors4(self):
self.assertEquals(self.graph.incoming_neighbors(5, True), set([1, 2, 3, 4, 6]))
self.assertEqual(self.graph.incoming_neighbors(5, True), set([1, 2, 3, 4, 6]))
def test_outgoing_neighbors1(self):
self.assertEquals(self.graph.outgoing_neighbors(1), set([2, 3]))
self.assertEqual(self.graph.outgoing_neighbors(1), set([2, 3]))
def test_outgoing_neighbors2(self):
self.assertEquals(self.graph.outgoing_neighbors(2), set([4]))
self.assertEqual(self.graph.outgoing_neighbors(2), set([4]))
def test_outgoing_neighbors3(self):
self.assertEquals(self.graph.outgoing_neighbors(1, True), set([2, 3, 4, 5, 6]))
self.assertEqual(self.graph.outgoing_neighbors(1, True), set([2, 3, 4, 5, 6]))
def test_outgoing_neighbors4(self):
self.assertEquals(self.graph.outgoing_neighbors(3), set([5]))
self.assertEqual(self.graph.outgoing_neighbors(3), set([5]))
def test_outgoing_neighbors5(self):
self.assertEquals(self.graph.outgoing_neighbors(5), set([]))
self.assertEqual(self.graph.outgoing_neighbors(5), set([]))
def test_remove_edge1(self):
self.graph.remove_edge(1, 2)
......@@ -165,11 +165,11 @@ class GraphTest(TopydoTest):
def test_str_output(self):
out = 'digraph g {\n 1\n 1 -> 2 [label="1"]\n 1 -> 3\n 2\n 2 -> 4 [label="Test"]\n 3\n 3 -> 5\n 4\n 4 -> 3\n 4 -> 6\n 5\n 6\n 6 -> 2\n}\n'
self.assertEquals(str(self.graph), out)
self.assertEqual(str(self.graph), out)
def test_dot_output_without_labels(self):
out = 'digraph g {\n 1\n 1 -> 2\n 1 -> 3\n 2\n 2 -> 4\n 3\n 3 -> 5\n 4\n 4 -> 3\n 4 -> 6\n 5\n 6\n 6 -> 2\n}\n'
self.assertEquals(self.graph.dot(False), out)
self.assertEqual(self.graph.dot(False), out)
if __name__ == '__main__':
unittest.main()
This diff is collapsed.
......@@ -16,33 +16,33 @@
import unittest
import CommandTest
import TestFacilities
from topydo.lib.ListContextCommand import ListContextCommand
from topydo.commands.ListContextCommand import ListContextCommand
from test.CommandTest import CommandTest
from test.TestFacilities import load_file_to_todolist
class ListContextCommandTest(CommandTest.CommandTest):
class ListContextCommandTest(CommandTest):
def test_contexts1(self):
todolist = TestFacilities.load_file_to_todolist("test/data/TodoListTest.txt")
todolist = load_file_to_todolist("test/data/TodoListTest.txt")
command = ListContextCommand([""], todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output,"Context1\nContext2\n")
self.assertEqual(self.output,"Context1\nContext2\n")
self.assertFalse(self.errors)
def test_contexts2(self):
todolist = TestFacilities.load_file_to_todolist("test/data/TodoListTest.txt")
todolist = load_file_to_todolist("test/data/TodoListTest.txt")
command = ListContextCommand(["aaa"], todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output,"Context1\nContext2\n")
self.assertEqual(self.output,"Context1\nContext2\n")
self.assertFalse(self.errors)
def test_help(self):
command = ListContextCommand(["help"], None, self.out, self.error)
command.execute()
self.assertEquals(self.output, "")
self.assertEquals(self.errors, command.usage() + "\n\n" + command.help() + "\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n\n" + command.help() + "\n")
if __name__ == '__main__':
unittest.main()
......@@ -16,33 +16,33 @@
import unittest
import CommandTest
import TestFacilities
from topydo.lib.ListProjectCommand import ListProjectCommand
from topydo.commands.ListProjectCommand import ListProjectCommand
from test.CommandTest import CommandTest
from test.TestFacilities import load_file_to_todolist
class ListProjectCommandTest(CommandTest.CommandTest):
class ListProjectCommandTest(CommandTest):
def test_projects1(self):
todolist = TestFacilities.load_file_to_todolist("test/data/TodoListTest.txt")
todolist = load_file_to_todolist("test/data/TodoListTest.txt")
command = ListProjectCommand([""], todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output,"Project1\nProject2\n")
self.assertEqual(self.output, "Project1\nProject2\n")
self.assertFalse(self.errors)
def test_projects2(self):
todolist = TestFacilities.load_file_to_todolist("test/data/TodoListTest.txt")
todolist = load_file_to_todolist("test/data/TodoListTest.txt")
command = ListProjectCommand(["aaa"], todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output,"Project1\nProject2\n")
self.assertEqual(self.output, "Project1\nProject2\n")
self.assertFalse(self.errors)
def test_help(self):
command = ListProjectCommand(["help"], None, self.out, self.error)
command.execute()
self.assertEquals(self.output, "")
self.assertEquals(self.errors, command.usage() + "\n\n" + command.help() + "\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n\n" + command.help() + "\n")
if __name__ == '__main__':
unittest.main()
This diff is collapsed.
......@@ -15,12 +15,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
from six import u
import CommandTest
from topydo.lib.PriorityCommand import PriorityCommand
from topydo.commands.PriorityCommand import PriorityCommand
from test.CommandTest import CommandTest
from topydo.lib.TodoList import TodoList
class PriorityCommandTest(CommandTest.CommandTest):
class PriorityCommandTest(CommandTest):
def setUp(self):
super(PriorityCommandTest, self).setUp()
todos = [
......@@ -35,40 +36,40 @@ class PriorityCommandTest(CommandTest.CommandTest):
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, "Priority changed from A to B\n| 1| (B) Foo\n")
self.assertEquals(self.errors, "")
self.assertEqual(self.output, "Priority changed from A to B\n| 1| (B) Foo\n")
self.assertEqual(self.errors, "")
def test_set_prio2(self):
command = PriorityCommand(["2", "Z"], self.todolist, self.out, self.error)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, "Priority set to Z.\n| 2| (Z) Bar\n")
self.assertEquals(self.errors, "")
self.assertEqual(self.output, "Priority set to Z.\n| 2| (Z) Bar\n")
self.assertEqual(self.errors, "")
def test_set_prio3(self):
command = PriorityCommand(["Foo", "B"], self.todolist, self.out, self.error)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, "Priority changed from A to B\n| 1| (B) Foo\n")
self.assertEquals(self.errors, "")
self.assertEqual(self.output, "Priority changed from A to B\n| 1| (B) Foo\n")
self.assertEqual(self.errors, "")
def test_set_prio4(self):
command = PriorityCommand(["1", "A"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "| 1| (A) Foo\n")
self.assertEquals(self.errors, "")
self.assertEqual(self.output, "| 1| (A) Foo\n")
self.assertEqual(self.errors, "")
def test_set_prio5(self):
command = PriorityCommand(["Foo", "2", "C"], self.todolist, self.out, self.error)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, "Priority changed from A to C\n| 1| (C) Foo\nPriority set to C.\n| 2| (C) Bar\n")
self.assertEquals(self.errors, "")
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_invalid1(self):
command = PriorityCommand(["99", "A"], self.todolist, self.out, self.error)
......@@ -76,7 +77,7 @@ class PriorityCommandTest(CommandTest.CommandTest):
self.assertFalse(self.todolist.is_dirty())
self.assertFalse(self.output)
self.assertEquals(self.errors, "Invalid todo number given.\n")
self.assertEqual(self.errors, "Invalid todo number given.\n")
def test_invalid2(self):
command = PriorityCommand(["1", "99", "A"], self.todolist, self.out, self.error)
......@@ -84,7 +85,7 @@ class PriorityCommandTest(CommandTest.CommandTest):
self.assertFalse(self.todolist.is_dirty())
self.assertFalse(self.output)
self.assertEquals(self.errors, "Invalid todo number given: 99.\n")
self.assertEqual(self.errors, "Invalid todo number given: 99.\n")
def test_invalid3(self):
command = PriorityCommand(["98", "99", "A"], self.todolist, self.out, self.error)
......@@ -92,7 +93,7 @@ class PriorityCommandTest(CommandTest.CommandTest):
self.assertFalse(self.todolist.is_dirty())
self.assertFalse(self.output)
self.assertEquals(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")
def test_invalid4(self):
command = PriorityCommand(["1", "ZZ"], self.todolist, self.out, self.error)
......@@ -100,7 +101,7 @@ class PriorityCommandTest(CommandTest.CommandTest):
self.assertFalse(self.todolist.is_dirty())
self.assertFalse(self.output)
self.assertEquals(self.errors, "Invalid priority given.\n")
self.assertEqual(self.errors, "Invalid priority given.\n")
def test_invalid5(self):
command = PriorityCommand(["A"], self.todolist, self.out, self.error)
......@@ -108,7 +109,7 @@ class PriorityCommandTest(CommandTest.CommandTest):
self.assertFalse(self.todolist.is_dirty())
self.assertFalse(self.output)
self.assertEquals(self.errors, command.usage() + "\n")
self.assertEqual(self.errors, command.usage() + "\n")
def test_invalid6(self):
command = PriorityCommand(["1"], self.todolist, self.out, self.error)
......@@ -116,7 +117,16 @@ class PriorityCommandTest(CommandTest.CommandTest):
self.assertFalse(self.todolist.is_dirty())
self.assertFalse(self.output)
self.assertEquals(self.errors, command.usage() + "\n")
self.assertEqual(self.errors, command.usage() + "\n")
def test_invalid7(self):
""" Throw an error with invalid argument containing special characters. """
command = PriorityCommand([u("Fo\u00d3B\u0105r"), "Bar", "C"], self.todolist, self.out, self.error, None)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEqual(self.output, "")
self.assertEqual(self.errors, u("Invalid todo number given: Fo\u00d3B\u0105r.\n"))
def test_empty(self):
command = PriorityCommand([], self.todolist, self.out, self.error)
......@@ -124,14 +134,14 @@ class PriorityCommandTest(CommandTest.CommandTest):
self.assertFalse(self.todolist.is_dirty())
self.assertFalse(self.output)
self.assertEquals(self.errors, command.usage() + "\n")
self.assertEqual(self.errors, command.usage() + "\n")
def test_help(self):
command = PriorityCommand(["help"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output, "")
self.assertEquals(self.errors, command.usage() + "\n\n" + command.help() + "\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n\n" + command.help() + "\n")
if __name__ == '__main__':
unittest.main()
......@@ -35,7 +35,7 @@ class RecurrenceTest(TopydoTest):
self.todo.set_tag(config().tag_due(), future.isoformat())
new_todo = advance_recurring_todo(self.todo)
self.assertEquals(new_todo.due_date(), new_due)
self.assertEqual(new_todo.due_date(), new_due)
def test_duedate2(self):
""" Where due date is today. """
......@@ -45,7 +45,7 @@ class RecurrenceTest(TopydoTest):
self.todo.set_tag(config().tag_due(), today.isoformat())
new_todo = advance_recurring_todo(self.todo)
self.assertEquals(new_todo.due_date(), new_due)
self.assertEqual(new_todo.due_date(), new_due)
def test_duedate3(self):
""" Where due date is in the past. """
......@@ -55,7 +55,7 @@ class RecurrenceTest(TopydoTest):
self.todo.set_tag(config().tag_due(), past.isoformat())
new_todo = advance_recurring_todo(self.todo)
self.assertEquals(new_todo.due_date(), new_due)
self.assertEqual(new_todo.due_date(), new_due)
def test_duedate4(self):
""" Where due date is in the past. """
......@@ -65,7 +65,7 @@ class RecurrenceTest(TopydoTest):
self.todo.set_tag(config().tag_due(), past.isoformat())
new_todo = strict_advance_recurring_todo(self.todo)
self.assertEquals(new_todo.due_date(), new_due)
self.assertEqual(new_todo.due_date(), new_due)
def test_duedate5(self):
""" Where due date is in the future. """
......@@ -75,7 +75,7 @@ class RecurrenceTest(TopydoTest):
self.todo.set_tag(config().tag_due(), future.isoformat())
new_todo = strict_advance_recurring_todo(self.todo)
self.assertEquals(new_todo.due_date(), new_due)
self.assertEqual(new_todo.due_date(), new_due)
def test_duedate6(self):
""" Where due date is today. """
......@@ -85,21 +85,21 @@ class RecurrenceTest(TopydoTest):
self.todo.set_tag(config().tag_due(), today.isoformat())
new_todo = strict_advance_recurring_todo(self.todo)
self.assertEquals(new_todo.due_date(), new_due)
self.assertEqual(new_todo.due_date(), new_due)
def test_noduedate1(self):
new_due = date.today() + timedelta(7)
new_todo = advance_recurring_todo(self.todo)
self.assertTrue(new_todo.has_tag(config().tag_due()))
self.assertEquals(new_todo.due_date(), new_due)
self.assertEqual(new_todo.due_date(), new_due)
def test_noduedate2(self):
new_due = date.today() + timedelta(7)
new_todo = strict_advance_recurring_todo(self.todo)
self.assertTrue(new_todo.has_tag(config().tag_due()))
self.assertEquals(new_todo.due_date(), new_due)
self.assertEqual(new_todo.due_date(), new_due)
def test_startdate1(self):
""" Start date is before due date. """
......@@ -110,19 +110,20 @@ class RecurrenceTest(TopydoTest):
new_start = date.today() + timedelta(6)
new_todo = advance_recurring_todo(self.todo)
self.assertEquals(new_todo.start_date(), new_start)
self.assertEqual(new_todo.start_date(), new_start)
def test_startdate2(self):
""" Strict recurrence. Start date is before due date. """
due = date.today() - timedelta(1)
self.todo.set_tag(config().tag_due(), date.today().isoformat())
yesterday = due - timedelta(1)
# pylint: disable=E1103
self.todo.set_tag(config().tag_start(), yesterday.isoformat())
new_start = date.today() + timedelta(5)
new_todo = strict_advance_recurring_todo(self.todo)
self.assertEquals(new_todo.start_date(), new_start)
self.assertEqual(new_todo.start_date(), new_start)
def test_startdate3(self):
""" Start date equals due date. """
......@@ -132,7 +133,7 @@ class RecurrenceTest(TopydoTest):
new_start = date.today() + timedelta(7)
new_todo = advance_recurring_todo(self.todo)
self.assertEquals(new_todo.start_date(), new_start)
self.assertEqual(new_todo.start_date(), new_start)
def test_no_recurrence(self):
self.todo.remove_tag('rec')
......
......@@ -18,9 +18,9 @@ from datetime import date, timedelta
import unittest
from topydo.lib.RelativeDate import relative_date_to_date
import TopydoTest
from test.TopydoTest import TopydoTest
class RelativeDateTester(TopydoTest.TopydoTest):
class RelativeDateTester(TopydoTest):
def setUp(self):
super(RelativeDateTester, self).setUp()
self.today = date.today()
......@@ -32,20 +32,20 @@ class RelativeDateTester(TopydoTest.TopydoTest):
def test_zero_days(self):
result = relative_date_to_date('0d')
self.assertEquals(result, self.today)
self.assertEqual(result, self.today)
def test_one_day(self):
result = relative_date_to_date('1d')
self.assertEquals(result, self.tomorrow)
self.assertEqual(result, self.tomorrow)
def test_one_week(self):
result = relative_date_to_date('1w')
self.assertEquals(result, date.today() + timedelta(weeks=1))
self.assertEqual(result, date.today() + timedelta(weeks=1))
def test_one_month(self):
test_date = date(2015, 1, 10)
result = relative_date_to_date('1m', test_date)
self.assertEquals(result, date(2015, 2, 10))
self.assertEqual(result, date(2015, 2, 10))
def test_one_month_ext(self):
test_date1 = date(2015, 1, 29)
......@@ -60,31 +60,31 @@ class RelativeDateTester(TopydoTest.TopydoTest):
result4 = relative_date_to_date('1m', test_date4)
result5 = relative_date_to_date('1m', test_date5)
self.assertEquals(result1, date(2015, 2, 28))
self.assertEquals(result2, date(2016, 2, 29))
self.assertEquals(result3, date(2016, 1, 31))
self.assertEquals(result4, date(2015, 8, 31))
self.assertEquals(result5, date(2015, 11, 30))
self.assertEqual(result1, date(2015, 2, 28))
self.assertEqual(result2, date(2016, 2, 29))
self.assertEqual(result3, date(2016, 1, 31))
self.assertEqual(result4, date(2015, 8, 31))
self.assertEqual(result5, date(2015, 11, 30))
def test_one_year(self):
test_date = date(2015, 1, 10)
result = relative_date_to_date('1y', test_date)
self.assertEquals(result, date(2016, 1, 10))
self.assertEqual(result, date(2016, 1, 10))
def test_leap_year(self):
test_date = date(2016, 2, 29)
result1 = relative_date_to_date('1y', test_date)
result2 = relative_date_to_date('4y', test_date)
self.assertEquals(result1, date(2017, 2, 28))
self.assertEquals(result2, date(2020, 2, 29))
self.assertEqual(result1, date(2017, 2, 28))
self.assertEqual(result2, date(2020, 2, 29))
def test_zero_months(self):
result = relative_date_to_date('0m')
self.assertEquals(result, self.today)
self.assertEqual(result, self.today)
def test_zero_years(self):
result = relative_date_to_date('0y')
self.assertEquals(result, self.today)
self.assertEqual(result, self.today)
def test_garbage1(self):
result = relative_date_to_date('0dd')
......@@ -92,40 +92,40 @@ class RelativeDateTester(TopydoTest.TopydoTest):
def test_one_day_capital(self):
result = relative_date_to_date('1D')
self.assertEquals(result, self.tomorrow)
self.assertEqual(result, self.tomorrow)
def test_today1(self):
result = relative_date_to_date('today')
self.assertEquals(result, self.today)
self.assertEqual(result, self.today)
def test_today2(self):
result = relative_date_to_date('tod')
self.assertEquals(result, self.today)
self.assertEqual(result, self.today)
def test_today3(self):
result = relative_date_to_date('today', \
date.today() + timedelta(1))
self.assertEquals(result, self.today)
self.assertEqual(result, self.today)
def test_tomorrow1(self):
result = relative_date_to_date('Tomorrow')
self.assertEquals(result, self.tomorrow)
self.assertEqual(result, self.tomorrow)
def test_tomorrow2(self):
result = relative_date_to_date('tom')
self.assertEquals(result, self.tomorrow)
self.assertEqual(result, self.tomorrow)
def test_monday1(self):
result = relative_date_to_date('monday')
self.assertEquals(result, self.monday)
self.assertEqual(result, self.monday)
def test_monday2(self):
result = relative_date_to_date('mo')
self.assertEquals(result, self.monday)
self.assertEqual(result, self.monday)
def test_monday3(self):
result = relative_date_to_date('mon')
self.assertEquals(result, self.monday)
self.assertEqual(result, self.monday)
def test_monday4(self):
result = relative_date_to_date('mondayy')
......@@ -133,11 +133,11 @@ class RelativeDateTester(TopydoTest.TopydoTest):
def test_offset1(self):
result = relative_date_to_date('1d', self.tomorrow)
self.assertEquals(result, date.today() + timedelta(2))
self.assertEqual(result, date.today() + timedelta(2))
def test_negative_period1(self):
result = relative_date_to_date('-1d')
self.assertEquals(result, date.today() - timedelta(1))
self.assertEqual(result, date.today() - timedelta(1))
def test_negative_period2(self):
result = relative_date_to_date('-0d')
......
......@@ -16,46 +16,46 @@
import unittest
import CommandTest
from topydo.lib.Config import config
from topydo.lib.SortCommand import SortCommand
import TestFacilities
from topydo.commands.SortCommand import SortCommand
from test.CommandTest import CommandTest
from test.TestFacilities import load_file_to_todolist
class SortCommandTest(CommandTest.CommandTest):
class SortCommandTest(CommandTest):
def setUp(self):
super(SortCommandTest, self).setUp()
self.todolist = TestFacilities.load_file_to_todolist("test/data/SorterTest1.txt")
self.todolist = load_file_to_todolist("test/data/SorterTest1.txt")
def test_sort1(self):
""" Alphabetically sorted """
command = SortCommand(["text"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(str(self.todolist), "First\n(A) Foo\n2014-06-14 Last")
self.assertEqual(str(self.todolist), "First\n(A) Foo\n2014-06-14 Last")
def test_sort2(self):
command = SortCommand([], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(str(self.todolist), "(A) Foo\n2014-06-14 Last\nFirst")
self.assertEqual(str(self.todolist), "(A) Foo\n2014-06-14 Last\nFirst")
def test_sort3(self):
""" Check that order does not influence the UID of a todo. """
config("test/data/todolist-uid.conf")
todo1 = self.todolist.todo('tpi')
todo1 = self.todolist.todo('7ui')
command = SortCommand(["text"], self.todolist, self.out, self.error)
command.execute()
todo2 = self.todolist.todo('tpi')
todo2 = self.todolist.todo('7ui')
self.assertEquals(todo1.source(), todo2.source())
self.assertEqual(todo1.source(), todo2.source())
def test_help(self):
command = SortCommand(["help"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output, "")
self.assertEquals(self.errors, command.usage() + "\n\n" + command.help() + "\n")
self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n\n" + command.help() + "\n")
if __name__ == '__main__':
unittest.main()
......@@ -33,8 +33,8 @@ class SorterTest(TopydoTest):
todos_sorted = todolist_to_string(p_sorter.sort(todos))
todos_ref = todolist_to_string(load_file(p_filename_ref))
self.assertEquals(todos_sorted, todos_ref)
self.assertEquals(todolist_to_string(todos), text_before)
self.assertEqual(todos_sorted, todos_ref)
self.assertEqual(todolist_to_string(todos), text_before)
def test_sort1(self):
""" Alphabetically sorted """
......@@ -128,7 +128,7 @@ class SorterTest(TopydoTest):
view = todolist.view(sorter, [])
result = load_file('test/data/SorterTest10-result.txt')
self.assertEquals(str(view), todolist_to_string(result))
self.assertEqual(str(view), todolist_to_string(result))
def test_sort15(self):
"""
......@@ -141,7 +141,7 @@ class SorterTest(TopydoTest):
view = todolist.view(sorter, [])
result = load_file('test/data/SorterTest11-result.txt')
self.assertEquals(str(view), todolist_to_string(result))
self.assertEqual(str(view), todolist_to_string(result))
def test_sort16(self):
"""
......@@ -153,7 +153,7 @@ class SorterTest(TopydoTest):
view = todolist.view(sorter, [])
result = load_file('test/data/SorterTest12-result.txt')
self.assertEquals(str(view), todolist_to_string(result))
self.assertEqual(str(view), todolist_to_string(result))
if __name__ == '__main__':
unittest.main()
This diff is collapsed.
......@@ -48,7 +48,7 @@ class TodoBaseTester(TopydoTest):
todo = TodoBase("(C) Foo id:1")
todo.add_tag('id', '2')
self.assertEquals(todo.source(), '(C) Foo id:1 id:2')
self.assertEqual(todo.source(), '(C) Foo id:1 id:2')
def test_set_tag1(self):
todo = TodoBase("(C) Foo foo:bar")
......@@ -146,7 +146,7 @@ class TodoBaseTester(TopydoTest):
todo = TodoBase("(A) Foo")
todo.set_priority('B')
self.assertEquals(todo.priority(), 'B')
self.assertEqual(todo.priority(), 'B')
self.assertTrue(re.match(r'^\(B\) Foo$', todo.src))
def test_set_priority2(self):
......@@ -154,7 +154,7 @@ class TodoBaseTester(TopydoTest):
todo = TodoBase("Foo")
todo.set_priority('B')
self.assertEquals(todo.priority(), 'B')
self.assertEqual(todo.priority(), 'B')
self.assertTrue(re.match(r'^\(B\) Foo$', todo.src))
def test_set_priority3(self):
......@@ -162,7 +162,7 @@ class TodoBaseTester(TopydoTest):
todo = TodoBase("(A) Foo")
todo.set_priority('AB')
self.assertEquals(todo.priority(), 'A')
self.assertEqual(todo.priority(), 'A')
self.assertTrue(re.match(r'^\(A\) Foo$', todo.src))
def test_set_priority4(self):
......@@ -173,7 +173,7 @@ class TodoBaseTester(TopydoTest):
todo.set_priority('B')
self.assertEquals(todo.priority(), 'B')
self.assertEqual(todo.priority(), 'B')
self.assertTrue(re.match(r'^\(B\) \(A\)Foo$', todo.src))
def test_set_priority5(self):
......@@ -181,7 +181,7 @@ class TodoBaseTester(TopydoTest):
todo = TodoBase("(A) Foo")
todo.set_priority(None)
self.assertEquals(todo.priority(), None)
self.assertEqual(todo.priority(), None)
self.assertTrue(re.match(r'^Foo$', todo.src))
def test_set_priority6(self):
......@@ -190,32 +190,32 @@ class TodoBaseTester(TopydoTest):
todo.set_priority('A')
self.assertFalse(todo.priority())
self.assertEquals(todo.src, "x 2014-06-13 Foo")
self.assertEqual(todo.src, "x 2014-06-13 Foo")
def test_project1(self):
todo = TodoBase("(C) Foo +Bar +Baz +Bar:")
self.assertEquals(len(todo.projects()), 2)
self.assertEqual(len(todo.projects()), 2)
self.assertIn('Bar', todo.projects())
self.assertIn('Baz', todo.projects())
def test_project2(self):
todo = TodoBase("(C) Foo +Bar+Baz")
self.assertEquals(len(todo.projects()), 1)
self.assertEqual(len(todo.projects()), 1)
self.assertIn('Bar+Baz', todo.projects())
def test_context1(self):
todo = TodoBase("(C) Foo @Bar @Baz @Bar:")
self.assertEquals(len(todo.contexts()), 2)
self.assertEqual(len(todo.contexts()), 2)
self.assertIn('Bar', todo.contexts())
self.assertIn('Baz', todo.contexts())
def test_context2(self):
todo = TodoBase("(C) Foo @Bar+Baz")
self.assertEquals(len(todo.contexts()), 1)
self.assertEqual(len(todo.contexts()), 1)
self.assertIn('Bar+Baz', todo.contexts())
def test_completion1(self):
......@@ -248,7 +248,7 @@ class TodoBaseTester(TopydoTest):
today_str = today.isoformat()
self.assertFalse(todo.priority())
self.assertEquals(todo.fields['completionDate'], today)
self.assertEqual(todo.fields['completionDate'], today)
self.assertTrue(re.match('^x ' + today_str + ' Foo', todo.src))
def test_set_complete2(self):
......@@ -258,7 +258,7 @@ class TodoBaseTester(TopydoTest):
today = date.today()
today_str = today.isoformat()
self.assertEquals(todo.fields['completionDate'], today)
self.assertEqual(todo.fields['completionDate'], today)
self.assertTrue(re.match('^x ' + today_str + ' 2014-06-12 Foo', \
todo.src))
......@@ -269,7 +269,7 @@ class TodoBaseTester(TopydoTest):
today = date.today()
today_str = today.isoformat()
self.assertEquals(todo.fields['completionDate'], today)
self.assertEqual(todo.fields['completionDate'], today)
self.assertTrue(re.match('^x ' + today_str + ' Foo', todo.src))
def test_set_complete4(self):
......@@ -279,21 +279,21 @@ class TodoBaseTester(TopydoTest):
today = date.today()
today_str = today.isoformat()
self.assertEquals(todo.fields['completionDate'], today)
self.assertEqual(todo.fields['completionDate'], today)
self.assertTrue(re.match('^x ' + today_str + ' 2014-06-12 Foo', todo.src))
def test_set_complete5(self):
todo = TodoBase("x 2014-06-13 Foo")
todo.set_completed()
self.assertEquals(todo.src, "x 2014-06-13 Foo")
self.assertEqual(todo.src, "x 2014-06-13 Foo")
def test_set_complete6(self):
todo = TodoBase("Foo")
yesterday = date.today() - timedelta(1)
todo.set_completed(yesterday)
self.assertEquals(todo.src, "x {} Foo".format(yesterday.isoformat()))
self.assertEqual(todo.src, "x {} Foo".format(yesterday.isoformat()))
def test_set_source_text(self):
todo = TodoBase("(B) Foo")
......@@ -301,8 +301,8 @@ class TodoBaseTester(TopydoTest):
new_text = "(C) Foo"
todo.set_source_text(new_text)
self.assertEquals(todo.src, new_text)
self.assertEquals(todo.priority(),'C')
self.assertEqual(todo.src, new_text)
self.assertEqual(todo.priority(),'C')
def test_set_creation_date1(self):
todo = TodoBase("Foo")
......@@ -310,8 +310,8 @@ class TodoBaseTester(TopydoTest):
todo.set_creation_date(creation_date)
self.assertEquals(todo.creation_date(), creation_date)
self.assertEquals(todo.src, "2014-07-24 Foo")
self.assertEqual(todo.creation_date(), creation_date)
self.assertEqual(todo.src, "2014-07-24 Foo")
def test_set_creation_date2(self):
todo = TodoBase("(A) Foo")
......@@ -319,8 +319,8 @@ class TodoBaseTester(TopydoTest):
todo.set_creation_date(creation_date)
self.assertEquals(todo.creation_date(), creation_date)
self.assertEquals(todo.src, "(A) 2014-07-24 Foo")
self.assertEqual(todo.creation_date(), creation_date)
self.assertEqual(todo.src, "(A) 2014-07-24 Foo")
def test_set_creation_date3(self):
todo = TodoBase("(A) 2014-07-23 Foo")
......@@ -328,8 +328,8 @@ class TodoBaseTester(TopydoTest):
todo.set_creation_date(creation_date)
self.assertEquals(todo.creation_date(), creation_date)
self.assertEquals(todo.src, "(A) 2014-07-24 Foo")
self.assertEqual(todo.creation_date(), creation_date)
self.assertEqual(todo.src, "(A) 2014-07-24 Foo")
def test_set_creation_date4(self):
todo = TodoBase("2014-07-23 Foo")
......@@ -337,8 +337,8 @@ class TodoBaseTester(TopydoTest):
todo.set_creation_date(creation_date)
self.assertEquals(todo.creation_date(), creation_date)
self.assertEquals(todo.src, "2014-07-24 Foo")
self.assertEqual(todo.creation_date(), creation_date)
self.assertEqual(todo.src, "2014-07-24 Foo")
def test_set_creation_date5(self):
todo = TodoBase("x 2014-07-25 2014-07-23 Foo")
......@@ -346,8 +346,8 @@ class TodoBaseTester(TopydoTest):
todo.set_creation_date(creation_date)
self.assertEquals(todo.creation_date(), creation_date)
self.assertEquals(todo.src, "x 2014-07-25 2014-07-24 Foo")
self.assertEqual(todo.creation_date(), creation_date)
self.assertEqual(todo.src, "x 2014-07-25 2014-07-24 Foo")
if __name__ == '__main__':
unittest.main()
......@@ -14,6 +14,7 @@
# 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 six import u
import unittest
from test.TestFacilities import load_file
......@@ -23,7 +24,12 @@ class TodoFileTest(TopydoTest):
def test_empty_file(self):
todofile = load_file('test/data/TodoFileTest1.txt')
self.assertEquals(len(todofile), 0)
self.assertEqual(len(todofile), 0)
def test_utf_8(self):
todofile = load_file('test/data/utf-8.txt')
self.assertEqual(todofile[0].source(), u('(C) \u25ba UTF-8 test \u25c4'))
if __name__ == '__main__':
unittest.main()
......@@ -37,12 +37,12 @@ class TodoListTester(TopydoTest):
self.todolist = TodoList(lines)
def test_contexts(self):
self.assertEquals(set(['Context1', 'Context2']), \
self.assertEqual(set(['Context1', 'Context2']), \
self.todolist.contexts())
self.assertFalse(self.todolist.is_dirty())
def test_projects(self):
self.assertEquals(set(['Project1', 'Project2']), \
self.assertEqual(set(['Project1', 'Project2']), \
self.todolist.projects())
self.assertFalse(self.todolist.is_dirty())
......@@ -51,18 +51,18 @@ class TodoListTester(TopydoTest):
count = self.todolist.count()
todo = self.todolist.add(text)
self.assertEquals(self.todolist.todo(count+1).source(), text)
self.assertEquals(set(['Project1', 'Project2', 'Project3']), \
self.assertEqual(self.todolist.todo(count+1).source(), text)
self.assertEqual(set(['Project1', 'Project2', 'Project3']), \
self.todolist.projects())
self.assertEquals(set(['Context1', 'Context2', 'Context3']), \
self.assertEqual(set(['Context1', 'Context2', 'Context3']), \
self.todolist.contexts())
self.assertEquals(self.todolist.number(todo), 6)
self.assertEqual(self.todolist.number(todo), 6)
self.assertTrue(self.todolist.is_dirty())
def test_add2(self):
text = str(self.todolist)
self.todolist.add('')
self.assertEquals(str(self.todolist), text)
self.assertEqual(str(self.todolist), text)
def test_add3a(self):
count = self.todolist.count()
......@@ -83,21 +83,21 @@ class TodoListTester(TopydoTest):
def test_add4(self):
text = str(self.todolist)
self.todolist.add(' ')
self.assertEquals(str(self.todolist), text)
self.assertEqual(str(self.todolist), text)
def test_add5(self):
text = str(self.todolist)
self.todolist.add("\n")
self.assertEquals(str(self.todolist), text)
self.assertEqual(str(self.todolist), text)
def test_delete1(self):
count = self.todolist.count()
todo = self.todolist.todo(2)
self.todolist.delete(todo)
self.assertEquals(self.todolist.todo(2).source(), \
self.assertEqual(self.todolist.todo(2).source(), \
"(C) Baz @Context1 +Project1 key:value")
self.assertEquals(self.todolist.count(), count - 1)
self.assertEqual(self.todolist.count(), count - 1)
self.assertTrue(self.todolist.is_dirty())
self.assertRaises(InvalidTodoException, self.todolist.number, todo)
......@@ -105,9 +105,9 @@ class TodoListTester(TopydoTest):
todo = self.todolist.todo(3)
self.todolist.append(todo, "@Context3")
self.assertEquals(todo.source(), \
self.assertEqual(todo.source(), \
"(C) Baz @Context1 +Project1 key:value @Context3")
self.assertEquals(set(['Context1', 'Context2', 'Context3']), \
self.assertEqual(set(['Context1', 'Context2', 'Context3']), \
self.todolist.contexts())
self.assertTrue(self.todolist.is_dirty())
......@@ -116,8 +116,8 @@ class TodoListTester(TopydoTest):
text = todo.text()
self.todolist.append(todo, "foo:bar")
self.assertEquals(todo.text(), text)
self.assertEquals(todo.source(), \
self.assertEqual(todo.text(), text)
self.assertEqual(todo.source(), \
"(C) Baz @Context1 +Project1 key:value foo:bar")
def test_append3(self):
......@@ -125,7 +125,7 @@ class TodoListTester(TopydoTest):
text = todo.text()
self.todolist.append(todo, '')
self.assertEquals(todo.text(), text)
self.assertEqual(todo.text(), text)
def test_todo(self):
count = self.todolist.count()
......@@ -136,11 +136,11 @@ class TodoListTester(TopydoTest):
def test_string(self):
# readlines() always ends a string with \n, but join() in str(todolist)
# doesn't necessarily.
self.assertEquals(str(self.todolist) + '\n', self.text)
self.assertEqual(str(self.todolist) + '\n', self.text)
def test_count(self):
""" Test that empty lines are not counted. """
self.assertEquals(self.todolist.count(), 5)
self.assertEqual(self.todolist.count(), 5)
def test_todo_by_dep_id(self):
""" Tests that todos can be retrieved by their id tag. """
......@@ -155,7 +155,7 @@ class TodoListTester(TopydoTest):
todo = self.todolist.todo(6)
self.assertIsInstance(todo, Todo)
self.assertEquals(todo.text(), "No number")
self.assertEqual(todo.text(), "No number")
def test_todo_number2(self):
todo = Todo("Non-existent")
......@@ -171,7 +171,7 @@ class TodoListTester(TopydoTest):
todo = self.todolist.todo(1)
self.todolist.set_priority(todo, 'F')
self.assertEquals(self.todolist.todo(1).priority(), 'F')
self.assertEqual(self.todolist.todo(1).priority(), 'F')
self.assertTrue(self.todolist.is_dirty())
def test_todo_priority2(self):
......@@ -183,7 +183,7 @@ class TodoListTester(TopydoTest):
def test_erase(self):
self.todolist.erase()
self.assertEquals(self.todolist.count(), 0)
self.assertEqual(self.todolist.count(), 0)
self.assertTrue(self.todolist.is_dirty())
def test_regex1(self):
......@@ -193,20 +193,20 @@ class TodoListTester(TopydoTest):
def test_regex3(self):
todo = self.todolist.todo("project2")
self.assertTrue(todo)
self.assertEquals(todo.source(), "(D) Bar @Context1 +Project2")
self.assertEqual(todo.source(), "(D) Bar @Context1 +Project2")
def test_uid1(self):
config("test/data/todolist-uid.conf")
self.assertEquals(self.todolist.todo('6iu').source(), "(C) Foo @Context2 Not@Context +Project1 Not+Project")
self.assertEqual(self.todolist.todo('t5c').source(), "(C) Foo @Context2 Not@Context +Project1 Not+Project")
def test_uid2(self):
""" Changing the priority should not change the identifier. """
config("test/data/todolist-uid.conf")
todo = self.todolist.todo('6iu')
todo = self.todolist.todo('t5c')
self.todolist.set_priority(todo, 'B')
self.assertEquals(self.todolist.todo('6iu').source(), "(B) Foo @Context2 Not@Context +Project1 Not+Project")
self.assertEqual(self.todolist.todo('t5c').source(), "(B) Foo @Context2 Not@Context +Project1 Not+Project")
def test_uid3(self):
"""
......@@ -220,10 +220,10 @@ class TodoListTester(TopydoTest):
""" Make sure that item has new text ID after append. """
config("test/data/todolist-uid.conf")
todo = self.todolist.todo('6iu')
todo = self.todolist.todo('t5c')
self.todolist.append(todo, "A")
self.assertNotEquals(self.todolist.number(todo), '6iu')
self.assertNotEqual(self.todolist.number(todo), 't5c')
class TodoListDependencyTester(TopydoTest):
def setUp(self):
......@@ -299,7 +299,7 @@ class TodoListDependencyTester(TopydoTest):
self.todolist.add_dependency(todo6, todo7)
self.assertEquals(projects, todo7.projects())
self.assertEqual(projects, todo7.projects())
def test_add_dep4(self):
"""
......@@ -312,7 +312,7 @@ class TodoListDependencyTester(TopydoTest):
self.todolist.add_dependency(todo6, todo8)
self.assertEquals(set(["Project", "AnotherProject"]), todo8.projects())
self.assertEqual(set(["Project", "AnotherProject"]), todo8.projects())
def test_remove_dep1(self):
from_todo = self.todolist.todo(3)
......@@ -328,7 +328,7 @@ class TodoListDependencyTester(TopydoTest):
to_todo = self.todolist.todo(4)
self.todolist.remove_dependency(from_todo, to_todo)
self.assertEquals(str(self.todolist), old)
self.assertEqual(str(self.todolist), old)
def test_remove_todo_check_children(self):
todo = self.todolist.todo(2)
......
......@@ -34,7 +34,7 @@ class ViewTest(TopydoTest):
todofilter = Filter.GrepFilter('+Project')
view = todolist.view(sorter, [todofilter])
self.assertEquals(str(view), todolist_to_string(ref))
self.assertEqual(str(view), todolist_to_string(ref))
if __name__ == '__main__':
unittest.main()
......
Foo @foóbąr due:tod id:1
Bar +baz t:tod before:1
[colorscheme]
priority_colors = A:1,B:2,C:3
[colorscheme]
priority_colors = A:magenta,B:light-cyan,C:gray
[colorscheme]
priority_colors = A:magenta,B:light-cyan,C:7,D:red,Z:foobar
[colorscheme]
priority_colors = A:,B:,C:
[colorscheme]
priority_colors =
project_color =
context_color =
link_color =
metadata_color =
[{"completed": false, "completion_date": null, "contexts": ["Context2"], "creation_date": null, "priority": "C", "projects": ["Project1"], "source": "(C) Foo @Context2 Not@Context +Project1 Not+Project", "tags": [], "text": "Foo @Context2 Not@Context +Project1 Not+Project"}, {"completed": false, "completion_date": null, "contexts": [], "creation_date": null, "priority": "C", "projects": [], "source": "(C) Drink beer @ home", "tags": [], "text": "Drink beer @ home"}, {"completed": false, "completion_date": null, "contexts": [], "creation_date": null, "priority": "C", "projects": [], "source": "(C) 13 + 29 = 42", "tags": [], "text": "13 + 29 = 42"}, {"completed": false, "completion_date": null, "contexts": ["Context1"], "creation_date": null, "priority": "D", "projects": ["Project2"], "source": "(D) Bar @Context1 +Project2 p:1", "tags": [["p", "1"]], "text": "Bar @Context1 +Project2"}]
This diff was suppressed by a .gitattributes entry.
[{"completed": false, "completion_date": null, "contexts": [], "creation_date": null, "priority": "C", "projects": [], "source": "(C) And some spécial tag:◄", "tags": [["tag", "◄"]], "text": "And some spécial"}]
(C) And some spécial tag:◄
(C) ► UTF-8 test ◄
......@@ -30,3 +30,16 @@ ignore_weekends = 1
append_parent_projects = 0
; Add parent contexts when adding sub todo items
append_parent_contexts = 0
[colorscheme]
; Configure colorscheme. Accepted values are: black, [light-]red, [light-]green,
; [light-]yellow, [light-]blue, [light-]magenta, [light-]cyan, white
; [light-]gray, darkgray or numbers from 0 to 255. When number is specified color
; is matched from Xterm color chart available here:
; http://en.wikipedia.org/wiki/File:Xterm_256color_chart.svg
; priority_colors = A:cyan,B:yellow,C:blue
; project_color = red
; context_color = magenta
; metadata_color = green
; link_color = light-cyan
......@@ -19,48 +19,36 @@ This module is aware of all supported submodules and hands out a Command
instance based on an argument list.
"""
from topydo.lib.Config import config
import sys
from topydo.lib.AddCommand import AddCommand
from topydo.lib.AppendCommand import AppendCommand
from topydo.lib.DeleteCommand import DeleteCommand
from topydo.lib.DepCommand import DepCommand
from topydo.lib.DepriCommand import DepriCommand
from topydo.lib.DoCommand import DoCommand
from topydo.lib.EditCommand import EditCommand
from topydo.lib.IcalCommand import IcalCommand
from topydo.lib.ListCommand import ListCommand
from topydo.lib.ListContextCommand import ListContextCommand
from topydo.lib.ListProjectCommand import ListProjectCommand
from topydo.lib.PostponeCommand import PostponeCommand
from topydo.lib.PriorityCommand import PriorityCommand
from topydo.lib.SortCommand import SortCommand
from topydo.lib.TagCommand import TagCommand
from topydo.lib.Config import config
_SUBCOMMAND_MAP = {
'add': AddCommand,
'app': AppendCommand,
'append': AppendCommand,
'del': DeleteCommand,
'dep': DepCommand,
'depri': DepriCommand,
'do': DoCommand,
'edit': EditCommand,
'ical': IcalCommand,
'ls': ListCommand,
'lscon': ListContextCommand,
'listcon': ListContextCommand,
'lsprj': ListProjectCommand,
'lsproj': ListProjectCommand,
'listprj': ListProjectCommand,
'listproj': ListProjectCommand,
'listproject': ListProjectCommand,
'listprojects': ListProjectCommand,
'postpone': PostponeCommand,
'pri': PriorityCommand,
'rm': DeleteCommand,
'sort': SortCommand,
'tag': TagCommand,
'add': 'AddCommand',
'app': 'AppendCommand',
'append': 'AppendCommand',
'del': 'DeleteCommand',
'dep': 'DepCommand',
'depri': 'DepriCommand',
'do': 'DoCommand',
'edit': 'EditCommand',
'exit': 'ExitCommand', # used for the prompt
'ical': 'IcalCommand', # deprecated
'ls': 'ListCommand',
'lscon': 'ListContextCommand',
'listcon': 'ListContextCommand',
'lsprj': 'ListProjectCommand',
'lsproj': 'ListProjectCommand',
'listprj': 'ListProjectCommand',
'listproj': 'ListProjectCommand',
'listproject': 'ListProjectCommand',
'listprojects': 'ListProjectCommand',
'postpone': 'PostponeCommand',
'pri': 'PriorityCommand',
'quit': 'ExitCommand',
'rm': 'DeleteCommand',
'sort': 'SortCommand',
'tag': 'TagCommand',
}
def get_subcommand(p_args):
......@@ -78,6 +66,18 @@ def get_subcommand(p_args):
If no valid command could be found, the subcommand part of the tuple
is None.
"""
def import_subcommand(p_subcommand):
"""
Returns the class of the requested subcommand. An invalid p_subcommand
will result in an ImportError, since this is a programming mistake
(most likely an error in the _SUBCOMMAND_MAP).
"""
classname = _SUBCOMMAND_MAP[p_subcommand]
modulename = 'topydo.commands.{}'.format(classname)
__import__(modulename, globals(), locals(), [classname], 0)
return getattr(sys.modules[modulename], classname)
result = None
args = p_args
......@@ -85,7 +85,7 @@ def get_subcommand(p_args):
subcommand = p_args[0]
if subcommand in _SUBCOMMAND_MAP:
result = _SUBCOMMAND_MAP[subcommand]
result = import_subcommand(subcommand)
args = args[1:]
elif subcommand == 'help':
try:
......@@ -100,12 +100,12 @@ def get_subcommand(p_args):
else:
p_command = config().default_command()
if p_command in _SUBCOMMAND_MAP:
result = _SUBCOMMAND_MAP[p_command]
result = import_subcommand(p_command)
# leave args unchanged
except IndexError:
p_command = config().default_command()
if p_command in _SUBCOMMAND_MAP:
result = _SUBCOMMAND_MAP[p_command]
result = import_subcommand(p_command)
return (result, args)
# 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/>.
""" Entry file for the Python todo.txt CLI. """
import sys
from topydo.cli.CLIApplicationBase import CLIApplicationBase, error
from topydo.lib import TodoFile
from topydo.lib.Config import config, ConfigError
# First thing is to poke the configuration and check whether it's sane
# The modules below may already read in configuration upon import, so
# make sure to bail out if the configuration is invalid.
try:
config()
except ConfigError as config_error:
error(str(config_error))
sys.exit(1)
from topydo.Commands import get_subcommand
from topydo.lib import TodoList
class CLIApplication(CLIApplicationBase):
"""
Class that represents the (original) Command Line Interface of Topydo.
"""
def __init__(self):
super(CLIApplication, self).__init__()
def run(self):
""" Main entry function. """
args = self._process_flags()
self.todofile = TodoFile.TodoFile(config().todotxt())
self.todolist = TodoList.TodoList(self.todofile.read())
(subcommand, args) = get_subcommand(args)
if subcommand == None:
self._usage()
if self._execute(subcommand, args) == False:
sys.exit(1)
def main():
""" Main entry point of the CLI. """
CLIApplication().run()
if __name__ == '__main__':
main()
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 - 2015 Bram Schoenmakers <me@bramschoenmakers.nl>
# Copyright (C) 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
......@@ -14,15 +14,22 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
""" Entry file for the Python todo.txt CLI. """
"""
Contains a base class for a CLI implementation of topydo and functions for the
I/O on the command-line.
"""
import getopt
import sys
from six import PY2
from six.moves import input
MAIN_OPTS = "c:d:ht:v"
def usage():
""" Prints the command-line usage of topydo. """
print """\
print("""\
Synopsis: topydo [-c <config>] [-d <archive>] [-t <todo.txt>] subcommand [help|args]
topydo -h
topydo -v
......@@ -52,9 +59,7 @@ Available commands:
* tag
Run `topydo help <subcommand>` for command-specific help.
"""
sys.exit(0)
""")
def write(p_file, p_string):
"""
......@@ -76,8 +81,8 @@ def error(p_string):
def version():
""" Print the current version and exit. """
from topydo.lib.Version import VERSION, LICENSE
print "topydo {}\n".format(VERSION)
print LICENSE
print("topydo {}\n".format(VERSION))
print(LICENSE)
sys.exit(0)
from topydo.lib.Config import config, ConfigError
......@@ -91,52 +96,59 @@ except ConfigError as config_error:
error(str(config_error))
sys.exit(1)
from topydo.lib.Commands import get_subcommand
from topydo.lib.ArchiveCommand import ArchiveCommand
from topydo.lib.SortCommand import SortCommand
from topydo.commands.ArchiveCommand import ArchiveCommand
from topydo.commands.SortCommand import SortCommand
from topydo.lib import TodoFile
from topydo.lib import TodoList
from topydo.lib import TodoListBase
from topydo.lib.Utils import escape_ansi
class CLIApplication(object):
class CLIApplicationBase(object):
"""
Class that represents the Command Line Interface of Topydo.
Base class for a Command Line Interfaces (CLI) for topydo. Examples are the
original CLI and the Prompt interface.
Handles input/output of the various subcommand.
Handles input/output of the various subcommands.
"""
def __init__(self):
self.todolist = TodoList.TodoList([])
self.todofile = None
self.config = config()
self.path = self.config.todotxt()
self.archive_path = self.config.archive()
def _usage(self):
usage()
sys.exit(0)
def _process_flags(self):
args = sys.argv[1:]
if PY2:
args = [arg.decode('utf-8') for arg in args]
try:
opts, args = getopt.getopt(sys.argv[1:], "c:d:ht:v")
opts, args = getopt.getopt(args, MAIN_OPTS)
except getopt.GetoptError as e:
error(str(e))
sys.exit(1)
alt_path = None
alt_archive = None
alt_config_path = None
overrides = {}
for opt, value in opts:
if opt == "-c":
self.config = config(value)
alt_config_path = value
elif opt == "-t":
alt_path = value
overrides[('topydo', 'filename')] = value
elif opt == "-d":
alt_archive = value
overrides[('topydo', 'archive_filename')] = value
elif opt == "-v":
version()
else:
usage()
self._usage()
self.path = alt_path if alt_path else self.config.todotxt()
self.archive_path = alt_archive \
if alt_archive else self.config.archive()
if alt_config_path:
config(alt_config_path, overrides)
elif len(overrides):
config(p_overrides=overrides)
return args
......@@ -147,7 +159,7 @@ class CLIApplication(object):
This means that all completed tasks are moved to the archive file
(defaults to done.txt).
"""
archive_file = TodoFile.TodoFile(self.archive_path)
archive_file = TodoFile.TodoFile(config().archive())
archive = TodoListBase.TodoListBase(archive_file.read())
if archive:
......@@ -163,6 +175,12 @@ class CLIApplication(object):
else:
pass # TODO
def _input(self):
"""
Returns a function that retrieves user input.
"""
return input
def _execute(self, p_command, p_args):
"""
Execute a subcommand with arguments. p_command is a class (not an
......@@ -173,36 +191,23 @@ class CLIApplication(object):
self.todolist,
lambda o: write(sys.stdout, o),
error,
raw_input)
return False if command.execute() == False else True
def run(self):
""" Main entry function. """
args = self._process_flags()
self._input())
todofile = TodoFile.TodoFile(self.path)
self.todolist = TodoList.TodoList(todofile.read())
if command.execute() != False:
self._post_execute()
return True
(subcommand, args) = get_subcommand(args)
if subcommand == None:
usage()
if self._execute(subcommand, args) == False:
sys.exit(1)
return False
def _post_execute(self):
if self.todolist.is_dirty():
self._archive()
if config().keep_sorted():
self._execute(SortCommand, [])
todofile.write(str(self.todolist))
self.todofile.write(str(self.todolist))
def main():
""" Main entry point of the CLI. """
CLIApplication().run()
def run(self):
raise NotImplementedError
if __name__ == '__main__':
main()
# Topydo - A todo.txt client written in Python.
# Copyright (C) 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/>.
""" Entry file for the topydo Prompt interface (CLI). """
import os.path
import sys
from topydo.cli.CLIApplicationBase import CLIApplicationBase, error, usage
from topydo.cli.TopydoCompleter import TopydoCompleter
from prompt_toolkit.shortcuts import get_input
from prompt_toolkit.history import History
from topydo.lib.Config import config, ConfigError
# First thing is to poke the configuration and check whether it's sane
# The modules below may already read in configuration upon import, so
# make sure to bail out if the configuration is invalid.
try:
config()
except ConfigError as config_error:
error(str(config_error))
sys.exit(1)
from topydo.Commands import get_subcommand
from topydo.lib import TodoFile
from topydo.lib import TodoList
def _todotxt_mtime():
"""
Returns the mtime for the configured todo.txt file.
"""
try:
return os.path.getmtime(config().todotxt())
except os.error:
# file not found
return None
class PromptApplication(CLIApplicationBase):
"""
This class implements a variant of topydo's CLI showing a shell and
offering auto-completion thanks to the prompt toolkit.
"""
def __init__(self):
super(PromptApplication, self).__init__()
self._process_flags()
self.mtime = None
self.completer = None
def _load_file(self):
"""
Reads the configured todo.txt file and loads it into the todo list
instance.
If the modification time of the todo.txt file is equal to the last time
it was checked, nothing will be done.
"""
current_mtime = _todotxt_mtime()
if not self.todofile or self.mtime != current_mtime:
self.todofile = TodoFile.TodoFile(config().todotxt())
self.todolist = TodoList.TodoList(self.todofile.read())
self.mtime = current_mtime
# suppress upstream issue with Python 2.7
# pylint: disable=no-value-for-parameter
self.completer = TopydoCompleter(self.todolist)
def run(self):
""" Main entry function. """
history = History()
while True:
# (re)load the todo.txt file (only if it has been modified)
self._load_file()
try:
user_input = get_input(u'topydo> ', history=history,
completer=self.completer).split()
except (EOFError, KeyboardInterrupt):
sys.exit(0)
mtime_after = _todotxt_mtime()
if self.mtime != mtime_after:
# refuse to perform operations such as 'del' and 'do' if the
# todo.txt file has been changed in the background.
error("WARNING: todo.txt file was modified by another application.\nTo prevent unintended changes, this operation was not executed.")
continue
(subcommand, args) = get_subcommand(user_input)
try:
if self._execute(subcommand, args) != False:
self._post_execute()
except TypeError:
usage()
def main():
""" Main entry point of the prompt interface. """
PromptApplication().run()
if __name__ == '__main__':
main()
# Topydo - A todo.txt client written in Python.
# Copyright (C) 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 datetime
import re
from prompt_toolkit.completion import Completer, Completion
from topydo.lib.Config import config
from topydo.Commands import _SUBCOMMAND_MAP
from topydo.lib.RelativeDate import relative_date_to_date
def _date_suggestions():
"""
Returns a list of relative date that is presented to the user as auto
complete suggestions.
"""
# don't use strftime, prevent locales to kick in
days_of_week = {
0: "Monday",
1: "Tuesday",
2: "Wednesday",
3: "Thursday",
4: "Friday",
5: "Saturday",
6: "Sunday"
}
dates = [
'today',
'tomorrow',
]
# show days of week up to next week
dow = datetime.date.today().weekday()
for i in range(dow + 2 % 7, dow + 7):
dates.append(days_of_week[i % 7])
# and some more relative days starting from next week
dates += ["1w", "2w", "1m", "2m", "3m", "1y"]
return dates
class TopydoCompleter(Completer):
def __init__(self, p_todolist):
self.todolist = p_todolist
def _subcommands(self, p_word_before_cursor):
subcommands = [sc for sc in sorted(_SUBCOMMAND_MAP.keys()) if sc.startswith(p_word_before_cursor)]
for command in subcommands:
yield Completion(command, -len(p_word_before_cursor))
def _projects(self, p_word_before_cursor):
projects = [p for p in self.todolist.projects() if p.startswith(p_word_before_cursor[1:])]
for project in projects:
yield Completion("+" + project, -len(p_word_before_cursor))
def _contexts(self, p_word_before_cursor):
contexts = [c for c in self.todolist.contexts() if c.startswith(p_word_before_cursor[1:])]
for context in contexts:
yield Completion("@" + context, -len(p_word_before_cursor))
def _dates(self, p_word_before_cursor):
to_absolute = lambda s: relative_date_to_date(s).isoformat()
start_value_pos = p_word_before_cursor.find(':') + 1
value = p_word_before_cursor[start_value_pos:]
for reldate in _date_suggestions():
if not reldate.startswith(value):
continue
yield Completion(reldate, -len(value), display_meta=to_absolute(reldate))
def get_completions(self, p_document, p_complete_event):
# include all characters except whitespaces (for + and @)
word_before_cursor = p_document.get_word_before_cursor(True)
is_first_word = not re.match(r'\s*\S+\s', p_document.current_line_before_cursor)
if is_first_word:
return self._subcommands(word_before_cursor)
elif word_before_cursor.startswith('+'):
return self._projects(word_before_cursor)
elif word_before_cursor.startswith('@'):
return self._contexts(word_before_cursor)
elif word_before_cursor.startswith(config().tag_due() + ':'):
return self._dates(word_before_cursor)
elif word_before_cursor.startswith(config().tag_start() + ':'):
return self._dates(word_before_cursor)
return []
# 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/>.
""" Entry file for the Python todo.txt CLI. """
import sys
import getopt
from topydo.cli.CLIApplicationBase import MAIN_OPTS, error
from topydo.cli.CLI import CLIApplication
def main():
""" Main entry point of the CLI. """
try:
args = sys.argv[1:]
try:
opts, args = getopt.getopt(args, MAIN_OPTS)
except getopt.GetoptError as e:
error(str(e))
sys.exit(1)
if args[0] == 'prompt':
try:
from topydo.cli.Prompt import PromptApplication
PromptApplication().run()
except ImportError:
error("You have to install prompt-toolkit to run prompt mode.")
else:
CLIApplication().run()
except IndexError:
CLIApplication().run()
if __name__ == '__main__':
main()
......@@ -18,6 +18,9 @@
from datetime import date
import re
from sys import stdin
import codecs
from os.path import expanduser
from topydo.lib.Config import config
from topydo.lib.Command import Command
......@@ -33,73 +36,109 @@ class AddCommand(Command):
super(AddCommand, self).__init__(
p_args, p_todolist, p_out, p_err, p_prompt)
self.text = ' '.join(p_args)
self.todo = None
self.from_file = None
def _preprocess_input_todo(self):
"""
Preprocesses user input when adding a task.
def _process_flags(self):
opts, args = self.getopt('f:')
It detects a priority mid-sentence and puts it at the start.
"""
self.text = re.sub(r'^(.+) (\([A-Z]\))(.*)$', r'\2 \1\3', self.text)
for opt, value in opts:
if opt == '-f':
self.from_file = expanduser(value)
def _postprocess_input_todo(self):
"""
Post-processes a parsed todo when adding it to the list.
self.args = args
* 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 = self.todo.tag_value(p_tag)
if value:
dateobj = relative_date_to_date(value)
if dateobj:
self.todo.set_tag(p_tag, dateobj.isoformat())
def get_todos_from_file(self):
if self.from_file == '-':
f = stdin
else:
f = codecs.open(self.from_file, 'r', encoding='utf-8')
todos = f.read().splitlines()
return todos
def _add_todo(self, p_todo_text):
def _preprocess_input_todo(p_todo_text):
"""
Preprocesses user input when adding a task.
It detects a priority mid-sentence and puts it at the start.
"""
todo_text = re.sub(r'^(.+) (\([A-Z]\))(.*)$', r'\2 \1\3', p_todo_text)
return todo_text
def _postprocess_input_todo(p_todo):
"""
Post-processes a parsed todo when adding it to the list.
def add_dependencies(p_tag):
for value in self.todo.tag_values(p_tag):
try:
dep = self.todolist.todo(value)
* 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 p_tag == 'after':
self.todolist.add_dependency(self.todo, dep)
elif p_tag == 'before' or p_tag == 'partof':
self.todolist.add_dependency(dep, self.todo)
except InvalidTodoException:
pass
if value:
dateobj = relative_date_to_date(value)
if dateobj:
p_todo.set_tag(p_tag, dateobj.isoformat())
self.todo.remove_tag(p_tag, value)
def add_dependencies(p_tag):
for value in p_todo.tag_values(p_tag):
try:
dep = self.todolist.todo(value)
convert_date(config().tag_start())
convert_date(config().tag_due())
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
add_dependencies('partof')
add_dependencies('before')
add_dependencies('after')
p_todo.remove_tag(p_tag, value)
self.todo.set_creation_date(date.today())
convert_date(config().tag_start())
convert_date(config().tag_due())
add_dependencies('partof')
add_dependencies('before')
add_dependencies('after')
p_todo.set_creation_date(date.today())
todo_text = _preprocess_input_todo(p_todo_text)
todo = self.todolist.add(todo_text)
_postprocess_input_todo(todo)
self.out(self.printer.print_todo(todo))
def execute(self):
""" Adds a todo item to the list. """
if not super(AddCommand, self).execute():
return False
if self.text:
self._preprocess_input_todo()
self.todo = self.todolist.add(self.text)
self._postprocess_input_todo()
self.printer.add_filter(PrettyPrinterNumbers(self.todolist))
self._process_flags()
if self.from_file:
new_todos = self.get_todos_from_file()
self.printer.add_filter(PrettyPrinterNumbers(self.todolist))
self.out(self.printer.print_todo(self.todo))
for todo in new_todos:
self._add_todo(todo)
else:
self.error(self.usage())
if self.text:
self._add_todo(self.text)
else:
self.error(self.usage())
def usage(self):
return """Synopsis: add <text>"""
return """Synopsis:
add <text>
add -f <file>
add -f -"""
def help(self):
return """\
......@@ -114,4 +153,6 @@ This subcommand automatically adds the creation date to the added item.
todo number (not the dependency number).
Example: add "Subtask partof:1"
-f : Add todo items from specified <file> or from standard input.
"""
......@@ -14,7 +14,7 @@
# 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 topydo.lib.DCommand import DCommand
from topydo.commands.DCommand import DCommand
class DeleteCommand(DCommand):
def __init__(self, p_args, p_todolist,
......
......@@ -16,7 +16,7 @@
from datetime import date
from topydo.lib.DCommand import DCommand
from topydo.commands.DCommand import DCommand
from topydo.lib.PrettyPrinter import PrettyPrinter
from topydo.lib.PrettyPrinterFilter import PrettyPrinterNumbers
from topydo.lib.Recurrence import advance_recurring_todo, strict_advance_recurring_todo, NoRecurrenceException
......
......@@ -18,14 +18,18 @@ import os
from subprocess import call, check_call, CalledProcessError
import tempfile
from six import text_type, u
from topydo.lib.ExpressionCommand import ExpressionCommand
from topydo.lib.MultiCommand import MultiCommand
from topydo.lib.Config import config
from topydo.lib.Todo import Todo
from topydo.lib.TodoListBase import InvalidTodoException
from topydo.lib.TodoList import TodoList
from topydo.lib.PrettyPrinterFilter import PrettyPrinterNumbers
# the true and only editor
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)
......@@ -54,14 +58,14 @@ class EditCommand(MultiCommand, ExpressionCommand):
def _todos_to_temp(self):
f = tempfile.NamedTemporaryFile()
for todo in self.todos:
f.write("%s\n" % todo.__str__())
f.write((text_type(todo) + "\n").encode('utf-8'))
f.seek(0)
return f
def _todos_from_temp(self, temp_file):
temp_file.seek(0)
todos = temp_file.read().splitlines()
def _todos_from_temp(self, p_temp_file):
p_temp_file.seek(0)
todos = p_temp_file.read().decode('utf-8').splitlines()
todo_objs = []
for todo in todos:
......@@ -69,10 +73,10 @@ class EditCommand(MultiCommand, ExpressionCommand):
return todo_objs
def _open_in_editor(self, temp_file, editor):
def _open_in_editor(self, p_temp_file, p_editor):
try:
return check_call([editor, temp_file.name])
except(CalledProcessError):
return check_call([p_editor, p_temp_file.name])
except CalledProcessError:
self.error('Something went wrong in the editor...')
return 1
......@@ -81,7 +85,7 @@ class EditCommand(MultiCommand, ExpressionCommand):
if len(self.invalid_numbers) > 1 or len(self.invalid_numbers) > 0 and len(self.todos) > 0:
for number in self.invalid_numbers:
errors.append("Invalid todo number given: {}.".format(number))
errors.append(u("Invalid todo number given: {}.").format(number))
elif len(self.invalid_numbers) == 1 and len(self.todos) == 0:
errors.append("Invalid todo number given.")
......@@ -96,9 +100,9 @@ class EditCommand(MultiCommand, ExpressionCommand):
self.printer.add_filter(PrettyPrinterNumbers(self.todolist))
try:
editor = os.environ['EDITOR'] or 'vi'
editor = os.environ['EDITOR'] or DEFAULT_EDITOR
except(KeyError):
editor = 'vi'
editor = DEFAULT_EDITOR
try:
if len(self.args) < 1:
......
# Topydo - A todo.txt client written in Python.
# Copyright (C) 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 sys
from topydo.lib.Command import Command
class ExitCommand(Command):
"""
A command that exits topydo. Used for the 'exit' and 'quit' subcommands on
the prompt CLI.
"""
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,
p_input)
def execute(self):
if not super(ExitCommand, self).execute():
return False
sys.exit(0)
# Topydo - A todo.txt client written in Python.
# Copyright (C) 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/>.
"""
Stub for the former 'ical' subcommand, now replaced with 'ls -f ical'.
To be removed.
"""
from topydo.lib.Command import Command
class IcalCommand(Command):
def __init__(self, p_args, p_todolist,
p_out=lambda a: None,
p_err=lambda a: None,
p_prompt=lambda a: None):
super(IcalCommand, self).__init__(
p_args, p_todolist, p_out, p_err, p_prompt)
def execute(self):
self.error("The 'ical' subcommand is deprecated, please use 'ls -f ical' instead.")
return False
def usage(self):
return """Synopsis: ical"""
def help(self):
return """\
Deprecated. Use 'ls -f ical' instead.
"""
......@@ -14,17 +14,14 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re
from topydo.lib.ExpressionCommand import ExpressionCommand
from topydo.lib.Config import config
from topydo.lib import Filter
from topydo.lib.PrettyPrinterFilter import (
PrettyPrinterIndentFilter,
PrettyPrinterHideTagFilter
)
from topydo.lib.Sorter import Sorter
from topydo.lib.View import View
from topydo.lib.IcalPrinter import IcalPrinter
from topydo.lib.JsonPrinter import JsonPrinter
class ListCommand(ExpressionCommand):
def __init__(self, p_args, p_todolist,
......@@ -34,42 +31,92 @@ class ListCommand(ExpressionCommand):
super(ListCommand, self).__init__(
p_args, p_todolist, p_out, p_err, p_prompt)
self.printer = None
self.sort_expression = config().sort_string()
self.show_all = False
def _poke_icalendar(self):
"""
Attempts to import the icalendar package. Returns True if it
succeeds, otherwise False.
Raises a SyntaxError when icalendar couldn't be imported (most likely
under Python 3.2.
"""
try:
import icalendar as _
except ImportError:
self.error("icalendar package is not installed.")
return False
# may also raise SyntaxError, but we'll deal with that in execute()
return True
def _process_flags(self):
opts, args = self.getopt('s:x')
opts, args = self.getopt('f:s:x')
for opt, value in opts:
if opt == '-x':
self.show_all = True
elif opt == '-s':
self.sort_expression = value
elif opt == '-f':
if value == 'json':
self.printer = JsonPrinter()
elif value == 'ical':
if self._poke_icalendar():
self.printer = IcalPrinter(self.todolist)
else:
self.printer = None
self.args = args
def _print(self):
""" Prints the todos. """
indent = config().list_indent()
hidden_tags = config().hidden_tags()
filters = []
filters.append(PrettyPrinterIndentFilter(indent))
filters.append(PrettyPrinterHideTagFilter(hidden_tags))
self.out(self._view().pretty_print(filters))
"""
Prints the todos in the right format.
Defaults to normal text output (with possible colors and other pretty
printing. If a format was specified on the commandline, this format is
sent to the output.
"""
def _print_text():
"""
Outputs a pretty-printed text format of the todo list.
"""
indent = config().list_indent()
hidden_tags = config().hidden_tags()
filters = []
filters.append(PrettyPrinterIndentFilter(indent))
filters.append(PrettyPrinterHideTagFilter(hidden_tags))
self.out(self._view().pretty_print(filters))
if self.printer == None:
_print_text()
else:
# we have set a special format, simply use the printer set in
# self.printer
self.out(str(self._view()))
def execute(self):
if not super(ListCommand, self).execute():
return False
self._process_flags()
self._print()
try:
self._process_flags()
except SyntaxError:
# importing icalendar failed, most likely due to Python 3.2
self.error("icalendar is not supported in this Python version.")
return False
self._print()
return True
def usage(self):
return """Synopsis: ls [-x] [-s <sort_expression>] [expression]"""
return """ Synopsis: ls [-x] [-s <sort_expression>] [-f <format>] [expression]"""
def help(self):
return """\
......@@ -81,6 +128,14 @@ Lists all relevant todos. A todo is relevant when:
When an expression is given, only the todos matching that expression are shown.
-f : Specify the output format, being 'text' (default), 'ical' or 'json'.
* 'text' - Text output with colors and identation if applicable.
* 'ical' - iCalendar (RFC 2445). Is not supported in Python 3.2. Be aware
that this is not a read-only operation, todo items may obtain
an 'ical' tag with a unique ID. Completed todo items may be
archived.
* 'json' - Javascript Object Notation (JSON)
-s : Sort the list according to a sort expression. Defaults to the expression
in the configuration.
-x : Show all todos (i.e. do not filter on dependencies or relevance).
......
......@@ -28,7 +28,7 @@ class ListContextCommand(Command):
if not super(ListContextCommand, self).execute():
return False
for context in sorted(self.todolist.contexts(), key=str.lower):
for context in sorted(self.todolist.contexts(), key=lambda s: s.lower()):
self.out(context)
def usage(self):
......
......@@ -28,7 +28,7 @@ class ListProjectCommand(Command):
if not super(ListProjectCommand, self).execute():
return False
for project in sorted(self.todolist.projects(), key=str.lower):
for project in sorted(self.todolist.projects(), key=lambda s: s.lower()):
self.out(project)
def usage(self):
......
......@@ -68,8 +68,10 @@ class PostponeCommand(MultiCommand):
if self.move_start_date and todo.has_tag(config().tag_start()):
length = todo.length()
new_start = new_due - timedelta(length)
# pylint: disable=E1103
todo.set_tag(config().tag_start(), new_start.isoformat())
# pylint: disable=E1103
todo.set_tag(config().tag_due(), new_due.isoformat())
self.todolist.set_dirty()
......
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