pyxecm 3.0.1__py3-none-any.whl → 3.1.1__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 (52) hide show
  1. pyxecm/avts.py +4 -4
  2. pyxecm/coreshare.py +14 -15
  3. pyxecm/helper/data.py +2 -1
  4. pyxecm/helper/web.py +11 -11
  5. pyxecm/helper/xml.py +41 -10
  6. pyxecm/otac.py +1 -1
  7. pyxecm/otawp.py +19 -19
  8. pyxecm/otca.py +878 -70
  9. pyxecm/otcs.py +1716 -349
  10. pyxecm/otds.py +332 -153
  11. pyxecm/otkd.py +4 -4
  12. pyxecm/otmm.py +1 -1
  13. pyxecm/otpd.py +246 -30
  14. {pyxecm-3.0.1.dist-info → pyxecm-3.1.1.dist-info}/METADATA +2 -1
  15. pyxecm-3.1.1.dist-info/RECORD +82 -0
  16. pyxecm_api/app.py +45 -35
  17. pyxecm_api/auth/functions.py +2 -2
  18. pyxecm_api/auth/router.py +2 -3
  19. pyxecm_api/common/functions.py +67 -12
  20. pyxecm_api/settings.py +0 -8
  21. pyxecm_api/terminal/router.py +1 -1
  22. pyxecm_api/v1_csai/router.py +33 -18
  23. pyxecm_customizer/browser_automation.py +161 -79
  24. pyxecm_customizer/customizer.py +43 -25
  25. pyxecm_customizer/guidewire.py +422 -8
  26. pyxecm_customizer/k8s.py +23 -27
  27. pyxecm_customizer/knowledge_graph.py +498 -20
  28. pyxecm_customizer/m365.py +45 -44
  29. pyxecm_customizer/payload.py +1723 -1188
  30. pyxecm_customizer/payload_list.py +3 -0
  31. pyxecm_customizer/salesforce.py +122 -79
  32. pyxecm_customizer/servicenow.py +27 -7
  33. pyxecm_customizer/settings.py +3 -1
  34. pyxecm_customizer/successfactors.py +2 -2
  35. pyxecm_customizer/translate.py +1 -1
  36. pyxecm-3.0.1.dist-info/RECORD +0 -96
  37. pyxecm_api/agents/__init__.py +0 -7
  38. pyxecm_api/agents/app.py +0 -13
  39. pyxecm_api/agents/functions.py +0 -119
  40. pyxecm_api/agents/models.py +0 -10
  41. pyxecm_api/agents/otcm_knowledgegraph/__init__.py +0 -1
  42. pyxecm_api/agents/otcm_knowledgegraph/functions.py +0 -85
  43. pyxecm_api/agents/otcm_knowledgegraph/models.py +0 -61
  44. pyxecm_api/agents/otcm_knowledgegraph/router.py +0 -74
  45. pyxecm_api/agents/otcm_user_agent/__init__.py +0 -1
  46. pyxecm_api/agents/otcm_user_agent/models.py +0 -20
  47. pyxecm_api/agents/otcm_user_agent/router.py +0 -65
  48. pyxecm_api/agents/otcm_workspace_agent/__init__.py +0 -1
  49. pyxecm_api/agents/otcm_workspace_agent/models.py +0 -40
  50. pyxecm_api/agents/otcm_workspace_agent/router.py +0 -200
  51. {pyxecm-3.0.1.dist-info → pyxecm-3.1.1.dist-info}/WHEEL +0 -0
  52. {pyxecm-3.0.1.dist-info → pyxecm-3.1.1.dist-info}/entry_points.txt +0 -0
pyxecm_customizer/m365.py CHANGED
@@ -32,8 +32,8 @@ request_login_headers = {
32
32
  "Accept": "application/json",
33
33
  }
34
34
 
35
- REQUEST_TIMEOUT = 60
36
- REQUEST_RETRY_DELAY = 20
35
+ REQUEST_TIMEOUT = 60.0
36
+ REQUEST_RETRY_DELAY = 20.0
37
37
  REQUEST_MAX_RETRIES = 3
38
38
 
39
39
 
@@ -259,7 +259,7 @@ class M365:
259
259
  json_data: dict | None = None,
260
260
  files: dict | None = None,
261
261
  params: dict | None = None,
262
- timeout: int | None = REQUEST_TIMEOUT,
262
+ timeout: float | None = REQUEST_TIMEOUT,
263
263
  show_error: bool = True,
264
264
  show_warning: bool = False,
265
265
  warning_message: str = "",
@@ -290,7 +290,7 @@ class M365:
290
290
  Add key-value pairs to the query string of the URL.
291
291
  When you use the params parameter, requests automatically appends
292
292
  the key-value pairs to the URL as part of the query string
293
- timeout (int | None, optional):
293
+ timeout (float | None, optional):
294
294
  Timeout for the request in seconds. Defaults to REQUEST_TIMEOUT.
295
295
  show_error (bool, optional):
296
296
  Whether or not an error should be logged in case of a failed REST call.
@@ -418,7 +418,7 @@ class M365:
418
418
  time.sleep(REQUEST_RETRY_DELAY) # Add a delay before retrying
419
419
  else:
420
420
  self.logger.error(
421
- "%s; timeout error.",
421
+ "%s; timeout error!",
422
422
  failure_message,
423
423
  )
424
424
  if retry_forever:
@@ -437,7 +437,7 @@ class M365:
437
437
  time.sleep(REQUEST_RETRY_DELAY) # Add a delay before retrying
438
438
  else:
439
439
  self.logger.error(
440
- "%s; connection error.",
440
+ "%s; connection error!",
441
441
  failure_message,
442
442
  )
443
443
  if retry_forever:
@@ -512,7 +512,7 @@ class M365:
512
512
 
513
513
  def exist_result_item(
514
514
  self,
515
- response: dict,
515
+ response: dict | None,
516
516
  key: str,
517
517
  value: str,
518
518
  sub_dict_name: str = "",
@@ -520,7 +520,7 @@ class M365:
520
520
  """Check existence of key / value pair in the response properties of an MS Graph API call.
521
521
 
522
522
  Args:
523
- response (dict):
523
+ response (dict | None):
524
524
  REST response from an MS Graph REST Call.
525
525
  key (str):
526
526
  The property name (key).
@@ -563,7 +563,7 @@ class M365:
563
563
 
564
564
  def get_result_value(
565
565
  self,
566
- response: dict,
566
+ response: dict | None,
567
567
  key: str,
568
568
  index: int = 0,
569
569
  sub_dict_name: str = "",
@@ -571,7 +571,7 @@ class M365:
571
571
  """Get value of a result property with a given key of an MS Graph API call.
572
572
 
573
573
  Args:
574
- response (dict):
574
+ response (dict | None):
575
575
  REST response from an MS Graph REST Call.
576
576
  key (str):
577
577
  The property name (key).
@@ -584,7 +584,7 @@ class M365:
584
584
  a case we use the sub_dict_name to access it.
585
585
 
586
586
  Returns:
587
- str:
587
+ str | None:
588
588
  The value for the key, None otherwise.
589
589
 
590
590
  """
@@ -678,7 +678,7 @@ class M365:
678
678
  return None
679
679
  else:
680
680
  self.logger.error(
681
- "Result needs to be a list or dict but it is of type -> %s",
681
+ "Result needs to be a list or dictionary but it is of type -> '%s'!",
682
682
  str(type(results)),
683
683
  )
684
684
  return None
@@ -953,7 +953,7 @@ class M365:
953
953
  # Some sanity checks:
954
954
  if user_email and ("@" not in user_email or "." not in user_email):
955
955
  self.logger.error(
956
- "User email -> %s is not a valid email address",
956
+ "User email -> %s is not a valid email address!",
957
957
  user_email,
958
958
  )
959
959
  return None
@@ -974,7 +974,7 @@ class M365:
974
974
  # Construct the email address without the alias
975
975
  user_email = user_email[:alias_index] + user_email[domain_index:]
976
976
  self.logger.info(
977
- "M365 user principal name -> %s",
977
+ "M365 user principal name -> '%s'.",
978
978
  user_email,
979
979
  )
980
980
 
@@ -1305,7 +1305,7 @@ class M365:
1305
1305
  )
1306
1306
  else:
1307
1307
  self.logger.info(
1308
- "Photo for M365 user with ID -> %s saved to -> '%s'",
1308
+ "Photo for M365 user with ID -> %s saved to -> '%s'.",
1309
1309
  user_id,
1310
1310
  file_path,
1311
1311
  )
@@ -1715,7 +1715,7 @@ class M365:
1715
1715
  group_id = self.get_result_value(response=response, key="id", index=0)
1716
1716
  if not group_id:
1717
1717
  self.logger.error(
1718
- "M365 Group -> %s does not exist! Cannot retrieve group members.",
1718
+ "M365 Group -> '%s' does not exist! Cannot retrieve group members.",
1719
1719
  group_name,
1720
1720
  )
1721
1721
  return None
@@ -1940,9 +1940,9 @@ class M365:
1940
1940
  headers=request_header,
1941
1941
  timeout=REQUEST_TIMEOUT,
1942
1942
  )
1943
- deleted_groups = self.parse_request_response(response)
1943
+ deleted_groups = self.parse_request_response(response) or {}
1944
1944
 
1945
- for group in deleted_groups["value"]:
1945
+ for group in deleted_groups.get("value", []):
1946
1946
  group_id = group["id"]
1947
1947
  response = self.purge_deleted_item(group_id)
1948
1948
 
@@ -1952,9 +1952,9 @@ class M365:
1952
1952
  headers=request_header,
1953
1953
  timeout=REQUEST_TIMEOUT,
1954
1954
  )
1955
- deleted_users = self.parse_request_response(response)
1955
+ deleted_users = self.parse_request_response(response) or {}
1956
1956
 
1957
- for user in deleted_users["value"]:
1957
+ for user in deleted_users.get("value", []):
1958
1958
  user_id = user["id"]
1959
1959
  response = self.purge_deleted_item(user_id)
1960
1960
 
@@ -2012,7 +2012,7 @@ class M365:
2012
2012
  group_id = self.get_result_value(response=response, key="id", index=0)
2013
2013
  if not group_id:
2014
2014
  self.logger.error(
2015
- "M365 Group -> %s not found. Cannot check if it has a M365 Team.",
2015
+ "M365 Group -> '%s' not found! Cannot check if it has a M365 Team.",
2016
2016
  group_name,
2017
2017
  )
2018
2018
  return False
@@ -2094,7 +2094,7 @@ class M365:
2094
2094
  team_id = self.get_result_value(response=response, key="id", index=0)
2095
2095
  if not team_id:
2096
2096
  self.logger.error(
2097
- "Failed to get the ID of the M365 Team -> %s via the M365 Group API",
2097
+ "Failed to get the ID of the M365 Team -> '%s' via the M365 Group API!",
2098
2098
  name,
2099
2099
  )
2100
2100
  return None
@@ -2139,7 +2139,7 @@ class M365:
2139
2139
  group_id = self.get_result_value(response=response, key="id", index=0)
2140
2140
  if not group_id:
2141
2141
  self.logger.error(
2142
- "M365 Group -> '%s' not found. It is required for creating a corresponding M365 Team.",
2142
+ "M365 Group -> '%s' not found! It is required for creating a corresponding M365 Team.",
2143
2143
  name,
2144
2144
  )
2145
2145
  return None
@@ -2258,7 +2258,7 @@ class M365:
2258
2258
 
2259
2259
  if not response:
2260
2260
  self.logger.error(
2261
- "Failed to delete M365 Team -> '%s' (%s)",
2261
+ "Failed to delete M365 Team -> '%s' (%s)!",
2262
2262
  name,
2263
2263
  team_id,
2264
2264
  )
@@ -2266,17 +2266,18 @@ class M365:
2266
2266
  counter += 1
2267
2267
 
2268
2268
  self.logger.info(
2269
- "%s M365 Team%s with name -> '%s' have been deleted.",
2269
+ "%s M365 Team%s with name -> '%s' %s been deleted.",
2270
2270
  str(counter),
2271
2271
  "s" if counter > 1 else "",
2272
2272
  name,
2273
+ "have" if counter > 1 else "has",
2273
2274
  )
2274
2275
  return True
2275
2276
  else:
2276
2277
  self.logger.info("No M365 Team with name -> '%s' found.", name)
2277
2278
  return False
2278
2279
  else:
2279
- self.logger.error("Failed to retrieve M365 Teams with name -> '%s'", name)
2280
+ self.logger.error("Failed to retrieve M365 Teams with name -> '%s'!", name)
2280
2281
  return False
2281
2282
 
2282
2283
  # end method definition
@@ -2328,7 +2329,7 @@ class M365:
2328
2329
  result = re.search(pattern, group_name)
2329
2330
  if result:
2330
2331
  self.logger.info(
2331
- "M365 Group name -> '%s' is matching pattern -> '%s'. Delete it now...",
2332
+ "M365 Group name -> '%s' is matching pattern -> '%s'. Deleting...",
2332
2333
  group_name,
2333
2334
  pattern,
2334
2335
  )
@@ -2456,7 +2457,7 @@ class M365:
2456
2457
  )
2457
2458
  if not channel:
2458
2459
  self.logger.error(
2459
- "Cannot find Channel -> %s on M365 Team -> %s",
2460
+ "Cannot find Channel -> '%s' on M365 Team -> '%s'!",
2460
2461
  channel_name,
2461
2462
  team_name,
2462
2463
  )
@@ -3282,7 +3283,7 @@ class M365:
3282
3283
  )
3283
3284
  if not channel:
3284
3285
  self.logger.error(
3285
- "Cannot find Channel -> '%s' on M365 Team -> '%s'",
3286
+ "Cannot find Channel -> '%s' on M365 Team -> '%s'!",
3286
3287
  channel_name,
3287
3288
  team_name,
3288
3289
  )
@@ -3375,7 +3376,7 @@ class M365:
3375
3376
  )
3376
3377
  if not channel:
3377
3378
  self.logger.error(
3378
- "Cannot find Channel -> '%s' for M365 Team -> '%s'",
3379
+ "Cannot find Channel -> '%s' for M365 Team -> '%s'!",
3379
3380
  channel_name,
3380
3381
  team_name,
3381
3382
  )
@@ -3394,7 +3395,7 @@ class M365:
3394
3395
  )
3395
3396
  if not tab:
3396
3397
  self.logger.error(
3397
- "Cannot find Tab -> '%s' on M365 Team -> '%s' (%s) and Channel -> '%s' (%s)",
3398
+ "Cannot find Tab -> '%s' on M365 Team -> '%s' (%s) and Channel -> '%s' (%s)!",
3398
3399
  tab_name,
3399
3400
  team_name,
3400
3401
  team_id,
@@ -3489,7 +3490,7 @@ class M365:
3489
3490
  )
3490
3491
  if not channel:
3491
3492
  self.logger.error(
3492
- "Cannot find Channel -> '%s' for M365 Team -> '%s'",
3493
+ "Cannot find Channel -> '%s' for M365 Team -> '%s'!",
3493
3494
  channel_name,
3494
3495
  team_name,
3495
3496
  )
@@ -3506,7 +3507,7 @@ class M365:
3506
3507
  tab_list = [item for item in response["value"] if item["displayName"] == tab_name]
3507
3508
  if not tab_list:
3508
3509
  self.logger.error(
3509
- "Cannot find Tab -> '%s' on M365 Team -> '%s' (%s) and Channel -> '%s' (%s)",
3510
+ "Cannot find Tab -> '%s' on M365 Team -> '%s' (%s) and Channel -> '%s' (%s)!",
3510
3511
  tab_name,
3511
3512
  team_name,
3512
3513
  team_id,
@@ -4298,7 +4299,7 @@ class M365:
4298
4299
  )
4299
4300
  if not result:
4300
4301
  self.logger.error(
4301
- "Failed to enter password in field -> '%s'",
4302
+ "Failed to enter password in field -> '%s'!",
4302
4303
  password_field_id,
4303
4304
  )
4304
4305
  success = False
@@ -4313,7 +4314,7 @@ class M365:
4313
4314
  )
4314
4315
  if password_confirm_field:
4315
4316
  self.logger.info(
4316
- "Found password confirmation field on returned page - it seems email verification requests consecutive password!",
4317
+ "Found password confirmation field on returned page - it seems email verification requests consecutive password.",
4317
4318
  )
4318
4319
  result = browser_automation_object.find_elem_and_set(
4319
4320
  selector=password_confirmation_field_id,
@@ -4322,7 +4323,7 @@ class M365:
4322
4323
  )
4323
4324
  if not result:
4324
4325
  self.logger.error(
4325
- "Failed to enter password in field -> '%s'",
4326
+ "Failed to enter password in field -> '%s'!",
4326
4327
  password_confirmation_field_id,
4327
4328
  )
4328
4329
  success = False
@@ -4334,7 +4335,7 @@ class M365:
4334
4335
  )
4335
4336
  if password_submit_button:
4336
4337
  self.logger.info(
4337
- "Submit password change dialog with button -> '%s' (found with XPath -> %s)",
4338
+ "Submit password change dialog with button -> '%s' (found with XPath -> %s).",
4338
4339
  password_submit_button.inner_text(),
4339
4340
  password_submit_xpath,
4340
4341
  )
@@ -4358,7 +4359,7 @@ class M365:
4358
4359
  )
4359
4360
  if terms_accept_button:
4360
4361
  self.logger.info(
4361
- "Accept terms of service with button -> '%s' (found with XPath -> %s)",
4362
+ "Accept terms of service with button -> '%s' (found with XPath -> %s).",
4362
4363
  terms_accept_button.inner_text(),
4363
4364
  terms_of_service_xpath,
4364
4365
  )
@@ -4368,7 +4369,7 @@ class M365:
4368
4369
  )
4369
4370
  if not result:
4370
4371
  self.logger.error(
4371
- "Failed to accept terms of service with button -> '%s'",
4372
+ "Failed to accept terms of service with button -> '%s'!",
4372
4373
  terms_accept_button.inner_text(),
4373
4374
  )
4374
4375
  success = False
@@ -4382,7 +4383,7 @@ class M365:
4382
4383
  else:
4383
4384
  # Salesforce (other than Core Share) is OK with the simple HTTP GET request:
4384
4385
  self.logger.info(
4385
- "Open URL -> %s to verify account or email change",
4386
+ "Open URL -> %s to verify account or email change...",
4386
4387
  url,
4387
4388
  )
4388
4389
  response = self._http_object.http_request(url=url, method="GET")
@@ -4396,14 +4397,14 @@ class M365:
4396
4397
  response = self.delete_mail(user_id=m365_user_id, email_id=email_id)
4397
4398
  if not response:
4398
4399
  self.logger.warning(
4399
- "Couldn't remove the mail from the inbox of user -> %s",
4400
+ "Couldn't remove the mail from the inbox of user -> %s!",
4400
4401
  user_email,
4401
4402
  )
4402
4403
  # We have success now and can break from the while loop
4403
4404
  return True
4404
4405
  else:
4405
4406
  self.logger.error(
4406
- "Failed to process e-mail verification for user -> %s",
4407
+ "Failed to process e-mail verification for user -> %s!",
4407
4408
  user_email,
4408
4409
  )
4409
4410
  return False
@@ -5710,7 +5711,7 @@ class M365:
5710
5711
  webpart = self.get_sharepoint_webpart(site_id=site_id, page_id=page_id, webpart_id=webpart_id)
5711
5712
  if not webpart:
5712
5713
  self.logger.error(
5713
- "Cannot find web part for site ID -> '%s', page -> '%s', webpart ID -> '%s'",
5714
+ "Cannot find web part for site ID -> '%s', page -> '%s', webpart ID -> '%s'!",
5714
5715
  site_id,
5715
5716
  page_id,
5716
5717
  webpart_id,
@@ -5806,7 +5807,7 @@ class M365:
5806
5807
  """
5807
5808
 
5808
5809
  if not user_id and not username:
5809
- self.logger.error("User missing to follow. Provide the user ID or its email address!")
5810
+ self.logger.error("No user given to follow SharePoint site. Provide the user ID or its email address!")
5810
5811
  return None
5811
5812
 
5812
5813
  user = self.get_user(user_email=username, user_id=user_id)