1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
#!/usr/bin/env python3
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.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)
fields = []
for xf in xml_fields:
f_type = F_TYPE_MAP.get(xf.attrib['format'])
# 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()
|