seleniumbase 4.24.11__py3-none-any.whl → 4.33.15__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.
Files changed (78) hide show
  1. sbase/__init__.py +1 -0
  2. sbase/steps.py +7 -0
  3. seleniumbase/__init__.py +16 -7
  4. seleniumbase/__version__.py +1 -1
  5. seleniumbase/behave/behave_sb.py +97 -32
  6. seleniumbase/common/decorators.py +16 -7
  7. seleniumbase/config/proxy_list.py +3 -3
  8. seleniumbase/config/settings.py +4 -0
  9. seleniumbase/console_scripts/logo_helper.py +47 -8
  10. seleniumbase/console_scripts/run.py +345 -335
  11. seleniumbase/console_scripts/sb_behave_gui.py +5 -12
  12. seleniumbase/console_scripts/sb_caseplans.py +6 -13
  13. seleniumbase/console_scripts/sb_commander.py +5 -12
  14. seleniumbase/console_scripts/sb_install.py +62 -54
  15. seleniumbase/console_scripts/sb_mkchart.py +13 -20
  16. seleniumbase/console_scripts/sb_mkdir.py +11 -17
  17. seleniumbase/console_scripts/sb_mkfile.py +69 -43
  18. seleniumbase/console_scripts/sb_mkpres.py +13 -20
  19. seleniumbase/console_scripts/sb_mkrec.py +88 -21
  20. seleniumbase/console_scripts/sb_objectify.py +30 -30
  21. seleniumbase/console_scripts/sb_print.py +5 -12
  22. seleniumbase/console_scripts/sb_recorder.py +16 -11
  23. seleniumbase/core/browser_launcher.py +1658 -221
  24. seleniumbase/core/log_helper.py +42 -27
  25. seleniumbase/core/mysql.py +1 -4
  26. seleniumbase/core/proxy_helper.py +35 -30
  27. seleniumbase/core/recorder_helper.py +24 -5
  28. seleniumbase/core/sb_cdp.py +1951 -0
  29. seleniumbase/core/sb_driver.py +162 -8
  30. seleniumbase/core/settings_parser.py +6 -0
  31. seleniumbase/core/style_sheet.py +10 -0
  32. seleniumbase/extensions/recorder.zip +0 -0
  33. seleniumbase/fixtures/base_case.py +1225 -614
  34. seleniumbase/fixtures/constants.py +10 -1
  35. seleniumbase/fixtures/js_utils.py +171 -144
  36. seleniumbase/fixtures/page_actions.py +177 -13
  37. seleniumbase/fixtures/page_utils.py +25 -53
  38. seleniumbase/fixtures/shared_utils.py +97 -11
  39. seleniumbase/js_code/active_css_js.py +1 -1
  40. seleniumbase/js_code/recorder_js.py +1 -1
  41. seleniumbase/plugins/base_plugin.py +2 -3
  42. seleniumbase/plugins/driver_manager.py +340 -65
  43. seleniumbase/plugins/pytest_plugin.py +276 -47
  44. seleniumbase/plugins/sb_manager.py +412 -99
  45. seleniumbase/plugins/selenium_plugin.py +122 -17
  46. seleniumbase/translate/translator.py +0 -7
  47. seleniumbase/undetected/__init__.py +59 -52
  48. seleniumbase/undetected/cdp.py +0 -1
  49. seleniumbase/undetected/cdp_driver/__init__.py +1 -0
  50. seleniumbase/undetected/cdp_driver/_contradict.py +110 -0
  51. seleniumbase/undetected/cdp_driver/browser.py +829 -0
  52. seleniumbase/undetected/cdp_driver/cdp_util.py +458 -0
  53. seleniumbase/undetected/cdp_driver/config.py +334 -0
  54. seleniumbase/undetected/cdp_driver/connection.py +639 -0
  55. seleniumbase/undetected/cdp_driver/element.py +1168 -0
  56. seleniumbase/undetected/cdp_driver/tab.py +1323 -0
  57. seleniumbase/undetected/dprocess.py +4 -7
  58. seleniumbase/undetected/options.py +6 -8
  59. seleniumbase/undetected/patcher.py +11 -13
  60. seleniumbase/undetected/reactor.py +0 -1
  61. seleniumbase/undetected/webelement.py +16 -3
  62. {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/LICENSE +1 -1
  63. {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/METADATA +299 -252
  64. {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/RECORD +67 -69
  65. {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/WHEEL +1 -1
  66. sbase/ReadMe.txt +0 -2
  67. seleniumbase/ReadMe.md +0 -25
  68. seleniumbase/common/ReadMe.md +0 -71
  69. seleniumbase/console_scripts/ReadMe.md +0 -731
  70. seleniumbase/drivers/ReadMe.md +0 -27
  71. seleniumbase/extensions/ReadMe.md +0 -12
  72. seleniumbase/masterqa/ReadMe.md +0 -61
  73. seleniumbase/resources/ReadMe.md +0 -31
  74. seleniumbase/resources/favicon.ico +0 -0
  75. seleniumbase/utilities/selenium_grid/ReadMe.md +0 -84
  76. seleniumbase/utilities/selenium_ide/ReadMe.md +0 -111
  77. {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/entry_points.txt +0 -0
  78. {seleniumbase-4.24.11.dist-info → seleniumbase-4.33.15.dist-info}/top_level.txt +0 -0
@@ -3,9 +3,11 @@ import os
3
3
  import shutil
4
4
  import sys
5
5
  import time
6
+ from contextlib import suppress
6
7
  from seleniumbase import config as sb_config
7
8
  from seleniumbase.config import settings
8
9
  from seleniumbase.fixtures import constants
10
+ from seleniumbase.fixtures import shared_utils
9
11
 
10
12
  python3_11_or_newer = False
11
13
  if sys.version_info >= (3, 11):
@@ -13,6 +15,11 @@ if sys.version_info >= (3, 11):
13
15
  py311_patch2 = constants.PatchPy311.PATCH
14
16
 
15
17
 
18
+ def __is_cdp_swap_needed(driver):
19
+ """If the driver is disconnected, use a CDP method when available."""
20
+ return shared_utils.is_cdp_swap_needed(driver)
21
+
22
+
16
23
  def log_screenshot(test_logpath, driver, screenshot=None, get=False):
17
24
  screenshot_name = settings.SCREENSHOT_NAME
18
25
  screenshot_path = os.path.join(test_logpath, screenshot_name)
@@ -32,6 +39,8 @@ def log_screenshot(test_logpath, driver, screenshot=None, get=False):
32
39
  if screenshot != screenshot_warning:
33
40
  with open(screenshot_path, "wb") as file:
34
41
  file.write(screenshot)
42
+ with suppress(Exception):
43
+ shared_utils.make_writable(screenshot_path)
35
44
  else:
36
45
  print("WARNING: %s" % screenshot_warning)
37
46
  if get:
@@ -281,14 +290,14 @@ def log_test_failure_data(test, test_logpath, driver, browser, url=None):
281
290
  sb_config._report_time = the_time
282
291
  sb_config._report_traceback = traceback_message
283
292
  sb_config._report_exception = exc_message
284
- try:
285
- if not os.path.exists(test_logpath):
293
+ if not os.path.exists(test_logpath):
294
+ with suppress(Exception):
286
295
  os.makedirs(test_logpath)
287
- except Exception:
288
- pass
289
- log_file = codecs.open(basic_file_path, "w+", "utf-8")
290
- log_file.writelines("\r\n".join(data_to_save))
291
- log_file.close()
296
+ with suppress(Exception):
297
+ log_file = codecs.open(basic_file_path, "w+", encoding="utf-8")
298
+ log_file.writelines("\r\n".join(data_to_save))
299
+ log_file.close()
300
+ shared_utils.make_writable(basic_file_path)
292
301
 
293
302
 
294
303
  def log_skipped_test_data(test, test_logpath, driver, browser, reason):
@@ -297,16 +306,12 @@ def log_skipped_test_data(test, test_logpath, driver, browser, reason):
297
306
  browser_version = None
298
307
  driver_version = None
299
308
  driver_name = None
300
- try:
309
+ with suppress(Exception):
301
310
  browser_version = get_browser_version(driver)
302
- except Exception:
303
- pass
304
- try:
311
+ with suppress(Exception):
305
312
  driver_name, driver_version = get_driver_name_and_version(
306
313
  driver, browser
307
314
  )
308
- except Exception:
309
- pass
310
315
  if browser_version:
311
316
  headless = ""
312
317
  if test.headless and browser in ["chrome", "edge", "firefox"]:
@@ -343,9 +348,11 @@ def log_skipped_test_data(test, test_logpath, driver, browser, reason):
343
348
  data_to_save.append(" * Skip Reason: %s" % reason)
344
349
  data_to_save.append("")
345
350
  file_path = os.path.join(test_logpath, "skip_reason.txt")
346
- log_file = codecs.open(file_path, "w+", encoding="utf-8")
347
- log_file.writelines("\r\n".join(data_to_save))
348
- log_file.close()
351
+ with suppress(Exception):
352
+ log_file = codecs.open(file_path, "w+", encoding="utf-8")
353
+ log_file.writelines("\r\n".join(data_to_save))
354
+ log_file.close()
355
+ shared_utils.make_writable(file_path)
349
356
 
350
357
 
351
358
  def log_page_source(test_logpath, driver, source=None):
@@ -354,7 +361,11 @@ def log_page_source(test_logpath, driver, source=None):
354
361
  page_source = source
355
362
  else:
356
363
  try:
357
- page_source = driver.page_source
364
+ page_source = None
365
+ if __is_cdp_swap_needed(driver):
366
+ page_source = driver.cdp.get_page_source()
367
+ else:
368
+ page_source = driver.page_source
358
369
  page_source = get_html_source_with_base_href(driver, page_source)
359
370
  except Exception:
360
371
  source = constants.Warnings.PAGE_SOURCE_UNDEFINED
@@ -368,15 +379,15 @@ def log_page_source(test_logpath, driver, source=None):
368
379
  "unresponsive, or closed prematurely!</h4>"
369
380
  )
370
381
  )
371
- try:
372
- if not os.path.exists(test_logpath):
382
+ if not os.path.exists(test_logpath):
383
+ with suppress(Exception):
373
384
  os.makedirs(test_logpath)
374
- except Exception:
375
- pass
376
385
  html_file_path = os.path.join(test_logpath, html_file_name)
377
- html_file = codecs.open(html_file_path, "w+", "utf-8")
378
- html_file.write(page_source)
379
- html_file.close()
386
+ with suppress(Exception):
387
+ html_file = codecs.open(html_file_path, "w+", encoding="utf-8")
388
+ html_file.write(page_source)
389
+ html_file.close()
390
+ shared_utils.make_writable(html_file_path)
380
391
 
381
392
 
382
393
  def get_test_id(test):
@@ -446,7 +457,11 @@ def get_test_name(test):
446
457
 
447
458
  def get_last_page(driver):
448
459
  try:
449
- last_page = driver.current_url
460
+ last_page = None
461
+ if __is_cdp_swap_needed(driver):
462
+ last_page = driver.cdp.get_current_url()
463
+ else:
464
+ last_page = driver.current_url
450
465
  except Exception:
451
466
  last_page = "[WARNING! Browser Not Open!]"
452
467
  if len(last_page) < 5:
@@ -543,7 +558,7 @@ def log_folder_setup(log_path, archive_logs=False):
543
558
  try:
544
559
  os.makedirs(log_path)
545
560
  except Exception:
546
- pass # Should only be reachable during multi-threaded runs
561
+ pass # Only reachable during multi-threaded runs
547
562
  else:
548
563
  saved_folder = "%s/../%s/" % (log_path, constants.Logs.SAVED)
549
564
  archived_folder = os.path.realpath(saved_folder) + "/"
@@ -551,7 +566,7 @@ def log_folder_setup(log_path, archive_logs=False):
551
566
  try:
552
567
  os.makedirs(archived_folder)
553
568
  except Exception:
554
- pass # Should only be reachable during multi-threaded runs
569
+ pass # Only reachable during multi-threaded runs
555
570
  archived_logs = "%slogs_%s" % (archived_folder, int(time.time()))
556
571
  if len(os.listdir(log_path)) > 0:
557
572
  try:
@@ -35,10 +35,7 @@ class DatabaseManager:
35
35
  import cryptography # noqa: F401
36
36
  import pymysql
37
37
  except Exception:
38
- if sys.version_info < (3, 7):
39
- shared_utils.pip_install("PyMySQL[rsa]", version="1.0.2")
40
- else:
41
- shared_utils.pip_install("PyMySQL[rsa]", version="1.1.0")
38
+ shared_utils.pip_install("PyMySQL[rsa]", version="1.1.1")
42
39
  import pymysql
43
40
  db_server = settings.DB_HOST
44
41
  db_port = settings.DB_PORT
@@ -2,10 +2,12 @@ import os
2
2
  import re
3
3
  import warnings
4
4
  import zipfile
5
+ from contextlib import suppress
5
6
  from seleniumbase.config import proxy_list
6
7
  from seleniumbase.config import settings
7
8
  from seleniumbase.fixtures import constants
8
9
  from seleniumbase.fixtures import page_utils
10
+ from seleniumbase.fixtures import shared_utils
9
11
 
10
12
  DOWNLOADS_DIR = constants.Files.DOWNLOADS_FOLDER
11
13
  PROXY_ZIP_PATH = os.path.join(DOWNLOADS_DIR, "proxy.zip")
@@ -109,31 +111,35 @@ def create_proxy_ext(
109
111
  """"minimum_chrome_version":"22.0.0"\n"""
110
112
  """}"""
111
113
  )
112
- import threading
113
-
114
- lock = threading.RLock() # Support multi-threaded tests. Eg. "pytest -n=4"
115
- with lock:
116
- abs_path = os.path.abspath(".")
117
- downloads_path = os.path.join(abs_path, DOWNLOADS_DIR)
118
- if not os.path.exists(downloads_path):
119
- os.mkdir(downloads_path)
120
- if zip_it:
121
- zf = zipfile.ZipFile(PROXY_ZIP_PATH, mode="w")
122
- zf.writestr("background.js", background_js)
123
- zf.writestr("manifest.json", manifest_json)
124
- zf.close()
125
- else:
126
- proxy_ext_dir = PROXY_DIR_PATH
127
- if not os.path.exists(proxy_ext_dir):
128
- os.mkdir(proxy_ext_dir)
129
- manifest_file = os.path.join(proxy_ext_dir, "manifest.json")
130
- with open(manifest_file, mode="w") as f:
131
- f.write(manifest_json)
132
- proxy_host = proxy_string.split(":")[0]
133
- proxy_port = proxy_string.split(":")[1]
134
- background_file = os.path.join(proxy_ext_dir, "background.js")
135
- with open(background_file, mode="w") as f:
136
- f.write(background_js)
114
+ abs_path = os.path.abspath(".")
115
+ downloads_path = os.path.join(abs_path, DOWNLOADS_DIR)
116
+ if not os.path.exists(downloads_path):
117
+ os.mkdir(downloads_path)
118
+ if zip_it:
119
+ zf = zipfile.ZipFile(PROXY_ZIP_PATH, mode="w")
120
+ zf.writestr("background.js", background_js)
121
+ zf.writestr("manifest.json", manifest_json)
122
+ zf.close()
123
+ with suppress(Exception):
124
+ shared_utils.make_writable(PROXY_ZIP_PATH)
125
+ else:
126
+ proxy_ext_dir = PROXY_DIR_PATH
127
+ if not os.path.exists(proxy_ext_dir):
128
+ os.mkdir(proxy_ext_dir)
129
+ with suppress(Exception):
130
+ shared_utils.make_writable(proxy_ext_dir)
131
+ manifest_file = os.path.join(proxy_ext_dir, "manifest.json")
132
+ with open(manifest_file, mode="w") as f:
133
+ f.write(manifest_json)
134
+ with suppress(Exception):
135
+ shared_utils.make_writable(manifest_json)
136
+ proxy_host = proxy_string.split(":")[0]
137
+ proxy_port = proxy_string.split(":")[1]
138
+ background_file = os.path.join(proxy_ext_dir, "background.js")
139
+ with open(background_file, mode="w") as f:
140
+ f.write(background_js)
141
+ with suppress(Exception):
142
+ shared_utils.make_writable(background_js)
137
143
 
138
144
 
139
145
  def remove_proxy_zip_if_present():
@@ -141,13 +147,12 @@ def remove_proxy_zip_if_present():
141
147
  Used in the implementation of https://stackoverflow.com/a/35293284
142
148
  for https://stackoverflow.com/questions/12848327/
143
149
  """
144
- try:
145
- if os.path.exists(PROXY_ZIP_PATH):
150
+ if os.path.exists(PROXY_ZIP_PATH):
151
+ with suppress(Exception):
146
152
  os.remove(PROXY_ZIP_PATH)
147
- if os.path.exists(PROXY_ZIP_LOCK):
153
+ if os.path.exists(PROXY_ZIP_LOCK):
154
+ with suppress(Exception):
148
155
  os.remove(PROXY_ZIP_LOCK)
149
- except Exception:
150
- pass
151
156
 
152
157
 
153
158
  def validate_proxy_string(proxy_string):
@@ -422,9 +422,14 @@ def generate_sbase_code(srt_actions):
422
422
  ):
423
423
  import unicodedata
424
424
 
425
- action[1][0] = unicodedata.normalize("NFKC", action[1][0])
426
- action[1][0] = action[1][0].replace("\n", "\\n")
427
- action[1][0] = action[1][0].replace("\u00B6", "")
425
+ text_list = False
426
+ try:
427
+ action[1][0] = unicodedata.normalize("NFKC", action[1][0])
428
+ action[1][0] = action[1][0].replace("\n", "\\n")
429
+ action[1][0] = action[1][0].replace("\u00B6", "")
430
+ except Exception:
431
+ text_list = True
432
+
428
433
  method = "assert_text"
429
434
  if action[0] == "as_et":
430
435
  method = "assert_exact_text"
@@ -437,7 +442,17 @@ def generate_sbase_code(srt_actions):
437
442
  elif action[0] == "da_et":
438
443
  method = "deferred_assert_exact_text"
439
444
  if action[1][1] != "html":
440
- if '"' not in action[1][0] and '"' not in action[1][1]:
445
+ if text_list and '"' not in action[1][1]:
446
+ sb_actions.append(
447
+ 'self.%s(%s, "%s")'
448
+ % (method, action[1][0], action[1][1])
449
+ )
450
+ elif text_list and "'" not in action[1][1]:
451
+ sb_actions.append(
452
+ "self.%s(%s, '%s')"
453
+ % (method, action[1][0], action[1][1])
454
+ )
455
+ elif '"' not in action[1][0] and '"' not in action[1][1]:
441
456
  sb_actions.append(
442
457
  'self.%s("%s", "%s")'
443
458
  % (method, action[1][0], action[1][1])
@@ -458,7 +473,11 @@ def generate_sbase_code(srt_actions):
458
473
  % (method, action[1][0], action[1][1])
459
474
  )
460
475
  else:
461
- if '"' not in action[1][0]:
476
+ if text_list:
477
+ sb_actions.append(
478
+ 'self.%s(%s)' % (method, action[1][0])
479
+ )
480
+ elif '"' not in action[1][0]:
462
481
  sb_actions.append(
463
482
  'self.%s("%s")' % (method, action[1][0])
464
483
  )