pyxecm 1.5__py3-none-any.whl → 2.0.0__py3-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.
Potentially problematic release.
This version of pyxecm might be problematic. Click here for more details.
- pyxecm/__init__.py +6 -2
- pyxecm/avts.py +1492 -0
- pyxecm/coreshare.py +1075 -960
- pyxecm/customizer/__init__.py +16 -4
- pyxecm/customizer/__main__.py +58 -0
- pyxecm/customizer/api/__init__.py +5 -0
- pyxecm/customizer/api/__main__.py +6 -0
- pyxecm/customizer/api/app.py +914 -0
- pyxecm/customizer/api/auth.py +154 -0
- pyxecm/customizer/api/metrics.py +92 -0
- pyxecm/customizer/api/models.py +13 -0
- pyxecm/customizer/api/payload_list.py +865 -0
- pyxecm/customizer/api/settings.py +103 -0
- pyxecm/customizer/browser_automation.py +332 -139
- pyxecm/customizer/customizer.py +1075 -1057
- pyxecm/customizer/exceptions.py +35 -0
- pyxecm/customizer/guidewire.py +322 -0
- pyxecm/customizer/k8s.py +787 -338
- pyxecm/customizer/log.py +107 -0
- pyxecm/customizer/m365.py +3424 -2270
- pyxecm/customizer/nhc.py +1169 -0
- pyxecm/customizer/openapi.py +258 -0
- pyxecm/customizer/payload.py +18201 -7030
- pyxecm/customizer/pht.py +1047 -210
- pyxecm/customizer/salesforce.py +836 -727
- pyxecm/customizer/sap.py +58 -41
- pyxecm/customizer/servicenow.py +851 -383
- pyxecm/customizer/settings.py +442 -0
- pyxecm/customizer/successfactors.py +408 -346
- pyxecm/customizer/translate.py +83 -48
- pyxecm/helper/__init__.py +5 -2
- pyxecm/helper/assoc.py +98 -38
- pyxecm/helper/data.py +2482 -742
- pyxecm/helper/logadapter.py +27 -0
- pyxecm/helper/web.py +229 -101
- pyxecm/helper/xml.py +528 -172
- pyxecm/maintenance_page/__init__.py +5 -0
- pyxecm/maintenance_page/__main__.py +6 -0
- pyxecm/maintenance_page/app.py +51 -0
- pyxecm/maintenance_page/settings.py +28 -0
- pyxecm/maintenance_page/static/favicon.avif +0 -0
- pyxecm/maintenance_page/templates/maintenance.html +165 -0
- pyxecm/otac.py +234 -140
- pyxecm/otawp.py +2689 -0
- pyxecm/otcs.py +12344 -7547
- pyxecm/otds.py +3166 -2219
- pyxecm/otiv.py +36 -21
- pyxecm/otmm.py +1363 -296
- pyxecm/otpd.py +231 -127
- pyxecm-2.0.0.dist-info/METADATA +145 -0
- pyxecm-2.0.0.dist-info/RECORD +54 -0
- {pyxecm-1.5.dist-info → pyxecm-2.0.0.dist-info}/WHEEL +1 -1
- pyxecm-1.5.dist-info/METADATA +0 -51
- pyxecm-1.5.dist-info/RECORD +0 -30
- {pyxecm-1.5.dist-info → pyxecm-2.0.0.dist-info/licenses}/LICENSE +0 -0
- {pyxecm-1.5.dist-info → pyxecm-2.0.0.dist-info}/top_level.txt +0 -0
pyxecm/customizer/translate.py
CHANGED
|
@@ -1,78 +1,101 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Experimental module to automate translations
|
|
3
|
-
|
|
4
|
-
Class: Translator
|
|
5
|
-
Methods:
|
|
6
|
-
|
|
7
|
-
__init__ : class initializer
|
|
8
|
-
config: Return the configuration parameters
|
|
9
|
-
translate: Translate a string from one language to another using the Google Translate V2 API
|
|
10
|
-
translateV3: Translate a string from one language to another using the Google Translate V3 API
|
|
11
|
-
|
|
12
|
-
"""
|
|
1
|
+
"""Experimental module to automate translations."""
|
|
13
2
|
|
|
14
3
|
__author__ = "Dr. Marc Diefenbruch"
|
|
15
|
-
__copyright__ = "Copyright 2024, OpenText"
|
|
4
|
+
__copyright__ = "Copyright (C) 2024-2025, OpenText"
|
|
16
5
|
__credits__ = ["Kai-Philip Gatzweiler"]
|
|
17
6
|
__maintainer__ = "Dr. Marc Diefenbruch"
|
|
18
7
|
__email__ = "mdiefenb@opentext.com"
|
|
19
8
|
|
|
20
9
|
import logging
|
|
10
|
+
|
|
21
11
|
import requests
|
|
22
12
|
|
|
23
|
-
|
|
13
|
+
default_logger = logging.getLogger("pyxecm.customizer.translate")
|
|
14
|
+
|
|
15
|
+
REQUEST_TIMEOUT = 60
|
|
24
16
|
|
|
25
17
|
|
|
26
18
|
class Translator:
|
|
27
|
-
"""Class for translation of of strings based on the Google Translate API.
|
|
28
|
-
|
|
19
|
+
"""Class Translator is used for translation of of strings based on the Google Translate API.
|
|
20
|
+
|
|
21
|
+
The class supports V2 and V3 translation APIs.
|
|
29
22
|
"""
|
|
30
23
|
|
|
24
|
+
logger: logging.Logger = default_logger
|
|
25
|
+
|
|
31
26
|
_config = None
|
|
32
27
|
_headers = None
|
|
33
28
|
|
|
34
|
-
def __init__(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
api_key: str,
|
|
32
|
+
project_key: str = "",
|
|
33
|
+
domain: str = "",
|
|
34
|
+
logger: logging.Logger = default_logger,
|
|
35
|
+
) -> None:
|
|
36
|
+
"""Initialize the Translate objects.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
api_key (str):
|
|
40
|
+
The Google Translate API key.
|
|
41
|
+
project_key (str, optional):
|
|
42
|
+
The Google project. Defaults to "".
|
|
43
|
+
domain (str, optional):
|
|
44
|
+
The domain. Defaults to "".
|
|
45
|
+
logger (logging.Logger, optional):
|
|
46
|
+
The logging object to log all messages. Defaults to default_logger.
|
|
47
|
+
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
if logger != default_logger:
|
|
51
|
+
self.logger = logger.getChild("translator")
|
|
52
|
+
for logfilter in logger.filters:
|
|
53
|
+
self.logger.addFilter(logfilter)
|
|
54
|
+
|
|
55
|
+
translate_config = {}
|
|
56
|
+
|
|
57
|
+
translate_config["apiKey"] = api_key
|
|
58
|
+
translate_config["translateUrlV2"] = "https://translation.googleapis.com/language/translate/v2"
|
|
59
|
+
translate_config["translateUrlV3"] = "https://translation.googleapis.com/v3/projects/{}:translateText".format(
|
|
60
|
+
project_key,
|
|
45
61
|
)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
62
|
+
translate_config["project"] = project_key
|
|
63
|
+
translate_config["parent"] = "projects/{}/locations/global".format(project_key)
|
|
64
|
+
translate_config["model"] = f"nmt{':{}'.format(domain) if domain else ''}"
|
|
49
65
|
|
|
50
66
|
self._headers = {
|
|
51
67
|
"Authorization": f"Bearer {api_key}",
|
|
52
68
|
"Content-Type": "application/json; charset=utf-8",
|
|
53
69
|
}
|
|
54
70
|
|
|
55
|
-
self._config =
|
|
71
|
+
self._config = translate_config
|
|
56
72
|
|
|
57
73
|
def config(self) -> dict:
|
|
58
|
-
"""Return the configuration parameters
|
|
74
|
+
"""Return the configuration parameters.
|
|
59
75
|
|
|
60
76
|
Returns:
|
|
61
|
-
dict:
|
|
77
|
+
dict:
|
|
78
|
+
The onfiguration parameters.
|
|
79
|
+
|
|
62
80
|
"""
|
|
63
81
|
|
|
64
82
|
return self._config
|
|
65
83
|
|
|
66
84
|
def translate(self, source_language: str, target_language: str, text: str) -> str:
|
|
67
|
-
"""Translate a string from one language to another using the Google Translate V2 API
|
|
85
|
+
"""Translate a string from one language to another using the Google Translate V2 API.
|
|
68
86
|
|
|
69
87
|
Args:
|
|
70
|
-
source_language (str):
|
|
71
|
-
|
|
72
|
-
|
|
88
|
+
source_language (str):
|
|
89
|
+
The source language.
|
|
90
|
+
target_language (str):
|
|
91
|
+
The target language.
|
|
92
|
+
text (str):
|
|
93
|
+
The string to translate.
|
|
73
94
|
|
|
74
95
|
Returns:
|
|
75
|
-
str:
|
|
96
|
+
str:
|
|
97
|
+
The translated string.
|
|
98
|
+
|
|
76
99
|
"""
|
|
77
100
|
|
|
78
101
|
params = {
|
|
@@ -84,10 +107,14 @@ class Translator:
|
|
|
84
107
|
|
|
85
108
|
request_url = self.config()["translateUrlV2"]
|
|
86
109
|
|
|
87
|
-
response = requests.post(
|
|
110
|
+
response = requests.post(
|
|
111
|
+
url=request_url,
|
|
112
|
+
params=params,
|
|
113
|
+
timeout=REQUEST_TIMEOUT,
|
|
114
|
+
)
|
|
88
115
|
|
|
89
116
|
if response.status_code != 200:
|
|
90
|
-
logger.error("Failed to translate text -> %s", response.content)
|
|
117
|
+
self.logger.error("Failed to translate text -> %s", response.content)
|
|
91
118
|
return None
|
|
92
119
|
|
|
93
120
|
translated_text = response.json()["data"]["translations"][0]["translatedText"]
|
|
@@ -96,16 +123,21 @@ class Translator:
|
|
|
96
123
|
|
|
97
124
|
# end method definition
|
|
98
125
|
|
|
99
|
-
def
|
|
100
|
-
"""Translate a string from one language to another using the Google Translate V3 API
|
|
126
|
+
def translate_v3(self, source_language: str, target_language: str, text: str) -> str:
|
|
127
|
+
"""Translate a string from one language to another using the Google Translate V3 API.
|
|
101
128
|
|
|
102
129
|
Args:
|
|
103
|
-
source_language (str):
|
|
104
|
-
|
|
105
|
-
|
|
130
|
+
source_language (str):
|
|
131
|
+
The source language.
|
|
132
|
+
target_language (str):
|
|
133
|
+
The destination language.
|
|
134
|
+
text (str):
|
|
135
|
+
The string to translate.
|
|
106
136
|
|
|
107
137
|
Returns:
|
|
108
|
-
str:
|
|
138
|
+
str:
|
|
139
|
+
The translated string.
|
|
140
|
+
|
|
109
141
|
"""
|
|
110
142
|
|
|
111
143
|
data = {
|
|
@@ -118,11 +150,14 @@ class Translator:
|
|
|
118
150
|
request_url = self.config()["translateUrlV3"]
|
|
119
151
|
|
|
120
152
|
response = requests.post(
|
|
121
|
-
url=request_url,
|
|
153
|
+
url=request_url,
|
|
154
|
+
headers=request_header,
|
|
155
|
+
json=data,
|
|
156
|
+
timeout=REQUEST_TIMEOUT,
|
|
122
157
|
)
|
|
123
158
|
|
|
124
159
|
if response.status_code != 200:
|
|
125
|
-
logger.error("Failed to translate text -> %s", response.content)
|
|
160
|
+
self.logger.error("Failed to translate text -> %s", response.content)
|
|
126
161
|
return None
|
|
127
162
|
|
|
128
163
|
translated_text = response.json()["data"]["translations"][0]["translatedText"]
|
pyxecm/helper/__init__.py
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
"""pyxecm helper classes, not for direct use"""
|
|
1
|
+
"""pyxecm helper classes, not for direct use."""
|
|
2
2
|
|
|
3
3
|
from .assoc import Assoc
|
|
4
|
+
from .data import Data
|
|
5
|
+
from .logadapter import PrefixLogAdapter
|
|
4
6
|
from .web import HTTP
|
|
5
7
|
from .xml import XML
|
|
6
|
-
|
|
8
|
+
|
|
9
|
+
__all__ = ["HTTP", "XML", "Assoc", "Data", "PrefixLogAdapter"]
|
pyxecm/helper/assoc.py
CHANGED
|
@@ -1,28 +1,21 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Extended ECM Assoc Module to implement functions to read / write from
|
|
3
|
-
so called "Assoc" data structures in Extended ECM. Right now this module
|
|
4
|
-
is used to tweak settings in XML-based transport packages that include
|
|
5
|
-
Assoc structures inside some of the XML elements.
|
|
6
|
-
|
|
7
|
-
Class: Assoc
|
|
8
|
-
Methods:
|
|
1
|
+
"""Assoc Module to implement functions to read / write from so called "Assoc" data structures in Content Server.
|
|
9
2
|
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
Right now this module is used to tweak settings in XML-based transport packages that include
|
|
4
|
+
Assoc structures inside some of the XML elements.
|
|
12
5
|
"""
|
|
13
6
|
|
|
14
7
|
__author__ = "Dr. Marc Diefenbruch"
|
|
15
|
-
__copyright__ = "Copyright 2024, OpenText"
|
|
8
|
+
__copyright__ = "Copyright (C) 2024-2025, OpenText"
|
|
16
9
|
__credits__ = ["Kai-Philip Gatzweiler"]
|
|
17
10
|
__maintainer__ = "Dr. Marc Diefenbruch"
|
|
18
11
|
__email__ = "mdiefenb@opentext.com"
|
|
19
12
|
|
|
20
|
-
import re
|
|
21
13
|
import html
|
|
14
|
+
import re
|
|
22
15
|
|
|
23
16
|
|
|
24
17
|
class Assoc:
|
|
25
|
-
"""Class to handle Extended ECM Assoc data structures."""
|
|
18
|
+
"""Class Assoc is used to handle Extended ECM Assoc data structures."""
|
|
26
19
|
|
|
27
20
|
@classmethod
|
|
28
21
|
def is_unicode_escaped(cls, assoc_string: str) -> bool:
|
|
@@ -33,6 +26,7 @@ class Assoc:
|
|
|
33
26
|
|
|
34
27
|
Returns:
|
|
35
28
|
bool: True if string is in Unicode, False otherwise
|
|
29
|
+
|
|
36
30
|
"""
|
|
37
31
|
|
|
38
32
|
pattern = r"\\u[0-9a-fA-F]{4}"
|
|
@@ -40,58 +34,100 @@ class Assoc:
|
|
|
40
34
|
|
|
41
35
|
return len(matches) > 0
|
|
42
36
|
|
|
37
|
+
# end method definition
|
|
38
|
+
|
|
43
39
|
@classmethod
|
|
44
40
|
def escape_unicode(cls, assoc_string: str) -> str:
|
|
45
|
-
"""Escape / Encode a given string in Unicode
|
|
41
|
+
"""Escape / Encode a given string in Unicode.
|
|
46
42
|
|
|
47
43
|
Args:
|
|
48
|
-
assoc_string (str):
|
|
44
|
+
assoc_string (str):
|
|
45
|
+
The source string to escape.
|
|
49
46
|
|
|
50
47
|
Returns:
|
|
51
|
-
str:
|
|
48
|
+
str:
|
|
49
|
+
The escaped string.
|
|
50
|
+
|
|
52
51
|
"""
|
|
53
52
|
|
|
54
53
|
encoded_string = assoc_string.encode("unicode_escape") # .decode()
|
|
55
54
|
|
|
56
55
|
return encoded_string
|
|
57
56
|
|
|
57
|
+
# end method definition
|
|
58
|
+
|
|
58
59
|
@classmethod
|
|
59
60
|
def unescape_unicode(cls, assoc_string: str) -> str:
|
|
60
|
-
"""Unescape / Decode a given string
|
|
61
|
+
"""Unescape / Decode a given string.
|
|
61
62
|
|
|
62
63
|
Args:
|
|
63
|
-
assoc_string (str):
|
|
64
|
+
assoc_string (str):
|
|
65
|
+
The source string to unescape.
|
|
64
66
|
|
|
65
67
|
Returns:
|
|
66
|
-
str:
|
|
68
|
+
str:
|
|
69
|
+
The unescaped string.
|
|
70
|
+
|
|
67
71
|
"""
|
|
68
72
|
try:
|
|
69
73
|
decoded_string = bytes(assoc_string, "utf-8").decode("unicode_escape")
|
|
70
|
-
return decoded_string
|
|
71
74
|
except UnicodeDecodeError:
|
|
72
75
|
return assoc_string
|
|
73
76
|
|
|
77
|
+
return decoded_string
|
|
78
|
+
|
|
79
|
+
# end method definition
|
|
80
|
+
|
|
74
81
|
@classmethod
|
|
75
82
|
def is_html_escaped(cls, assoc_string: str) -> bool:
|
|
83
|
+
"""Check if an Assoc String is HTML escaped.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
assoc_string (str):
|
|
87
|
+
The string to test for HTML escaping.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
bool:
|
|
91
|
+
True = string is HTML escaped, False if now
|
|
92
|
+
|
|
93
|
+
"""
|
|
94
|
+
|
|
76
95
|
decoded_string = html.unescape(assoc_string)
|
|
96
|
+
|
|
77
97
|
return assoc_string != decoded_string
|
|
78
98
|
|
|
99
|
+
# end method definition
|
|
100
|
+
|
|
79
101
|
@classmethod
|
|
80
102
|
def unescape_html(cls, assoc_string: str) -> str:
|
|
103
|
+
"""HTML unescape a a string.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
assoc_string (str): the string to unescape.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
str: unescaped string
|
|
110
|
+
|
|
111
|
+
"""
|
|
112
|
+
|
|
81
113
|
decoded_string = html.unescape(assoc_string)
|
|
82
114
|
return decoded_string
|
|
83
115
|
|
|
116
|
+
# end method definition
|
|
117
|
+
|
|
84
118
|
@classmethod
|
|
85
119
|
def string_to_dict(cls, assoc_string: str) -> dict:
|
|
86
120
|
"""Convert an Assoc string to a Python dict.
|
|
87
|
-
|
|
88
|
-
|
|
121
|
+
|
|
122
|
+
Each comma-separated element of the Assoc will become a dict element.
|
|
89
123
|
|
|
90
124
|
Args:
|
|
91
|
-
assoc_string (str):
|
|
125
|
+
assoc_string (str):
|
|
126
|
+
The source Assoc string to convert.
|
|
92
127
|
|
|
93
128
|
Returns:
|
|
94
129
|
dict: Python dict with the Assoc elements
|
|
130
|
+
|
|
95
131
|
"""
|
|
96
132
|
|
|
97
133
|
if cls.is_html_escaped(assoc_string):
|
|
@@ -132,15 +168,20 @@ class Assoc:
|
|
|
132
168
|
|
|
133
169
|
return assoc_dict
|
|
134
170
|
|
|
171
|
+
# end method definition
|
|
172
|
+
|
|
135
173
|
@classmethod
|
|
136
174
|
def dict_to_string(cls, assoc_dict: dict) -> str:
|
|
137
|
-
"""Convert a Python dict to an Assoc string
|
|
175
|
+
"""Convert a Python dict to an Assoc string.
|
|
138
176
|
|
|
139
177
|
Args:
|
|
140
|
-
assoc_dict (dict):
|
|
178
|
+
assoc_dict (dict):
|
|
179
|
+
The source dictionary to convert.
|
|
141
180
|
|
|
142
181
|
Returns:
|
|
143
|
-
str:
|
|
182
|
+
str:
|
|
183
|
+
The resulting Assoc string.
|
|
184
|
+
|
|
144
185
|
"""
|
|
145
186
|
|
|
146
187
|
assoc_string: str = "A<1,?,"
|
|
@@ -162,20 +203,29 @@ class Assoc:
|
|
|
162
203
|
assoc_string += ">"
|
|
163
204
|
return assoc_string
|
|
164
205
|
|
|
206
|
+
# end method definition
|
|
207
|
+
|
|
165
208
|
@classmethod
|
|
166
209
|
def extract_substring(
|
|
167
|
-
cls,
|
|
210
|
+
cls,
|
|
211
|
+
input_string: str,
|
|
212
|
+
start_sequence: str,
|
|
213
|
+
stop_sequence: str,
|
|
168
214
|
) -> str | None:
|
|
169
|
-
"""
|
|
170
|
-
by a strart and stop sequence.
|
|
215
|
+
"""Extract a substring that is delimited by a start and stop sequence.
|
|
171
216
|
|
|
172
217
|
Args:
|
|
173
|
-
input_string (str):
|
|
174
|
-
|
|
175
|
-
|
|
218
|
+
input_string (str):
|
|
219
|
+
Input string to search the delimited substring in.
|
|
220
|
+
start_sequence (str):
|
|
221
|
+
Start esequence of characters.
|
|
222
|
+
stop_sequence (str):
|
|
223
|
+
Stop sequence of characters
|
|
176
224
|
|
|
177
225
|
Returns:
|
|
178
|
-
str | None:
|
|
226
|
+
str | None:
|
|
227
|
+
The deliminated substring or None if not found.
|
|
228
|
+
|
|
179
229
|
"""
|
|
180
230
|
|
|
181
231
|
start_index = input_string.find(start_sequence)
|
|
@@ -189,17 +239,25 @@ class Assoc:
|
|
|
189
239
|
end_index += len(stop_sequence)
|
|
190
240
|
return input_string[start_index:end_index]
|
|
191
241
|
|
|
242
|
+
# end method definition
|
|
243
|
+
|
|
192
244
|
@classmethod
|
|
193
245
|
def extract_assoc_string(cls, input_string: str, is_escaped: bool = False) -> str:
|
|
194
|
-
"""Extract an Assoc from a string.
|
|
246
|
+
"""Extract an Assoc from a string.
|
|
247
|
+
|
|
248
|
+
The assoc is deliminated by A< ... >.
|
|
195
249
|
|
|
196
250
|
Args:
|
|
197
|
-
input_string (str):
|
|
198
|
-
|
|
199
|
-
|
|
251
|
+
input_string (str):
|
|
252
|
+
Input string that includes the Assoc as a substring.
|
|
253
|
+
is_escaped (bool, optional):
|
|
254
|
+
Whether or not the input string includes the
|
|
255
|
+
assoc escaped or not.
|
|
200
256
|
|
|
201
257
|
Returns:
|
|
202
|
-
str:
|
|
258
|
+
str:
|
|
259
|
+
The assoc string.
|
|
260
|
+
|
|
203
261
|
"""
|
|
204
262
|
|
|
205
263
|
if is_escaped:
|
|
@@ -207,3 +265,5 @@ class Assoc:
|
|
|
207
265
|
else:
|
|
208
266
|
assoc_string = cls.extract_substring(input_string, "A<", ">")
|
|
209
267
|
return assoc_string
|
|
268
|
+
|
|
269
|
+
# end method definition
|