Commit 09532f61 authored by Bram Schoenmakers's avatar Bram Schoenmakers

Refactored the View class and Unicode support cleanups.

This started as a refactoring of the View class: to get rid of the
pretty_print() function and anything releated to printers. So the View
class now solely focusses on sorting and viewing a bunch of todos. It's
up to the users of the View class to retrieve the todos in the view and
pass them on to a Printer instance.

The View class was quite involved with the proper Unicode support that
was added lately. There were still encoded string passed through this
class rather than Unicode strings. Getting rid of this affected
basically all other places in the codebase.

The result is that there are less string conversions; printed todo items
stay Unicode as long as possible, until they're actually written out to
standard output or to a file. I got rid of one text_type() call from the
six library, all @python_2_unicode_compatible decorators are gone and
the tests no longer need the utf8() function because everything is
Unicode now.

Remove utf8 function.
parent 34a5d7a4
......@@ -29,7 +29,7 @@ from io import StringIO
from topydo.commands import AddCommand
from topydo.commands import ListCommand
from test.CommandTest import CommandTest, utf8
from test.CommandTest import CommandTest
from topydo.lib.Config import config
from topydo.lib import TodoList
......@@ -127,7 +127,7 @@ class AddCommandTest(CommandTest):
self.assertFalse(self.todolist.todo(1).has_tag("after"))
self.assertEqual(self.todolist.todo(1).source(), self.today + " Foo")
self.assertEqual(self.output, "| 1| " + str(self.todolist.todo(1)) + "\n")
self.assertEqual(self.output, "| 1| " + self.todolist.todo(1).source() + "\n")
self.assertEqual(self.errors, "")
def test_add_dep5(self):
......@@ -137,7 +137,7 @@ class AddCommandTest(CommandTest):
self.assertFalse(self.todolist.todo(1).has_tag("after"))
self.assertEqual(self.todolist.todo(1).source(), self.today + " Foo")
self.assertEqual(self.output, "| 1| " + str(self.todolist.todo(1)) + "\n")
self.assertEqual(self.output, "| 1| " + self.todolist.todo(1).source() + "\n")
self.assertEqual(self.errors, "")
def test_add_dep6(self):
......@@ -248,7 +248,7 @@ class AddCommandTest(CommandTest):
command = AddCommand.AddCommand([u("Special \u25c4")], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(self.output, utf8(u("| 1| {} Special \u25c4\n").format(self.today)))
self.assertEqual(self.output, u("| 1| {} Special \u25c4\n").format(self.today))
self.assertEqual(self.errors, "")
@mock.patch("topydo.commands.AddCommand.stdin", StringIO(u("Fo\u00f3 due:tod id:1\nB\u0105r before:1")))
......@@ -256,14 +256,14 @@ class AddCommandTest(CommandTest):
command = AddCommand.AddCommand(["-f", "-"], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(self.output, utf8(u("| 1| {tod} Fo\u00f3 due:{tod} id:1\n| 2| {tod} B\u0105r p:1\n".format(tod=self.today))))
self.assertEqual(self.output, u("| 1| {tod} Fo\u00f3 due:{tod} id:1\n| 2| {tod} B\u0105r p:1\n".format(tod=self.today)))
self.assertEqual(self.errors, "")
def test_add_from_file(self):
command = AddCommand.AddCommand(["-f", "test/data/AddCommandTest-from_file.txt"], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(self.output, utf8(u("| 1| {tod} Foo @fo\u00f3b\u0105r due:{tod} id:1\n| 2| {tod} Bar +baz t:{tod} p:1\n".format(tod=self.today))))
self.assertEqual(self.output, u("| 1| {tod} Foo @fo\u00f3b\u0105r due:{tod} id:1\n| 2| {tod} Bar +baz t:{tod} p:1\n".format(tod=self.today)))
self.assertEqual(self.errors, "")
def test_help(self):
......
......@@ -31,8 +31,8 @@ class ArchiveCommandTest(CommandTest):
self.assertTrue(todolist.is_dirty())
self.assertTrue(archive.is_dirty())
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")
self.assertEqual(todolist.print_todos(), "x Not complete\n(C) Active")
self.assertEqual(archive.print_todos(), "x 2014-10-19 Complete\nx 2014-10-20 Another one complete")
if __name__ == '__main__':
unittest.main()
......
......@@ -15,7 +15,6 @@
# 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
......@@ -34,13 +33,5 @@ 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()
......@@ -116,7 +116,7 @@ class DeleteCommandTest(CommandTest):
command = DeleteCommand(["8to"], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(str(self.todolist), "Foo")
self.assertEqual(self.todolist.print_todos(), "Foo")
self.assertRaises(InvalidTodoException, self.todolist.todo, 'b0n')
def test_multi_del1(self):
......
......@@ -17,7 +17,7 @@
import unittest
# We're searching for 'mock'
# pylint: disable=no-name-in-module
# pylint: disable=no-name-in-module
try:
from unittest import mock
except ImportError:
......@@ -27,7 +27,7 @@ from six import u
import os
from topydo.commands.EditCommand import EditCommand
from test.CommandTest import CommandTest, utf8
from test.CommandTest import CommandTest
from topydo.lib.TodoList import TodoList
from topydo.lib.Todo import Todo
from topydo.lib.Config import config
......@@ -44,7 +44,6 @@ class EditCommandTest(CommandTest):
self.todolist = TodoList(todos)
@mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor')
def test_edit1(self, mock_open_in_editor):
""" Preserve dependencies after editing. """
......@@ -55,7 +54,7 @@ class EditCommandTest(CommandTest):
self.assertTrue(self.todolist.is_dirty())
self.assertEqual(self.errors, "")
self.assertEqual(str(self.todolist), utf8(u("Bar p:1 @test\nBaz @test\nFo\u00f3B\u0105\u017a\nFoo id:1")))
self.assertEqual(self.todolist.print_todos(), u("Bar p:1 @test\nBaz @test\nFo\u00f3B\u0105\u017a\nFoo id:1"))
@mock.patch('topydo.commands.EditCommand.EditCommand._todos_from_temp')
@mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor')
......@@ -69,7 +68,7 @@ class EditCommandTest(CommandTest):
self.assertTrue(self.todolist.is_dirty())
self.assertEqual(self.errors, "")
self.assertEqual(str(self.todolist), utf8(u("Foo id:1\nBaz @test\nFo\u00f3B\u0105\u017a\nLazy Cat")))
self.assertEqual(self.todolist.print_todos(), u("Foo id:1\nBaz @test\nFo\u00f3B\u0105\u017a\nLazy Cat"))
def test_edit3(self):
""" Throw an error after invalid todo number given as argument. """
......@@ -99,7 +98,7 @@ class EditCommandTest(CommandTest):
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")))
self.assertEqual(self.todolist.print_todos(), 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. """
......@@ -121,7 +120,7 @@ class EditCommandTest(CommandTest):
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")))
self.assertEqual(self.todolist.print_todos(), u("Foo id:1\nBar p:1 @test\nBaz @test\nLazy Cat"))
@mock.patch('topydo.commands.EditCommand.EditCommand._todos_from_temp')
@mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor')
......@@ -133,12 +132,12 @@ class EditCommandTest(CommandTest):
command = EditCommand(["-e", "@test"], self.todolist, self.out, self.error, None)
command.execute()
expected = utf8(u("| 3| Lazy Cat\n| 4| Lazy Dog\n"))
expected = 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")))
self.assertEqual(self.todolist.print_todos(), u("Foo id:1\nFo\u00f3B\u0105\u017a\nLazy Cat\nLazy Dog"))
@mock.patch('topydo.commands.EditCommand.call')
def test_edit_archive(self, mock_call):
......
......@@ -330,7 +330,7 @@ class OrdinalTagFilterTest(TopydoTest):
result = otf.filter(self.todos)
self.assertEqual(len(result), 1)
self.assertEqual(str(result[0]), self.todo1)
self.assertEqual(result[0].source(), self.todo1)
def test_filter2(self):
otf = Filter.OrdinalTagFilter('due:=today')
......@@ -338,7 +338,7 @@ class OrdinalTagFilterTest(TopydoTest):
result = otf.filter(self.todos)
self.assertEqual(len(result), 1)
self.assertEqual(str(result[0]), self.todo1)
self.assertEqual(result[0].source(), self.todo1)
def test_filter3(self):
otf = Filter.OrdinalTagFilter('due:>today')
......@@ -346,7 +346,7 @@ class OrdinalTagFilterTest(TopydoTest):
result = otf.filter(self.todos)
self.assertEqual(len(result), 1)
self.assertEqual(str(result[0]), self.todo2)
self.assertEqual(result[0].source(), self.todo2)
def test_filter4(self):
otf = Filter.OrdinalTagFilter('due:<1w')
......@@ -354,8 +354,8 @@ class OrdinalTagFilterTest(TopydoTest):
result = otf.filter(self.todos)
self.assertEqual(len(result), 2)
self.assertEqual(str(result[0]), self.todo1)
self.assertEqual(str(result[1]), self.todo2)
self.assertEqual(result[0].source(), self.todo1)
self.assertEqual(result[1].source(), self.todo2)
def test_filter5(self):
otf = Filter.OrdinalTagFilter('due:!today')
......@@ -363,7 +363,7 @@ class OrdinalTagFilterTest(TopydoTest):
result = otf.filter(self.todos)
self.assertEqual(len(result), 1)
self.assertEqual(str(result[0]), self.todo2)
self.assertEqual(result[0].source(), self.todo2)
if __name__ == '__main__':
unittest.main()
......
......@@ -22,7 +22,7 @@ import unittest
from topydo.lib.Config import config
from topydo.commands.ListCommand import ListCommand
from test.CommandTest import CommandTest, utf8
from test.CommandTest import CommandTest
from test.TestFacilities import load_file_to_todolist
class ListCommandTest(CommandTest):
......@@ -219,7 +219,7 @@ class ListCommandUnicodeTest(CommandTest):
self.assertFalse(self.todolist.is_dirty())
expected = utf8(u("| 1| (C) And some sp\u00e9cial tag:\u25c4\n"))
expected = u("| 1| (C) And some sp\u00e9cial tag:\u25c4\n")
self.assertEqual(self.output, expected)
......@@ -252,7 +252,7 @@ class ListCommandJsonTest(CommandTest):
with codecs.open('test/data/ListCommandUnicodeTest.json', 'r', encoding='utf-8') as json:
jsontext = json.read()
self.assertEqual(self.output, utf8(jsontext))
self.assertEqual(self.output, jsontext)
self.assertEqual(self.errors, "")
def replace_ical_tags(p_text):
......@@ -308,7 +308,7 @@ class ListCommandIcalTest(CommandTest):
with codecs.open('test/data/ListCommandUnicodeTest.ics', 'r', encoding='utf-8') as ical:
icaltext = ical.read()
self.assertEqual(replace_ical_tags(self.output), utf8(replace_ical_tags(icaltext)))
self.assertEqual(replace_ical_tags(self.output), replace_ical_tags(icaltext))
self.assertEqual(self.errors, "")
if __name__ == '__main__':
......
......@@ -31,13 +31,13 @@ class SortCommandTest(CommandTest):
command = SortCommand(["text"], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(str(self.todolist), "First\n(A) Foo\n2014-06-14 Last")
self.assertEqual(self.todolist.print_todos(), "First\n(A) Foo\n2014-06-14 Last")
def test_sort2(self):
command = SortCommand([], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(str(self.todolist), "(A) Foo\n2014-06-14 Last\nFirst")
self.assertEqual(self.todolist.print_todos(), "(A) Foo\n2014-06-14 Last\nFirst")
def test_sort3(self):
""" Check that order does not influence the UID of a todo. """
......
......@@ -19,7 +19,7 @@ import unittest
from topydo.lib.Config import config
from topydo.lib.Sorter import Sorter
from test.TestFacilities import load_file, todolist_to_string, load_file_to_todolist
from test.TestFacilities import load_file, todolist_to_string, load_file_to_todolist, print_view
from test.TopydoTest import TopydoTest
class SorterTest(TopydoTest):
......@@ -128,7 +128,7 @@ class SorterTest(TopydoTest):
view = todolist.view(sorter, [])
result = load_file('test/data/SorterTest10-result.txt')
self.assertEqual(str(view), todolist_to_string(result))
self.assertEqual(print_view(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.assertEqual(str(view), todolist_to_string(result))
self.assertEqual(print_view(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.assertEqual(str(view), todolist_to_string(result))
self.assertEqual(print_view(view), todolist_to_string(result))
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 topydo.lib.PrettyPrinter import PrettyPrinter
from topydo.lib.Todo import Todo
from topydo.lib.TodoFile import TodoFile
from topydo.lib.TodoList import TodoList
......@@ -42,4 +43,8 @@ def load_file_to_todolist(p_filename):
def todolist_to_string(p_list):
""" Converts a todo list to a single string. """
return '\n'.join([str(t) for t in p_list])
return '\n'.join([t.source() for t in p_list])
def print_view(p_view):
printer = PrettyPrinter()
return printer.print_list(p_view.todos)
......@@ -133,11 +133,6 @@ class TodoListTester(TopydoTest):
self.assertRaises(InvalidTodoException, self.todolist.todo, count + 100)
self.assertFalse(self.todolist.is_dirty())
def test_string(self):
# readlines() always ends a string with \n, but join() in str(todolist)
# doesn't necessarily.
self.assertEqual(str(self.todolist) + '\n', self.text)
def test_count(self):
""" Test that empty lines are not counted. """
self.assertEqual(self.todolist.count(), 5)
......
......@@ -18,7 +18,7 @@ import unittest
from topydo.lib import Filter
from topydo.lib.Sorter import Sorter
from test.TestFacilities import load_file, todolist_to_string
from test.TestFacilities import load_file, todolist_to_string, print_view
from topydo.lib.TodoFile import TodoFile
from topydo.lib.TodoList import TodoList
from test.TopydoTest import TopydoTest
......@@ -34,7 +34,7 @@ class ViewTest(TopydoTest):
todofilter = Filter.GrepFilter('+Project')
view = todolist.view(sorter, [todofilter])
self.assertEqual(str(view), todolist_to_string(ref))
self.assertEqual(print_view(view), todolist_to_string(ref))
if __name__ == '__main__':
unittest.main()
......
......@@ -166,7 +166,7 @@ class CLIApplicationBase(object):
command.execute()
if archive.is_dirty():
archive_file.write(str(archive))
archive_file.write(archive.print_todos())
def _help(self, args):
if args == None:
......@@ -205,7 +205,7 @@ class CLIApplicationBase(object):
if config().keep_sorted():
self._execute(SortCommand, [])
self.todofile.write(str(self.todolist))
self.todofile.write(self.todolist.print_todos())
def run(self):
raise NotImplementedError
......
......@@ -17,6 +17,7 @@
from topydo.lib.Command import Command, InvalidCommandArgument
from topydo.lib.Config import config
from topydo.lib import Filter
from topydo.lib.PrettyPrinter import pretty_printer_factory
from topydo.lib.Sorter import Sorter
from topydo.lib.TodoListBase import InvalidTodoException
from topydo.lib.View import View
......@@ -34,6 +35,8 @@ class DepCommand(Command):
except InvalidCommandArgument:
self.subsubcommand = None
self.printer = pretty_printer_factory(self.todolist)
def _handle_add(self):
(from_todo, to_todo) = self._get_todos()
......@@ -97,9 +100,8 @@ class DepCommand(Command):
if todos:
sorter = Sorter(config().sort_string())
instance_filter = Filter.InstanceFilter(todos)
view = View(sorter, [instance_filter], self.todolist,
self.printer)
self.out(view.pretty_print())
view = View(sorter, [instance_filter], self.todolist)
self.out(self.printer.print_list(view.todos))
except InvalidTodoException:
self.error("Invalid todo number given.")
except InvalidCommandArgument:
......
......@@ -18,7 +18,7 @@ import os
from subprocess import call, check_call, CalledProcessError
import tempfile
from six import text_type, u
from six import u
from topydo.lib.ExpressionCommand import ExpressionCommand
from topydo.lib.MultiCommand import MultiCommand
......@@ -58,7 +58,7 @@ class EditCommand(MultiCommand, ExpressionCommand):
def _todos_to_temp(self):
f = tempfile.NamedTemporaryFile()
for todo in self.todos:
f.write((text_type(todo) + "\n").encode('utf-8'))
f.write((todo.source() + "\n").encode('utf-8'))
f.seek(0)
return f
......@@ -118,7 +118,7 @@ class EditCommand(MultiCommand, ExpressionCommand):
return call([editor, archive]) == 0
if self.is_expression:
self.todos = self._view().todos()
self.todos = self._view().todos
else:
self.get_todos(self.args)
......
......@@ -16,6 +16,7 @@
from topydo.lib.ExpressionCommand import ExpressionCommand
from topydo.lib.Config import config
from topydo.lib.PrettyPrinter import pretty_printer_factory
from topydo.lib.PrettyPrinterFilter import (
PrettyPrinterIndentFilter,
PrettyPrinterHideTagFilter
......@@ -81,10 +82,8 @@ class ListCommand(ExpressionCommand):
sent to the output.
"""
def _print_text():
"""
Outputs a pretty-printed text format of the todo list.
"""
if self.printer == None:
# create a standard printer with some filters
indent = config().list_indent()
hidden_tags = config().hidden_tags()
......@@ -92,14 +91,9 @@ class ListCommand(ExpressionCommand):
filters.append(PrettyPrinterIndentFilter(indent))
filters.append(PrettyPrinterHideTagFilter(hidden_tags))
self.out(self._view().pretty_print(filters))
self.printer = pretty_printer_factory(self.todolist, 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()))
self.out(self.printer.print_list(self._view().todos))
def execute(self):
if not super(ListCommand, self).execute():
......
......@@ -70,4 +70,4 @@ class ExpressionCommand(Command):
sorter = Sorter(self.sort_expression)
filters = self._filters()
return View(sorter, filters, self.todolist, self.printer)
return View(sorter, filters, self.todolist)
......@@ -14,6 +14,11 @@
# 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.PrettyPrinterFilter import (
PrettyPrinterColorFilter,
PrettyPrinterNumbers
)
class Printer(object):
"""
An abstract class that turns todo items into strings.
......@@ -21,8 +26,8 @@ class Printer(object):
Subclasses must at least implement the print_todo method.
"""
def print_todo(self, p_todo):
""" Base implementation. Simply returns the string conversion. """
return str(p_todo)
""" Base implementation."""
return p_todo.source()
def print_list(self, p_todos):
"""
......@@ -57,9 +62,26 @@ class PrettyPrinter(Printer):
def print_todo(self, p_todo):
""" Given a todo item, pretty print it. """
todo_str = str(p_todo)
todo_str = p_todo.source()
for ppf in self.filters:
todo_str = ppf.filter(todo_str, p_todo)
return todo_str
def pretty_printer_factory(p_todolist, p_additional_filters=None):
""" Returns a pretty printer suitable for the ls and dep subcommands. """
p_additional_filters = p_additional_filters or []
printer = PrettyPrinter()
printer.add_filter(PrettyPrinterNumbers(p_todolist))
for ppf in p_additional_filters:
printer.add_filter(ppf)
# apply colors at the last step, the ANSI codes may confuse the
# preceding filters.
printer.add_filter(PrettyPrinterColorFilter())
return printer
......@@ -17,6 +17,7 @@
""" Provides filters used for pretty printing. """
import re
from six import u
from topydo.lib.Config import config
from topydo.lib.Colors import Colors, NEUTRAL_COLOR
......@@ -99,7 +100,7 @@ class PrettyPrinterNumbers(PrettyPrinterFilter):
def filter(self, p_todo_str, p_todo):
""" Prepends the number to the todo string. """
return "|{:>3}| {}".format(self.todolist.number(p_todo), p_todo_str)
return u("|{:>3}| {}").format(self.todolist.number(p_todo), p_todo_str)
class PrettyPrinterHideTagFilter(PrettyPrinterFilter):
""" Removes all occurences of the given tags from the text. """
......
......@@ -20,12 +20,11 @@ This module contains the class that represents a single todo item.
from datetime import date
import re
from six import python_2_unicode_compatible, u
from six import u
from topydo.lib.TodoParser import parse_line
from topydo.lib.Utils import is_valid_priority
@python_2_unicode_compatible
class TodoBase(object):
"""
This class represents a single todo item in a todo.txt file. It maintains
......@@ -227,6 +226,3 @@ class TodoBase(object):
""" Returns the creation date of a todo. """
return self.fields['creationDate']
def __str__(self):
""" A printer for the todo item. """
return self.source()
......@@ -49,7 +49,7 @@ class TodoFile(object):
to the file.
"""
todofile = open(self.path, 'w')
todofile = codecs.open(self.path, 'w', encoding="utf-8")
if p_todos is list:
for todo in p_todos:
......
......@@ -20,6 +20,7 @@ A list of todo items.
from topydo.lib.Config import config
from topydo.lib.Graph import DirectedGraph
from topydo.lib.PrettyPrinter import PrettyPrinter
from topydo.lib.TodoListBase import TodoListBase
class TodoList(TodoListBase):
......@@ -231,4 +232,3 @@ class TodoList(TodoListBase):
for todo in self._todos:
todo.attributes['parents'] = self.parents(todo)
......@@ -255,7 +255,10 @@ class TodoListBase(object):
self._todo_id_map[todo] = uid
self._id_todo_map[uid] = todo
def __str__(self):
def print_todos(self):
"""
Returns a pretty-printed string (without colors) of the todo items in
this list.
"""
printer = PrettyPrinter()
return printer.print_list(self._todos)
......@@ -16,66 +16,23 @@
""" A view is a list of todos, sorted and filtered. """
from six import python_2_unicode_compatible
from topydo.lib.PrettyPrinterFilter import (
PrettyPrinterColorFilter,
PrettyPrinterNumbers
)
from topydo.lib.PrettyPrinter import PrettyPrinter
@python_2_unicode_compatible
class View(object):
"""
A view is instantiated by a todo list, usually obtained from a todo.txt
file. Also a sorter and a list of filters should be given that is applied
to the list.
A printer can be passed, but it won't be used when pretty_print() is
called, since it will instantiate its own pretty printer instance.
"""
def __init__(self, p_sorter, p_filters, p_todolist,
p_printer=PrettyPrinter()):
def __init__(self, p_sorter, p_filters, p_todolist):
self._todolist = p_todolist
self._viewdata = []
self._sorter = p_sorter
self._filters = p_filters
self._printer = p_printer
self.update()
def update(self):
"""
Updates the view data. Should be called when the backing todo list
has changed.
"""
self._viewdata = self._sorter.sort(self._todolist.todos())
for _filter in self._filters:
self._viewdata = _filter.filter(self._viewdata)
def pretty_print(self, p_pp_filters=None):
""" Pretty prints the view. """
p_pp_filters = p_pp_filters or []
# since we're using filters, always use PrettyPrinter
printer = PrettyPrinter()
printer.add_filter(PrettyPrinterNumbers(self._todolist))
for ppf in p_pp_filters:
printer.add_filter(ppf)
# apply colors at the last step, the ANSI codes may confuse the
# preceding filters.
printer.add_filter(PrettyPrinterColorFilter())
return printer.print_list(self._viewdata)
@property
def todos(self):
""" Returns a sorted and filtered list of todos in this view. """
return self._viewdata
result = self._sorter.sort(self._todolist.todos())
for _filter in self._filters:
result = _filter.filter(result)
def __str__(self):
return self._printer.print_list(self._viewdata)
return result
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