Package fliesclient :: Module flies
[hide private]
[frames] | no frames]

Source Code for Module fliesclient.flies

  1  #vim:set et sts=4 sw=4: 
  2  # 
  3  # Flies Python Client 
  4  # 
  5  # Copyright (c) 2010 Jian Ni <jni@redhat.com> 
  6  # Copyright (c) 2010 Red Hat, Inc. 
  7  # 
  8  # This library is free software; you can redistribute it and/or 
  9  # modify it under the terms of the GNU Lesser General Public 
 10  # License as published by the Free Software Foundation; either 
 11  # version 2 of the License, or (at your option) any later version. 
 12  # 
 13  # This library is distributed in the hope that it will be useful, 
 14  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 16  # GNU Lesser General Public License for more details. 
 17  # 
 18  # You should have received a copy of the GNU Lesser General Public 
 19  # License along with this program; if not, write to the 
 20  # Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
 21  # Boston, MA  02111-1307  USA 
 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   
45 -class FliesConsole:
46
47 - def __init__(self):
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
69 - def _print_usage(self):
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
77 - def _print_help_info(self, args):
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
112 - def _command_help(self, command):
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
129 - def _list_help(self):
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
135 - def _projec_info_help(self):
136 print ('flies project info [OPTIONS]')
137
138 - def _project_create_help(self):
139 print ('flies project create [PROJECT_ID] [OPTIONS]')
140
141 - def _iteration_info_help(self):
142 print ('flies iteration info [OPTIONS]')
143
144 - def _iteration_create_help(self):
145 print ('flies iteration create [ITERATION_ID] [OPTIONS]')
146
147 - def _publican_push_help(self):
148 print ('flies publican push [OPTIONS] {document}')
149
150 - def _publican_pull_help(self):
151 print ('flies publican pull [OPTIONS] {document}')
152
153 - def _list_projects(self):
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
170 - def _get_project(self):
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
190 - def _get_iteration(self):
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
208 - def _create_project(self, args):
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
239 - def _create_iteration(self, args):
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
275 - def _list_folder(self, tmlpath):
276 if os.path.isdir(tmlpath): 277 filelist = os.listdir(tmlpath) 278 return filelist 279 else: 280 return None
281
282 - def _create_resource(self, filepath):
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 # Strip the file name 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
308 - def _push_publican(self, args):
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 #if file not specified, push all the files in pot folder to flies server 329 if not args: 330 if not tmlfolder: 331 print "Please provide template folder for processing in fliesrc" 332 sys.exit() 333 334 #check the pot folder to find all the pot file 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
372 - def _hash_matches(self, message, id):
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 # If the PO file doesn't exist 401 # create a PO file based on POT and language 402 if not os.path.isfile(pofile): 403 #copy the content of pot file to po file 404 shutil.copy(potfile, pofile) 405 406 #read the content of the po file 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 # copy any other stuff you need to transfer 419 # finally save resulting pot to outpath as myfile_lang.po 420 po.save() 421 print "Successfully create %s in %s"%(pofilename, outpath)
422
423 - def _pull_publican(self, args):
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 #if file no specified, retrieve all the files of project 453 if not args: 454 #list the files in project 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
477 - def _remove_project(self):
478 pass
479
480 - def _remove_iteration(self):
481 pass
482
483 - def _project_status(self):
484 pass
485
486 - def _process_command_line(self):
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
537 - def run(self):
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
569 -def main():
570 client = FliesConsole() 571 client.run()
572 573 if __name__ == "__main__": 574 main() 575