Commit 15f497ee authored by Bram Schoenmakers's avatar Bram Schoenmakers

Merge branch 'master' into ls-format

parents 691074ad ea00801f
...@@ -14,11 +14,22 @@ matrix: ...@@ -14,11 +14,22 @@ matrix:
- python: "pypy" - python: "pypy"
- python: "pypy3" - python: "pypy3"
install: install:
- "python -m pip install pip --upgrade"
- "pip install ." - "pip install ."
- "pip install icalendar" - "pip install .[ical]"
- "pip install pylint" - "pip install .[test]"
script: "./run-tests.sh" - "pip install coveralls"
script:
- "green -vvr"
- "python -m pylint --errors-only topydo test"
# Cache Dependencies # Cache Dependencies
after_script:
- if [[ $TRAVIS_PYTHON_VERSION == 3.4 ]]; then
coveralls;
fi
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then
coveralls;
fi
cache: cache:
directories: directories:
- $HOME/travis/.cache/pip - $HOME/travis/.cache/pip
......
...@@ -5,10 +5,6 @@ smoothly into topydo. ...@@ -5,10 +5,6 @@ smoothly into topydo.
### General ### General
* 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.
* Use descriptive commit messages. The post * Use descriptive commit messages. The post
[How to write a commit message](http://chris.beams.io/posts/git-commit/) by [How to write a commit message](http://chris.beams.io/posts/git-commit/) by
Chris Beams has some good guidelines. Chris Beams has some good guidelines.
...@@ -26,7 +22,7 @@ smoothly into topydo. ...@@ -26,7 +22,7 @@ smoothly into topydo.
* Run tests with: * Run tests with:
./run-tests.sh [python2|python3] green
Obviously, I won't accept anything that makes the tests fail. When you submit 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 a Pull Request, Travis CI will automatically run all tests for various Python
......
topydo topydo
====== ======
[![Build Status](https://travis-ci.org/bram85/topydo.svg?branch=master)](https://travis-ci.org/bram85/topydo) [![Join the chat at https://gitter.im/bram85/topydo](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bram85/topydo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=bram85&url=https://github.com/bram85/topydo&title=topydo&language=&tags=github&category=software) [![Build Status](https://travis-ci.org/bram85/topydo.svg?branch=master)](https://travis-ci.org/bram85/topydo) [![Coverage Status](https://coveralls.io/repos/bram85/topydo/badge.svg?branch=master&service=github)](https://coveralls.io/github/bram85/topydo?branch=master) [![Join the chat at https://gitter.im/bram85/topydo](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bram85/topydo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=bram85&url=https://github.com/bram85/topydo&title=topydo&language=&tags=github&category=software)
topydo is a todo list application using the [todo.txt format][1]. It is heavily topydo is a todo list application using the [todo.txt format][1]. It is heavily
inspired by the [todo.txt CLI][2] by Gina Trapani. This tool is actually a inspired by the [todo.txt CLI][2] by Gina Trapani. This tool is actually a
...@@ -43,6 +43,6 @@ Demo ...@@ -43,6 +43,6 @@ Demo
[2]: https://github.com/ginatrapani/todo.txt-cli [2]: https://github.com/ginatrapani/todo.txt-cli
[3]: https://github.com/bram85/todo.txt-tools [3]: https://github.com/bram85/todo.txt-tools
[4]: https://github.com/bram85/topydo/wiki [4]: https://github.com/bram85/topydo/wiki
[5]: https://raw.githubusercontent.com/bram85/topydo/stable/doc/topydo.gif [5]: https://raw.githubusercontent.com/bram85/topydo/master/doc/topydo.gif
[6]: https://github.com/jonathanslenders/python-prompt-toolkit [6]: https://github.com/jonathanslenders/python-prompt-toolkit
[7]: https://github.com/collective/icalendar [7]: https://github.com/collective/icalendar
#!/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
...@@ -35,9 +35,12 @@ setup( ...@@ -35,9 +35,12 @@ setup(
], ],
extras_require = { extras_require = {
':sys_platform=="win32"': ['colorama>=0.2.5'], ':sys_platform=="win32"': ['colorama>=0.2.5'],
':python_version=="2.7"': ['ushlex'],
'ical': ['icalendar'], 'ical': ['icalendar'],
'prompt-toolkit': ['prompt-toolkit >= 0.53'], 'prompt-toolkit': ['prompt-toolkit >= 0.53'],
'edit-cmd-tests': ['mock'], 'edit-cmd-tests': ['mock'],
'test': ['green', 'coverage'],
'test:python_version!="3.2"': ['pylint'],
}, },
entry_points= { entry_points= {
'console_scripts': ['topydo = topydo.cli.UILoader:main'], 'console_scripts': ['topydo = topydo.cli.UILoader:main'],
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib.Utils import escape_ansi from topydo.lib.Utils import escape_ansi
......
[aliases] [aliases]
foo = rm -f test foo = rm -f test
baz = FooBar baz = FooBar
format = ls -F "|I| x c d {(}p{)} s k" -n 25
smile = ls
...@@ -20,7 +20,7 @@ from io import StringIO ...@@ -20,7 +20,7 @@ from io import StringIO
from six import u from six import u
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from topydo.commands import AddCommand, ListCommand from topydo.commands import AddCommand, ListCommand
from topydo.lib import TodoList from topydo.lib import TodoList
from topydo.lib.Config import config from topydo.lib.Config import config
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
import unittest import unittest
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from topydo.commands.AppendCommand import AppendCommand from topydo.commands.AppendCommand import AppendCommand
from topydo.lib.TodoList import TodoList from topydo.lib.TodoList import TodoList
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
import unittest import unittest
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from test.Facilities import load_file_to_todolist from test.facilities import load_file_to_todolist
from topydo.commands.ArchiveCommand import ArchiveCommand from topydo.commands.ArchiveCommand import ArchiveCommand
from topydo.lib.TodoList import TodoList from topydo.lib.TodoList import TodoList
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
import unittest import unittest
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib.Colors import NEUTRAL_COLOR, Colors from topydo.lib.Colors import NEUTRAL_COLOR, Colors
from topydo.lib.Config import config from topydo.lib.Config import config
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
import unittest import unittest
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib.Config import config from topydo.lib.Config import config
......
...@@ -18,7 +18,7 @@ import unittest ...@@ -18,7 +18,7 @@ import unittest
from six import u from six import u
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from topydo.commands.DeleteCommand import DeleteCommand from topydo.commands.DeleteCommand import DeleteCommand
from topydo.lib.Config import config from topydo.lib.Config import config
from topydo.lib.TodoList import TodoList from topydo.lib.TodoList import TodoList
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
import unittest import unittest
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from topydo.commands.DepCommand import DepCommand from topydo.commands.DepCommand import DepCommand
from topydo.lib.TodoList import TodoList from topydo.lib.TodoList import TodoList
......
...@@ -18,7 +18,7 @@ import unittest ...@@ -18,7 +18,7 @@ import unittest
from six import u from six import u
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from topydo.commands.DepriCommand import DepriCommand from topydo.commands.DepriCommand import DepriCommand
from topydo.lib.TodoList import TodoList from topydo.lib.TodoList import TodoList
......
...@@ -19,7 +19,7 @@ from datetime import date, timedelta ...@@ -19,7 +19,7 @@ from datetime import date, timedelta
from six import u from six import u
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from topydo.commands.DoCommand import DoCommand from topydo.commands.DoCommand import DoCommand
from topydo.lib.TodoList import TodoList from topydo.lib.TodoList import TodoList
......
...@@ -19,7 +19,7 @@ import unittest ...@@ -19,7 +19,7 @@ import unittest
from six import u from six import u
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from topydo.commands.EditCommand import EditCommand from topydo.commands.EditCommand import EditCommand
from topydo.lib.Config import config from topydo.lib.Config import config
from topydo.lib.Todo import Todo from topydo.lib.Todo import Todo
...@@ -96,24 +96,7 @@ class EditCommandTest(CommandTest): ...@@ -96,24 +96,7 @@ class EditCommandTest(CommandTest):
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.is_dirty())
self.assertEqual(self.errors, "Invalid todo number given: 5.\n") self.assertEqual(self.errors, "Invalid todo number given: 5.\n")
@mock.patch('topydo.commands.EditCommand._is_edited') def test_edit05(self):
@mock.patch('topydo.commands.EditCommand.EditCommand._todos_from_temp')
@mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor')
def test_edit05(self, mock_open_in_editor, mock_todos_from_temp, mock_is_edited):
""" 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')]
mock_is_edited.return_value = True
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(self.todolist.print_todos(), u("Foo id:1\nBar p:1 @test\nBaz @test\nFo\u00f3B\u0105\u017a"))
def test_edit06(self):
""" """
Throw an error with invalid argument containing special characters. Throw an error with invalid argument containing special characters.
""" """
...@@ -128,7 +111,7 @@ class EditCommandTest(CommandTest): ...@@ -128,7 +111,7 @@ class EditCommandTest(CommandTest):
@mock.patch('topydo.commands.EditCommand._is_edited') @mock.patch('topydo.commands.EditCommand._is_edited')
@mock.patch('topydo.commands.EditCommand.EditCommand._todos_from_temp') @mock.patch('topydo.commands.EditCommand.EditCommand._todos_from_temp')
@mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor') @mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor')
def test_edit07(self, mock_open_in_editor, mock_todos_from_temp, mock_is_edited): def test_edit06(self, mock_open_in_editor, mock_todos_from_temp, mock_is_edited):
""" Edit todo with special characters. """ """ Edit todo with special characters. """
mock_open_in_editor.return_value = 0 mock_open_in_editor.return_value = 0
mock_todos_from_temp.return_value = [Todo('Lazy Cat')] mock_todos_from_temp.return_value = [Todo('Lazy Cat')]
...@@ -146,7 +129,7 @@ class EditCommandTest(CommandTest): ...@@ -146,7 +129,7 @@ class EditCommandTest(CommandTest):
@mock.patch('topydo.commands.EditCommand._is_edited') @mock.patch('topydo.commands.EditCommand._is_edited')
@mock.patch('topydo.commands.EditCommand.EditCommand._todos_from_temp') @mock.patch('topydo.commands.EditCommand.EditCommand._todos_from_temp')
@mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor') @mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor')
def test_edit08(self, mock_open_in_editor, mock_todos_from_temp, mock_is_edited): def test_edit07(self, mock_open_in_editor, mock_todos_from_temp, mock_is_edited):
""" Don't perform write if tempfile is unchanged """ """ Don't perform write if tempfile is unchanged """
mock_open_in_editor.return_value = 0 mock_open_in_editor.return_value = 0
mock_todos_from_temp.return_value = [Todo('Only one line')] mock_todos_from_temp.return_value = [Todo('Only one line')]
......
...@@ -19,9 +19,9 @@ ...@@ -19,9 +19,9 @@
import unittest import unittest
from datetime import date, timedelta from datetime import date, timedelta
from test.Facilities import (load_file, load_file_to_todolist, from test.facilities import (load_file, load_file_to_todolist,
todolist_to_string) todolist_to_string)
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib import Filter from topydo.lib import Filter
from topydo.lib.Todo import Todo from topydo.lib.Todo import Todo
......
...@@ -18,7 +18,7 @@ import unittest ...@@ -18,7 +18,7 @@ import unittest
from six import u from six import u
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.Commands import get_subcommand from topydo.Commands import get_subcommand
from topydo.commands.AddCommand import AddCommand from topydo.commands.AddCommand import AddCommand
from topydo.commands.DeleteCommand import DeleteCommand from topydo.commands.DeleteCommand import DeleteCommand
...@@ -38,7 +38,7 @@ class GetSubcommandTest(TopydoTest): ...@@ -38,7 +38,7 @@ class GetSubcommandTest(TopydoTest):
self.assertTrue(issubclass(real_cmd, AddCommand)) self.assertTrue(issubclass(real_cmd, AddCommand))
self.assertEqual(final_args, ["help"]) self.assertEqual(final_args, ["help"])
def test_alias(self): def test_alias01(self):
config("test/data/aliases.conf") config("test/data/aliases.conf")
args = ["foo"] args = ["foo"]
...@@ -46,6 +46,22 @@ class GetSubcommandTest(TopydoTest): ...@@ -46,6 +46,22 @@ class GetSubcommandTest(TopydoTest):
self.assertTrue(issubclass(real_cmd, DeleteCommand)) self.assertTrue(issubclass(real_cmd, DeleteCommand))
self.assertEqual(final_args, ["-f", "test"]) self.assertEqual(final_args, ["-f", "test"])
def test_alias02(self):
config("test/data/aliases.conf")
args = ["format"]
real_cmd, final_args = get_subcommand(args)
self.assertTrue(issubclass(real_cmd, ListCommand))
self.assertEqual(final_args, ["-F", "|I| x c d {(}p{)} s k", "-n", "25"])
def test_alias03(self):
config("test/data/aliases.conf")
args = ["smile"]
real_cmd, final_args = get_subcommand(args)
self.assertTrue(issubclass(real_cmd, ListCommand))
self.assertEqual(final_args, [u("\u263b")])
def test_default_cmd01(self): def test_default_cmd01(self):
args = ["bar"] args = ["bar"]
real_cmd, final_args = get_subcommand(args) real_cmd, final_args = get_subcommand(args)
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
import unittest import unittest
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib.Graph import DirectedGraph from topydo.lib.Graph import DirectedGraph
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
import unittest import unittest
from datetime import date from datetime import date
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib.Config import config from topydo.lib.Config import config
from topydo.lib.Importance import importance from topydo.lib.Importance import importance
from topydo.lib.Todo import Todo from topydo.lib.Todo import Todo
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
import unittest import unittest
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib.JsonPrinter import JsonPrinter from topydo.lib.JsonPrinter import JsonPrinter
from topydo.lib.Todo import Todo from topydo.lib.Todo import Todo
......
...@@ -20,8 +20,8 @@ import unittest ...@@ -20,8 +20,8 @@ import unittest
from six import u from six import u
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from test.Facilities import load_file_to_todolist from test.facilities import load_file_to_todolist
from topydo.commands.ListCommand import ListCommand from topydo.commands.ListCommand import ListCommand
from topydo.lib.Config import config from topydo.lib.Config import config
...@@ -226,6 +226,48 @@ class ListCommandTest(CommandTest): ...@@ -226,6 +226,48 @@ class ListCommandTest(CommandTest):
self.assertFalse(self.todolist.is_dirty()) self.assertFalse(self.todolist.is_dirty())
self.assertEqual(self.output, '| 1| Foo.\n') self.assertEqual(self.output, '| 1| Foo.\n')
def test_list31(self):
""" Don't show any todos with -n 0 """
command = ListCommand(["-n", "0"], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(self.output, "")
self.assertEqual(self.errors, "")
def test_list32(self):
""" Only show the top todo. """
command = ListCommand(["-n", "1"], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(self.output, "| 1| (C) Foo @Context2 Not@Context +Project1 Not+Project\n")
self.assertEqual(self.errors, "")
def test_list33(self):
""" Negative values result in showing all relevent todos. """
command = ListCommand(["-n", "-1"], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(self.output, "| 1| (C) Foo @Context2 Not@Context +Project1 Not+Project\n| 4| (C) Drink beer @ home\n| 5| (C) 13 + 29 = 42\n| 2| (D) Bar @Context1 +Project2\n")
self.assertEqual(self.errors, "")
def test_list34(self):
""" Test non-integer value for -n """
config(p_overrides={('ls', 'list_limit'): '2'})
command = ListCommand(["-n", "foo"], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(self.output, "| 1| (C) Foo @Context2 Not@Context +Project1 Not+Project\n| 4| (C) Drink beer @ home\n")
self.assertEqual(self.errors, "")
def test_list35(self):
""" -x flag takes precedence over -n """
command = ListCommand(["-x", "-n", "foo"], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(self.output, "| 1| (C) Foo @Context2 Not@Context +Project1 Not+Project\n| 3| (C) Baz @Context1 +Project1 key:value\n| 4| (C) Drink beer @ home\n| 5| (C) 13 + 29 = 42\n| 2| (D) Bar @Context1 +Project2\n| 6| x 2014-12-12 Completed but with date:2014-12-12\n")
self.assertEqual(self.errors, "")
def test_help(self): def test_help(self):
command = ListCommand(["help"], self.todolist, self.out, self.error) command = ListCommand(["help"], self.todolist, self.out, self.error)
command.execute() command.execute()
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
import unittest import unittest
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from test.Facilities import load_file_to_todolist from test.facilities import load_file_to_todolist
from topydo.commands.ListContextCommand import ListContextCommand from topydo.commands.ListContextCommand import ListContextCommand
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
import unittest import unittest
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from test.Facilities import load_file_to_todolist from test.facilities import load_file_to_todolist
from topydo.commands.ListProjectCommand import ListProjectCommand from topydo.commands.ListProjectCommand import ListProjectCommand
......
...@@ -19,7 +19,7 @@ from datetime import date, timedelta ...@@ -19,7 +19,7 @@ from datetime import date, timedelta
from six import u from six import u
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from topydo.commands.PostponeCommand import PostponeCommand from topydo.commands.PostponeCommand import PostponeCommand
from topydo.lib.TodoList import TodoList from topydo.lib.TodoList import TodoList
......
...@@ -18,7 +18,7 @@ import unittest ...@@ -18,7 +18,7 @@ import unittest
from six import u from six import u
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from topydo.commands.PriorityCommand import PriorityCommand from topydo.commands.PriorityCommand import PriorityCommand
from topydo.lib.TodoList import TodoList from topydo.lib.TodoList import TodoList
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
import unittest import unittest
from datetime import date, timedelta from datetime import date, timedelta
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib.Config import config from topydo.lib.Config import config
from topydo.lib.Recurrence import NoRecurrenceException, advance_recurring_todo from topydo.lib.Recurrence import NoRecurrenceException, advance_recurring_todo
from topydo.lib.Todo import Todo from topydo.lib.Todo import Todo
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
import unittest import unittest
from datetime import date, timedelta from datetime import date, timedelta
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib.RelativeDate import relative_date_to_date from topydo.lib.RelativeDate import relative_date_to_date
......
...@@ -22,7 +22,7 @@ from glob import glob ...@@ -22,7 +22,7 @@ from glob import glob
from six import u from six import u
from uuid import uuid4 from uuid import uuid4
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from topydo.commands.AddCommand import AddCommand from topydo.commands.AddCommand import AddCommand
from topydo.commands.ArchiveCommand import ArchiveCommand from topydo.commands.ArchiveCommand import ArchiveCommand
from topydo.commands.DeleteCommand import DeleteCommand from topydo.commands.DeleteCommand import DeleteCommand
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
import unittest import unittest
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from test.Facilities import load_file_to_todolist from test.facilities import load_file_to_todolist
from topydo.commands.SortCommand import SortCommand from topydo.commands.SortCommand import SortCommand
from topydo.lib.Config import config from topydo.lib.Config import config
......
...@@ -16,9 +16,9 @@ ...@@ -16,9 +16,9 @@
import unittest import unittest
from test.Facilities import (load_file, load_file_to_todolist, print_view, from test.facilities import (load_file, load_file_to_todolist, print_view,
todolist_to_string) todolist_to_string)
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib.Config import config from topydo.lib.Config import config
from topydo.lib.Sorter import Sorter from topydo.lib.Sorter import Sorter
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
import unittest import unittest
from test.CommandTestCase import CommandTest from test.command_testcase import CommandTest
from topydo.commands.TagCommand import TagCommand from topydo.commands.TagCommand import TagCommand
from topydo.lib.TodoList import TodoList from topydo.lib.TodoList import TodoList
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
import unittest import unittest
from datetime import date, timedelta from datetime import date, timedelta
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib.Todo import Todo from topydo.lib.Todo import Todo
......
...@@ -20,7 +20,7 @@ import re ...@@ -20,7 +20,7 @@ import re
import unittest import unittest
from datetime import date, timedelta from datetime import date, timedelta
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib.TodoBase import TodoBase from topydo.lib.TodoBase import TodoBase
......
...@@ -18,8 +18,8 @@ import unittest ...@@ -18,8 +18,8 @@ import unittest
from six import u from six import u
from test.Facilities import load_file from test.facilities import load_file
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
class TodoFileTest(TopydoTest): class TodoFileTest(TopydoTest):
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
import re import re
import unittest import unittest
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib.Config import config from topydo.lib.Config import config
from topydo.lib.Todo import Todo from topydo.lib.Todo import Todo
from topydo.lib.TodoFile import TodoFile from topydo.lib.TodoFile import TodoFile
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
import unittest import unittest
from test.Facilities import load_file, print_view, todolist_to_string from test.facilities import load_file, print_view, todolist_to_string
from test.TopydoTestCase import TopydoTest from test.topydo_testcase import TopydoTest
from topydo.lib import Filter from topydo.lib import Filter
from topydo.lib.Sorter import Sorter from topydo.lib.Sorter import Sorter
from topydo.lib.TodoFile import TodoFile from topydo.lib.TodoFile import TodoFile
......
...@@ -50,6 +50,7 @@ append_parent_contexts = 0 ...@@ -50,6 +50,7 @@ append_parent_contexts = 0
[aliases] [aliases]
;showall = ls -x ;showall = ls -x
;next = ls -n 1
;lsproj = lsprj ;lsproj = lsprj
;listprj = lsprj ;listprj = lsprj
;listproj = lsprj ;listproj = lsprj
......
...@@ -101,12 +101,9 @@ except ConfigError as config_error: ...@@ -101,12 +101,9 @@ except ConfigError as config_error:
error(str(config_error)) error(str(config_error))
sys.exit(1) sys.exit(1)
from topydo.commands.ArchiveCommand import ArchiveCommand
from topydo.commands.SortCommand import SortCommand
from topydo.lib import TodoFile from topydo.lib import TodoFile
from topydo.lib import TodoList from topydo.lib import TodoList
from topydo.lib import TodoListBase from topydo.lib import TodoListBase
from topydo.lib.ChangeSet import ChangeSet
from topydo.lib.Utils import escape_ansi from topydo.lib.Utils import escape_ansi
...@@ -178,6 +175,7 @@ class CLIApplicationBase(object): ...@@ -178,6 +175,7 @@ class CLIApplicationBase(object):
self.backup.add_archive(archive) self.backup.add_archive(archive)
if archive: if archive:
from topydo.commands.ArchiveCommand import ArchiveCommand
command = ArchiveCommand(self.todolist, archive) command = ArchiveCommand(self.todolist, archive)
command.execute() command.execute()
...@@ -196,14 +194,21 @@ class CLIApplicationBase(object): ...@@ -196,14 +194,21 @@ class CLIApplicationBase(object):
""" """
return input return input
def is_read_only(self, p_command):
""" Returns True when the given command class is read-only. """
read_only_commands = tuple(cmd + 'Command' for cmd in ('Revert', ) +
READ_ONLY_COMMANDS)
return p_command.__module__.endswith(read_only_commands)
def _execute(self, p_command, p_args): def _execute(self, p_command, p_args):
""" """
Execute a subcommand with arguments. p_command is a class (not an Execute a subcommand with arguments. p_command is a class (not an
object). object).
""" """
cmds_wo_backup = tuple(cmd + 'Command' for cmd in ('Revert', ) + READ_ONLY_COMMANDS) if config().backup_count() > 0 and p_command and not self.is_read_only(p_command):
if config().backup_count() > 0 and p_command and not p_command.__module__.endswith(cmds_wo_backup):
call = [p_command.__module__.lower()[16:-7]] + p_args # strip "topydo.commands" and "Command" call = [p_command.__module__.lower()[16:-7]] + p_args # strip "topydo.commands" and "Command"
from topydo.lib.ChangeSet import ChangeSet
self.backup = ChangeSet(self.todolist, p_call=call) self.backup = ChangeSet(self.todolist, p_call=call)
command = p_command( command = p_command(
...@@ -232,6 +237,7 @@ class CLIApplicationBase(object): ...@@ -232,6 +237,7 @@ class CLIApplicationBase(object):
self._archive() self._archive()
if config().keep_sorted(): if config().keep_sorted():
from topydo.commands.SortCommand import SortCommand
self._execute(SortCommand, []) self._execute(SortCommand, [])
if self.backup: if self.backup:
......
...@@ -101,15 +101,14 @@ class PromptApplication(CLIApplicationBase): ...@@ -101,15 +101,14 @@ class PromptApplication(CLIApplicationBase):
sys.exit(0) sys.exit(0)
mtime_after = _todotxt_mtime() mtime_after = _todotxt_mtime()
(subcommand, args) = get_subcommand(user_input)
if self.mtime != mtime_after: # refuse to perform operations such as 'del' and 'do' if the
# refuse to perform operations such as 'del' and 'do' if the # todo.txt file has been changed in the background.
# todo.txt file has been changed in the background. if subcommand and not self.is_read_only(subcommand) and self.mtime != mtime_after:
error("WARNING: todo.txt file was modified by another application.\nTo prevent unintended changes, this operation was not executed.") error("WARNING: todo.txt file was modified by another application.\nTo prevent unintended changes, this operation was not executed.")
continue continue
(subcommand, args) = get_subcommand(user_input)
try: try:
if self._execute(subcommand, args) != False: if self._execute(subcommand, args) != False:
self._post_execute() self._post_execute()
......
...@@ -116,16 +116,12 @@ class EditCommand(MultiCommand): ...@@ -116,16 +116,12 @@ class EditCommand(MultiCommand):
new_todos = self._todos_from_temp(temp_todos) new_todos = self._todos_from_temp(temp_todos)
if _is_edited(orig_mtime, temp_todos): if _is_edited(orig_mtime, temp_todos):
if len(new_todos) == len(self.todos): for todo in self.todos:
for todo in self.todos: BASE_TODOLIST(self.todolist).delete(todo)
BASE_TODOLIST(self.todolist).delete(todo)
for todo in new_todos:
for todo in new_todos: self.todolist.add_todo(todo)
self.todolist.add_todo(todo) self.out(self.printer.print_todo(todo))
self.out(self.printer.print_todo(todo))
else:
self.error('Number of edited todos is not equal to '
'number of supplied todo IDs.')
else: else:
self.error('Editing aborted. Nothing to do.') self.error('Editing aborted. Nothing to do.')
else: else:
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
from topydo.lib.Config import config from topydo.lib.Config import config
from topydo.lib.ExpressionCommand import ExpressionCommand from topydo.lib.ExpressionCommand import ExpressionCommand
from topydo.lib.IcalPrinter import IcalPrinter
from topydo.lib.JsonPrinter import JsonPrinter
from topydo.lib.PrettyPrinter import pretty_printer_factory from topydo.lib.PrettyPrinter import pretty_printer_factory
from topydo.lib.PrettyPrinterFilter import (PrettyPrinterHideTagFilter, from topydo.lib.PrettyPrinterFilter import (PrettyPrinterHideTagFilter,
PrettyPrinterIndentFilter, PrettyPrinterIndentFilter,
...@@ -51,7 +49,7 @@ class ListCommand(ExpressionCommand): ...@@ -51,7 +49,7 @@ class ListCommand(ExpressionCommand):
return True return True
def _process_flags(self): def _process_flags(self):
opts, args = self.getopt('f:F:s:x') opts, args = self.getopt('f:F:n:s:x')
for opt, value in opts: for opt, value in opts:
if opt == '-x': if opt == '-x':
...@@ -60,14 +58,21 @@ class ListCommand(ExpressionCommand): ...@@ -60,14 +58,21 @@ class ListCommand(ExpressionCommand):
self.sort_expression = value self.sort_expression = value
elif opt == '-f': elif opt == '-f':
if value == 'json': if value == 'json':
from topydo.lib.JsonPrinter import JsonPrinter
self.printer = JsonPrinter() self.printer = JsonPrinter()
elif value == 'ical': elif value == 'ical':
if self._poke_icalendar(): if self._poke_icalendar():
from topydo.lib.IcalPrinter import IcalPrinter
self.printer = IcalPrinter(self.todolist) self.printer = IcalPrinter(self.todolist)
else: else:
self.printer = None self.printer = None
elif opt == '-F': elif opt == '-F':
self.format = value self.format = value
elif opt == '-n':
try:
self.limit = int(value)
except ValueError:
pass # use default value in configuration
self.args = args self.args = args
......
...@@ -110,7 +110,7 @@ class ChangeSet(object): ...@@ -110,7 +110,7 @@ class ChangeSet(object):
self._write() self._write()
self.close() self.close()
def delete(self, p_timestamp=None): def delete(self, p_timestamp=None, p_write=True):
""" Removes backup from the backup file. """ """ Removes backup from the backup file. """
timestamp = p_timestamp or self.timestamp timestamp = p_timestamp or self.timestamp
index = self._get_index() index = self._get_index()
...@@ -119,7 +119,9 @@ class ChangeSet(object): ...@@ -119,7 +119,9 @@ class ChangeSet(object):
del self.backup_dict[timestamp] del self.backup_dict[timestamp]
index.remove(index[[change[0] for change in index].index(timestamp)]) index.remove(index[[change[0] for change in index].index(timestamp)])
self._save_index(index) self._save_index(index)
self._write()
if p_write:
self._write()
except KeyError: except KeyError:
pass pass
...@@ -143,12 +145,15 @@ class ChangeSet(object): ...@@ -143,12 +145,15 @@ class ChangeSet(object):
""" """
Removes oldest backups that exceed the limit configured in backup_count Removes oldest backups that exceed the limit configured in backup_count
option. option.
Does not write back to file system, make sure to call self._write()
afterwards.
""" """
index = self._get_index() index = self._get_index()
backup_limit = config().backup_count() - 1 backup_limit = config().backup_count() - 1
for changeset in index[backup_limit:]: for changeset in index[backup_limit:]:
self.delete(changeset[0]) self.delete(changeset[0], p_write=False)
def get_backup(self, p_todolist): def get_backup(self, p_todolist):
""" """
......
...@@ -17,9 +17,13 @@ ...@@ -17,9 +17,13 @@
import os import os
import shlex import shlex
from six import iteritems from six import iteritems, PY2
from six.moves import configparser from six.moves import configparser
if PY2:
import ushlex as shlex
import codecs
class ConfigError(Exception): class ConfigError(Exception):
def __init__(self, p_text): def __init__(self, p_text):
self.text = p_text self.text = p_text
...@@ -133,7 +137,15 @@ class _Config: ...@@ -133,7 +137,15 @@ class _Config:
if p_path is not None: if p_path is not None:
files = [p_path] files = [p_path]
self.cp.read(files) if PY2:
for path in files:
try:
with codecs.open(path, 'r', encoding='utf-8') as f:
self.cp.readfp(f)
except IOError:
pass
else:
self.cp.read(files)
self._supplement_sections() self._supplement_sections()
......
...@@ -37,6 +37,7 @@ class ExpressionCommand(Command): ...@@ -37,6 +37,7 @@ class ExpressionCommand(Command):
self.sort_expression = config().sort_string() self.sort_expression = config().sort_string()
self.show_all = False self.show_all = False
self.limit = config().list_limit()
# Commands using last argument differently (i.e as something other than # Commands using last argument differently (i.e as something other than
# todo ID/expression) have to set attribute below to True. # todo ID/expression) have to set attribute below to True.
self.last_argument = False self.last_argument = False
...@@ -75,7 +76,7 @@ class ExpressionCommand(Command): ...@@ -75,7 +76,7 @@ class ExpressionCommand(Command):
filters += arg_filters() filters += arg_filters()
if not self.show_all: if not self.show_all:
filters.append(Filter.LimitFilter(config().list_limit())) filters.append(Filter.LimitFilter(self.limit))
return filters return filters
......
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