SmartlingApiSdk 3.1.6__py2-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. SmartlingApiSdk-3.1.6.dist-info/METADATA +14 -0
  2. SmartlingApiSdk-3.1.6.dist-info/RECORD +53 -0
  3. SmartlingApiSdk-3.1.6.dist-info/WHEEL +5 -0
  4. SmartlingApiSdk-3.1.6.dist-info/top_level.txt +4 -0
  5. smartlingApiSdk/ApiResponse.py +67 -0
  6. smartlingApiSdk/ApiV2.py +73 -0
  7. smartlingApiSdk/AuthClient.py +78 -0
  8. smartlingApiSdk/Constants.py +78 -0
  9. smartlingApiSdk/Credentials.py +74 -0
  10. smartlingApiSdk/FileApiBase.py +127 -0
  11. smartlingApiSdk/FileApiV2.py +210 -0
  12. smartlingApiSdk/HttpClient.py +155 -0
  13. smartlingApiSdk/Logger.py +64 -0
  14. smartlingApiSdk/MultipartPostHandler.py +127 -0
  15. smartlingApiSdk/ObsoleteApiV1.py +94 -0
  16. smartlingApiSdk/ObsoleteSmartlingFileApi.py +108 -0
  17. smartlingApiSdk/ProjectsApiV2.py +52 -0
  18. smartlingApiSdk/ProxySettings.py +27 -0
  19. smartlingApiSdk/Settings.py +28 -0
  20. smartlingApiSdk/SmartlingDirective.py +38 -0
  21. smartlingApiSdk/SmartlingFileApiV2.py +189 -0
  22. smartlingApiSdk/SmartlingProjectsApiV2.py +65 -0
  23. smartlingApiSdk/UploadData.py +49 -0
  24. smartlingApiSdk/UrlV2Helper.py +74 -0
  25. smartlingApiSdk/__init__.py +23 -0
  26. smartlingApiSdk/api/AccountProjectsApi.py +120 -0
  27. smartlingApiSdk/api/ContextApi.py +250 -0
  28. smartlingApiSdk/api/EstimatesApi.py +201 -0
  29. smartlingApiSdk/api/FilesApi.py +343 -0
  30. smartlingApiSdk/api/JobBatchesV2Api.py +134 -0
  31. smartlingApiSdk/api/JobsApi.py +612 -0
  32. smartlingApiSdk/api/StringsApi.py +110 -0
  33. smartlingApiSdk/api/TagsApi.py +142 -0
  34. smartlingApiSdk/api/__init__.py +4 -0
  35. smartlingApiSdk/example/AccountProjectsExample.py +197 -0
  36. smartlingApiSdk/example/ContextExample.py +347 -0
  37. smartlingApiSdk/example/EstimatesExample.py +298 -0
  38. smartlingApiSdk/example/FilesExample.py +498 -0
  39. smartlingApiSdk/example/FilesSimpleExample.py +101 -0
  40. smartlingApiSdk/example/JobBatchesV2Example.py +186 -0
  41. smartlingApiSdk/example/JobsExample.py +672 -0
  42. smartlingApiSdk/example/MultipleAccountsExample.py +74 -0
  43. smartlingApiSdk/example/MultipleProjectsExample.py +118 -0
  44. smartlingApiSdk/example/StringsExample.py +224 -0
  45. smartlingApiSdk/example/TagsExample.py +214 -0
  46. smartlingApiSdk/example/__init__.py +4 -0
  47. smartlingApiSdk/resources/ctx_api_test.png +0 -0
  48. smartlingApiSdk/resources/java.properties +10 -0
  49. smartlingApiSdk/resources/javaUTF16.properties +0 -0
  50. smartlingApiSdk/resources/test.csv +1 -0
  51. smartlingApiSdk/resources/test_import.xml +5 -0
  52. smartlingApiSdk/resources/test_import_es.xml +5 -0
  53. smartlingApiSdk/version.py +20 -0
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.1
2
+ Name: SmartlingApiSdk
3
+ Version: 3.1.6
4
+ Summary: python library to work with Smartling translation services APIs
5
+ Home-page: UNKNOWN
6
+ Author: Smartling, Inc.
7
+ Author-email: aartamonov@smartling.com
8
+ License: Apache License v2.0
9
+ Keywords: translation localization internationalization
10
+ Platform: UNKNOWN
11
+
12
+ python SDK to work with Smartling API for computer assisted translation
13
+
14
+
@@ -0,0 +1,53 @@
1
+ smartlingApiSdk/ApiResponse.py,sha256=Z3zZOokJnzXSNv3QeSUGKhFDZddKpYNzIcYKywLeeic,2286
2
+ smartlingApiSdk/ApiV2.py,sha256=YURZ7LUAyw6mOPRTwbuG1jmCKw5NZ6oEfQKoKghQDjc,3105
3
+ smartlingApiSdk/AuthClient.py,sha256=2ouzC3LgjZeOtGbbGH7SfAYWOk0xpRz4Wvvvg6XXYTY,2831
4
+ smartlingApiSdk/Constants.py,sha256=IWfAKUKdD0znvKH-YY4HIYhCsHLA07lafqP-s97VwFc,2155
5
+ smartlingApiSdk/Credentials.py,sha256=mn2uIbWCTkwE-pBQFhtgPzsiKAiRUni-VIXY7Wc6uJc,2565
6
+ smartlingApiSdk/FileApiBase.py,sha256=46-n57YNyLEvaolZ1zDUTJmAL6ev0Dg0BXxtz6PRRRo,5046
7
+ smartlingApiSdk/FileApiV2.py,sha256=bKFqSTU7S5egQke2-FSKZDCb6Cznl_NOxLQeTx6wm2c,8855
8
+ smartlingApiSdk/HttpClient.py,sha256=IoFk-pRTU8lE_iDhKSfX_jnuJXn6zQ2-cKXfvcUfdsQ,5982
9
+ smartlingApiSdk/Logger.py,sha256=mjiMsXDm3ScGJi023C62eBByJ8sKMwyXctA3U3DDsz0,1954
10
+ smartlingApiSdk/MultipartPostHandler.py,sha256=uSH8gVF27_8GI_APGqynJ_sCM-Lni1g-a9IWfZ88NF4,4681
11
+ smartlingApiSdk/ObsoleteApiV1.py,sha256=E1mbV_zhSq1AB8UIofhP_EDqVnJarIK4oxFEFKpPkVE,3769
12
+ smartlingApiSdk/ObsoleteSmartlingFileApi.py,sha256=k4VI8DL4lsN5urHX7FYy4SjpORFSq6L4X1yDM8qgE_c,5208
13
+ smartlingApiSdk/ProjectsApiV2.py,sha256=8XBLVVUGQNgQFt05VgbWWI2BZjnPSEHSIdLgCkBX7yA,1970
14
+ smartlingApiSdk/ProxySettings.py,sha256=qcCzasZA09E46XHXfqYOYdlCanzm6OKYW1gfXRs8wzU,1025
15
+ smartlingApiSdk/Settings.py,sha256=x-CN71SEAP1Q3piG3sgKGVywT8ydti4BfahxJEX_-SQ,927
16
+ smartlingApiSdk/SmartlingDirective.py,sha256=5q993mwiKMAa0Jy8OdmHrBnnHklo-hep3z7UgqDQjOo,1191
17
+ smartlingApiSdk/SmartlingFileApiV2.py,sha256=FU1WTEN-LxCLxFptUZRwL4Ipa6dS331dozyL6WhEuzk,9839
18
+ smartlingApiSdk/SmartlingProjectsApiV2.py,sha256=PiuoxW6i_kdXhr3fjc6WkOhh64eA9V46wAHJ7lPVlng,2697
19
+ smartlingApiSdk/UploadData.py,sha256=0LVFGECq4nYQ4M_nZKI1JHhdr6nfbplwAO7_nr_Cegs,1457
20
+ smartlingApiSdk/UrlV2Helper.py,sha256=wFV6U0Y5Y2WG5YLVZa9E-XDPmf5eVG23tt_eupjIk04,3205
21
+ smartlingApiSdk/__init__.py,sha256=qdVmH7eXiL4lQzfaI0FatSD4wSBap5t0sVUh5p0r_x0,743
22
+ smartlingApiSdk/version.py,sha256=2mKIa33NQxUN4rYR5uX6GYH4kZbEcKHS7OWa0Cx-VR4,686
23
+ smartlingApiSdk/api/AccountProjectsApi.py,sha256=b1onXCMpW5h7HZkssdzRg2m1JJVSUqVvgwtWO4s8l10,4752
24
+ smartlingApiSdk/api/ContextApi.py,sha256=odfBimYYN4zxvcAbGePP0btEJlibq57qjrLVfBFMlFE,9896
25
+ smartlingApiSdk/api/EstimatesApi.py,sha256=4B5t4gtNLmR07H-2Hi_S96tGSKrEyWmQVBA_IwGGlMc,8471
26
+ smartlingApiSdk/api/FilesApi.py,sha256=innbMQkl_GLkRGpi7Y97ZzZG_UQP1idzrSsXYvaOa00,15936
27
+ smartlingApiSdk/api/JobBatchesV2Api.py,sha256=rZZvZj5NucQb1HooLG4pQCmQEOygszD54Uewg8nvkQo,6368
28
+ smartlingApiSdk/api/JobsApi.py,sha256=xUZSwI0mCFC_fsF-lNhvyspgPy8ggf_JZ_GlPm3z2Vw,25353
29
+ smartlingApiSdk/api/StringsApi.py,sha256=mInS484yAqI7QFWO8D95JeAlm_6TqK9uQTP9kvnwZC4,4792
30
+ smartlingApiSdk/api/TagsApi.py,sha256=ULvdrovHa-79GH6AWiiGqe-696ddO2OjooD7jAFj_Jk,6151
31
+ smartlingApiSdk/api/__init__.py,sha256=SKWZ9FbAuABhf__YLJJ1Ca9FGKJMl6QcXRx47M-enlo,48
32
+ smartlingApiSdk/example/AccountProjectsExample.py,sha256=YMOmOJ2XHzDuPMb_-v6jJ79fM_m3zcwt9x5asbAuvw4,7185
33
+ smartlingApiSdk/example/ContextExample.py,sha256=nF-n6qo8Tt6GjkWyR9agnYvXI1CoR9tvlWLeWbNTKZM,13247
34
+ smartlingApiSdk/example/EstimatesExample.py,sha256=OF2wK5of-KOCc9pHlf0illPdtvu9F4cka_K4z2Tta4c,11738
35
+ smartlingApiSdk/example/FilesExample.py,sha256=HqbX0NlJcX3DGZk2i2Skd1_Rf19sGMyFJsGMfPUlvm0,21115
36
+ smartlingApiSdk/example/FilesSimpleExample.py,sha256=7rmgAJfVjiaNiz4knmVe7X0EmlJo232AI9lUx9ENxI0,3171
37
+ smartlingApiSdk/example/JobBatchesV2Example.py,sha256=MGfAoZMyDwtXV1TffwRFd4vS2Ye8KlpcucjCrJuyuiY,8143
38
+ smartlingApiSdk/example/JobsExample.py,sha256=w-y87I-3ij8IDPIp9kcjzMiVQ6NTRNAJq7aVHxWXN1w,27326
39
+ smartlingApiSdk/example/MultipleAccountsExample.py,sha256=Twd5Yq9V2_76kK86tZb8E7FOxtgljZ5J2IXoYMlkaLI,2770
40
+ smartlingApiSdk/example/MultipleProjectsExample.py,sha256=6Faa4DqL1RL8zDK8lnmk2yqL84LuZCBU55t5FNYgm40,4647
41
+ smartlingApiSdk/example/StringsExample.py,sha256=GHSQhVG90a4BPSdUstyf5Si8ie9yoLgusvrqjJeGnQQ,9083
42
+ smartlingApiSdk/example/TagsExample.py,sha256=1KkSriVU0CEbbkZtdFox7jH-Uy_cMWi1bQPvOo0j9Ek,8496
43
+ smartlingApiSdk/example/__init__.py,sha256=SKWZ9FbAuABhf__YLJJ1Ca9FGKJMl6QcXRx47M-enlo,48
44
+ smartlingApiSdk/resources/ctx_api_test.png,sha256=QuHjmQp7LQK36XjdSPP7xsnVMab3tmS1WkYyc8Uwvyc,86324
45
+ smartlingApiSdk/resources/java.properties,sha256=rnVIRoE_ZcKPCNRbpyKeP44gAV2pMsYcGv6ZVINB9f4,131
46
+ smartlingApiSdk/resources/javaUTF16.properties,sha256=qdf-viEU2xkzzFW6foepsvtoT1BGGzJfyYP7OMOljRk,442
47
+ smartlingApiSdk/resources/test.csv,sha256=5KiwUBT6oMFg_FtODmVPbLO1bP3BY2j8eNIu4CtW9OU,32
48
+ smartlingApiSdk/resources/test_import.xml,sha256=TM_flmNi8kp4eRI5QONKj-k0F8o29qe0Bp4x_F13V0U,155
49
+ smartlingApiSdk/resources/test_import_es.xml,sha256=Lgw-dZnmvsmM1uS7iSZjwE7eYKbWKf1h5lIdpa4x4sU,152
50
+ SmartlingApiSdk-3.1.6.dist-info/METADATA,sha256=Lo-_WPn_T_HVDLnX0pXjgW90TYdIHBoFjOkdhBireiM,392
51
+ SmartlingApiSdk-3.1.6.dist-info/WHEEL,sha256=1VPi6hfNQaRRNuEdK_3dv9o8COtLGnHWJghhj4CQ28k,92
52
+ SmartlingApiSdk-3.1.6.dist-info/top_level.txt,sha256=e38w7yd0va1Chiw-UZcdu7NkI0jewljDg-OR21eenL0,86
53
+ SmartlingApiSdk-3.1.6.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.37.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py2-none-any
5
+
@@ -0,0 +1,4 @@
1
+ smartlingApiSdk
2
+ smartlingApiSdk/api
3
+ smartlingApiSdk/example
4
+ smartlingApiSdk/resources
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: utf-8 -*-
3
+
4
+
5
+ """ Copyright 2012-2021 Smartling, Inc.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this work except in compliance with the License.
9
+ * You may obtain a copy of the License in the LICENSE file, or at:
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ """
19
+
20
+ import json
21
+
22
+
23
+ class Data:
24
+ """ provides dictionary items to be object attributes """
25
+ def __init__(self, dict):
26
+ self.dict = dict
27
+
28
+ def __getattr__(self, key):
29
+ return self.dict[key]
30
+
31
+ def __str__(self):
32
+ return repr(self.dict)
33
+
34
+
35
+ class ApiResponse:
36
+ """ response object to store parsed json response as python object, it also behaves like string for backward
37
+ compatibility with previous SDK versions where response was a string """
38
+ def __init__(self, responseString, statusCode, headers):
39
+ self.statusCode = statusCode
40
+ self.responseString = responseString
41
+ self.responseDict = json.loads(responseString)
42
+ self.isApiResonse = self.responseDict.get('response', None) and dict == type(self.responseDict['response'])
43
+ self.headers = headers
44
+ if self.isApiResonse:
45
+ self.parseResponse()
46
+
47
+ def parseResponse(self):
48
+ """ parses json and fills object attributes according json attributes """
49
+
50
+ for k, v in list(self.responseDict['response'].items()):
51
+ if k == 'data':
52
+ self.data = Data(v)
53
+ else:
54
+ setattr(self, k, v)
55
+
56
+ def __getattr__(self, key):
57
+ """ provides string object methods to be available for response to behave like a string """
58
+ if hasattr(self.responseDict, key):
59
+ return getattr(self.responseDict, key)
60
+
61
+ try:
62
+ return self.__dict__[key]
63
+ except:
64
+ raise AttributeError("ApiResponse has no attribute %r" % ( key ))
65
+
66
+ def __str__(self):
67
+ return str(self.responseString)
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: utf-8 -*-
3
+
4
+
5
+ """ Copyright 2012-2021 Smartling, Inc.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this work except in compliance with the License.
9
+ * You may obtain a copy of the License in the LICENSE file, or at:
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ """
19
+
20
+ # FileApi class implementation
21
+
22
+ from .AuthClient import AuthClient
23
+ from .Constants import FileTypes
24
+ from .Constants import Params
25
+ from .FileApiBase import FileApiBase
26
+ from .SmartlingDirective import SmartlingDirective
27
+ from .UrlV2Helper import UrlV2Helper
28
+ from .version import version
29
+
30
+
31
+ class ApiV2(FileApiBase):
32
+ """ Api v2 basic functionality """
33
+ hostProd = 'api.smartling.com'
34
+ hostStg = 'api.stg.smartling.net'
35
+ clientUid = "{\"client\":\"smartling-api-sdk-python\",\"version\":\"%s\"}" % version
36
+
37
+ def __init__(self, userIdentifier, userSecret, projectId, proxySettings=None, permanentHeaders={}, env='prod'):
38
+ self.host = self.hostProd
39
+ self.userIdentifier = userIdentifier
40
+ if 'stg'==env:
41
+ self.host = self.hostStg
42
+ FileApiBase.__init__(self, self.host, userIdentifier, userSecret, proxySettings, permanentHeaders=permanentHeaders)
43
+ self.authClient = AuthClient(self.host, userIdentifier, userSecret, proxySettings)
44
+ self.urlHelper = UrlV2Helper(projectId)
45
+
46
+ def addAuth(self, params):
47
+ token = self.authClient.getToken()
48
+ if token is None:
49
+ raise Exception("Error getting token, userIdentifier:%s" % (self.userIdentifier))
50
+ return {"Authorization": "Bearer " + token}
51
+
52
+ def validateFileTypes(self, kw):
53
+ fileTypes = kw.get("fileTypes", [])
54
+ if type(fileTypes) != type([]) and type(fileTypes) != type(()):
55
+ fileTypes = [fileTypes]
56
+ for t in fileTypes:
57
+ if not getattr(FileTypes, t, None):
58
+ unsupported = "\nUnsupported file type:%s\n" % t
59
+ raise Exception(unsupported)
60
+
61
+ def checkRetrievalType(self, kw):
62
+ if Params.RETRIEVAL_TYPE in kw and not kw[Params.RETRIEVAL_TYPE] in Params.allowedRetrievalTypes:
63
+ Exception("Not allowed value `%s` for parameter:%s try one of %s" % (kw[Params.RETRIEVAL_TYPE],
64
+ Params.RETRIEVAL_TYPE,
65
+ Params.allowedRetrievalTypes))
66
+
67
+ def processDirectives(self, params, directives):
68
+ for name, value in list(directives.items()):
69
+ params[SmartlingDirective.SL_PREFIX + name] = value
70
+
71
+ def addLibIdDirective(self, params):
72
+ name = "client_lib_id"
73
+ params[SmartlingDirective.SL_PREFIX + name] = self.clientUid
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: utf-8 -*-
3
+
4
+
5
+ """ Copyright 2012-2021 Smartling, Inc.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this work except in compliance with the License.
9
+ * You may obtain a copy of the License in the LICENSE file, or at:
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ """
19
+
20
+ from .HttpClient import HttpClient
21
+ from .ApiResponse import ApiResponse
22
+ from .Constants import ReqMethod
23
+
24
+ import time
25
+
26
+
27
+ class AuthClient:
28
+ authUri = "/auth-api/v2/authenticate"
29
+ refreshUri = "/auth-api/v2/authenticate/refresh"
30
+ timeJitter = 5 # Seconds off server expiration time
31
+
32
+ def __init__(self, host, userIdentifier, userSecret, proxySettings=None):
33
+ self.httpClient = HttpClient(host, proxySettings)
34
+ self.userIdentifier = userIdentifier
35
+ self.userSecret = userSecret
36
+ self.accessExpiresAt = 0
37
+ self.refreshExpiresAt = 0
38
+
39
+ def request(self, uri, body):
40
+ header = {"Content-Type": "application/json"}
41
+ body = body.encode()
42
+ response_data, status_code, headers = self.httpClient.getHttpResponseAndStatus(
43
+ ReqMethod.POST, uri, params={}, extraHeaders=header, requestBody=body)
44
+ apiResponse = ApiResponse(response_data, status_code, headers)
45
+
46
+ now = time.time()
47
+ try:
48
+ self.accessToken = apiResponse.data.accessToken
49
+ self.refreshToken = apiResponse.data.refreshToken
50
+ self.accessExpiresAt = now + apiResponse.data.expiresIn - self.timeJitter
51
+ self.refreshExpiresAt = now + apiResponse.data.refreshExpiresIn - self.timeJitter
52
+ except Exception as e:
53
+ print(e)
54
+ self.accessToken = None
55
+
56
+ def authenticate(self):
57
+ body = '{"userIdentifier": "%s", "userSecret": "%s"}' % (self.userIdentifier, self.userSecret)
58
+ if '@smartling.com' in self.userIdentifier:
59
+ self.request(self.authUri + '/user', body)
60
+ else:
61
+ self.request(self.authUri, body)
62
+
63
+ def refresh(self):
64
+ body = '{"refreshToken":"%s"}' % self.refreshToken
65
+ self.request(self.refreshUri, body)
66
+
67
+ def getToken(self):
68
+ if not getattr(self, 'accessToken', None):
69
+ self.authenticate()
70
+ return self.accessToken
71
+
72
+ now = time.time()
73
+ if now >= self.accessExpiresAt:
74
+ if now < self.refreshExpiresAt:
75
+ self.refresh()
76
+ else:
77
+ self.authenticate()
78
+ return self.accessToken
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: utf-8 -*-
3
+
4
+
5
+ """ Copyright 2012-2021 Smartling, Inc.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this work except in compliance with the License.
9
+ * You may obtain a copy of the License in the LICENSE file, or at:
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ """
19
+
20
+ #constants for File API
21
+
22
+
23
+ class Params:
24
+ allowedRetrievalTypes = ('pending', 'published', 'pseudo', 'contextMatchingInstrumented')
25
+
26
+ API_KEY = 'apiKey'
27
+ PROJECT_ID = 'projectId'
28
+ FILE_PATH = 'file_path'
29
+ FILE_URI = 'fileUri'
30
+ FILE_TYPE = 'fileType'
31
+ LOCALE = 'locale'
32
+ FILE = 'file'
33
+ APPROVED = 'approved'
34
+ RETRIEVAL_TYPE = 'retrievalType'
35
+ FILE_URI_NEW = 'newFileUri'
36
+ CALLBACK_URL = 'callbackUrl'
37
+ LOCALES_TO_APPROVE = 'localesToApprove'
38
+ LOCALE_IDS = 'localeIds'
39
+ LOCALE_IDS_BRACKET = 'localeIds[]'
40
+ FILE_URIS = 'fileUris'
41
+
42
+ class Uri:
43
+ base = '/v1/file/'
44
+ UPLOAD = base + 'upload'
45
+ LIST = base + 'list'
46
+ GET = base + 'get'
47
+ STATUS = base + 'status'
48
+ DELETE = base + 'delete'
49
+ RENAME = base + 'rename'
50
+ IMPORT = base + 'import'
51
+ LAST_MODIFIED = base + 'last_modified'
52
+
53
+
54
+ class ReqMethod:
55
+ POST = "POST"
56
+ GET = "GET"
57
+ DELETE = "DELETE"
58
+ PUT = "PUT"
59
+
60
+
61
+ class FileTypes:
62
+ android = "android"
63
+ ios = "ios"
64
+ gettext = "gettext"
65
+ html = "html"
66
+ javaProperties = "javaProperties"
67
+ yaml = "yaml"
68
+ xliff = "xliff"
69
+ xml = "xml"
70
+ json = "json"
71
+ docx = "docx"
72
+ pptx = "pptx"
73
+ xlsx = "xlsx"
74
+ idml = "idml"
75
+ qt = "qt"
76
+ resx = "resx"
77
+ plaintext = "plaintext"
78
+ cvs = "cvs"
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: utf-8 -*-
3
+
4
+
5
+ """ Copyright 2012-2021 Smartling, Inc.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this work except in compliance with the License.
9
+ * You may obtain a copy of the License in the LICENSE file, or at:
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ """
19
+
20
+ import os
21
+
22
+
23
+ class CredentialsNotSet(Exception):
24
+ noKeyMessage = """
25
+ don't forget to set real MY_PROJECT_ID, MY_USER_IDENTIFIER, MY_USER_SECRET, MY_LOCALE
26
+ in Credentials class
27
+ or use environment variables:
28
+ export SL_LOCALE=**-**
29
+ export SL_USER_IDENTIFIER=******************************
30
+ export SL_USER_SECRET=*******************************************************
31
+
32
+ #optional
33
+ export SL_ACCOUNT_UID=******* #required only to list projects api call
34
+ export SL_PROJECT_ID=******* #required for api calls `projects` and `project_details`
35
+ """
36
+
37
+ def __init__(self, id, env):
38
+ self.id = id
39
+ self.env = env
40
+
41
+ def getMessage(self):
42
+ res = self.noKeyMessage
43
+ if 'stg' == self.env:
44
+ res = res.replace('SL_USER_IDENTIFIER=', 'SL_USER_IDENTIFIER_STG=')
45
+ res = res.replace('SL_USER_SECRET=', 'SL_USER_SECRET_STG=')
46
+ return res
47
+
48
+ def __str__(self):
49
+ return "Missing:" + self.id + self.getMessage()
50
+
51
+
52
+ class Credentials():
53
+
54
+ MY_PROJECT_ID = "CHANGE_ME"
55
+ MY_ACCOUNT_UID = "CHANGE_ME"
56
+ MY_USER_IDENTIFIER = "CHANGE_ME"
57
+ MY_USER_SECRET = "CHANGE_ME"
58
+ MY_LOCALE ="CHANGE_ME"
59
+
60
+ CREDS = ("PROJECT_ID", "ACCOUNT_UID", "USER_IDENTIFIER", "USER_SECRET", "LOCALE")
61
+ OPTIONAL_CREDS = ("ACCOUNT_UID", "LOCALE")
62
+
63
+ def __init__(self, env='prod'):
64
+ for id in self.CREDS:
65
+ cred = "MY_"+id
66
+ suffix = ''
67
+ if env == 'stg' and id.startswith("USER_"):
68
+ suffix = '_STG'
69
+ value = getattr(self, cred + suffix, "CHANGE_ME")
70
+ if "CHANGE_ME" == value:
71
+ value = os.environ.get('SL_' + id + suffix, getattr(self, cred))
72
+ if "CHANGE_ME" == value and id not in self.OPTIONAL_CREDS:
73
+ raise CredentialsNotSet('SL_' + id + suffix, env)
74
+ setattr(self, cred, value)
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/python
2
+ # -*- coding: utf-8 -*-
3
+
4
+
5
+ """ Copyright 2012-2021 Smartling, Inc.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this work except in compliance with the License.
9
+ * You may obtain a copy of the License in the LICENSE file, or at:
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ """
19
+
20
+ #FileApi class implementation
21
+
22
+ from .HttpClient import HttpClient, isPython3
23
+ from .MultipartPostHandler import MultipartPostHandler
24
+ from .Constants import Params, ReqMethod
25
+ from .ApiResponse import ApiResponse
26
+ from .Logger import Logger
27
+ from .Settings import Settings
28
+ import io
29
+ import sys
30
+ import logging
31
+ import json
32
+
33
+
34
+ class FileApiBase:
35
+ """ basic class implementing low-level api calls """
36
+ response_as_string = False
37
+
38
+ def __init__(self, host, apiKey, projectId, proxySettings=None, permanentHeaders={}):
39
+ self.host = host
40
+ self.apiKey = apiKey
41
+ self.projectId = projectId
42
+ self.proxySettings = proxySettings
43
+ self.httpClient = HttpClient(host, proxySettings, permanentHeaders=permanentHeaders)
44
+ sys.stdout = Logger('python-sdk', Settings.logLevel, Settings.logPath)
45
+ sys.stderr = Logger('STDERR', logging.ERROR, Settings.logPath)
46
+
47
+ def addAuth(self, params):
48
+ params[Params.API_KEY] = self.apiKey
49
+ params[Params.PROJECT_ID] = self.projectId
50
+ return {}
51
+
52
+ def processFile(self, file):
53
+ """"
54
+ returns file-like object form string or file
55
+ tries to treat string as file path or make it file-like object to be uploaded
56
+ """
57
+ if not file or file==type(file):
58
+ return file
59
+ try:
60
+ f = open(file, 'rb')
61
+ except:
62
+ f = io.StringIO(file)
63
+ f.seek(0)
64
+ f.name = 'String'
65
+ return f
66
+
67
+ def filterOutDefaults(self, params):
68
+ if hasattr(params, 'items'):
69
+ for k, v in list(params.items()):
70
+ if k == 'namespace':
71
+ continue #when namespace is not specified it's replaced with 'smartling.strings-api.default.namespace' for strings api
72
+ if bool == type(v): continue
73
+ if not v: del params[k]
74
+ if k == 'projectId': del params[k]
75
+
76
+ def uploadMultipart(self, uri, params, response_as_string=False):
77
+ self.filterOutDefaults(params)
78
+ authHeader = self.addAuth(params)
79
+ if Params.FILE_PATH in params:
80
+ params[Params.FILE] = open(params[Params.FILE_PATH], 'rb')
81
+ del params[Params.FILE_PATH] # no need in extra field in POST
82
+
83
+ response_data, status_code, headers = self.getHttpResponseAndStatus(ReqMethod.POST ,uri, params, MultipartPostHandler, extraHeaders = authHeader)
84
+ response_data = response_data.strip()
85
+ if self.response_as_string or response_as_string or not self.isJsonResponse(headers):
86
+ return response_data, status_code
87
+ return ApiResponse(response_data, status_code, headers), status_code
88
+
89
+ def commandJson(self, method, uri, params):
90
+ authHeader = self.addAuth(params)
91
+ authHeader['Content-Type'] = 'application/json'
92
+ self.filterOutDefaults(params)
93
+ jsonBody = json.dumps(params).encode('utf8')
94
+
95
+ data, code, headers = self.httpClient.getHttpResponseAndStatus(method, uri, params={}, requestBody = jsonBody, extraHeaders = authHeader)
96
+ if not code in [200,202]:
97
+ rId = headers.get("X-SL-RequestId","Unknown")
98
+ print ("code:%d RequestId:%s jsonBody=%s" % (code, rId, jsonBody))
99
+
100
+
101
+ if self.response_as_string or not self.isJsonResponse(headers):
102
+ return data, code
103
+ return ApiResponse(data, code, headers), code
104
+
105
+ def getHttpResponseAndStatus(self, method, uri, params, handler=None, extraHeaders = None):
106
+ return self.httpClient.getHttpResponseAndStatus(method, uri, params, handler, extraHeaders = extraHeaders)
107
+
108
+ def getResponseAndStatus(self, method, uri, params):
109
+ authHeader = self.addAuth(params)
110
+ return self.getHttpResponseAndStatus(method, uri, params, extraHeaders = authHeader)
111
+
112
+ def isJsonResponse(self, headers):
113
+ if isPython3:
114
+ hdr = 'Content-Type'
115
+ else:
116
+ hdr = 'content-type'
117
+ return 'json' in headers.get(hdr,'')
118
+
119
+ def command(self, method, uri, params):
120
+ self.filterOutDefaults(params)
121
+ data, code, headers = self.getResponseAndStatus(method, uri, params)
122
+ if self.response_as_string or not self.isJsonResponse(headers):
123
+ return data, code
124
+ result = ApiResponse(data, code, headers)
125
+ if result.isApiResonse:
126
+ return result, code
127
+ return data, code