| OLD | NEW | 
|---|
| 1 # This file is part of the Adblock Plus web scripts, | 1 # This file is part of the Adblock Plus web scripts, | 
| 2 # Copyright (C) 2006-present eyeo GmbH | 2 # Copyright (C) 2006-present eyeo GmbH | 
| 3 # | 3 # | 
| 4 # Adblock Plus is free software: you can redistribute it and/or modify | 4 # Adblock Plus is free software: you can redistribute it and/or modify | 
| 5 # it under the terms of the GNU General Public License version 3 as | 5 # it under the terms of the GNU General Public License version 3 as | 
| 6 # published by the Free Software Foundation. | 6 # published by the Free Software Foundation. | 
| 7 # | 7 # | 
| 8 # Adblock Plus is distributed in the hope that it will be useful, | 8 # Adblock Plus is distributed in the hope that it will be useful, | 
| 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of | 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| 11 # GNU General Public License for more details. | 11 # GNU General Public License for more details. | 
| 12 # | 12 # | 
| 13 # You should have received a copy of the GNU General Public License | 13 # You should have received a copy of the GNU General Public License | 
| 14 # along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 14 # along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| 15 | 15 | 
| 16 from __future__ import unicode_literals | 16 from __future__ import unicode_literals | 
| 17 | 17 | 
| 18 import json | 18 import json | 
|  | 19 try: | 
|  | 20     import urlparse | 
|  | 21 except ImportError: | 
|  | 22     # It's Python 3 | 
|  | 23     import urllib.parse as urlparse | 
| 19 | 24 | 
| 20 import requests | 25 import requests | 
| 21 | 26 | 
| 22 __all__ = [ | 27 __all__ = [ | 
| 23     'XTMCloudAPI', 'XTMCloudException', 'get_token', | 28     'XTMCloudAPI', 'XTMCloudException', 'get_token', | 
| 24 ] | 29 ] | 
| 25 | 30 | 
| 26 _BASE_URL = 'https://wstest2.xtm-intl.com/rest-api/' | 31 _BASE_URL = 'https://wstest2.xtm-intl.com/rest-api/' | 
| 27 | 32 | 
| 28 | 33 | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 69     } | 74     } | 
| 70 | 75 | 
| 71     class _SuccessCodes: | 76     class _SuccessCodes: | 
| 72         CREATE = 201 | 77         CREATE = 201 | 
| 73         UPLOAD = 200 | 78         UPLOAD = 200 | 
| 74         DOWNLOAD = 200 | 79         DOWNLOAD = 200 | 
| 75         GET_TARGET_LANGS = 200 | 80         GET_TARGET_LANGS = 200 | 
| 76         ADD_TARGET_LANGS = 200 | 81         ADD_TARGET_LANGS = 200 | 
| 77         GET_WORKFLOW_IDS = 200 | 82         GET_WORKFLOW_IDS = 200 | 
| 78 | 83 | 
| 79     def __init__(self, token): | 84     def __init__(self, token, base_url): | 
| 80         """Constructor. | 85         """Constructor. | 
| 81 | 86 | 
| 82         Parameters | 87         Parameters | 
| 83         ---------- | 88         ---------- | 
| 84         token: str | 89         token: str | 
| 85             Token used to authenticate with the API. | 90             Token used to authenticate with the API. | 
|  | 91         base_url: str | 
|  | 92             Url used to connect to the API. | 
| 86 | 93 | 
| 87         """ | 94         """ | 
| 88         self._token = token | 95         self._token = token | 
| 89         self.base_url = _BASE_URL | 96         self.base_url = base_url | 
| 90 | 97 | 
| 91     def _execute(self, url, data=None, files=None, stream=False, | 98     def _execute(self, url, data=None, files=None, stream=False, | 
| 92                  params=None, headers=None): | 99                  params=None, headers=None): | 
| 93         """Send request to the API and return the response. | 100         """Send request to the API and return the response. | 
| 94 | 101 | 
| 95         Parameters | 102         Parameters | 
| 96         ---------- | 103         ---------- | 
| 97         url: str | 104         url: str | 
| 98             The url we're making the request to. | 105             The url we're making the request to. | 
| 99         data: dict | 106         data: dict | 
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 211         } | 218         } | 
| 212 | 219 | 
| 213         if files: | 220         if files: | 
| 214             file_names, files_to_upload = self._construct_files_dict( | 221             file_names, files_to_upload = self._construct_files_dict( | 
| 215                 files, 'translationFiles[{}]') | 222                 files, 'translationFiles[{}]') | 
| 216             data.update(file_names) | 223             data.update(file_names) | 
| 217         else: | 224         else: | 
| 218             # Hacky way to go around 415 error code | 225             # Hacky way to go around 415 error code | 
| 219             files_to_upload = {'a': 'b'} | 226             files_to_upload = {'a': 'b'} | 
| 220 | 227 | 
| 221         url = self.base_url + self._UrlPaths.CREATE | 228         url = urlparse.urljoin(self.base_url, self._UrlPaths.CREATE) | 
| 222 | 229 | 
| 223         response = self._execute(url, data=data, files=files_to_upload) | 230         response = self._execute(url, data=data, files=files_to_upload) | 
| 224 | 231 | 
| 225         if response.status_code != self._SuccessCodes.CREATE: | 232         if response.status_code != self._SuccessCodes.CREATE: | 
| 226             # The creation was not successful | 233             # The creation was not successful | 
| 227             raise XTMCloudException(response.status_code, | 234             raise XTMCloudException(response.status_code, | 
| 228                                     response.text.decode('utf-8'), | 235                                     response.text.decode('utf-8'), | 
| 229                                     'creating job') | 236                                     'creating job') | 
| 230 | 237 | 
| 231         data = json.loads(response.text.encode('utf-8')) | 238         data = json.loads(response.text.encode('utf-8')) | 
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 268         file_names, files_to_upload = self._construct_files_dict( | 275         file_names, files_to_upload = self._construct_files_dict( | 
| 269             files, 'files[{}]', | 276             files, 'files[{}]', | 
| 270         ) | 277         ) | 
| 271 | 278 | 
| 272         if len(files_to_upload.keys()) == 0: | 279         if len(files_to_upload.keys()) == 0: | 
| 273             raise Exception('Error: No files provided for upload.') | 280             raise Exception('Error: No files provided for upload.') | 
| 274 | 281 | 
| 275         data = {'matchType': self._MATCH_TYPE[overwrite]} | 282         data = {'matchType': self._MATCH_TYPE[overwrite]} | 
| 276         data.update(file_names) | 283         data.update(file_names) | 
| 277 | 284 | 
| 278         url = self.base_url + self._UrlPaths.UPLOAD.format(project_id) | 285         url = urlparse.urljoin( | 
|  | 286             self.base_url, self._UrlPaths.UPLOAD.format(project_id), | 
|  | 287         ) | 
| 279 | 288 | 
| 280         response = self._execute(url, data=data, files=files_to_upload) | 289         response = self._execute(url, data=data, files=files_to_upload) | 
| 281 | 290 | 
| 282         if response.status_code != self._SuccessCodes.UPLOAD: | 291         if response.status_code != self._SuccessCodes.UPLOAD: | 
| 283             raise XTMCloudException(response.status_code, | 292             raise XTMCloudException(response.status_code, | 
| 284                                     response.text.encode('utf-8'), | 293                                     response.text.encode('utf-8'), | 
| 285                                     'uploading files') | 294                                     'uploading files') | 
| 286 | 295 | 
| 287         return json.loads(response.text.encode('utf-8'))['jobs'] | 296         return json.loads(response.text.encode('utf-8'))['jobs'] | 
| 288 | 297 | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 300         ------- | 309         ------- | 
| 301         bytes | 310         bytes | 
| 302             The contents of the zip file returned by the API | 311             The contents of the zip file returned by the API | 
| 303 | 312 | 
| 304         Raises | 313         Raises | 
| 305         ------ | 314         ------ | 
| 306         XTMCloudException | 315         XTMCloudException | 
| 307             If the request is flawed in any way. | 316             If the request is flawed in any way. | 
| 308 | 317 | 
| 309         """ | 318         """ | 
| 310         url = (self.base_url + self._UrlPaths.DOWNLOAD).format(project_id) | 319         url = urlparse.urljoin( | 
|  | 320             self.base_url, self._UrlPaths.DOWNLOAD.format(project_id), | 
|  | 321         ) | 
| 311 | 322 | 
| 312         exception_msg = { | 323         exception_msg = { | 
| 313             400: 'Invalid request', | 324             400: 'Invalid request', | 
| 314             401: 'Authentication failed', | 325             401: 'Authentication failed', | 
| 315             500: 'Internal server error', | 326             500: 'Internal server error', | 
| 316             404: 'Project not found.', | 327             404: 'Project not found.', | 
| 317         } | 328         } | 
| 318 | 329 | 
| 319         response = self._execute(url, params={'fileType': files_type}, | 330         response = self._execute(url, params={'fileType': files_type}, | 
| 320                                  stream=True) | 331                                  stream=True) | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 340         ------- | 351         ------- | 
| 341         iterable | 352         iterable | 
| 342             With the target languages for this project. | 353             With the target languages for this project. | 
| 343 | 354 | 
| 344         Raises | 355         Raises | 
| 345         ------ | 356         ------ | 
| 346         XTMCloudException | 357         XTMCloudException | 
| 347             If the request is unsuccessful. | 358             If the request is unsuccessful. | 
| 348 | 359 | 
| 349         """ | 360         """ | 
| 350         url = (self.base_url + self._UrlPaths.GET_TARGET_LANG).format( | 361         url = urlparse.urljoin( | 
| 351             project_id, | 362             self.base_url, self._UrlPaths.GET_TARGET_LANG.format(project_id), | 
| 352         ) | 363         ) | 
| 353 | 364 | 
| 354         response = self._execute(url, stream=True) | 365         response = self._execute(url, stream=True) | 
| 355 | 366 | 
| 356         if response.status_code != self._SuccessCodes.GET_TARGET_LANGS: | 367         if response.status_code != self._SuccessCodes.GET_TARGET_LANGS: | 
| 357             raise XTMCloudException(response.status_code, response.content, | 368             raise XTMCloudException(response.status_code, response.content, | 
| 358                                     'extracting target languages') | 369                                     'extracting target languages') | 
| 359 | 370 | 
| 360         data = json.loads(response.content.encode('utf-8')) | 371         data = json.loads(response.content.encode('utf-8')) | 
| 361         return {item['targetLanguage'] for item in data} | 372         return {item['targetLanguage'] for item in data} | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 372 | 383 | 
| 373         Raises | 384         Raises | 
| 374         ------- | 385         ------- | 
| 375         XTMCloudException | 386         XTMCloudException | 
| 376             If the request to the API was not successful. | 387             If the request to the API was not successful. | 
| 377 | 388 | 
| 378         """ | 389         """ | 
| 379         data = json.dumps({ | 390         data = json.dumps({ | 
| 380             'targetLanguages': target_languages, | 391             'targetLanguages': target_languages, | 
| 381         }) | 392         }) | 
| 382         url = (self.base_url + self._UrlPaths.ADD_TARGET_LANG).format( | 393 | 
| 383             project_id, | 394         url = urlparse.urljoin( | 
|  | 395             self.base_url, self._UrlPaths.ADD_TARGET_LANG.format(project_id), | 
| 384         ) | 396         ) | 
|  | 397 | 
| 385         headers = {'content-type': 'application/json'} | 398         headers = {'content-type': 'application/json'} | 
| 386 | 399 | 
| 387         response = self._execute(url, data=data, headers=headers) | 400         response = self._execute(url, data=data, headers=headers) | 
| 388 | 401 | 
| 389         if response.status_code != self._SuccessCodes.ADD_TARGET_LANGS: | 402         if response.status_code != self._SuccessCodes.ADD_TARGET_LANGS: | 
| 390             raise XTMCloudException(response.status_code, response.content, | 403             raise XTMCloudException(response.status_code, response.content, | 
| 391                                     'adding target languages to project') | 404                                     'adding target languages to project') | 
| 392 | 405 | 
| 393     def get_workflows_by_name(self, name): | 406     def get_workflows_by_name(self, name): | 
| 394         """Get workflows with a specific name. | 407         """Get workflows with a specific name. | 
| 395 | 408 | 
| 396         Parameters | 409         Parameters | 
| 397         ---------- | 410         ---------- | 
| 398         name: str | 411         name: str | 
| 399             The name of the workflow we're looking for. | 412             The name of the workflow we're looking for. | 
| 400 | 413 | 
| 401         Returns | 414         Returns | 
| 402         ------- | 415         ------- | 
| 403         iterable | 416         iterable | 
| 404             Of workflow ids that match the name provided. | 417             Of workflow ids that match the name provided. | 
| 405 | 418 | 
| 406         """ | 419         """ | 
| 407         url = self.base_url + self._UrlPaths.GET_WORKFLOW_IDS | 420         url = urlparse.urljoin(self.base_url, self._UrlPaths.GET_WORKFLOW_IDS) | 
| 408 | 421 | 
| 409         response = self._execute(url, params={'name': name}) | 422         response = self._execute(url, params={'name': name}) | 
| 410 | 423 | 
| 411         if response.status_code != self._SuccessCodes.GET_WORKFLOW_IDS: | 424         if response.status_code != self._SuccessCodes.GET_WORKFLOW_IDS: | 
| 412             raise XTMCloudException(response.status_code, response.content, | 425             raise XTMCloudException(response.status_code, response.content, | 
| 413                                     'extracting workflow ids') | 426                                     'extracting workflow ids') | 
| 414 | 427 | 
| 415         valid_ids = [] | 428         valid_ids = [] | 
| 416         for item in json.loads(response.content.encode('utf-8')): | 429         for item in json.loads(response.content.encode('utf-8')): | 
| 417             if name.lower().replace(' ', '') == \ | 430             if name.lower().replace(' ', '') == \ | 
| 418                     item['name'].lower().replace(' ', ''): | 431                     item['name'].lower().replace(' ', ''): | 
| 419                 valid_ids.append(item['id']) | 432                 valid_ids.append(item['id']) | 
| 420         return valid_ids | 433         return valid_ids | 
| 421 | 434 | 
| 422 | 435 | 
| 423 def get_token(username, password, user_id): | 436 def get_token(username, password, user_id, base_url): | 
| 424     """Generate an API token from username and password. | 437     """Generate an API token from username and password. | 
| 425 | 438 | 
| 426     Parameters | 439     Parameters | 
| 427     ---------- | 440     ---------- | 
| 428     username: str | 441     username: str | 
| 429         The username used to generate the token. | 442         The username used to generate the token. | 
| 430     password: str | 443     password: str | 
| 431         The password used to generate the token. | 444         The password used to generate the token. | 
| 432     user_id: int | 445     user_id: int | 
| 433         The user ID used to generate the token. | 446         The user ID used to generate the token. | 
|  | 447     base_url: str | 
|  | 448         The url used to connect to the API | 
| 434 | 449 | 
| 435     Returns | 450     Returns | 
| 436     ------- | 451     ------- | 
| 437     str | 452     str | 
| 438         The resulting token generated by the API. | 453         The resulting token generated by the API. | 
| 439 | 454 | 
| 440     Raises | 455     Raises | 
| 441     ------ | 456     ------ | 
| 442     XTMCloudException | 457     XTMCloudException | 
| 443         If the credentials provided were invalid. | 458         If the credentials provided were invalid. | 
| 444 | 459 | 
| 445     """ | 460     """ | 
| 446     request_body = json.dumps({ | 461     request_body = json.dumps({ | 
| 447         'client': username, | 462         'client': username, | 
| 448         'password': password, | 463         'password': password, | 
| 449         'userId': user_id, | 464         'userId': user_id, | 
| 450     }) | 465     }) | 
| 451 | 466 | 
| 452     url = _BASE_URL + 'auth/token' | 467     url = urlparse.urljoin(base_url, 'auth/token') | 
| 453 | 468 | 
| 454     headers = {'content-type': 'application/json'} | 469     headers = {'content-type': 'application/json'} | 
| 455 | 470 | 
| 456     response = requests.post(url, data=request_body, headers=headers) | 471     response = requests.post(url, data=request_body, headers=headers) | 
| 457 | 472 | 
| 458     if response.status_code == 200: | 473     if response.status_code == 200: | 
| 459         return json.loads(response.text)['token'].encode() | 474         return json.loads(response.text)['token'].encode() | 
| 460 | 475 | 
| 461     raise XTMCloudException(response.status_code, | 476     raise XTMCloudException(response.status_code, | 
| 462                             response.text.encode('utf-8'), | 477                             response.text.encode('utf-8'), | 
| 463                             'generating token') | 478                             'generating token') | 
| OLD | NEW | 
|---|