1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 __all__ = (
24 "FliesConsole",
25 )
26
27 import getopt, sys
28 import json
29 import os.path
30 import hashlib
31 import shutil
32 from parseconfig import FliesConfig
33 from publican import Publican
34 from flieslib import *
35
36 sub_command = {
37 'help':[],
38 'list':[],
39 'status':[],
40 'project':['info','create', 'remove'],
41 'iteration':['info', 'create', 'remove'],
42 'publican':['push', 'pull']
43 }
44
46
48 config = FliesConfig()
49 server = config.get_config_value("server")
50 project_id = config.get_config_value("project.id")
51 iteration_id = config.get_config_value("project.iteration.id")
52 user = config.get_config_value("user")
53 apikey = config.get_config_value("apikey")
54 potfolder = config.get_config_value("potfolder")
55 pofolder = config.get_config_value("pofolder")
56 self.options = {
57 'server' : server,
58 'project_id':project_id,
59 'iteration_id':iteration_id,
60 'user':user,
61 'apikey':apikey,
62 'potfolder':potfolder,
63 'pofolder':pofolder,
64 'name':'',
65 'desc':'',
66 'lang':''
67 }
68
70 print ('\nClient for talking to a Flies Server\n\n'
71 'basic commands:\n\n'
72 'list List all available projects\n'
73 'project info Retrieve a project\n'
74 'iteration info Retrieve a iteration\n\n'
75 "Use 'flies help' for the full list of commands")
76
78 """
79 Output the general help information or the help information for each command
80 @param args: the name of command and sub command
81 """
82 if not args:
83 print ('Client for talking to a Flies Server:\n\n'
84 'list of commands:\n\n'
85 ' list List all available projects\n'
86 ' project info Retrieve a project\n'
87 ' iteration info Retrieve a iteration\n'
88 ' project create Create a project\n'
89 ' iteration create Create a iteration of a project\n'
90 ' publican pull Pull the content of publican file\n'
91 ' publican push Push the content of publican to Flies Server\n')
92 else:
93 command = args[0]
94 sub = args[1:]
95 if sub_command.has_key(command):
96 if sub_command[command]:
97 if sub:
98 if sub[0] in sub_command[command]:
99 command = command+'_'+sub[0]
100 else:
101 print "Can not find such command"
102 sys.exit()
103 else:
104 print "Please complete the command!"
105 sys.exit()
106 else:
107 print "Can not find such command"
108 sys.exit()
109
110 self._command_help(command)
111
113 if command == 'list':
114 self._list_help()
115 elif command == 'project_info':
116 self._projec_info_help()
117 elif command == 'project_create':
118 self._project_create_help()
119 elif command == 'iteration_info':
120 self._iteration_info_help()
121 elif command == 'iteration_create':
122 self._iteration_create_help()
123 elif command == 'publican_push':
124 self._publican_push_help()
125 elif command == 'publican_pull':
126 self._publican_pull_help()
127
128
130 print ('flies list [OPTIONS]\n\n'
131 'list all available projects\n\n'
132 'options:\n\n'
133 ' --server url address of the Flies server')
134
136 print ('flies project info [OPTIONS]')
137
139 print ('flies project create [PROJECT_ID] [OPTIONS]')
140
142 print ('flies iteration info [OPTIONS]')
143
145 print ('flies iteration create [ITERATION_ID] [OPTIONS]')
146
148 print ('flies publican push [OPTIONS] {document}')
149
151 print ('flies publican pull [OPTIONS] {document}')
152
154 """
155 List the information of all the project on the flies server
156 """
157 flies = FliesResource(self.options['server'])
158 projects = flies.projects.list()
159
160 if not projects:
161 print "There is no projects on the server or the server not working"
162 sys.exit()
163 for project in projects:
164 print ("Id: %s")%project.id
165 print ("Name: %s")%project.name
166 print ("Type: %s")%project.type
167 for link in project.links:
168 print ("Links: %s\n")%[link.href, link.type, link.rel]
169
171 """
172 Retrieve the information of a project
173 """
174 if not self.options['project_id']:
175 print 'Please use flies project info --project=project_id to retrieve the project info'
176 sys.exit()
177
178 flies = FliesResource(self.options['server'])
179 try:
180 p = flies.projects.get(self.options['project_id'])
181 print ("Id: %s")%p.id
182 print ("Name: %s")%p.name
183 print ("Type: %s")%p.type
184 print ("Description: %s")%p.desc
185 except NoSuchProjectException as e:
186 print "No Such Project on the server"
187 except InvalidOptionException as e:
188 print "Options are not valid"
189
191 """
192 Retrieve the information of a project iteration.
193 """
194 if not self.options['iteration_id'] or not self.options['project_id']:
195 print 'Please use flies iteration info --project=project_id --iteration=iteration_id to retrieve the iteration'
196 sys.exit()
197
198 flies = FliesResource(self.options['server'])
199 try:
200 project = flies.projects.get(self.options['project_id'])
201 iteration = project.get_iteration(self.options['iteration_id'])
202 print ("Id: %s")%iteration.id
203 print ("Name: %s")%iteration.name
204 print ("Description: %s")%iteration.desc
205 except NoSuchProjectException as e:
206 print "No Such Project on the server"
207
209 """
210 Create project with the project id
211 @param args: project id
212 """
213 if self.options['user'] and self.options['apikey']:
214 flies = FliesResource(self.options['server'], self.options['user'], self.options['apikey'])
215 else:
216 print "Please provide username and apikey in .fliesrc"
217 sys.exit()
218
219 if not args:
220 print "Please provide PROJECT_ID for creating project"
221 sys.exit()
222
223 if not self.options['name']:
224 print "Please provide Project name by '--name' option"
225 sys.exit()
226
227 try:
228 p = Project(id = args[0], name = self.options['name'], desc = self.options['desc'])
229 result = flies.projects.create(p)
230 if result == "Success":
231 print "Success create the project"
232 except NoSuchProjectException as e:
233 print "No Such Project on the server"
234 except UnAuthorizedException as e:
235 print "Unauthorized Operation"
236 except ProjectExistException as e:
237 print "The project is alreasy exist on the server"
238
240 """
241 Create iteration with the iteration id
242 @param args: iteration id
243 """
244 if self.options['user'] and self.options['apikey']:
245 flies = FliesResource(self.options['server'], self.options['user'], self.options['apikey'])
246 else:
247 print "Please provide username and apikey in .fliesrc"
248 sys.exit()
249
250 if not args:
251 print "Please provide ITERATION_ID for creating iteration"
252 sys.exit()
253
254 if not self.options['name']:
255 print "Please provide Iteration name by '--name' option"
256 sys.exit()
257
258 try:
259 iteration = Iteration()
260 iteration.id = args[0]
261 iteration.name = self.options['name']
262 iteration.desc = self.options['desc']
263 result = flies.projects.iterations.create(self.options['project_id'], iteration)
264 if result == "Success":
265 print "Success create the itearion"
266 except ProjectExistException as e:
267 print "The iteration is already exist on the server"
268 except NoSuchProjectException as e:
269 print "No Such Project on the server"
270 except UnAuthorizedException as e:
271 print "Unauthorized Operation"
272 except InvalidOptionException as e:
273 print "Options are not valid"
274
276 if os.path.isdir(tmlpath):
277 filelist = os.listdir(tmlpath)
278 return filelist
279 else:
280 return None
281
283 """
284 Parse the pot file and create the request body
285 @param filepath: the path of the pot file
286 """
287 if '/' in filepath:
288 file = filepath.split('/')[-1]
289 path = filepath
290 else:
291 file = filepath
292 path = os.path.join(os.getcwd(), file)
293
294 if '.' in file:
295
296 filename = file.split('.')[0]
297 else:
298 filename = file
299
300 if not os.path.isfile(path):
301 raise NoSuchFileException('Error', 'The file %s does not exist'%file)
302
303 publican = Publican(path)
304 textflows = publican.covert_txtflow()
305 items = {'name':filename, 'contentType':'application/x-gettext', 'lang':'en', 'extensions':[], 'textFlows':textflows}
306 return json.dumps(items)
307
309 """
310 Push the content of publican files to a Project iteration on Flies server
311 @param args: name of the publican file
312 """
313 if self.options['user'] and self.options['apikey']:
314 flies = FliesResource(self.options['server'], self.options['user'], self.options['apikey'])
315 else:
316 print "Please provide username and apikey in .fliesrc"
317 sys.exit()
318
319 if not self.options['project_id']:
320 print "Please provide valid project id by '--project' option"
321 sys.exit()
322
323 if not self.options['iteration_id']:
324 print "Please provide valid iteration id by fliesrc or by '--iteration' option"
325 sys.exit()
326
327 tmlfolder = self.options['potfolder']
328
329 if not args:
330 if not tmlfolder:
331 print "Please provide template folder for processing in fliesrc"
332 sys.exit()
333
334
335 filelist = self.list_folder(tmlfolder)
336 if filelist:
337 for pot in filelist:
338 print "\nPush the content of %s to Flies server: "%pot
339
340 try:
341 body = self._create_resource(tmlfolder+'/'+pot)
342 except NoSuchFileException as e:
343 print "%s :%s"%(e.expr, e.msg)
344 continue
345
346 try:
347 result = flies.documents.commit_translation(self.options['project_id'], self.options['iteration_id'], body)
348 if result:
349 print "Successfully push %s to the Flies server"%pot
350 except UnAuthorizedException as e:
351 print "%s :%s"%(e.expr, e.msg)
352 break
353 except (BadRequestBodyException, SameNameDocumentException) as e:
354 print "%s :%s"%(e.expr, e.msg)
355 continue
356 else:
357 raise NoSuchFileException('Error', 'The template folder is empty')
358 else:
359 print "\nPush the content of %s to Flies server: "%args[0]
360 try:
361 body = self._create_resource(args[0])
362 except NoSuchFileException as e:
363 print "%s :%s"%(e.expr, e.msg)
364 sys.exit()
365 try:
366 result = flies.documents.commit_translation(self.options['project_id'], self.options['iteration_id'], body)
367 if result:
368 print "Successfully push %s to the Flies server"%args[0]
369 except (UnAuthorizedException, BadRequestBodyException, SameNameDocumentException) as e:
370 print "%s :%s"%(e.expr, e.msg)
371
373 m = hashlib.md5()
374 m.update(message.msgid.encode('utf-8'))
375 if m.hexdigest() == id:
376 return True
377 else:
378 return False
379
380 - def _create_pofile(self, lang, file, translations, tmlpath, outpath):
381 """
382 Create PO file based on the POT file in POT folder
383 @param lang: language
384 @param translations: the json object of the content retrieved from server
385 @param tmlpath: the pot folder
386 @param outpath: the po folder for output
387 """
388 if '.' in file:
389 filename = file.split('.')[0]
390 else:
391 filename = file
392
393 pofilename = filename+'_%s.po'%lang.replace('-', '_')
394 pofile = os.path.join(outpath, pofilename)
395 potfile = os.path.join(tmlpath, filename+'.pot')
396
397 if not os.path.isfile(potfile):
398 raise UnAvaliablePOTException('Error', 'The requested POT file is not available')
399
400
401
402 if not os.path.isfile(pofile):
403
404 shutil.copy(potfile, pofile)
405
406
407 publican = Publican(pofile)
408 po = publican.load_po()
409
410 content = json.loads(translations)
411 targets = content.get('textFlowTargets')
412
413 for message in po:
414 for translation in targets:
415 if self._hash_matches(message, translation.get('resId')):
416 message.msgstr = translation.get('content')
417
418
419
420 po.save()
421 print "Successfully create %s in %s"%(pofilename, outpath)
422
424 """
425 Retrieve the content of documents in a Project iteration from Flies server. If the name of publican
426 file is specified, the content of that file will be pulled from server. Otherwise, all the document of that
427 Project iteration will be pulled from server.
428 @param args: the name of publican file
429 """
430 if not self.options['lang']:
431 print "Please specify the language by '--lang' option"
432 sys.exit()
433
434 if not self.options['project_id']:
435 print "Please provide valid project id by '--project' option"
436 sys.exit()
437
438 if not self.options['iteration_id']:
439 print "Please provide valid iteration id by fliesrc or by '--iteration' option"
440 sys.exit()
441
442 if not self.options['potfolder']:
443 print "Please provide folder for storting the template files in fliesrc"
444 sys.exit()
445
446 if not self.options['pofolder']:
447 print "Please provide folder for storting the output files in fliesrc"
448 sys.exit()
449
450 flies = FliesResource(self.options['server'])
451
452
453 if not args:
454
455 filelist = flies.documents.get_file_list(self.options['project_id'], self.options['iteration_id'])
456
457 if filelist:
458 for file in filelist:
459 print "\nFetch the content of %s from Flies server: "%file
460 try:
461 result = flies.documents.retrieve_translation(self.options['lang'], self.options['project_id'], self.options['iteration_id'], file)
462 self._create_pofile(self.options['lang'], file, result, self.options['potfolder'], self.options['pofolder'])
463 except UnAuthorizedException as e:
464 print "%s :%s"%(e.expr, e.msg)
465 break
466 except UnAvaliableResourceException as e:
467 print "%s :%s"%(e.expr, e.msg)
468 continue
469 else:
470 print "\nFetch the content of %s from Flies server: "%args[0]
471 try:
472 result = flies.documents.retrieve_translation(self.options['lang'], self.options['project_id'], self.options['iteration_id'], args[0])
473 self._create_pofile(self.options['lang'], args[0], result, self.options['potfolder'], self.options['pofolder'])
474 except (UnAuthorizedException, UnAvaliableResourceException) as e:
475 print "%s :%s"%(e.expr, e.msg)
476
479
482
485
487 """
488 Parse the command line to generate command options and sub_command
489 """
490 try:
491 opts, args = getopt.gnu_getopt(sys.argv[1:], "v", ["server=", "project=", "iteration=", "name=", "description=", "lang="])
492 except getopt.GetoptError, err:
493 print str(err)
494 sys.exit(2)
495
496 if args:
497 command = args[0]
498 sub = args[1:]
499 if sub_command.has_key(command):
500 if sub_command[command]:
501 if sub[0]:
502 if sub[0] in sub_command[command]:
503 command = command+'_'+sub[0]
504 command_args = sub[1:]
505 else:
506 print "Can not find such command"
507 sys.exit()
508 else:
509 print "Please complete the command!"
510 sys.exit()
511 else:
512 command_args = sub
513 else:
514 print "Can not find such command"
515 sys.exit()
516 else:
517 self._print_usage()
518 sys.exit()
519
520 if opts:
521 for o, a in opts:
522 if o in ("--server"):
523 self.options['server'] = a
524 elif o in ("--name"):
525 self.options['name'] = a
526 elif o in ("--description"):
527 self.options['desc'] = a
528 elif o in ("--project"):
529 self.options['project_id'] = a
530 elif o in ("--iteration"):
531 self.options['iteration_id'] = a
532 elif o in ("--lang"):
533 self.options['lang'] = a
534
535 return command, command_args
536
538 command, command_args = self._process_command_line()
539
540 if command == 'help':
541 self._print_help_info(command_args)
542 else:
543 if not self.options['server']:
544 print "Please provide valid server url by fliesrc or by '--server' option"
545 sys.exit()
546
547 if command == 'list':
548 self._list_projects()
549 elif command == 'status':
550 self._poject_status()
551 elif command == 'project_info':
552 self._get_project()
553 elif command == 'project_create':
554 self._create_project(command_args)
555 elif command == 'project_remove':
556 self._remove_project(command_args)
557 elif command == 'iteration_info':
558 self._get_iteration()
559 elif command == 'iteration_create':
560 self._create_iteration(command_args)
561 elif command == 'iteration_remove':
562 self._remove_iteration(command_args)
563 elif command == 'publican_push':
564 self._push_publican(command_args)
565 elif command == 'publican_pull':
566 self._pull_publican(command_args)
567
568
572
573 if __name__ == "__main__":
574 main()
575