Commit cd7fc25d authored by Bram Schoenmakers's avatar Bram Schoenmakers

Introduced 'json' subcommand to convert todo.txt to JSON.

parent 33d3b444
# 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 codecs
import re
import sys
import unittest
from topydo.lib.Config import config
from topydo.commands.JsonCommand import JsonCommand
from test.CommandTest import CommandTest, utf8
from test.TestFacilities import load_file_to_todolist
class JsonCommandTest(CommandTest):
def setUp(self):
super(JsonCommandTest, self).setUp()
self.todolist = load_file_to_todolist("test/data/ListCommandTest.txt")
def test_json(self):
command = JsonCommand([""], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
jsontext = ""
with codecs.open('test/data/ListCommandTest.json', 'r', encoding='utf-8') as json:
jsontext = json.read()
self.assertEqual(self.output, jsontext)
self.assertEqual(self.errors, "")
def test_help(self):
command = JsonCommand(["help"], self.todolist, self.out, self.error)
command.execute()
self.assertEqual(self.output, "")
self.assertEqual(self.errors, command.usage() + "\n\n" + command.help() + "\n")
class JsonCommandUnicodeTest(CommandTest):
def setUp(self):
super(JsonCommandUnicodeTest, self).setUp()
self.todolist = load_file_to_todolist("test/data/ListCommandUnicodeTest.txt")
def test_json_unicode(self):
command = JsonCommand([""], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
jsontext = ""
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.errors, "")
if __name__ == '__main__':
unittest.main()
[{"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"}]
[{"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"}]
......@@ -34,6 +34,7 @@ _SUBCOMMAND_MAP = {
'edit': 'EditCommand',
'exit': 'ExitCommand', # used for the prompt
'ical': 'IcalCommand',
'json': 'JsonCommand',
'ls': 'ListCommand',
'lscon': 'ListContextCommand',
'listcon': 'ListContextCommand',
......
# 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/>.
"""
Implements a subcommand that outputs an JSON file.
"""
from topydo.lib.JsonPrinter import JsonPrinter
from topydo.commands.ListCommand import ListCommand
class JsonCommand(ListCommand):
def __init__(self, p_args, p_todolist,
p_out=lambda a: None,
p_err=lambda a: None,
p_prompt=lambda a: None):
super(JsonCommand, self).__init__(
p_args, p_todolist, p_out, p_err, p_prompt)
self.printer = JsonPrinter()
def _print(self):
self.out(str(self._view()))
def execute(self):
return super(JsonCommand, self).execute()
def usage(self):
return """Synopsis: json [-x] [expression]"""
def help(self):
return """\
Similar to the 'ls' subcommand, except that the todos are printed in JSON
format such that other applications can process it.
By default prints the active todo items, possibly filtered by the given
expression.
For the supported options, please refer to the help text of 'ls'
(topydo help ls).
Note: topydo does not support reading JSON files, this is merely a dump.
"""
# 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/>.
"""
Provides a printer that transforms a list of Todo items to a JSON structure
such that other applications can process it.
"""
import json
from topydo.lib.PrettyPrinter import Printer
def _convert_todo(p_todo):
""" Converts a Todo instance to a dictionary. """
creation_date = p_todo.creation_date()
completion_date = p_todo.completion_date()
result = {
'source': p_todo.source(),
'text': p_todo.text(),
'priority': p_todo.priority(),
'completed': p_todo.is_completed(),
'tags': p_todo.tags(),
'projects': list(p_todo.projects()),
'contexts': list(p_todo.contexts()),
'creation_date':
creation_date.isoformat() if creation_date else None,
'completion_date':
completion_date.isoformat() if completion_date else None
}
return result
class JsonPrinter(Printer):
"""
A printer that converts a list of Todo items to a string in JSON format.
"""
def __init__(self):
super(JsonPrinter, self).__init__()
def print_todo(self, p_todo):
return json.dumps(_convert_todo(p_todo), ensure_ascii=False,
sort_keys=True)
def print_list(self, p_todos):
result = []
for todo in p_todos:
result.append(_convert_todo(todo))
return json.dumps(result, ensure_ascii=False, sort_keys=True)
......@@ -130,6 +130,13 @@ class TodoBase(object):
value = p_value if p_value != "" else r'\S+'
self.src = re.sub(r'\s?\b' + p_key + ':' + value + r'\b', '', self.src)
def tags(self):
"""
Returns a list of tuples with key-value pairs representing tags in
this todo item.
"""
return self.fields['tags']
def set_priority(self, p_priority):
"""
Sets the priority of the todo. Must be a single capital letter [A-Z],
......
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