mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
170 lines
5.2 KiB
Python
Executable file
170 lines
5.2 KiB
Python
Executable file
#! /usr/bin/python
|
|
###############################################################################
|
|
#
|
|
# Copyright 2006 - 2015, Paul Beckingham, Federico Hernandez.
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
# in the Software without restriction, including without limitation the rights
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included
|
|
# in all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
# SOFTWARE.
|
|
#
|
|
# http://www.opensource.org/licenses/mit-license.php
|
|
#
|
|
###############################################################################
|
|
"""
|
|
export-sql.py -- Export the taskwarrior database as a series of SQL commands.
|
|
|
|
Example usage::
|
|
|
|
$ PYTHONIOENCODING=UTF-8 ./export-sql.py | sqlite3 mytasks.db
|
|
$ /usr/bin/sqlite3 mytasks.db "select * from annotations;"
|
|
|
|
This script has only been tested with sqlite3, but in theory, it could be
|
|
easily modified to supported mysql, postgres or whatever you choose.
|
|
|
|
Author: Ralph Bean
|
|
"""
|
|
|
|
import sys
|
|
import commands
|
|
import json
|
|
|
|
from datetime import datetime
|
|
|
|
# Note that you may want to modify the field sizes to suit your usage.
|
|
table_definitions = """
|
|
CREATE TABLE tasks (
|
|
uuid VARCHAR(255) NOT NULL,
|
|
description VARCHAR(255) NOT NULL,
|
|
entry DATETIME NOT NULL,
|
|
end DATETIME,
|
|
priority VARCHAR(32),
|
|
project VARCHAR(32),
|
|
status VARCHAR(32),
|
|
PRIMARY KEY (uuid)
|
|
);
|
|
|
|
CREATE TABLE annotations (
|
|
uuid VARCHAR(255) NOT NULL,
|
|
description VARCHAR(255) NOT NULL,
|
|
entry DATETIME NOT NULL,
|
|
FOREIGN KEY(uuid) REFERENCES tasks(uuid)
|
|
);
|
|
"""
|
|
|
|
|
|
replacements = {
|
|
'"': '&dquot;',
|
|
"'": '"',
|
|
'[': '&open;',
|
|
']': '&close;',
|
|
'/': '\\/',
|
|
}
|
|
|
|
|
|
def escape(s):
|
|
""" Escape a string in the taskwarrior style """
|
|
|
|
for unsafe, safe in replacements.iteritems():
|
|
s = s.replace(unsafe, safe)
|
|
return s
|
|
|
|
|
|
# A lookup table for how to convert various values by type to SQL
|
|
conversion_lookup = {
|
|
# Tack on an extra set of quotes
|
|
unicode: lambda v: "'%s'" % escape(v),
|
|
# Do the same as for unicode
|
|
str: lambda v: convert(unicode(v)),
|
|
# Convert to ISO format and do the same as for unicode
|
|
datetime: lambda v: convert(v.isoformat(' ')),
|
|
# Replace python None with SQL NULL
|
|
type(None): lambda v: 'NULL',
|
|
}
|
|
|
|
# Compose a value with its corresponding function in conversion_lookup
|
|
convert = lambda v: conversion_lookup.get(type(v), lambda v: v)(v)
|
|
|
|
|
|
def parse_datetime(task):
|
|
""" Parse the datetime strings given to us by `task export` """
|
|
|
|
for key in ['entry', 'end']:
|
|
if key in task:
|
|
task[key] = datetime.strptime(task[key], "%Y%m%dT%H%M%SZ")
|
|
return task
|
|
|
|
|
|
def to_sql(task):
|
|
""" Create a list of SQL INSERT statements out of a task python dict """
|
|
|
|
def make_annotation(annot):
|
|
""" Create a list of SQL INSERT statements for an annotation """
|
|
|
|
annot['uuid'] = task['uuid']
|
|
template = "{uuid}, {description}, {entry}"
|
|
annot = dict(zip(annot.keys(), map(convert, annot.values())))
|
|
values = template.format(**annot)
|
|
return "INSERT INTO \"annotations\" VALUES(%s)" % values
|
|
|
|
template = u"{uuid}, {description}, {entry}, {end}, " + \
|
|
u"{priority}, {project}, {status}"
|
|
|
|
nullables = ['end', 'priority', 'project', 'status']
|
|
defaults = dict([(key, None) for key in nullables])
|
|
defaults['annotations'] = []
|
|
defaults.update(task)
|
|
|
|
defaults = dict(zip(defaults.keys(), map(convert, defaults.values())))
|
|
|
|
values = template.format(**defaults)
|
|
annotations = map(make_annotation, defaults['annotations'])
|
|
|
|
return ["INSERT INTO \"tasks\" VALUES(%s)" % values] + annotations
|
|
|
|
|
|
def main():
|
|
""" Return a list of SQL statements. """
|
|
|
|
# Use the taskwarrior 2.0+ export command to filter and return JSON
|
|
command = "task rc.verbose=nothing rc.json.array=yes " + " ".join(sys.argv[1:]) + " export"
|
|
|
|
# Load each task from json to a python dict
|
|
tasks = json.loads(commands.getoutput(command))
|
|
|
|
# Mangle datetime strings into python datetime objects
|
|
tasks = map(parse_datetime, tasks)
|
|
|
|
# Produce formatted SQL statements for each task
|
|
inserts = sum(map(to_sql, tasks), [])
|
|
|
|
return inserts
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# Get the INSERT statements
|
|
lines = main()
|
|
|
|
# Combine them with semicolons
|
|
sql = table_definitions + ";\n".join(lines) + ';'
|
|
|
|
# Print them out, decorated with sqlite3 trappings
|
|
print u"""
|
|
BEGIN TRANSACTION;
|
|
{sql}
|
|
COMMIT;""".format(sql=sql)
|
|
|
|
###############################################################################
|