pyxecm 3.0.0__py3-none-any.whl → 3.1.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/avts.py +4 -4
- pyxecm/coreshare.py +14 -15
- pyxecm/helper/data.py +2 -1
- pyxecm/helper/web.py +11 -11
- pyxecm/helper/xml.py +41 -10
- pyxecm/otac.py +1 -1
- pyxecm/otawp.py +19 -19
- pyxecm/otca.py +870 -67
- pyxecm/otcs.py +1567 -280
- pyxecm/otds.py +332 -153
- pyxecm/otkd.py +4 -4
- pyxecm/otmm.py +1 -1
- pyxecm/otpd.py +246 -30
- pyxecm-3.1.0.dist-info/METADATA +127 -0
- pyxecm-3.1.0.dist-info/RECORD +82 -0
- pyxecm_api/app.py +45 -35
- pyxecm_api/auth/functions.py +2 -2
- pyxecm_api/auth/router.py +2 -3
- pyxecm_api/common/functions.py +164 -12
- pyxecm_api/settings.py +0 -8
- pyxecm_api/terminal/router.py +1 -1
- pyxecm_api/v1_csai/router.py +33 -18
- pyxecm_customizer/browser_automation.py +98 -48
- pyxecm_customizer/customizer.py +43 -25
- pyxecm_customizer/guidewire.py +422 -8
- pyxecm_customizer/k8s.py +23 -27
- pyxecm_customizer/knowledge_graph.py +501 -20
- pyxecm_customizer/m365.py +45 -44
- pyxecm_customizer/payload.py +1684 -1159
- pyxecm_customizer/payload_list.py +3 -0
- pyxecm_customizer/salesforce.py +122 -79
- pyxecm_customizer/servicenow.py +27 -7
- pyxecm_customizer/settings.py +3 -1
- pyxecm_customizer/successfactors.py +2 -2
- pyxecm_customizer/translate.py +1 -1
- pyxecm-3.0.0.dist-info/METADATA +0 -48
- pyxecm-3.0.0.dist-info/RECORD +0 -96
- pyxecm_api/agents/__init__.py +0 -7
- pyxecm_api/agents/app.py +0 -13
- pyxecm_api/agents/functions.py +0 -119
- pyxecm_api/agents/models.py +0 -10
- pyxecm_api/agents/otcm_knowledgegraph/__init__.py +0 -1
- pyxecm_api/agents/otcm_knowledgegraph/functions.py +0 -85
- pyxecm_api/agents/otcm_knowledgegraph/models.py +0 -61
- pyxecm_api/agents/otcm_knowledgegraph/router.py +0 -74
- pyxecm_api/agents/otcm_user_agent/__init__.py +0 -1
- pyxecm_api/agents/otcm_user_agent/models.py +0 -20
- pyxecm_api/agents/otcm_user_agent/router.py +0 -65
- pyxecm_api/agents/otcm_workspace_agent/__init__.py +0 -1
- pyxecm_api/agents/otcm_workspace_agent/models.py +0 -40
- pyxecm_api/agents/otcm_workspace_agent/router.py +0 -200
- {pyxecm-3.0.0.dist-info → pyxecm-3.1.0.dist-info}/WHEEL +0 -0
- {pyxecm-3.0.0.dist-info → pyxecm-3.1.0.dist-info}/entry_points.txt +0 -0
pyxecm/otkd.py
CHANGED
|
@@ -50,8 +50,8 @@ REQUEST_UPLOAD_HEADERS = {
|
|
|
50
50
|
# DO NOT set "Content-Type" manually
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
REQUEST_TIMEOUT = 60
|
|
54
|
-
REQUEST_RETRY_DELAY = 20
|
|
53
|
+
REQUEST_TIMEOUT = 60.0
|
|
54
|
+
REQUEST_RETRY_DELAY = 20.0
|
|
55
55
|
REQUEST_MAX_RETRIES = 2
|
|
56
56
|
|
|
57
57
|
default_logger = logging.getLogger(MODULE_NAME)
|
|
@@ -301,7 +301,7 @@ class OTKD:
|
|
|
301
301
|
data: dict | None = None,
|
|
302
302
|
json_data: dict | None = None,
|
|
303
303
|
files: dict | None = None,
|
|
304
|
-
timeout:
|
|
304
|
+
timeout: float | None = REQUEST_TIMEOUT,
|
|
305
305
|
show_error: bool = True,
|
|
306
306
|
show_warning: bool = False,
|
|
307
307
|
warning_message: str = "",
|
|
@@ -327,7 +327,7 @@ class OTKD:
|
|
|
327
327
|
files (dict | None, optional):
|
|
328
328
|
Dictionary of {"name": file-tuple} for multipart encoding upload.
|
|
329
329
|
File-tuple can be a 2-tuple ("filename", fileobj) or a 3-tuple ("filename", fileobj, "content_type")
|
|
330
|
-
timeout (
|
|
330
|
+
timeout (float | None, optional):
|
|
331
331
|
The timeout for the request in seconds. Defaults to REQUEST_TIMEOUT.
|
|
332
332
|
show_error (bool, optional):
|
|
333
333
|
Whether or not an error should be logged in case of a failed REST call.
|
pyxecm/otmm.py
CHANGED
pyxecm/otpd.py
CHANGED
|
@@ -9,11 +9,46 @@ __email__ = "mdiefenb@opentext.com"
|
|
|
9
9
|
import json
|
|
10
10
|
import logging
|
|
11
11
|
import os
|
|
12
|
+
import platform
|
|
13
|
+
import sys
|
|
14
|
+
import time
|
|
15
|
+
from http import HTTPStatus
|
|
16
|
+
from importlib.metadata import version
|
|
12
17
|
|
|
13
18
|
import requests
|
|
14
19
|
from requests.auth import HTTPBasicAuth
|
|
15
20
|
from requests_toolbelt.multipart.encoder import MultipartEncoder
|
|
16
21
|
|
|
22
|
+
APP_NAME = "pyxecm"
|
|
23
|
+
APP_VERSION = version("pyxecm")
|
|
24
|
+
MODULE_NAME = APP_NAME + ".otpd"
|
|
25
|
+
|
|
26
|
+
PYTHON_VERSION = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
27
|
+
OS_INFO = f"{platform.system()} {platform.release()}"
|
|
28
|
+
ARCH_INFO = platform.machine()
|
|
29
|
+
REQUESTS_VERSION = requests.__version__
|
|
30
|
+
|
|
31
|
+
USER_AGENT = (
|
|
32
|
+
f"{APP_NAME}/{APP_VERSION} ({MODULE_NAME}/{APP_VERSION}; "
|
|
33
|
+
f"Python/{PYTHON_VERSION}; {OS_INFO}; {ARCH_INFO}; Requests/{REQUESTS_VERSION})"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
REQUEST_HEADERS = {
|
|
37
|
+
"User-Agent": USER_AGENT,
|
|
38
|
+
"accept": "application/json;charset=utf-8",
|
|
39
|
+
"Content-Type": "application/json",
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
REQUEST_FORM_HEADERS = {
|
|
43
|
+
"User-Agent": USER_AGENT,
|
|
44
|
+
"accept": "application/json;charset=utf-8",
|
|
45
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
REQUEST_TIMEOUT = 60.0
|
|
49
|
+
REQUEST_RETRY_DELAY = 20.0
|
|
50
|
+
REQUEST_MAX_RETRIES = 2
|
|
51
|
+
|
|
17
52
|
default_logger = logging.getLogger("pyxecm.otpd")
|
|
18
53
|
|
|
19
54
|
request_headers = {
|
|
@@ -93,15 +128,17 @@ class OTPD:
|
|
|
93
128
|
otpd_base_url = protocol + "://" + otpd_config["hostname"]
|
|
94
129
|
if str(port) not in ["80", "443"]:
|
|
95
130
|
otpd_base_url += ":{}".format(port)
|
|
96
|
-
otpd_base_url += "/ServerManager"
|
|
97
131
|
otpd_config["baseUrl"] = otpd_base_url
|
|
98
132
|
|
|
99
|
-
|
|
133
|
+
otpd_servermanager_url = otpd_base_url + "/ServerManager"
|
|
134
|
+
otpd_config["serverManagerUrl"] = otpd_servermanager_url
|
|
135
|
+
|
|
136
|
+
otpd_rest_url = otpd_servermanager_url + "/api"
|
|
100
137
|
otpd_config["restUrl"] = otpd_rest_url
|
|
101
138
|
|
|
102
139
|
otpd_config["settingsUrl"] = otpd_rest_url + "/v1/settings"
|
|
103
140
|
|
|
104
|
-
otpd_config["importDatabaseUrl"] =
|
|
141
|
+
otpd_config["importDatabaseUrl"] = otpd_servermanager_url + "/servlet/import"
|
|
105
142
|
|
|
106
143
|
self._config = otpd_config
|
|
107
144
|
|
|
@@ -174,32 +211,6 @@ class OTPD:
|
|
|
174
211
|
|
|
175
212
|
# end method definition
|
|
176
213
|
|
|
177
|
-
def base_url(self) -> str:
|
|
178
|
-
"""Return the base URL of PowerDocs.
|
|
179
|
-
|
|
180
|
-
Returns:
|
|
181
|
-
string:
|
|
182
|
-
The base URL.
|
|
183
|
-
|
|
184
|
-
"""
|
|
185
|
-
|
|
186
|
-
return self.config()["baseUrl"]
|
|
187
|
-
|
|
188
|
-
# end method definition
|
|
189
|
-
|
|
190
|
-
def rest_url(self) -> str:
|
|
191
|
-
"""Return the REST URL of PowerDocs.
|
|
192
|
-
|
|
193
|
-
Returns:
|
|
194
|
-
string:
|
|
195
|
-
The REST URL.
|
|
196
|
-
|
|
197
|
-
"""
|
|
198
|
-
|
|
199
|
-
return self.config()["restUrl"]
|
|
200
|
-
|
|
201
|
-
# end method definition
|
|
202
|
-
|
|
203
214
|
def parse_request_response(
|
|
204
215
|
self,
|
|
205
216
|
response_object: object,
|
|
@@ -270,7 +281,7 @@ class OTPD:
|
|
|
270
281
|
return self._jsessionid
|
|
271
282
|
|
|
272
283
|
auth_url = (
|
|
273
|
-
self.
|
|
284
|
+
self.config()["serverManagerUrl"]
|
|
274
285
|
+ "/j_security_check?j_username="
|
|
275
286
|
+ self.config()["username"]
|
|
276
287
|
+ "&j_password="
|
|
@@ -482,3 +493,208 @@ class OTPD:
|
|
|
482
493
|
return None
|
|
483
494
|
|
|
484
495
|
# end method definition
|
|
496
|
+
|
|
497
|
+
def do_request(
|
|
498
|
+
self,
|
|
499
|
+
url: str,
|
|
500
|
+
method: str = "GET",
|
|
501
|
+
headers: dict | None = None,
|
|
502
|
+
data: dict | None = None,
|
|
503
|
+
json_data: dict | None = None,
|
|
504
|
+
files: dict | None = None,
|
|
505
|
+
timeout: float | None = REQUEST_TIMEOUT,
|
|
506
|
+
show_error: bool = True,
|
|
507
|
+
show_warning: bool = False,
|
|
508
|
+
warning_message: str = "",
|
|
509
|
+
failure_message: str = "",
|
|
510
|
+
success_message: str = "",
|
|
511
|
+
max_retries: int = REQUEST_MAX_RETRIES,
|
|
512
|
+
retry_forever: bool = False,
|
|
513
|
+
parse_request_response: bool = True,
|
|
514
|
+
) -> dict | None:
|
|
515
|
+
"""Call an OTDS REST API in a safe way.
|
|
516
|
+
|
|
517
|
+
Args:
|
|
518
|
+
url (str):
|
|
519
|
+
The URL to send the request to.
|
|
520
|
+
method (str, optional):
|
|
521
|
+
The HTTP method (GET, POST, etc.). Defaults to "GET".
|
|
522
|
+
headers (dict | None, optional):
|
|
523
|
+
The request headers. Defaults to None.
|
|
524
|
+
data (dict | None, optional):
|
|
525
|
+
Request payload. Defaults to None
|
|
526
|
+
json_data (dict | None, optional):
|
|
527
|
+
Request payload for the JSON parameter. Defaults to None.
|
|
528
|
+
files (dict | None, optional):
|
|
529
|
+
Dictionary of {"name": file-tuple} for multipart encoding upload.
|
|
530
|
+
File-tuple can be a 2-tuple ("filename", fileobj) or a 3-tuple ("filename", fileobj, "content_type")
|
|
531
|
+
timeout (int | None, optional):
|
|
532
|
+
The timeout for the request in seconds. Defaults to REQUEST_TIMEOUT.
|
|
533
|
+
show_error (bool, optional):
|
|
534
|
+
Whether or not an error should be logged in case of a failed REST call.
|
|
535
|
+
If False, then only a warning is logged. Defaults to True.
|
|
536
|
+
show_warning (bool, optional):
|
|
537
|
+
Whether or not an warning should be logged in case of a
|
|
538
|
+
failed REST call.
|
|
539
|
+
If False, then only a warning is logged. Defaults to True.
|
|
540
|
+
warning_message (str, optional):
|
|
541
|
+
Specific warning message. Defaults to "". If not given the error_message will be used.
|
|
542
|
+
failure_message (str, optional):
|
|
543
|
+
Specific error message. Defaults to "".
|
|
544
|
+
success_message (str, optional):
|
|
545
|
+
Specific success message. Defaults to "".
|
|
546
|
+
max_retries (int, optional):
|
|
547
|
+
How many retries on Connection errors? Default is REQUEST_MAX_RETRIES.
|
|
548
|
+
retry_forever (bool, optional):
|
|
549
|
+
Eventually wait forever - without timeout. Defaults to False.
|
|
550
|
+
parse_request_response (bool, optional):
|
|
551
|
+
Defines if the response.text should be interpreted as json and loaded into a dictionary.
|
|
552
|
+
True is the default.
|
|
553
|
+
|
|
554
|
+
Returns:
|
|
555
|
+
dict | None:
|
|
556
|
+
Response of OTDS REST API or None in case of an error.
|
|
557
|
+
|
|
558
|
+
"""
|
|
559
|
+
|
|
560
|
+
if headers is None:
|
|
561
|
+
headers = REQUEST_HEADERS
|
|
562
|
+
|
|
563
|
+
# In case of an expired session we reauthenticate and
|
|
564
|
+
# try 1 more time. Session expiration should not happen
|
|
565
|
+
# twice in a row:
|
|
566
|
+
retries = 0
|
|
567
|
+
|
|
568
|
+
while True:
|
|
569
|
+
try:
|
|
570
|
+
response = requests.request(
|
|
571
|
+
method=method,
|
|
572
|
+
url=url,
|
|
573
|
+
data=data,
|
|
574
|
+
json=json_data,
|
|
575
|
+
files=files,
|
|
576
|
+
headers=headers,
|
|
577
|
+
timeout=timeout,
|
|
578
|
+
)
|
|
579
|
+
|
|
580
|
+
if response.ok:
|
|
581
|
+
if success_message:
|
|
582
|
+
self.logger.info(success_message)
|
|
583
|
+
if parse_request_response:
|
|
584
|
+
return self.parse_request_response(response)
|
|
585
|
+
else:
|
|
586
|
+
return response
|
|
587
|
+
else:
|
|
588
|
+
# Handle plain HTML responses to not pollute the logs
|
|
589
|
+
content_type = response.headers.get("content-type", None)
|
|
590
|
+
response_text = (
|
|
591
|
+
"HTML content (only printed in debug log)" if content_type == "text/html" else response.text
|
|
592
|
+
)
|
|
593
|
+
|
|
594
|
+
if show_error:
|
|
595
|
+
self.logger.error(
|
|
596
|
+
"%s; status -> %s/%s; error -> %s",
|
|
597
|
+
failure_message,
|
|
598
|
+
response.status_code,
|
|
599
|
+
HTTPStatus(response.status_code).phrase,
|
|
600
|
+
response_text,
|
|
601
|
+
)
|
|
602
|
+
elif show_warning:
|
|
603
|
+
self.logger.warning(
|
|
604
|
+
"%s; status -> %s/%s; warning -> %s",
|
|
605
|
+
warning_message if warning_message else failure_message,
|
|
606
|
+
response.status_code,
|
|
607
|
+
HTTPStatus(response.status_code).phrase,
|
|
608
|
+
response_text,
|
|
609
|
+
)
|
|
610
|
+
if content_type == "text/html":
|
|
611
|
+
self.logger.debug(
|
|
612
|
+
"%s; status -> %s/%s; warning -> %s",
|
|
613
|
+
failure_message,
|
|
614
|
+
response.status_code,
|
|
615
|
+
HTTPStatus(response.status_code).phrase,
|
|
616
|
+
response.text,
|
|
617
|
+
)
|
|
618
|
+
return None
|
|
619
|
+
except requests.exceptions.Timeout:
|
|
620
|
+
if retries <= max_retries:
|
|
621
|
+
self.logger.warning(
|
|
622
|
+
"Request timed out. Retrying in %s seconds...",
|
|
623
|
+
str(REQUEST_RETRY_DELAY),
|
|
624
|
+
)
|
|
625
|
+
retries += 1
|
|
626
|
+
time.sleep(REQUEST_RETRY_DELAY) # Add a delay before retrying
|
|
627
|
+
else:
|
|
628
|
+
self.logger.error(
|
|
629
|
+
"%s; timeout error.",
|
|
630
|
+
failure_message,
|
|
631
|
+
)
|
|
632
|
+
if retry_forever:
|
|
633
|
+
# If it fails after REQUEST_MAX_RETRIES retries we let it wait forever
|
|
634
|
+
self.logger.warning("Turn timeouts off and wait forever...")
|
|
635
|
+
timeout = None
|
|
636
|
+
else:
|
|
637
|
+
return None
|
|
638
|
+
except requests.exceptions.ConnectionError:
|
|
639
|
+
if retries <= max_retries:
|
|
640
|
+
self.logger.warning(
|
|
641
|
+
"Connection error. Retrying in %s seconds...",
|
|
642
|
+
str(REQUEST_RETRY_DELAY),
|
|
643
|
+
)
|
|
644
|
+
retries += 1
|
|
645
|
+
time.sleep(REQUEST_RETRY_DELAY) # Add a delay before retrying
|
|
646
|
+
else:
|
|
647
|
+
self.logger.error(
|
|
648
|
+
"%s; connection error.",
|
|
649
|
+
failure_message,
|
|
650
|
+
)
|
|
651
|
+
if retry_forever:
|
|
652
|
+
# If it fails after REQUEST_MAX_RETRIES retries we let it wait forever
|
|
653
|
+
self.logger.warning("Turn timeouts off and wait forever...")
|
|
654
|
+
timeout = None
|
|
655
|
+
time.sleep(REQUEST_RETRY_DELAY) # Add a delay before retrying
|
|
656
|
+
else:
|
|
657
|
+
return None
|
|
658
|
+
# end try
|
|
659
|
+
self.logger.info(
|
|
660
|
+
"Retrying REST API %s call -> %s... (retry = %s",
|
|
661
|
+
method,
|
|
662
|
+
url,
|
|
663
|
+
str(retries),
|
|
664
|
+
)
|
|
665
|
+
# end while True
|
|
666
|
+
|
|
667
|
+
# end method definition
|
|
668
|
+
|
|
669
|
+
def generate_document(self, payload: str) -> dict | None:
|
|
670
|
+
"""Generate a PowerDocs document based on the provided XML payload.
|
|
671
|
+
|
|
672
|
+
Args:
|
|
673
|
+
payload (str):
|
|
674
|
+
The XML payload to generate the document.
|
|
675
|
+
|
|
676
|
+
Returns:
|
|
677
|
+
dict | None:
|
|
678
|
+
The request response or None in case of an error.
|
|
679
|
+
|
|
680
|
+
"""
|
|
681
|
+
|
|
682
|
+
if not payload:
|
|
683
|
+
self.logger.error("Cannot generate PowerDocs document from empty payload!")
|
|
684
|
+
return None
|
|
685
|
+
|
|
686
|
+
url = self.config()["baseUrl"] + "/c4ApplicationServer/rest/document"
|
|
687
|
+
|
|
688
|
+
body = {"documentgeneration": payload}
|
|
689
|
+
|
|
690
|
+
response = self.do_request(
|
|
691
|
+
url=url,
|
|
692
|
+
method="POST",
|
|
693
|
+
headers=REQUEST_FORM_HEADERS,
|
|
694
|
+
data=body,
|
|
695
|
+
show_error=True,
|
|
696
|
+
failure_message="Failed to generate PowerDocs document",
|
|
697
|
+
parse_request_response=False,
|
|
698
|
+
)
|
|
699
|
+
|
|
700
|
+
return response
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyxecm
|
|
3
|
+
Version: 3.1.0
|
|
4
|
+
Summary: A Python library to interact with Opentext Content Management Rest API
|
|
5
|
+
Project-URL: Homepage, https://github.com/opentext/pyxecm
|
|
6
|
+
Author-email: Kai Gatzweiler <kgatzweiler@opentext.com>, "Dr. Marc Diefenbruch" <mdiefenb@opentext.com>
|
|
7
|
+
Keywords: appworks,archivecenter,contentserver,extendedecm,opentext,otds
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content :: Content Management System
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Requires-Dist: lxml>=6.0.0
|
|
16
|
+
Requires-Dist: opentelemetry-api>=1.34.1
|
|
17
|
+
Requires-Dist: opentelemetry-exporter-otlp>=1.34.1
|
|
18
|
+
Requires-Dist: opentelemetry-instrumentation-requests>=0.55b1
|
|
19
|
+
Requires-Dist: opentelemetry-instrumentation-threading>=0.55b1
|
|
20
|
+
Requires-Dist: opentelemetry-sdk>=1.34.1
|
|
21
|
+
Requires-Dist: pandas>=2.3.1
|
|
22
|
+
Requires-Dist: requests-toolbelt>=1.0.0
|
|
23
|
+
Requires-Dist: requests>=2.32.4
|
|
24
|
+
Requires-Dist: suds>=1.2.0
|
|
25
|
+
Requires-Dist: websockets>=15.0.1
|
|
26
|
+
Requires-Dist: xmltodict>=0.14.2
|
|
27
|
+
Provides-Extra: api
|
|
28
|
+
Requires-Dist: asyncio>=3.4.3; extra == 'api'
|
|
29
|
+
Requires-Dist: fastapi>=0.116.0; extra == 'api'
|
|
30
|
+
Requires-Dist: jinja2>=3.1.6; extra == 'api'
|
|
31
|
+
Requires-Dist: opentelemetry-api>=1.34.1; extra == 'api'
|
|
32
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.55b1; extra == 'api'
|
|
33
|
+
Requires-Dist: opentelemetry-sdk>=1.34.1; extra == 'api'
|
|
34
|
+
Requires-Dist: prometheus-fastapi-instrumentator>=7.1.0; extra == 'api'
|
|
35
|
+
Requires-Dist: pydantic-settings>=2.10.1; extra == 'api'
|
|
36
|
+
Requires-Dist: python-multipart>=0.0.20; extra == 'api'
|
|
37
|
+
Requires-Dist: uvicorn>=0.35.0; extra == 'api'
|
|
38
|
+
Provides-Extra: customizer
|
|
39
|
+
Requires-Dist: kubernetes>=33.1.0; extra == 'customizer'
|
|
40
|
+
Requires-Dist: openpyxl>=3.1.5; extra == 'customizer'
|
|
41
|
+
Requires-Dist: playwright>=1.53.0; extra == 'customizer'
|
|
42
|
+
Requires-Dist: pydantic>=2.11.7; extra == 'customizer'
|
|
43
|
+
Requires-Dist: python-hcl2>=7.2.1; extra == 'customizer'
|
|
44
|
+
Provides-Extra: magic
|
|
45
|
+
Requires-Dist: python-magic; extra == 'magic'
|
|
46
|
+
Provides-Extra: pyvis
|
|
47
|
+
Requires-Dist: pyvis>=0.3.2; extra == 'pyvis'
|
|
48
|
+
Provides-Extra: sap
|
|
49
|
+
Requires-Dist: pyrfc==3.3.1; extra == 'sap'
|
|
50
|
+
Description-Content-Type: text/markdown
|
|
51
|
+
|
|
52
|
+
# PYXECM
|
|
53
|
+
|
|
54
|
+
A python library to interact with Opentext Content Mangement REST API.
|
|
55
|
+
The product API documentation is available on [OpenText Developer](https://developer.opentext.com/ce/products/extendedecm)
|
|
56
|
+
Detailed documentation of this package is available [here](https://opentext.github.io/pyxecm/).
|
|
57
|
+
|
|
58
|
+
## Quick start - Library usage
|
|
59
|
+
|
|
60
|
+
Install the latest version from pypi:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install pyxecm
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Start using the package libraries
|
|
67
|
+
|
|
68
|
+
example usage of the OTCS class, more details can be found in the docs:
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from pyxecm import OTCS
|
|
72
|
+
|
|
73
|
+
otcs_object = OTCS(
|
|
74
|
+
protocol="https",
|
|
75
|
+
hostname="otcs.domain.tld",
|
|
76
|
+
port="443",
|
|
77
|
+
public_url="otcs.domain.tld",
|
|
78
|
+
username="admin",
|
|
79
|
+
password="********",
|
|
80
|
+
base_path="/cs/llisapi.dll",
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
otcs_object.authenticate()
|
|
84
|
+
|
|
85
|
+
nodes = otcs_object.get_subnodes(2000)
|
|
86
|
+
|
|
87
|
+
for node in nodes["results"]:
|
|
88
|
+
print(node["data"]["properties"]["id"], node["data"]["properties"]["name"])
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Quick start - Customizer usage
|
|
92
|
+
|
|
93
|
+
- Create an `.env` file as described here: [sample-environment-variables](customizerapisettings/#sample-environment-variables)
|
|
94
|
+
- Create an payload file to define what the customizer should do, as described here [payload-syntax](payload-syntax)
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
pip install pyxecm[customizer]
|
|
98
|
+
|
|
99
|
+
pyxecm-customizer PAYLOAD.tfvars/PAYLOAD.yaml
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Quick start - API
|
|
103
|
+
|
|
104
|
+
- Install pyxecm with api and customizer dependencies
|
|
105
|
+
- Launch the Rest API server
|
|
106
|
+
- Access the Customizer API at [http://localhost:8000/api](http://localhost:8000/api)
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
pip install pyxecm[api,customizer]
|
|
110
|
+
|
|
111
|
+
pyxecm-api
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Disclaimer
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
Copyright © 2025 Open Text Corporation, All Rights Reserved.
|
|
118
|
+
The above copyright notice and this permission notice shall be included in all
|
|
119
|
+
copies or substantial portions of the Software.
|
|
120
|
+
|
|
121
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
122
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
123
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
124
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
125
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
126
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
127
|
+
SOFTWARE.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
pyxecm/__init__.py,sha256=KNvTFbDVHylf8Ub28osm5Dw0W-ck-94y27lIBuE32RE,441
|
|
2
|
+
pyxecm/avts.py,sha256=NEd1JdJCVmNohp_A-ZxAIMQZX5NCJFMhyKV6cdLFgTw,56960
|
|
3
|
+
pyxecm/coreshare.py,sha256=oz5SASlOC_e4-OIazFUrIA7gB6DfpC7RY4Ck7AHKcvQ,95999
|
|
4
|
+
pyxecm/otac.py,sha256=itsxIkIhIHdAiRCLRegmxCejE3kqpWxgwaJvAGNqzzg,22849
|
|
5
|
+
pyxecm/otawp.py,sha256=9kQghTIrnHP5I_GOmnAlvPhJk433b0dcdVzQHx0fSAM,112962
|
|
6
|
+
pyxecm/otca.py,sha256=8rBAnLGNcEK9UAdRz6bSzDqe5Smvvp0lLl8oaV7yQbE,99352
|
|
7
|
+
pyxecm/otcs.py,sha256=GIXA1BIV8oTZEO3-30MG0eG0TQLNtuvjAzpNmBa2JCE,815063
|
|
8
|
+
pyxecm/otds.py,sha256=gTyHwCSFVJbEia3h-xcPY0UL1fS58VxuI0l9uA3lC6c,191581
|
|
9
|
+
pyxecm/otiv.py,sha256=I5lt4sz7TN3W7BCstCKQY2WQnei-t0tXdM4QjRQRmWI,2358
|
|
10
|
+
pyxecm/otkd.py,sha256=3c37FwQ-KDBN48O1wZVxX46BiQDRtb2-KrXZ7HG54Fg,47488
|
|
11
|
+
pyxecm/otmm.py,sha256=MC4roK8SNG3RPj7Nb-iwn8siH9CLLmhwTmw-84i6zm4,80733
|
|
12
|
+
pyxecm/otpd.py,sha256=MXtgaRMEgVXBbc6hPm9tXq--NpzYAkSMnaL_p2H4b7E,23875
|
|
13
|
+
pyxecm/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
pyxecm/helper/__init__.py,sha256=B35HdIZC9wZ1m_sx4NOPggyFFJoXmFuA1T2tuPDU1W8,246
|
|
15
|
+
pyxecm/helper/assoc.py,sha256=yOh4GFZEkTfIaVVrHBr4bhMtIv-E76oDVWGqaUdVqyA,7321
|
|
16
|
+
pyxecm/helper/data.py,sha256=L92y9dagzJLwdfZW-ISUemkJEuGFo8kGz3r18c01GPc,123363
|
|
17
|
+
pyxecm/helper/logadapter.py,sha256=ExrIKpA2JKegkTIky0wDDTgPYSvVmwQLrDh5jko_6hQ,724
|
|
18
|
+
pyxecm/helper/otel_config.py,sha256=nMzNi3Jv2_kmYG4thzDpN95bqjy6MbRfV6nlpIZ6SjQ,907
|
|
19
|
+
pyxecm/helper/web.py,sha256=YqR72jWSeg3dOEdhN6b09s-kSnHbTjDIl56QC5NvNtE,13386
|
|
20
|
+
pyxecm/helper/xml.py,sha256=6FJ-ApiJmBBo6IwtnWj93DVB016ZTSlQIMXQNvFumOI,47091
|
|
21
|
+
pyxecm_api/__init__.py,sha256=8oXxEEFSu2afpyQURpxMA2qTZAB3MUdbBrndogDn5Oc,92
|
|
22
|
+
pyxecm_api/__main__.py,sha256=Q2tcaoSExPMUwGVBrE4AHT8DNvB4XIgwoN4EPDx5Rt8,117
|
|
23
|
+
pyxecm_api/app.py,sha256=OkBipbCPeDM8KO-LvehYKdSyXcXvVHSwz4vXx8CZdZY,7256
|
|
24
|
+
pyxecm_api/settings.py,sha256=Zu4LnBsCUm9bi7riE_uP2JynWkSmUjJtGrLmSZQXpRg,5535
|
|
25
|
+
pyxecm_api/auth/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
|
|
26
|
+
pyxecm_api/auth/functions.py,sha256=hdu4XPS975r8LsbH_3OKNQOEMvnbD40zhRh1nO1hIyQ,3331
|
|
27
|
+
pyxecm_api/auth/models.py,sha256=lKebaIHbALZ10quCCKQ3wf7w8V6k84tFXcPV1zbQsS0,271
|
|
28
|
+
pyxecm_api/auth/router.py,sha256=H58owZMM9lcskUITWSJPZYQr6IM66MyV7h9G36HPpQM,2140
|
|
29
|
+
pyxecm_api/common/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
|
|
30
|
+
pyxecm_api/common/functions.py,sha256=-WpWLKkiHzv2WmR3zIBrF2Z1ADcDlC5ifJWLyG7cu-s,8963
|
|
31
|
+
pyxecm_api/common/metrics.py,sha256=kOJ1DZveZJ7xFd1pB12Zbkq6Z-evaTivpgO_ujVbsxM,2707
|
|
32
|
+
pyxecm_api/common/models.py,sha256=c76ysWUt40A875DirsFMXttxwjHvBYvjuOVEXePSZ9k,456
|
|
33
|
+
pyxecm_api/common/router.py,sha256=BXi3SMvkswCIftoVkJIP_Wx8gd3WKJsE3rq6Pult50I,3482
|
|
34
|
+
pyxecm_api/terminal/__init__.py,sha256=RHlTzdGeOY0_dvvNZS_wq6uJcY1OatIUHwCxAUwklaE,43
|
|
35
|
+
pyxecm_api/terminal/router.py,sha256=cYL93inAB9qux-IFg-TpZjdRHWF_OSkbABlXyG69ukc,3582
|
|
36
|
+
pyxecm_api/v1_csai/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
|
|
37
|
+
pyxecm_api/v1_csai/models.py,sha256=c0VEJP09jsTW83dpHtZnooNvg3SZNuyMHEBCgWQDJ1s,489
|
|
38
|
+
pyxecm_api/v1_csai/router.py,sha256=5MuzlVzUTEjgBTE2yGtvplt2jekxS4zcl_lqUcz3LVU,5198
|
|
39
|
+
pyxecm_api/v1_csai/statics/bindings/utils.js,sha256=MRPHMxfDDJnqr7x4KRYWDOfSMYOhSGFdoElmQ-lWDLA,6311
|
|
40
|
+
pyxecm_api/v1_csai/statics/tom-select/tom-select.complete.min.js,sha256=f2dQEyWhXp7M5o3MsmgS6zJ_Gq4pXFxSxSTsYrPxPc0,44776
|
|
41
|
+
pyxecm_api/v1_csai/statics/tom-select/tom-select.css,sha256=JgqUGftl29aF9fEJ-ObePYuXmhVAUK-Tp2GiLTTt54Q,9328
|
|
42
|
+
pyxecm_api/v1_csai/statics/vis-9.1.2/vis-network.css,sha256=LoLURa1YeOqIFlJHDOYyYB-PVfG5nm6-zf-GFGAObQ4,220163
|
|
43
|
+
pyxecm_api/v1_csai/statics/vis-9.1.2/vis-network.min.js,sha256=HyDwc28yy5vt-PY4OyXP6i-Dnhq-gNboBAtNW-o3jGk,468813
|
|
44
|
+
pyxecm_api/v1_maintenance/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
|
|
45
|
+
pyxecm_api/v1_maintenance/functions.py,sha256=NDU08aHzPi7KXxKMA4KPHwc-LkpiqqwZU7Wif8yjaJk,3001
|
|
46
|
+
pyxecm_api/v1_maintenance/models.py,sha256=HcrhBg9hhRZg4Y6xuus9T8SCNIsL8ZxX1uuaRrBnFBw,271
|
|
47
|
+
pyxecm_api/v1_maintenance/router.py,sha256=gL_f_-9Slq7yzzOO1uS1aB8N3GduKnm1__7b6cSH7VI,2238
|
|
48
|
+
pyxecm_api/v1_otcs/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
|
|
49
|
+
pyxecm_api/v1_otcs/functions.py,sha256=YKC4b6nVtlnBGcu2WqSRLmS3faXagkAokrBMXUblkJE,2012
|
|
50
|
+
pyxecm_api/v1_otcs/router.py,sha256=VCtGmObA2TVJREwx4mA047SzSpsJlfxhRXA6DdlppZw,7055
|
|
51
|
+
pyxecm_api/v1_payload/__init__.py,sha256=ranS8DEliiC4Mlo-bVva9Maj5q08I0I6NJflUFIvOvw,19
|
|
52
|
+
pyxecm_api/v1_payload/functions.py,sha256=xA06ACS4NWUut0FXfrw6Ww-R94y43PVSESyEiZEhKAA,6295
|
|
53
|
+
pyxecm_api/v1_payload/models.py,sha256=eD9A2K23L_cGhBDTO1FGVGJMQ1COaYWmcr-ELE66tOA,1006
|
|
54
|
+
pyxecm_api/v1_payload/router.py,sha256=2twiLBeNNDGIEQ6SCZwLFgd8oYOzgbskS-Q3OL-lKe4,15441
|
|
55
|
+
pyxecm_customizer/__init__.py,sha256=x2NhDlNcubRC-jXzqT02j9kQGXBo36QAehjmcQuSbXw,721
|
|
56
|
+
pyxecm_customizer/__main__.py,sha256=QGQlJJAdLmJccArwPT8XEhBOMSJ-Z8gwLrtHPNfL8Ps,1407
|
|
57
|
+
pyxecm_customizer/browser_automation.py,sha256=q1305oZ3a_JI8fLpc0u0T5D_8YSFW0C8-LQpOY0pwXc,69540
|
|
58
|
+
pyxecm_customizer/customizer.py,sha256=Nzz3wndPp9r5GVpOzLtdNUOuIsCZ2GYdIS1HhWdboBM,84938
|
|
59
|
+
pyxecm_customizer/exceptions.py,sha256=YXX0in-UGXfJb6Fei01JQetOtAHqUiITb49OTSaZRkE,909
|
|
60
|
+
pyxecm_customizer/guidewire.py,sha256=1smNNDW-9FdrpqVu0r74KqgEqtq9M7LgpopUJvRSLrE,67049
|
|
61
|
+
pyxecm_customizer/k8s.py,sha256=DcxLKKuvV3S4DYqP4jUygn32aeGtD0c1FOXumZzqqdY,55837
|
|
62
|
+
pyxecm_customizer/knowledge_graph.py,sha256=9Yu-Y7Co7A54qEayRT9e0SKYHlMfDmDVAH12k5gSf3A,46469
|
|
63
|
+
pyxecm_customizer/log.py,sha256=2DmGF3b-ZIOAJCPSmZmxGD7BNxY4-mZm0H_X0HeJedE,916
|
|
64
|
+
pyxecm_customizer/m365.py,sha256=xQGdY9ti44e93c5tPbgCHjvrM-SjQr2F1iApJMb0-Pk,213957
|
|
65
|
+
pyxecm_customizer/payload.py,sha256=JKye3d-ac-Z6IFInFPh50AnI47mREGHZhYdLeyQH8qM,1365927
|
|
66
|
+
pyxecm_customizer/payload_list.py,sha256=MCpCzarmQ-5u7FSW7djNOMSjv373Ltx-9rEDIuhEboI,28266
|
|
67
|
+
pyxecm_customizer/salesforce.py,sha256=lGkQcEYg5YIWc7SF2TELT6yfgrn4pnbCrf8wXGk-PMc,64557
|
|
68
|
+
pyxecm_customizer/sap.py,sha256=lD_riOZhYjbZ0_pUZyqhxP6guzBM__TcUjZhSgDowoE,6506
|
|
69
|
+
pyxecm_customizer/servicenow.py,sha256=K26DQiXd-SMMyft9CLCKtw_vb3oKf6VGdTEzm7XMqYI,66292
|
|
70
|
+
pyxecm_customizer/settings.py,sha256=SPm6sBFiMMuFquNwKBnkUcqPZLtVBQ5K6CGjsLJNaOc,21409
|
|
71
|
+
pyxecm_customizer/successfactors.py,sha256=CcWGXwYcqp4jJ805XQZfY50iXcCEiJg6uVUq5AjRqXs,38661
|
|
72
|
+
pyxecm_customizer/translate.py,sha256=TViU9Erp4lXzZi2jQSmBpjVWS0kIW-I_Y5C0z25z-tQ,4960
|
|
73
|
+
pyxecm_maintenance_page/__init__.py,sha256=09to4a8rygOIN6Z1SCN9tLtW1qPUC78Z-scDbpt0E-Q,136
|
|
74
|
+
pyxecm_maintenance_page/__main__.py,sha256=N_0tw2upUPQZhTYCaIr75LogyaEsp-mlZCon-lIyaxM,158
|
|
75
|
+
pyxecm_maintenance_page/app.py,sha256=pTOeZfgPPq6BT7P8naUjW-ZT9dXqwX6DWazIVL-9Fkc,1997
|
|
76
|
+
pyxecm_maintenance_page/settings.py,sha256=VRReZeNdza7i7lgnQ3wVojzoPDGXZnzr5rsMJY1EnHk,955
|
|
77
|
+
pyxecm_maintenance_page/static/favicon.avif,sha256=POuuPXKbjHVP3BjNLpFIx8MfkQg5z2LZA7sK6lejARg,1543
|
|
78
|
+
pyxecm_maintenance_page/templates/maintenance.html,sha256=0OAinv7jmj3Aa7GNCIoBLDGEMW1-_HdJfwWmkmb6Cs4,5581
|
|
79
|
+
pyxecm-3.1.0.dist-info/METADATA,sha256=C6gl_je1-QeK7NROKoR0Sm_hk4pQXPuXabc6is81GYA,4566
|
|
80
|
+
pyxecm-3.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
81
|
+
pyxecm-3.1.0.dist-info/entry_points.txt,sha256=prc1mDdpd3bQk98VRBozI363mDUgSwDibDKXGNqKqgI,151
|
|
82
|
+
pyxecm-3.1.0.dist-info/RECORD,,
|