pyxecm 2.0.3__py3-none-any.whl → 3.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.

Files changed (94) hide show
  1. pyxecm/coreshare.py +76 -8
  2. pyxecm/helper/data.py +16 -24
  3. pyxecm/helper/otel_config.py +26 -0
  4. pyxecm/helper/web.py +1 -2
  5. pyxecm/otca.py +1356 -16
  6. pyxecm/otcs.py +4238 -758
  7. pyxecm/otds.py +4 -12
  8. pyxecm/otmm.py +4 -5
  9. pyxecm/py.typed +0 -0
  10. pyxecm-3.0.0.dist-info/METADATA +48 -0
  11. pyxecm-3.0.0.dist-info/RECORD +96 -0
  12. {pyxecm-2.0.3.dist-info → pyxecm-3.0.0.dist-info}/WHEEL +1 -2
  13. pyxecm-3.0.0.dist-info/entry_points.txt +4 -0
  14. {pyxecm/customizer/api → pyxecm_api}/__main__.py +1 -1
  15. pyxecm_api/agents/__init__.py +7 -0
  16. pyxecm_api/agents/app.py +13 -0
  17. pyxecm_api/agents/functions.py +119 -0
  18. pyxecm_api/agents/models.py +10 -0
  19. pyxecm_api/agents/otcm_knowledgegraph/functions.py +85 -0
  20. pyxecm_api/agents/otcm_knowledgegraph/models.py +61 -0
  21. pyxecm_api/agents/otcm_knowledgegraph/router.py +74 -0
  22. pyxecm_api/agents/otcm_user_agent/models.py +20 -0
  23. pyxecm_api/agents/otcm_user_agent/router.py +65 -0
  24. pyxecm_api/agents/otcm_workspace_agent/models.py +40 -0
  25. pyxecm_api/agents/otcm_workspace_agent/router.py +200 -0
  26. pyxecm_api/app.py +221 -0
  27. {pyxecm/customizer/api → pyxecm_api}/auth/functions.py +10 -2
  28. {pyxecm/customizer/api → pyxecm_api}/auth/router.py +4 -3
  29. {pyxecm/customizer/api → pyxecm_api}/common/functions.py +39 -9
  30. {pyxecm/customizer/api → pyxecm_api}/common/metrics.py +1 -2
  31. {pyxecm/customizer/api → pyxecm_api}/common/router.py +12 -11
  32. {pyxecm/customizer/api → pyxecm_api}/settings.py +30 -6
  33. {pyxecm/customizer/api → pyxecm_api}/terminal/router.py +1 -1
  34. {pyxecm/customizer/api → pyxecm_api}/v1_csai/router.py +39 -10
  35. pyxecm_api/v1_csai/statics/bindings/utils.js +189 -0
  36. pyxecm_api/v1_csai/statics/tom-select/tom-select.complete.min.js +356 -0
  37. pyxecm_api/v1_csai/statics/tom-select/tom-select.css +334 -0
  38. pyxecm_api/v1_csai/statics/vis-9.1.2/vis-network.css +1 -0
  39. pyxecm_api/v1_csai/statics/vis-9.1.2/vis-network.min.js +27 -0
  40. pyxecm_api/v1_maintenance/__init__.py +1 -0
  41. {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/functions.py +3 -3
  42. {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/router.py +8 -8
  43. pyxecm_api/v1_otcs/__init__.py +1 -0
  44. {pyxecm/customizer/api → pyxecm_api}/v1_otcs/functions.py +7 -5
  45. {pyxecm/customizer/api → pyxecm_api}/v1_otcs/router.py +24 -13
  46. pyxecm_api/v1_payload/__init__.py +1 -0
  47. {pyxecm/customizer/api → pyxecm_api}/v1_payload/functions.py +10 -7
  48. {pyxecm/customizer/api → pyxecm_api}/v1_payload/router.py +11 -10
  49. {pyxecm/customizer → pyxecm_customizer}/__init__.py +8 -0
  50. {pyxecm/customizer → pyxecm_customizer}/__main__.py +15 -21
  51. {pyxecm/customizer → pyxecm_customizer}/browser_automation.py +414 -103
  52. {pyxecm/customizer → pyxecm_customizer}/customizer.py +178 -116
  53. {pyxecm/customizer → pyxecm_customizer}/guidewire.py +60 -20
  54. {pyxecm/customizer → pyxecm_customizer}/k8s.py +4 -4
  55. pyxecm_customizer/knowledge_graph.py +719 -0
  56. pyxecm_customizer/log.py +35 -0
  57. {pyxecm/customizer → pyxecm_customizer}/m365.py +41 -33
  58. {pyxecm/customizer → pyxecm_customizer}/payload.py +2359 -1991
  59. {pyxecm/customizer/api/common → pyxecm_customizer}/payload_list.py +57 -65
  60. {pyxecm/customizer → pyxecm_customizer}/salesforce.py +1 -1
  61. {pyxecm/customizer → pyxecm_customizer}/sap.py +6 -2
  62. {pyxecm/customizer → pyxecm_customizer}/servicenow.py +2 -4
  63. {pyxecm/customizer → pyxecm_customizer}/settings.py +7 -6
  64. {pyxecm/customizer → pyxecm_customizer}/successfactors.py +40 -28
  65. {pyxecm/customizer → pyxecm_customizer}/translate.py +14 -10
  66. {pyxecm/maintenance_page → pyxecm_maintenance_page}/__main__.py +1 -1
  67. {pyxecm/maintenance_page → pyxecm_maintenance_page}/app.py +16 -6
  68. pyxecm/customizer/api/app.py +0 -163
  69. pyxecm/customizer/log.py +0 -107
  70. pyxecm/customizer/nhc.py +0 -1169
  71. pyxecm/customizer/openapi.py +0 -258
  72. pyxecm/customizer/pht.py +0 -1357
  73. pyxecm-2.0.3.dist-info/METADATA +0 -119
  74. pyxecm-2.0.3.dist-info/RECORD +0 -78
  75. pyxecm-2.0.3.dist-info/licenses/LICENSE +0 -202
  76. pyxecm-2.0.3.dist-info/top_level.txt +0 -1
  77. {pyxecm/customizer/api → pyxecm_api}/__init__.py +0 -0
  78. {pyxecm/customizer/api/auth → pyxecm_api/agents/otcm_knowledgegraph}/__init__.py +0 -0
  79. {pyxecm/customizer/api/common → pyxecm_api/agents/otcm_user_agent}/__init__.py +0 -0
  80. {pyxecm/customizer/api/v1_csai → pyxecm_api/agents/otcm_workspace_agent}/__init__.py +0 -0
  81. {pyxecm/customizer/api/v1_maintenance → pyxecm_api/auth}/__init__.py +0 -0
  82. {pyxecm/customizer/api → pyxecm_api}/auth/models.py +0 -0
  83. {pyxecm/customizer/api/v1_otcs → pyxecm_api/common}/__init__.py +0 -0
  84. {pyxecm/customizer/api → pyxecm_api}/common/models.py +0 -0
  85. {pyxecm/customizer/api → pyxecm_api}/terminal/__init__.py +0 -0
  86. {pyxecm/customizer/api/v1_payload → pyxecm_api/v1_csai}/__init__.py +0 -0
  87. {pyxecm/customizer/api → pyxecm_api}/v1_csai/models.py +0 -0
  88. {pyxecm/customizer/api → pyxecm_api}/v1_maintenance/models.py +0 -0
  89. {pyxecm/customizer/api → pyxecm_api}/v1_payload/models.py +0 -0
  90. {pyxecm/customizer → pyxecm_customizer}/exceptions.py +0 -0
  91. {pyxecm/maintenance_page → pyxecm_maintenance_page}/__init__.py +0 -0
  92. {pyxecm/maintenance_page → pyxecm_maintenance_page}/settings.py +0 -0
  93. {pyxecm/maintenance_page → pyxecm_maintenance_page}/static/favicon.avif +0 -0
  94. {pyxecm/maintenance_page → pyxecm_maintenance_page}/templates/maintenance.html +0 -0
@@ -0,0 +1,35 @@
1
+ """Common logging handler for VictoriaLogs and the LogCountFilter."""
2
+
3
+ import logging
4
+
5
+ import pandas as pd
6
+
7
+
8
+ class LogCountFilter(logging.Filter):
9
+ """LogFilter to be assinged to thread_logger to count the number os messages by level."""
10
+
11
+ def __init__(self, payload_items: pd.DataFrame, index: int) -> None:
12
+ """LogCountFilter initializer.
13
+
14
+ Args:
15
+ payload_items (pd.DataFrame): _description_
16
+ index (int): _description_
17
+
18
+ """
19
+ super().__init__()
20
+ self.index = index
21
+ self.payload_items = payload_items
22
+
23
+ def filter(self, record: logging.LogRecord) -> bool:
24
+ """Filter method.
25
+
26
+ Args:
27
+ record (_type_): _description_
28
+
29
+ Returns:
30
+ bool: _description_
31
+
32
+ """
33
+ level_name = (record.levelname).lower()
34
+ self.payload_items.loc[self.index, f"log_{level_name}"] += 1
35
+ return True
@@ -16,16 +16,16 @@ import re
16
16
  import time
17
17
  import urllib.parse
18
18
  import zipfile
19
- from datetime import datetime, timezone
19
+ from datetime import UTC, datetime
20
20
  from http import HTTPStatus
21
21
  from urllib.parse import quote
22
22
 
23
23
  import requests
24
-
25
- from pyxecm.customizer.browser_automation import BrowserAutomation
26
24
  from pyxecm.helper import HTTP
27
25
 
28
- default_logger = logging.getLogger("pyxecm.customizer.m365")
26
+ from .browser_automation import BrowserAutomation
27
+
28
+ default_logger = logging.getLogger("pyxecm_customizer.m365")
29
29
 
30
30
  request_login_headers = {
31
31
  "Content-Type": "application/x-www-form-urlencoded",
@@ -1297,8 +1297,7 @@ class M365:
1297
1297
 
1298
1298
  try:
1299
1299
  with open(file_path, "wb") as file:
1300
- for chunk in response.iter_content(chunk_size=8192):
1301
- file.write(chunk)
1300
+ file.writelines(response.iter_content(chunk_size=8192))
1302
1301
  except OSError:
1303
1302
  self.logger.error(
1304
1303
  "Error saving photo for user with ID -> %s!",
@@ -2267,13 +2266,14 @@ class M365:
2267
2266
  counter += 1
2268
2267
 
2269
2268
  self.logger.info(
2270
- "%s M365 Teams with name -> '%s' have been deleted.",
2269
+ "%s M365 Team%s with name -> '%s' have been deleted.",
2271
2270
  str(counter),
2271
+ "s" if counter > 1 else "",
2272
2272
  name,
2273
2273
  )
2274
2274
  return True
2275
2275
  else:
2276
- self.logger.info("No M365 Teams with name -> '%s' found.", name)
2276
+ self.logger.info("No M365 Team with name -> '%s' found.", name)
2277
2277
  return False
2278
2278
  else:
2279
2279
  self.logger.error("Failed to retrieve M365 Teams with name -> '%s'", name)
@@ -4221,7 +4221,7 @@ class M365:
4221
4221
  # Extract just the date:
4222
4222
  latest_email_date = latest_email["receivedDateTime"].split("T")[0]
4223
4223
  # Get the current date (today):
4224
- today_date = datetime.now(timezone.utc).strftime("%Y-%m-%d")
4224
+ today_date = datetime.now(UTC).strftime("%Y-%m-%d")
4225
4225
  # We do a sanity check here: the verification mail should be from today,
4226
4226
  # otherwise we assume it is an old mail and we need to wait for the
4227
4227
  # new verification mail to yet arrive:
@@ -4256,17 +4256,23 @@ class M365:
4256
4256
  return False
4257
4257
  # Simulate a "click" on this URL:
4258
4258
  if use_browser_automation:
4259
+ self.logger.info("Using browser automation for email verification...")
4259
4260
  # Core Share needs a full browser:
4260
- browser_automation_object = BrowserAutomation(
4261
- take_screenshots=True,
4262
- automation_name="email-verification",
4263
- logger=self.logger,
4264
- )
4261
+ try:
4262
+ browser_automation_object = BrowserAutomation(
4263
+ take_screenshots=True,
4264
+ automation_name="email-verification",
4265
+ logger=self.logger,
4266
+ )
4267
+ except Exception:
4268
+ self.logger.error("Failed to create browser automation object. Bailing out...")
4269
+ return False
4270
+
4265
4271
  self.logger.info(
4266
- "Open URL -> %s to verify account or email change (using browser automation)",
4272
+ "Open URL -> %s to verify account or email change...",
4267
4273
  url,
4268
4274
  )
4269
- success = browser_automation_object.get_page(url)
4275
+ success = browser_automation_object.get_page(url=url)
4270
4276
  if success:
4271
4277
  user_interaction_required = False
4272
4278
  self.logger.info(
@@ -4275,7 +4281,7 @@ class M365:
4275
4281
  )
4276
4282
  if password_field_id:
4277
4283
  password_field = browser_automation_object.find_elem(
4278
- find_elem=password_field_id,
4284
+ selector=password_field_id,
4279
4285
  show_error=False,
4280
4286
  )
4281
4287
  if password_field:
@@ -4286,8 +4292,8 @@ class M365:
4286
4292
  "Found password field on returned page - it seems email verification requests password entry!",
4287
4293
  )
4288
4294
  result = browser_automation_object.find_elem_and_set(
4289
- find_elem=password_field_id,
4290
- elem_value=password,
4295
+ selector=password_field_id,
4296
+ value=password,
4291
4297
  is_sensitive=True,
4292
4298
  )
4293
4299
  if not result:
@@ -4302,7 +4308,7 @@ class M365:
4302
4308
  )
4303
4309
  if user_interaction_required and password_confirmation_field_id:
4304
4310
  password_confirm_field = browser_automation_object.find_elem(
4305
- find_elem=password_confirmation_field_id,
4311
+ selector=password_confirmation_field_id,
4306
4312
  show_error=False,
4307
4313
  )
4308
4314
  if password_confirm_field:
@@ -4310,8 +4316,8 @@ class M365:
4310
4316
  "Found password confirmation field on returned page - it seems email verification requests consecutive password!",
4311
4317
  )
4312
4318
  result = browser_automation_object.find_elem_and_set(
4313
- find_elem=password_confirmation_field_id,
4314
- elem_value=password,
4319
+ selector=password_confirmation_field_id,
4320
+ value=password,
4315
4321
  is_sensitive=True,
4316
4322
  )
4317
4323
  if not result:
@@ -4322,19 +4328,19 @@ class M365:
4322
4328
  success = False
4323
4329
  if user_interaction_required and password_submit_xpath:
4324
4330
  password_submit_button = browser_automation_object.find_elem(
4325
- find_elem=password_submit_xpath,
4326
- find_method="xpath",
4331
+ selector=password_submit_xpath,
4332
+ selector_type="xpath",
4327
4333
  show_error=False,
4328
4334
  )
4329
4335
  if password_submit_button:
4330
4336
  self.logger.info(
4331
4337
  "Submit password change dialog with button -> '%s' (found with XPath -> %s)",
4332
- password_submit_button.text,
4338
+ password_submit_button.inner_text(),
4333
4339
  password_submit_xpath,
4334
4340
  )
4335
4341
  result = browser_automation_object.find_elem_and_click(
4336
- find_elem=password_submit_xpath,
4337
- find_method="xpath",
4342
+ selector=password_submit_xpath,
4343
+ selector_type="xpath",
4338
4344
  )
4339
4345
  if not result:
4340
4346
  self.logger.error(
@@ -4346,30 +4352,32 @@ class M365:
4346
4352
  # which require a short wait time. It seems it is required!
4347
4353
  time.sleep(1)
4348
4354
  terms_accept_button = browser_automation_object.find_elem(
4349
- find_elem=terms_of_service_xpath,
4350
- find_method="xpath",
4355
+ selector=terms_of_service_xpath,
4356
+ selector_type="xpath",
4351
4357
  show_error=False,
4352
4358
  )
4353
4359
  if terms_accept_button:
4354
4360
  self.logger.info(
4355
4361
  "Accept terms of service with button -> '%s' (found with XPath -> %s)",
4356
- terms_accept_button.text,
4362
+ terms_accept_button.inner_text(),
4357
4363
  terms_of_service_xpath,
4358
4364
  )
4359
4365
  result = browser_automation_object.find_elem_and_click(
4360
- find_elem=terms_of_service_xpath,
4361
- find_method="xpath",
4366
+ selector=terms_of_service_xpath,
4367
+ selector_type="xpath",
4362
4368
  )
4363
4369
  if not result:
4364
4370
  self.logger.error(
4365
4371
  "Failed to accept terms of service with button -> '%s'",
4366
- terms_accept_button.text,
4372
+ terms_accept_button.inner_text(),
4367
4373
  )
4368
4374
  success = False
4369
4375
  else:
4370
4376
  self.logger.info(
4371
4377
  "No Terms of Service acceptance required.",
4372
4378
  )
4379
+ # end if user_interaction_required and password_submit_xpath:
4380
+ # end if success:
4373
4381
  # end if use_browser_automation
4374
4382
  else:
4375
4383
  # Salesforce (other than Core Share) is OK with the simple HTTP GET request: