diff options
Diffstat (limited to 'scripts/tellico2lesana')
-rwxr-xr-x | scripts/tellico2lesana | 141 |
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() |