diff options
| author | Elena ``of Valhalla'' Grandi <valhalla@trueelena.org> | 2018-09-02 19:44:16 +0200 | 
|---|---|---|
| committer | Elena ``of Valhalla'' Grandi <valhalla@trueelena.org> | 2018-09-02 19:44:16 +0200 | 
| commit | 19efeef16031676f6fc99cc61e833f77c70fff43 (patch) | |
| tree | 84cc3db92784436186c3f06b5a776c2242aeb291 /scripts | |
| parent | 2178154a17ce04c4d9cc21b7a9430e3a91dcb759 (diff) | |
| parent | bb14bc77bd21284136ed7cc092b93c1a8d6026c1 (diff) | |
Merge branch 'tellico'
Diffstat (limited to 'scripts')
| -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() | 
