summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElena ``of Valhalla'' Grandi <valhalla@trueelena.org>2018-09-02 19:44:16 +0200
committerElena ``of Valhalla'' Grandi <valhalla@trueelena.org>2018-09-02 19:44:16 +0200
commit19efeef16031676f6fc99cc61e833f77c70fff43 (patch)
tree84cc3db92784436186c3f06b5a776c2242aeb291
parent2178154a17ce04c4d9cc21b7a9430e3a91dcb759 (diff)
parentbb14bc77bd21284136ed7cc092b93c1a8d6026c1 (diff)
Merge branch 'tellico'
-rwxr-xr-xscripts/tellico2lesana141
1 files changed, 141 insertions, 0 deletions
diff --git a/scripts/tellico2lesana b/scripts/tellico2lesana
new file mode 100755
index 0000000..0b0ec64
--- /dev/null
+++ b/scripts/tellico2lesana
@@ -0,0 +1,141 @@
+#!/usr/bin/env python3
+
+import datetime
+from xml.etree import ElementTree
+import zipfile
+
+import lesana
+
+import guacamole
+
+
+NS = {'tellico': 'http://periapsis.org/tellico/'}
+
+# https://docs.kde.org/trunk5/en/extragear-office/tellico/field-type-values.html
+F_TYPE_MAP = {
+ '0': 'string', # not in the specs, but seen in the wild
+ '1': 'string',
+ '2': 'text',
+ '3': 'string',
+ '4': 'bool',
+ '6': 'integer',
+ '7': 'url',
+ '8': 'list', # single column table
+ '10': 'file',
+ '12': 'timestamp', # date
+ '14': 'integer', # rating
+
+ }
+
+
+class T2L(guacamole.Command):
+ """
+ Manage collections
+ """
+
+ def register_arguments(self, parser):
+ parser.add_argument(
+ '-c', '--collection',
+ help='Name of the new lesana collection',
+ default=None,
+ )
+ parser.add_argument(
+ 'file',
+ help='Tellico file to convert to lesana.',
+ )
+
+ def read_field_data(self, xfield):
+ if xfield.tag in self.date_fields:
+ for child in xfield:
+ if 'year' in child.tag:
+ year = child.text
+ elif 'month' in child.tag:
+ month = child.text
+ elif 'day' in child.tag:
+ day = child.text
+ try:
+ data = datetime.date(
+ int(year),
+ int(month),
+ int(day)
+ )
+ except ValueError:
+ data = None
+ elif xfield.iter().__next__():
+ data = []
+ for child in xfield:
+ data.append(self.read_field_data(child))
+ else:
+ data = xfield.text
+ return data
+
+
+ def invoked(self, ctx):
+ with zipfile.ZipFile(ctx.args.file, 'r') as zp:
+ tree = ElementTree.parse(zp.open('tellico.xml'))
+ # open collection
+ xml_collection = tree.getroot().find('tellico:collection', NS)
+
+ # get collection settings
+ title = xml_collection.attrib['title']
+ xml_fields = xml_collection.find('tellico:fields', NS)
+ self.date_fields = []
+ fields = []
+ for xf in xml_fields:
+ if xf.attrib['type'] == '12':
+ self.date_fields.append(
+ '{' + NS['tellico'] + '}' + xf.attrib['name']
+ )
+ f_type = F_TYPE_MAP.get(xf.attrib['type'])
+ # TODO: support fields with the multiple values flag
+ # (they should probably become lists)
+ try:
+ flags = int(xf.attrib['flags'])
+ except ValueError:
+ flags = 0
+ if flags % 2 == 1:
+ l_type = f_type
+ f_type = 'list'
+ else:
+ l_type = None
+ field = {
+ 'name': xf.attrib['name'],
+ 'type': f_type,
+ 'help': xf.attrib['title'],
+ }
+ if l_type:
+ field['list'] = l_type
+ fields.append(field)
+ # Create a collection with the settings we have loaded
+ directory = ctx.args.collection or ctx.args.file.replace(
+ '.tc',
+ '.lesana'
+ )
+ self.collection = lesana.collection.Collection.init(
+ directory=directory,
+ git_enabled=False,
+ settings={
+ 'name': title,
+ 'fields': fields,
+ }
+ )
+
+ # import data
+ for xe in xml_collection.findall('tellico:entry', NS):
+ data = {
+ 'uid': xe.attrib['id']
+ }
+ for xfield in xe.getchildren():
+ field_name = xfield.tag.replace(
+ '{'+NS['tellico']+'}',
+ '')
+ data[field_name] = self.read_field_data(xfield)
+ new_entry = lesana.collection.Entry(self.collection, data=data)
+ self.collection.save_entries([new_entry])
+ self.collection.update_cache()
+
+
+
+
+if __name__ == '__main__':
+ T2L().main()