1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 """
21 Kenozooid's logbook command line user interface.
22 """
23
24 import sys
25 import os.path
26 from functools import partial
27 import logging
28
29 from kenozooid.component import inject
30 from kenozooid.cli import CLICommand, add_master_command, add_uddf_input
31 from kenozooid.util import nformat
32
33 log = logging.getLogger('kenozooid.cli.logbook')
34
35
36
37 add_master_command('dive',
38 'Kenozooid dive management commands',
39 'manage dives in UDDF file')
40
41
42 add_master_command('site',
43 'Kenozooid dive site management commands',
44 'manage dive sites in UDDF file')
45
46
47 add_master_command('buddy',
48 'Kenozooid dive buddy management commands',
49 'manage dive buddies in UDDF file')
54 """
55 List dives from UDDF file.
56 """
57 description = 'list dives stored in UDDF file'
58
59 @classmethod
61 """
62 Add options for dive list fetched from UDDF file.
63 """
64 parser.add_argument('input',
65 nargs='+',
66 help='UDDF files with dive data')
67
68
70 """
71 Execute command for list of dives in UDDF file.
72 """
73 import kenozooid.logbook as kl
74
75 for fin in args.input:
76 dives = kl.find_dives([fin])
77 print('{}:'.format(fin))
78 for i, d in enumerate(kl.list_dives(dives), 1):
79 print('{:5}: {:>4} {:>9} {:>9} ({:>5}) {:>9} {:>9}'.format(i,
80 d[0] or ' -- ', d[1], d[2], d[3] or ' --- ', d[4], d[5]))
81
86 """
87 Add a dive to logbook file.
88 """
89 description = 'add dive to logbook file'
90
91 @classmethod
93 """
94 Add options for dive adding to logbook file.
95 """
96 parser.add_argument('datetime', help='date and optional time of a dive')
97 parser.add_argument('depth', help='maximum depth of a dive')
98 parser.add_argument('duration', help='duration of a dive')
99 parser.add_argument('-s', '--site', metavar='site', help='dive site')
100 parser.add_argument('-b', '--buddy',
101 nargs='+',
102 metavar='buddy',
103 help='dive buddies')
104 parser.add_argument('logbook', help='logbook file')
105
106
108 """
109 Execute command for adding dives into logbook file.
110 """
111 import kenozooid.logbook as kl
112 import kenozooid.data as kd
113 from dateutil.parser import parse as dparse
114
115 lfile = args.logbook
116
117 datetime = dparse(args.datetime)
118 depth = float(args.depth)
119 duration = float(args.duration) * 60
120
121 site = args.site
122 buddy = args.buddy
123
124 dive = kd.Dive(datetime=datetime, depth=depth, duration=duration)
125 kl.add_dive(dive, lfile, qsite=site, qbuddies=buddy)
126
131 """
132 Copy dives to logbook file.
133 """
134 description = 'copy dives to logbook file'
135
136 @classmethod
138 """
139 Add options for dive copying to logbook file.
140 """
141 add_uddf_input(parser)
142 parser.add_argument('logbook', help='logbook file')
143
144
153
158 """
159 Add dive site to UDDF file.
160 """
161 description = 'add dive site to UDDF file'
162
163 @classmethod
165 """
166 Add options for dive site adding to UDDF file.
167 """
168 parser.add_argument('-c', '--coords',
169 nargs=2,
170 metavar=('x', 'y'),
171 type=float,
172 help='coordinates (longitude and latitude) of dive site')
173
174
175
176
177
178
179
180
181 parser.add_argument('id',
182 nargs='?',
183 help='id of dive site')
184 parser.add_argument('location',
185 nargs=1,
186 help='location of dive site, i.e. Scapa Flow, Red Sea')
187 parser.add_argument('name',
188 nargs=1,
189 help='name of dive site, i.e. SMS Markgraf, SS Thistlegorm')
190 parser.add_argument('output',
191 nargs=1,
192 help='UDDF output file')
193
194
196 """
197 Execute command for adding dive site into UDDF file.
198 """
199 import kenozooid.uddf as ku
200
201 id = args.id
202 if args.coords:
203 x, y = args.coords
204 else:
205 x, y = None, None
206 location = args.location[0]
207 name = args.name[0]
208 fout = args.output[0]
209
210 if os.path.exists(fout):
211 doc = ku.parse(fout).getroot()
212 else:
213 doc = ku.create()
214
215 ku.create_site_data(doc, id=id, location=location, name=name, x=x, y=y)
216 ku.save(doc, fout)
217
222 """
223 List dive sites from UDDF file.
224 """
225 description = 'list dive sites stored in UDDF file'
226
227 @classmethod
229 """
230 Add options for dive site list fetched from UDDF file.
231 """
232 parser.add_argument('site',
233 nargs='?',
234 help='dive site search string; matches id or partially dive' \
235 ' site name')
236 parser.add_argument('input',
237 nargs='+',
238 help='UDDF files with dive sites')
239
240
242 """
243 Execute command for list of dive sites in UDDF file.
244 """
245 import kenozooid.uddf as ku
246
247 fmt = '{0:4}: {1.id:10} {1.location:20} {1.name:20}'
248
249 if args.site:
250 query = ku.XP_FIND_SITE
251 else:
252 query = '//uddf:site'
253 files = args.input
254
255 for fin in files:
256 nodes = ku.find(fin, query, site=args.site)
257 print('{}:'.format(fin))
258 for i, n in enumerate(nodes):
259 n = ku.site_data(n)
260
261 coords = ''
262 if n.x is not None:
263 coords = ' {0.x: #.9},{0.y: #.9}'.format(n)
264
265 print(nformat(fmt, i + 1, n) + coords)
266
271 """
272 Remove dive site from UDDF file.
273 """
274 description = 'remove dive site stored in UDDF file'
275
276 @classmethod
278 """
279 Add options for removal of dive site from UDDF file.
280 """
281 parser.add_argument('site',
282 nargs=1,
283 help='dive site search string; matches id or partially dive' \
284 ' site name')
285 parser.add_argument('input',
286 nargs=1,
287 help='UDDF file with dive sites')
288
289
302
307 """
308 Add dive buddy to UDDF file.
309 """
310 description = 'add dive buddy to UDDF file'
311
312 @classmethod
314 """
315 Add options for dive buddy adding to UDDF file.
316 """
317 parser.add_argument('-m', '--member',
318 nargs=2,
319 metavar=('org', 'number'),
320 help='organization and its member id number i.e. CFT 123')
321 parser.add_argument('id',
322 nargs='?',
323 help='id of a buddy, i.e. tcora')
324 parser.add_argument('name',
325 nargs=1,
326 help='buddy name, i.e. "Tom Cora", "Thomas Henry Corra"'
327 ' or "Corra, Thomas Henry"')
328 parser.add_argument('output',
329 nargs=1,
330 help='UDDF output file')
331
332
334 """
335 Execute command for adding dive buddy into UDDF file.
336 """
337 import kenozooid.uddf as ku
338
339 if args.member:
340 org, number = args.member
341 else:
342 org, number = None, None
343
344 id = args.id
345 fn, mn, ln = _name_parse(args.name[0])
346 fout = args.output[0]
347
348 if os.path.exists(fout):
349 doc = ku.parse(fout).getroot()
350 else:
351 doc = ku.create()
352
353 ku.create_buddy_data(doc, id=id, fname=fn, mname=mn,
354 lname=ln, org=org, number=number)
355
356 ku.save(doc, fout)
357
361 """
362 List dive buddies from UDDF file.
363 """
364 description = 'list dive buddies stored in UDDF file'
365
366 @classmethod
368 """
369 Add options for dive buddy list fetched from UDDF file.
370 """
371 parser.add_argument('buddy',
372 nargs='?',
373 help='buddy search string; matches id, member number or'
374 ' partially firstname or lastname')
375 parser.add_argument('input',
376 nargs='+',
377 help='UDDF file with dive buddies')
378
379
381 """
382 Execute command for list of dive buddies in UDDF file.
383 """
384 import kenozooid.uddf as ku
385
386 fmt = '{0:4}: {1.id:10} {1.fname:10} {1.lname:20}' \
387 ' {1.org:5} {1.number:11}'
388
389 if args.buddy:
390 query = ku.XP_FIND_BUDDY
391 else:
392 query = '//uddf:buddy'
393 files = args.input
394
395 for fin in files:
396 nodes = ku.find(fin, query, buddy=args.buddy)
397 print('{}:'.format(fin))
398 for i, n in enumerate(nodes):
399 b = ku.buddy_data(n)
400 print(nformat(fmt, i + 1, b))
401
405 """
406 Remove dive buddies from UDDF file.
407 """
408 description = 'remove dive buddies stored in UDDF file'
409
410 @classmethod
412 """
413 Add options for removal of dive buddy from UDDF file.
414 """
415 parser.add_argument('buddy',
416 nargs=1,
417 help='buddy search string; matches id, member number or'
418 ' partially firstname or lastname')
419 parser.add_argument('input',
420 nargs=1,
421 help='UDDF file with dive buddies')
422
423
436
440 """
441 Upgrade a file to newer version of UDDF.
442 """
443 description = 'upgrade UDDF file to newer version'
444
445 @classmethod
447 """
448 Add options for UDDF file format upgrade.
449 """
450 parser.add_argument('input',
451 nargs='+',
452 help='input UDDF file')
453
454
456 """
457 Execute command UDDF file upgrade.
458 """
459 import kenozooid.uddf as ku
460 import kenozooid.logbook as kl
461
462 for fin in args.input:
463 try:
464 print('Upgrading {}'.format(fin))
465 doc = kl.upgrade_file(fin)
466 ku.save(doc.getroot(), fin)
467 except Exception as ex:
468 print('Cannot upgrade file {}'.format(fin), file=sys.stderr)
469 print('Error: {}'.format(ex))
470
475 """
476 Enumerate dives.
477 """
478 description = 'enumerate dives'
479
480 @classmethod
482 """
483 Add options for dive enumeration.
484 """
485 parser.add_argument('-ns', '---dive-total-number',
486 metavar='dive_total_number',
487 nargs='?',
488 type=int,
489 default=1,
490 help='start of total dive number')
491 parser.add_argument('input',
492 nargs='+',
493 help='UDDF files with dive data')
494
495
497 """
498 Execute command to enumerate dives.
499 """
500 import kenozooid.logbook as kl
501 kl.enum_dives(args.input, args.dive_total_number)
502
506 """
507 Parse name data from a string. The name string is in simplified BibTeX
508 format, i.e.
509
510 - Tom
511 - Tom Cora
512 - Thomas Henry Corra
513 - Corra, Thomas Henry
514
515 Parsed name is tuple consisting of first name, middle name and last
516 name.
517 """
518 f, m, l = None, None, None
519
520 t = name.split(',')
521 if len(t) == 1:
522 nd = t[0].strip().split(' ', 2)
523 if len(nd) == 3:
524 f, m, l = nd
525 elif len(nd) == 2:
526 f, l = nd
527 elif len(nd) == 1:
528 f = nd[0]
529 elif len(t) == 2:
530 l = t[0].strip()
531 nd = t[1].strip().split(' ', 1)
532 f = nd[0]
533 if len(nd) == 2:
534 m = nd[1]
535 else:
536 raise ValueError('Cannot parse name')
537
538 if f:
539 f = f.strip()
540 if m:
541 m = m.strip()
542 if l:
543 l = l.strip()
544 return f, m, l
545
546
547
548