memoQProject.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. from suds.client import Client
  2. import datetime
  3. import os
  4. import memoQFile
  5. from base64 import b64decode, b64encode
  6. import json
  7. class Languages(object):
  8. """Encapsulates project languages."""
  9. def __init__(self):
  10. self.target = []
  11. self.source = None
  12. class Project(object):
  13. """Encapsulates basic project information."""
  14. def __init__(self):
  15. self.__guid = None
  16. now = datetime.datetime.now()
  17. self.name = 'Test_{}'.format(str(now).replace(":", "-"))
  18. self.domain = "Python"
  19. self.documents = None
  20. self.languages = Languages()
  21. self.deadline = now + datetime.timedelta(days=2)
  22. def get_project_guid(self):
  23. return self.__guid
  24. def set_project_guid(self, value):
  25. self.__guid = value
  26. def populate_project_info(self, projectInfo):
  27. """Populates name, domain, languages, deadline from project information as received
  28. from memoQ server."""
  29. if projectInfo != None:
  30. self.name = projectInfo['Name']
  31. self.domain = projectInfo['Domain']
  32. self.languages.target.extend(
  33. [x for x in projectInfo['TargetLanguageCodes'].string])
  34. self.languages.source = projectInfo['SourceLanguageCode']
  35. self.deadline = projectInfo['Deadline']
  36. class MemoQProject(object):
  37. """Client for memoQ Server projects API."""
  38. def __init__(self):
  39. with open("config.json") as json_file:
  40. self.config = json.load(json_file)
  41. if self.config["api_base_url"] != "":
  42. apiURL = self.config["api_base_url"] + \
  43. "/memoqservices/ServerProject?wsdl"
  44. self.client = Client(apiURL)
  45. self.project = Project()
  46. def __repr__(self):
  47. if self.project.get_project_guid() != None:
  48. return "{} - {}\n{} - {}\n{}".format(self.project.name, self.project.get_project_guid(), self.project.languages.source, (", ").join([x for x in self.project.languages.target]), str(self.project.deadline))
  49. else:
  50. return "No project!"
  51. def get_project_by_domain(self, domain):
  52. """Gets first project of given domain name."""
  53. filter = self.client.factory.create(
  54. '{http://kilgray.com/memoqservices/2007}ServerProjectListFilter')
  55. filter.Domain = domain
  56. projects = self.client.service.ListProjects(filter)
  57. if projects:
  58. self.project.set_project_guid(projects[0][0]['ServerProjectGuid'])
  59. self.project.populate_project_info(projects[0][0])
  60. else:
  61. self.project.set_project_guid(None)
  62. def get_project_by_guid(self, guid):
  63. """Gets project information for project of given guid."""
  64. project_info = self.client.service.GetProject(guid)
  65. if project_info != None:
  66. self.project.set_project_guid(guid)
  67. self.project.populate_project_info(project_info)
  68. else:
  69. self.project.set_project_guid(None)
  70. def template_project_options(self, template_guid):
  71. """Needs guid of memoQ project template.
  72. Returns options needed for creating memoQ project from template."""
  73. if self.project.languages.source != None:
  74. options = self.client.factory.create(
  75. '{http://kilgray.com/memoqservices/2007}TemplateBasedProjectCreateInfo')
  76. options.TemplateGuid = template_guid
  77. options.Name = self.project.name
  78. options.SourceLanguageCode = self.project.languages.source
  79. options.Domain = self.project.domain
  80. options.CreatorUser = self.config["creator_guid"]
  81. return options
  82. else:
  83. return None
  84. def create_project_from_template(self, templateGuid):
  85. """Creates memoQ project from given project template.
  86. Sets new project as active project on success."""
  87. options = self.template_project_options(templateGuid)
  88. if options != None:
  89. result = self.client.service.CreateProjectFromTemplate(options)
  90. if result.ResultStatus == "Success":
  91. self.get_project_by_guid(result.ProjectGuid)
  92. else:
  93. self.project.set_project_guid(None)
  94. def project_options(self):
  95. """Returns options needed for creating memoQ project."""
  96. if len(self.project.languages.target) and self.project.languages.source != None:
  97. options = self.client.factory.create(
  98. '{http://kilgray.com/memoqservices/2007}ServerProjectDesktopDocsCreateInfo')
  99. options.Name = self.project.name
  100. options.SourceLanguageCode = self.project.languages.source
  101. options.TargetLanguageCodes.string = self.project.languages.target
  102. options.Deadline = self.project.deadline
  103. options.RecordVersionHistory = True
  104. options.CreatorUser = self.config["creator_guid"]
  105. resources = self.client.factory.create(
  106. '{http://schemas.datacontract.org/2004/07/MemoQServices}ServerProjectResourcesInPackages')
  107. options.PackageResourceHandling.value = resources.LinkRemote
  108. return options
  109. else:
  110. return None
  111. def create_project(self):
  112. """Creates memoQ project. Sets new project as active project on success."""
  113. options = self.project_options()
  114. if options != None:
  115. project_guid = self.client.service.CreateProject2(options)
  116. if project_guid != None:
  117. self.get_project_by_guid(project_guid)
  118. else:
  119. self.project.set_project_guid(None)
  120. def import_document(self, path):
  121. """Uploads and then imports given file to active project for all target languages.
  122. Returns true on success."""
  123. file_client = memoQFile.MemoQFile()
  124. file_guid = file_client.upload_file(path)
  125. if file_guid == None:
  126. return False
  127. langs = self.client.factory.create(
  128. '{http://kilgray.com/memoqservices/2007}targetLangCodes')
  129. langs.string = self.project.languages.target
  130. result = self.client.service.ImportTranslationDocument(
  131. self.project.get_project_guid(), file_guid, langs)
  132. if result != None:
  133. return True
  134. else:
  135. return False
  136. def get_project_documents(self):
  137. """Gets list of documents from active project."""
  138. options = self.client.factory.create(
  139. '{http://kilgray.com/memoqservices/2007}ListServerProjectTranslationDocument2Options')
  140. options.FillInAssignmentInformation = True
  141. if self.project.get_project_guid() != None:
  142. self.documents = self.client.service.ListProjectTranslationDocuments2(
  143. self.project.get_project_guid(), options)
  144. def document_guids(self):
  145. """Returns guids of documents from active project."""
  146. if self.documents == None:
  147. self.get_project_documents()
  148. return [x.DocumentGuid for x in self.documents[0]]
  149. def print_documents(self):
  150. """Prints basic information on documents from active project."""
  151. if self.documents == None:
  152. self.get_project_documents()
  153. for document in self.documents[0]:
  154. print("{} ({}) - {}\n".format(document.DocumentName,
  155. document.TargetLangCode, document.DocumentGuid))
  156. def export_documents(self, path):
  157. """Exports all documents from active project to given path.
  158. Prints path to each file on success and returns true."""
  159. if self.project.get_project_guid() == None:
  160. return "No project!"
  161. if self.project.documents == None:
  162. self.get_project_documents()
  163. export_results = []
  164. for guid in self.document_guids():
  165. export_results.append(
  166. self.client.service.ExportTranslationDocument(self.project.get_project_guid(), guid))
  167. file_client = memoQFile.MemoQFile()
  168. if len(export_results):
  169. for document in export_results:
  170. print(file_client.download_file(path, document.FileGuid))
  171. return True
  172. else:
  173. return False
  174. def export_documents2(self, path):
  175. """Exports all documents from active project to given path using extended method.
  176. Prints path to each file on success and returns true."""
  177. if self.project.get_project_guid() == None:
  178. return "No project!"
  179. if self.documents == None:
  180. self.get_project_documents()
  181. options = self.client.factory.create(
  182. '{http://kilgray.com/memoqservices/2007}DocumentExportOptions')
  183. options.CopySourceToEmptyTarget = True
  184. export_results = []
  185. for guid in self.document_guids():
  186. export_results.append(self.client.service.ExportTranslationDocument2(
  187. self.project.get_project_guid(), guid, options))
  188. file_client = memoQFile.MemoQFile()
  189. if len(export_results):
  190. for document in export_results:
  191. print(file_client.download_file(path, document.FileGuid))
  192. return True
  193. else:
  194. return False
  195. def statistics_options(self):
  196. """Returns options for statistics."""
  197. options = self.client.factory.create(
  198. '{http://kilgray.com/memoqservices/2007}StatisticsOptions')
  199. options.Analysis_ProjectTMs = True
  200. options.Analysis_Homogenity = True
  201. options.ShowResultsPerFile = True
  202. options.RepetitionPreferenceOver100 = True
  203. statistics_algorithm = self.client.factory.create(
  204. '{http://schemas.datacontract.org/2004/07/MemoQServices}StatisticsAlgorithm')
  205. options.Algorithm.value = statistics_algorithm.MemoQ
  206. return options
  207. def run_statistics(self):
  208. """Returns statistics for all documents and language combinations of active project,
  209. none on failure."""
  210. options = self.statistics_options()
  211. statistics_format = self.client.factory.create(
  212. '{http://schemas.datacontract.org/2004/07/MemoQServices}StatisticsResultFormat')
  213. languages = self.client.factory.create(
  214. '{http://kilgray.com/memoqservices/2007}targetLangCodes')
  215. languages.string = self.project.languages.target
  216. try:
  217. stats = self.client.service.GetStatisticsOnProject(
  218. self.project.get_project_guid(), languages, options, statistics_format.CSV_MemoQ)
  219. if stats.ResultStatus == "Success":
  220. return stats
  221. else:
  222. return None
  223. except Exception as e:
  224. print(str(e))
  225. def save_statistics(self, path):
  226. """Saves statictis to given path (one file per language combination).
  227. Returns path to statistics file(s)."""
  228. statistics = self.run_statistics()
  229. if statistics != None:
  230. for stat in statistics.ResultsForTargetLangs.StatisticsResultForLang:
  231. output_file = '{}_{}.csv'.format(
  232. stat.TargetLangCode, self.project.name)
  233. with open(output_file, 'wb') as target:
  234. target.write(b64decode(stat.ResultData))
  235. filename = '{}_{}.csv'.format(
  236. stat.TargetLangCode, self.project.name)
  237. output_file = os.path.join(path, filename)
  238. with open(output_file, 'wb') as target:
  239. # Statistics are base64 and utf-16 encoded, so we need to
  240. # decode first
  241. stat_data = b64decode(stat.ResultData).decode("utf-16")
  242. # Changing delimiter to ,
  243. stat_data = stat_data.replace(";", ",")
  244. target.write(stat_data.encode("utf-8"))
  245. return output_file
  246. def delete(self):
  247. """Deletes active project permamently. WARNING! Not possible to recover!"""
  248. self.client.service.DeleteProject(self.project.get_project_guid())