seleniumbase 4.41.7__tar.gz → 4.41.9__tar.gz

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 (157) hide show
  1. {seleniumbase-4.41.7/seleniumbase.egg-info → seleniumbase-4.41.9}/PKG-INFO +4 -4
  2. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/README.md +2 -2
  3. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/requirements.txt +1 -1
  4. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/__version__.py +1 -1
  5. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/common/decorators.py +3 -1
  6. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/browser_launcher.py +22 -22
  7. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/sb_cdp.py +49 -43
  8. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/fixtures/page_actions.py +2 -4
  9. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/__init__.py +6 -3
  10. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/cdp_driver/config.py +25 -0
  11. {seleniumbase-4.41.7 → seleniumbase-4.41.9/seleniumbase.egg-info}/PKG-INFO +4 -4
  12. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase.egg-info/requires.txt +1 -1
  13. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/setup.py +1 -1
  14. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/.gitignore +0 -0
  15. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/LICENSE +0 -0
  16. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/MANIFEST.in +0 -0
  17. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/install.sh +0 -0
  18. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/pyproject.toml +0 -0
  19. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/pytest.ini +0 -0
  20. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/sbase/__init__.py +0 -0
  21. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/sbase/__main__.py +0 -0
  22. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/sbase/steps.py +0 -0
  23. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/__init__.py +0 -0
  24. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/__main__.py +0 -0
  25. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/behave/__init__.py +0 -0
  26. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/behave/behave_helper.py +0 -0
  27. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/behave/behave_sb.py +0 -0
  28. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/behave/steps.py +0 -0
  29. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/common/__init__.py +0 -0
  30. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/common/encryption.py +0 -0
  31. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/common/exceptions.py +0 -0
  32. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/common/obfuscate.py +0 -0
  33. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/common/unobfuscate.py +0 -0
  34. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/config/__init__.py +0 -0
  35. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/config/ad_block_list.py +0 -0
  36. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/config/proxy_list.py +0 -0
  37. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/config/settings.py +0 -0
  38. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/__init__.py +0 -0
  39. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/logo_helper.py +0 -0
  40. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/rich_helper.py +0 -0
  41. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/run.py +0 -0
  42. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/sb_behave_gui.py +0 -0
  43. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/sb_caseplans.py +0 -0
  44. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/sb_commander.py +0 -0
  45. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/sb_install.py +0 -0
  46. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/sb_mkchart.py +0 -0
  47. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/sb_mkdir.py +0 -0
  48. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/sb_mkfile.py +0 -0
  49. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/sb_mkpres.py +0 -0
  50. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/sb_mkrec.py +0 -0
  51. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/sb_objectify.py +0 -0
  52. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/sb_print.py +0 -0
  53. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/console_scripts/sb_recorder.py +0 -0
  54. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/__init__.py +0 -0
  55. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/application_manager.py +0 -0
  56. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/capabilities_parser.py +0 -0
  57. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/colored_traceback.py +0 -0
  58. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/create_db_tables.sql +0 -0
  59. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/detect_b_ver.py +0 -0
  60. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/download_helper.py +0 -0
  61. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/encoded_images.py +0 -0
  62. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/jqc_helper.py +0 -0
  63. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/log_helper.py +0 -0
  64. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/mysql.py +0 -0
  65. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/proxy_helper.py +0 -0
  66. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/recorder_helper.py +0 -0
  67. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/report_helper.py +0 -0
  68. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/s3_manager.py +0 -0
  69. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/sb_driver.py +0 -0
  70. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/session_helper.py +0 -0
  71. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/settings_parser.py +0 -0
  72. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/style_sheet.py +0 -0
  73. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/testcase_manager.py +0 -0
  74. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/tour_helper.py +0 -0
  75. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/core/visual_helper.py +0 -0
  76. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/drivers/__init__.py +0 -0
  77. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/drivers/cft_drivers/__init__.py +0 -0
  78. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/drivers/chs_drivers/__init__.py +0 -0
  79. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/extensions/__init__.py +0 -0
  80. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/extensions/ad_block.zip +0 -0
  81. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/extensions/disable_csp.zip +0 -0
  82. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/extensions/recorder.zip +0 -0
  83. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/extensions/sbase_ext.zip +0 -0
  84. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/fixtures/__init__.py +0 -0
  85. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/fixtures/base_case.py +0 -0
  86. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/fixtures/constants.py +0 -0
  87. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/fixtures/css_to_xpath.py +0 -0
  88. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/fixtures/errors.py +0 -0
  89. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/fixtures/js_utils.py +0 -0
  90. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/fixtures/page_utils.py +0 -0
  91. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/fixtures/shared_utils.py +0 -0
  92. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/fixtures/unittest_helper.py +0 -0
  93. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/fixtures/words.py +0 -0
  94. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/fixtures/xpath_to_css.py +0 -0
  95. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/js_code/__init__.py +0 -0
  96. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/js_code/active_css_js.py +0 -0
  97. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/js_code/live_js.py +0 -0
  98. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/js_code/recorder_js.py +0 -0
  99. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/masterqa/__init__.py +0 -0
  100. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/masterqa/master_qa.py +0 -0
  101. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/plugins/__init__.py +0 -0
  102. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/plugins/base_plugin.py +0 -0
  103. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/plugins/basic_test_info.py +0 -0
  104. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/plugins/db_reporting_plugin.py +0 -0
  105. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/plugins/driver_manager.py +0 -0
  106. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/plugins/page_source.py +0 -0
  107. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/plugins/pytest_plugin.py +0 -0
  108. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/plugins/s3_logging_plugin.py +0 -0
  109. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/plugins/sb_manager.py +0 -0
  110. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/plugins/screen_shots.py +0 -0
  111. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/plugins/selenium_plugin.py +0 -0
  112. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/resources/__init__.py +0 -0
  113. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/translate/__init__.py +0 -0
  114. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/translate/chinese.py +0 -0
  115. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/translate/dutch.py +0 -0
  116. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/translate/french.py +0 -0
  117. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/translate/italian.py +0 -0
  118. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/translate/japanese.py +0 -0
  119. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/translate/korean.py +0 -0
  120. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/translate/master_dict.py +0 -0
  121. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/translate/portuguese.py +0 -0
  122. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/translate/russian.py +0 -0
  123. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/translate/spanish.py +0 -0
  124. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/translate/translator.py +0 -0
  125. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/cdp.py +0 -0
  126. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/cdp_driver/__init__.py +0 -0
  127. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/cdp_driver/_contradict.py +0 -0
  128. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/cdp_driver/browser.py +0 -0
  129. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/cdp_driver/cdp_util.py +0 -0
  130. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/cdp_driver/connection.py +0 -0
  131. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/cdp_driver/element.py +0 -0
  132. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/cdp_driver/tab.py +0 -0
  133. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/dprocess.py +0 -0
  134. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/options.py +0 -0
  135. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/patcher.py +0 -0
  136. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/reactor.py +0 -0
  137. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/undetected/webelement.py +0 -0
  138. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/utilities/__init__.py +0 -0
  139. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/utilities/selenium_grid/__init__.py +0 -0
  140. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/utilities/selenium_grid/download_selenium_server.py +0 -0
  141. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/utilities/selenium_grid/font_color +0 -0
  142. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/utilities/selenium_grid/grid-hub +0 -0
  143. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/utilities/selenium_grid/grid-node +0 -0
  144. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/utilities/selenium_grid/grid_hub.py +0 -0
  145. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/utilities/selenium_grid/grid_node.py +0 -0
  146. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/utilities/selenium_grid/register-grid-node.bat +0 -0
  147. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/utilities/selenium_grid/register-grid-node.sh +0 -0
  148. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/utilities/selenium_grid/start-grid-hub.bat +0 -0
  149. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/utilities/selenium_grid/start-grid-hub.sh +0 -0
  150. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/utilities/selenium_ide/__init__.py +0 -0
  151. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase/utilities/selenium_ide/convert_ide.py +0 -0
  152. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase.egg-info/SOURCES.txt +0 -0
  153. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase.egg-info/dependency_links.txt +0 -0
  154. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase.egg-info/entry_points.txt +0 -0
  155. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/seleniumbase.egg-info/top_level.txt +0 -0
  156. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/setup.cfg +0 -0
  157. {seleniumbase-4.41.7 → seleniumbase-4.41.9}/virtualenv_install.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: seleniumbase
3
- Version: 4.41.7
3
+ Version: 4.41.9
4
4
  Summary: A complete web automation framework for end-to-end testing.
5
5
  Home-page: https://github.com/seleniumbase/SeleniumBase
6
6
  Author: Michael Mintz
@@ -143,7 +143,7 @@ Requires-Dist: allure-python-commons>=2.13.5; extra == "allure"
143
143
  Requires-Dist: allure-behave>=2.13.5; extra == "allure"
144
144
  Provides-Extra: coverage
145
145
  Requires-Dist: coverage>=7.6.1; python_version < "3.9" and extra == "coverage"
146
- Requires-Dist: coverage>=7.10.6; python_version >= "3.9" and extra == "coverage"
146
+ Requires-Dist: coverage>=7.10.7; python_version >= "3.9" and extra == "coverage"
147
147
  Requires-Dist: pytest-cov>=5.0.0; python_version < "3.9" and extra == "coverage"
148
148
  Requires-Dist: pytest-cov>=7.0.0; python_version >= "3.9" and extra == "coverage"
149
149
  Provides-Extra: flake8
@@ -275,7 +275,7 @@ Dynamic: summary
275
275
 
276
276
  --------
277
277
 
278
- <p align="left">📗 For performing a Google Search without hitting the "unusual traffic" page, you can use SeleniumBase UC Mode. Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py">SeleniumBase/examples/raw_google.py</a>, which exports the search results into different formats (PDF, HTML, PNG):</p>
278
+ <p align="left">📗 For performing a Google Search without hitting the "unusual traffic" page, you can use SeleniumBase UC Mode.<br />Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py">SeleniumBase/examples/raw_google.py</a>, which exports results into different formats (PDF, HTML, PNG):</p>
279
279
 
280
280
  ```python
281
281
  from seleniumbase import SB
@@ -295,7 +295,7 @@ with SB(test=True, uc=True) as sb:
295
295
 
296
296
  > `python raw_google.py`
297
297
 
298
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py"><img src="https://seleniumbase.github.io/cdn/img/google_sb_result.png" alt="SeleniumBase on Google" title="SeleniumBase on Google" width="440" /></a>
298
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py"><img src="https://seleniumbase.github.io/cdn/img/google_sb_result.png" alt="SeleniumBase on Google" title="SeleniumBase on Google" width="480" /></a>
299
299
 
300
300
  --------
301
301
 
@@ -65,7 +65,7 @@
65
65
 
66
66
  --------
67
67
 
68
- <p align="left">📗 For performing a Google Search without hitting the "unusual traffic" page, you can use SeleniumBase UC Mode. Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py">SeleniumBase/examples/raw_google.py</a>, which exports the search results into different formats (PDF, HTML, PNG):</p>
68
+ <p align="left">📗 For performing a Google Search without hitting the "unusual traffic" page, you can use SeleniumBase UC Mode.<br />Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py">SeleniumBase/examples/raw_google.py</a>, which exports results into different formats (PDF, HTML, PNG):</p>
69
69
 
70
70
  ```python
71
71
  from seleniumbase import SB
@@ -85,7 +85,7 @@ with SB(test=True, uc=True) as sb:
85
85
 
86
86
  > `python raw_google.py`
87
87
 
88
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py"><img src="https://seleniumbase.github.io/cdn/img/google_sb_result.png" alt="SeleniumBase on Google" title="SeleniumBase on Google" width="440" /></a>
88
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py"><img src="https://seleniumbase.github.io/cdn/img/google_sb_result.png" alt="SeleniumBase on Google" title="SeleniumBase on Google" width="480" /></a>
89
89
 
90
90
  --------
91
91
 
@@ -80,7 +80,7 @@ rich>=14.1.0,<15
80
80
  # ("pip install -r requirements.txt" also installs this, but "pip install -e ." won't.)
81
81
 
82
82
  coverage>=7.6.1;python_version<"3.9"
83
- coverage>=7.10.6;python_version>="3.9"
83
+ coverage>=7.10.7;python_version>="3.9"
84
84
  pytest-cov>=5.0.0;python_version<"3.9"
85
85
  pytest-cov>=7.0.0;python_version>="3.9"
86
86
  flake8==5.0.4;python_version<"3.9"
@@ -1,2 +1,2 @@
1
1
  # seleniumbase package
2
- __version__ = "4.41.7"
2
+ __version__ = "4.41.9"
@@ -53,7 +53,9 @@ def print_runtime(description=None, limit=None):
53
53
  name = description
54
54
  info = c1 + "<info>" + cr
55
55
  # Print times with a statistically significant number of decimal places
56
- if run_time < 0.0001:
56
+ if run_time < 0.00001:
57
+ print("%s - {%s} ran for %.8f seconds." % (info, name, run_time))
58
+ elif run_time < 0.0001:
57
59
  print("%s - {%s} ran for %.7f seconds." % (info, name, run_time))
58
60
  elif run_time < 0.001:
59
61
  print("%s - {%s} ran for %.6f seconds." % (info, name, run_time))
@@ -12,6 +12,7 @@ import types
12
12
  import urllib3
13
13
  import warnings
14
14
  from contextlib import suppress
15
+ from filelock import FileLock
15
16
  from selenium import webdriver
16
17
  from selenium.common.exceptions import ElementClickInterceptedException
17
18
  from selenium.common.exceptions import InvalidSessionIdException
@@ -429,6 +430,12 @@ def __is_cdp_swap_needed(driver):
429
430
  return shared_utils.is_cdp_swap_needed(driver)
430
431
 
431
432
 
433
+ def uc_execute_cdp_cmd(driver, *args, **kwargs):
434
+ if not driver.is_connected():
435
+ driver.connect()
436
+ return driver.default_execute_cdp_cmd(*args, **kwargs)
437
+
438
+
432
439
  def uc_special_open_if_cf(
433
440
  driver,
434
441
  url,
@@ -641,7 +648,7 @@ def uc_open_with_cdp_mode(driver, url=None, **kwargs):
641
648
  )
642
649
  loop.run_until_complete(driver.cdp_base.wait(0))
643
650
 
644
- gui_lock = fasteners.InterProcessLock(constants.MultiBrowser.PYAUTOGUILOCK)
651
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
645
652
 
646
653
  if (
647
654
  "chrome-extension://" in str(driver.cdp_base.main_tab)
@@ -1080,9 +1087,7 @@ def uc_gui_press_key(driver, key):
1080
1087
  install_pyautogui_if_missing(driver)
1081
1088
  import pyautogui
1082
1089
  pyautogui = get_configured_pyautogui(pyautogui)
1083
- gui_lock = fasteners.InterProcessLock(
1084
- constants.MultiBrowser.PYAUTOGUILOCK
1085
- )
1090
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1086
1091
  with gui_lock:
1087
1092
  pyautogui.press(key)
1088
1093
 
@@ -1091,9 +1096,7 @@ def uc_gui_press_keys(driver, keys):
1091
1096
  install_pyautogui_if_missing(driver)
1092
1097
  import pyautogui
1093
1098
  pyautogui = get_configured_pyautogui(pyautogui)
1094
- gui_lock = fasteners.InterProcessLock(
1095
- constants.MultiBrowser.PYAUTOGUILOCK
1096
- )
1099
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1097
1100
  with gui_lock:
1098
1101
  for key in keys:
1099
1102
  pyautogui.press(key)
@@ -1103,9 +1106,7 @@ def uc_gui_write(driver, text):
1103
1106
  install_pyautogui_if_missing(driver)
1104
1107
  import pyautogui
1105
1108
  pyautogui = get_configured_pyautogui(pyautogui)
1106
- gui_lock = fasteners.InterProcessLock(
1107
- constants.MultiBrowser.PYAUTOGUILOCK
1108
- )
1109
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1109
1110
  with gui_lock:
1110
1111
  pyautogui.write(text)
1111
1112
 
@@ -1138,9 +1139,7 @@ def _uc_gui_click_x_y(driver, x, y, timeframe=0.25, uc_lock=False):
1138
1139
  % (x, y, screen_width, screen_height)
1139
1140
  )
1140
1141
  if uc_lock:
1141
- gui_lock = fasteners.InterProcessLock(
1142
- constants.MultiBrowser.PYAUTOGUILOCK
1143
- )
1142
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1144
1143
  with gui_lock: # Prevent issues with multiple processes
1145
1144
  pyautogui.moveTo(x, y, timeframe, pyautogui.easeOutQuad)
1146
1145
  if timeframe >= 0.25:
@@ -1159,9 +1158,7 @@ def _uc_gui_click_x_y(driver, x, y, timeframe=0.25, uc_lock=False):
1159
1158
 
1160
1159
 
1161
1160
  def uc_gui_click_x_y(driver, x, y, timeframe=0.25):
1162
- gui_lock = fasteners.InterProcessLock(
1163
- constants.MultiBrowser.PYAUTOGUILOCK
1164
- )
1161
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1165
1162
  with gui_lock: # Prevent issues with multiple processes
1166
1163
  install_pyautogui_if_missing(driver)
1167
1164
  import pyautogui
@@ -1227,6 +1224,7 @@ def _on_a_cf_turnstile_page(driver):
1227
1224
  'data-callback="onCaptchaSuccess"' in source
1228
1225
  or "/challenge-platform/scripts/" in source
1229
1226
  or 'id="challenge-widget-' in source
1227
+ or "challenges.cloudf" in source
1230
1228
  or "cf-turnstile-" in source
1231
1229
  ):
1232
1230
  return True
@@ -1279,9 +1277,7 @@ def _uc_gui_click_captcha(
1279
1277
  x = None
1280
1278
  y = None
1281
1279
  visible_iframe = True
1282
- gui_lock = fasteners.InterProcessLock(
1283
- constants.MultiBrowser.PYAUTOGUILOCK
1284
- )
1280
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1285
1281
  with gui_lock: # Prevent issues with multiple processes
1286
1282
  needs_switch = False
1287
1283
  width_ratio = 1.0
@@ -1642,9 +1638,7 @@ def _uc_gui_handle_captcha_(driver, frame="iframe", ctype=None):
1642
1638
  import pyautogui
1643
1639
  pyautogui = get_configured_pyautogui(pyautogui)
1644
1640
  visible_iframe = True
1645
- gui_lock = fasteners.InterProcessLock(
1646
- constants.MultiBrowser.PYAUTOGUILOCK
1647
- )
1641
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1648
1642
  with gui_lock: # Prevent issues with multiple processes
1649
1643
  needs_switch = False
1650
1644
  if not __is_cdp_swap_needed(driver):
@@ -5690,6 +5684,12 @@ def get_local_driver(
5690
5684
  driver, *args, **kwargs
5691
5685
  )
5692
5686
  )
5687
+ driver.default_execute_cdp_cmd = driver.execute_cdp_cmd
5688
+ driver.execute_cdp_cmd = (
5689
+ lambda *args, **kwargs: uc_execute_cdp_cmd(
5690
+ driver, *args, **kwargs
5691
+ )
5692
+ )
5693
5693
  driver._is_hidden = (headless or headless2)
5694
5694
  driver._is_using_uc = True
5695
5695
  with suppress(Exception):
@@ -6,6 +6,7 @@ import re
6
6
  import sys
7
7
  import time
8
8
  from contextlib import suppress
9
+ from filelock import FileLock
9
10
  from seleniumbase import config as sb_config
10
11
  from seleniumbase.config import settings
11
12
  from seleniumbase.fixtures import constants
@@ -1065,24 +1066,42 @@ class CDPMethods():
1065
1066
  time.sleep(0.044)
1066
1067
  return self.loop.run_until_complete(self.page.medimize())
1067
1068
 
1068
- def set_window_rect(self, x, y, width, height):
1069
- if self.get_window()[1].window_state.value == "minimized":
1070
- self.loop.run_until_complete(
1069
+ def __set_window_rect(self, x, y, width, height, uc_lock=False):
1070
+ if uc_lock:
1071
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1072
+ with gui_lock:
1073
+ self.__make_sure_pyautogui_lock_is_writable()
1074
+ if self.get_window()[1].window_state.value == "minimized":
1075
+ self.loop.run_until_complete(
1076
+ self.page.set_window_size(
1077
+ left=x, top=y, width=width, height=height)
1078
+ )
1079
+ time.sleep(0.044)
1080
+ return self.loop.run_until_complete(
1081
+ self.page.set_window_size(
1082
+ left=x, top=y, width=width, height=height)
1083
+ )
1084
+ else:
1085
+ if self.get_window()[1].window_state.value == "minimized":
1086
+ self.loop.run_until_complete(
1087
+ self.page.set_window_size(
1088
+ left=x, top=y, width=width, height=height)
1089
+ )
1090
+ time.sleep(0.044)
1091
+ return self.loop.run_until_complete(
1071
1092
  self.page.set_window_size(
1072
1093
  left=x, top=y, width=width, height=height)
1073
1094
  )
1074
- time.sleep(0.044)
1075
- return self.loop.run_until_complete(
1076
- self.page.set_window_size(
1077
- left=x, top=y, width=width, height=height)
1078
- )
1095
+
1096
+ def set_window_rect(self, x, y, width, height):
1097
+ return self.__set_window_rect(x, y, width, height, uc_lock=True)
1079
1098
 
1080
1099
  def reset_window_size(self):
1081
1100
  x = settings.WINDOW_START_X
1082
1101
  y = settings.WINDOW_START_Y
1083
1102
  width = settings.CHROME_START_WIDTH
1084
1103
  height = settings.CHROME_START_HEIGHT
1085
- self.set_window_rect(x, y, width, height)
1104
+ self.__set_window_rect(x, y, width, height, uc_lock=True)
1086
1105
  self.__add_light_pause()
1087
1106
 
1088
1107
  def open_new_window(self, url=None, switch_to=True):
@@ -1548,9 +1567,7 @@ class CDPMethods():
1548
1567
  self.__install_pyautogui_if_missing()
1549
1568
  import pyautogui
1550
1569
  pyautogui = self.__get_configured_pyautogui(pyautogui)
1551
- gui_lock = fasteners.InterProcessLock(
1552
- constants.MultiBrowser.PYAUTOGUILOCK
1553
- )
1570
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1554
1571
  with gui_lock:
1555
1572
  self.__make_sure_pyautogui_lock_is_writable()
1556
1573
  pyautogui.press(key)
@@ -1562,9 +1579,7 @@ class CDPMethods():
1562
1579
  self.__install_pyautogui_if_missing()
1563
1580
  import pyautogui
1564
1581
  pyautogui = self.__get_configured_pyautogui(pyautogui)
1565
- gui_lock = fasteners.InterProcessLock(
1566
- constants.MultiBrowser.PYAUTOGUILOCK
1567
- )
1582
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1568
1583
  with gui_lock:
1569
1584
  self.__make_sure_pyautogui_lock_is_writable()
1570
1585
  for key in keys:
@@ -1577,9 +1592,7 @@ class CDPMethods():
1577
1592
  self.__install_pyautogui_if_missing()
1578
1593
  import pyautogui
1579
1594
  pyautogui = self.__get_configured_pyautogui(pyautogui)
1580
- gui_lock = fasteners.InterProcessLock(
1581
- constants.MultiBrowser.PYAUTOGUILOCK
1582
- )
1595
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1583
1596
  with gui_lock:
1584
1597
  self.__make_sure_pyautogui_lock_is_writable()
1585
1598
  pyautogui.write(text)
@@ -1598,9 +1611,7 @@ class CDPMethods():
1598
1611
  % (x, y, screen_width, screen_height)
1599
1612
  )
1600
1613
  if uc_lock:
1601
- gui_lock = fasteners.InterProcessLock(
1602
- constants.MultiBrowser.PYAUTOGUILOCK
1603
- )
1614
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1604
1615
  with gui_lock: # Prevent issues with multiple processes
1605
1616
  self.__make_sure_pyautogui_lock_is_writable()
1606
1617
  pyautogui.moveTo(x, y, timeframe, pyautogui.easeOutQuad)
@@ -1619,9 +1630,7 @@ class CDPMethods():
1619
1630
  pyautogui.click(x=x, y=y)
1620
1631
 
1621
1632
  def gui_click_x_y(self, x, y, timeframe=0.25):
1622
- gui_lock = fasteners.InterProcessLock(
1623
- constants.MultiBrowser.PYAUTOGUILOCK
1624
- )
1633
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1625
1634
  with gui_lock: # Prevent issues with multiple processes
1626
1635
  self.__make_sure_pyautogui_lock_is_writable()
1627
1636
  self.__install_pyautogui_if_missing()
@@ -1645,7 +1654,7 @@ class CDPMethods():
1645
1654
  sb_config._saved_width_ratio = width_ratio
1646
1655
  self.minimize()
1647
1656
  self.__add_light_pause()
1648
- self.set_window_rect(win_x, win_y, width, height)
1657
+ self.__set_window_rect(win_x, win_y, width, height)
1649
1658
  self.__add_light_pause()
1650
1659
  x = x * width_ratio
1651
1660
  y = y * width_ratio
@@ -1661,11 +1670,16 @@ class CDPMethods():
1661
1670
  self.loop.run_until_complete(self.page.wait())
1662
1671
 
1663
1672
  def _on_a_cf_turnstile_page(self):
1673
+ time.sleep(0.042)
1664
1674
  source = self.get_page_source()
1675
+ if not source or len(source) < 400:
1676
+ time.sleep(0.22)
1677
+ source = self.get_page_source()
1665
1678
  if (
1666
1679
  'data-callback="onCaptchaSuccess"' in source
1667
1680
  or "/challenge-platform/scripts/" in source
1668
1681
  or 'id="challenge-widget-' in source
1682
+ or "challenges.cloudf" in source
1669
1683
  or "cf-turnstile-" in source
1670
1684
  ):
1671
1685
  return True
@@ -1795,6 +1809,7 @@ class CDPMethods():
1795
1809
  self.loop.run_until_complete(self.page.evaluate(script))
1796
1810
  self.loop.run_until_complete(self.page.wait())
1797
1811
  with suppress(Exception):
1812
+ time.sleep(0.08)
1798
1813
  element_rect = self.get_gui_element_rect(selector, timeout=1)
1799
1814
  e_x = element_rect["x"]
1800
1815
  e_y = element_rect["y"]
@@ -1804,6 +1819,7 @@ class CDPMethods():
1804
1819
  else:
1805
1820
  y = e_y + 22
1806
1821
  sb_config._saved_cf_x_y = (x, y)
1822
+ time.sleep(0.08)
1807
1823
  self.gui_click_x_y(x, y)
1808
1824
 
1809
1825
  def __gui_drag_drop(self, x1, y1, x2, y2, timeframe=0.25, uc_lock=False):
@@ -1824,9 +1840,7 @@ class CDPMethods():
1824
1840
  % (x2, y2, screen_width, screen_height)
1825
1841
  )
1826
1842
  if uc_lock:
1827
- gui_lock = fasteners.InterProcessLock(
1828
- constants.MultiBrowser.PYAUTOGUILOCK
1829
- )
1843
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1830
1844
  with gui_lock: # Prevent issues with multiple processes
1831
1845
  pyautogui.moveTo(x1, y1, 0.25, pyautogui.easeOutQuad)
1832
1846
  self.__add_light_pause()
@@ -1844,9 +1858,7 @@ class CDPMethods():
1844
1858
  def gui_drag_drop_points(self, x1, y1, x2, y2, timeframe=0.35):
1845
1859
  """Use PyAutoGUI to drag-and-drop from one point to another.
1846
1860
  Can simulate click-and-hold when using the same point twice."""
1847
- gui_lock = fasteners.InterProcessLock(
1848
- constants.MultiBrowser.PYAUTOGUILOCK
1849
- )
1861
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1850
1862
  with gui_lock: # Prevent issues with multiple processes
1851
1863
  self.__install_pyautogui_if_missing()
1852
1864
  import pyautogui
@@ -1869,7 +1881,7 @@ class CDPMethods():
1869
1881
  sb_config._saved_width_ratio = width_ratio
1870
1882
  self.minimize()
1871
1883
  self.__add_light_pause()
1872
- self.set_window_rect(win_x, win_y, width, height)
1884
+ self.__set_window_rect(win_x, win_y, width, height)
1873
1885
  self.__add_light_pause()
1874
1886
  x1 = x1 * width_ratio
1875
1887
  y1 = y1 * (width_ratio - 0.02)
@@ -1913,9 +1925,7 @@ class CDPMethods():
1913
1925
  % (x, y, screen_width, screen_height)
1914
1926
  )
1915
1927
  if uc_lock:
1916
- gui_lock = fasteners.InterProcessLock(
1917
- constants.MultiBrowser.PYAUTOGUILOCK
1918
- )
1928
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1919
1929
  with gui_lock: # Prevent issues with multiple processes
1920
1930
  pyautogui.moveTo(x, y, timeframe, pyautogui.easeOutQuad)
1921
1931
  time.sleep(0.056)
@@ -1929,9 +1939,7 @@ class CDPMethods():
1929
1939
  print(" <DEBUG> pyautogui.moveTo(%s, %s)" % (x, y))
1930
1940
 
1931
1941
  def gui_hover_x_y(self, x, y, timeframe=0.25):
1932
- gui_lock = fasteners.InterProcessLock(
1933
- constants.MultiBrowser.PYAUTOGUILOCK
1934
- )
1942
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1935
1943
  with gui_lock: # Prevent issues with multiple processes
1936
1944
  self.__install_pyautogui_if_missing()
1937
1945
  import pyautogui
@@ -1964,7 +1972,7 @@ class CDPMethods():
1964
1972
  if width_ratio < 0.45 or width_ratio > 2.55:
1965
1973
  width_ratio = 1.01
1966
1974
  sb_config._saved_width_ratio = width_ratio
1967
- self.set_window_rect(win_x, win_y, width, height)
1975
+ self.__set_window_rect(win_x, win_y, width, height)
1968
1976
  self.__add_light_pause()
1969
1977
  self.bring_active_window_to_front()
1970
1978
  elif (
@@ -1995,9 +2003,7 @@ class CDPMethods():
1995
2003
  self.loop.run_until_complete(self.page.wait())
1996
2004
 
1997
2005
  def gui_hover_and_click(self, hover_selector, click_selector):
1998
- gui_lock = fasteners.InterProcessLock(
1999
- constants.MultiBrowser.PYAUTOGUILOCK
2000
- )
2006
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
2001
2007
  with gui_lock:
2002
2008
  self.__make_sure_pyautogui_lock_is_writable()
2003
2009
  self.bring_active_window_to_front()
@@ -2579,7 +2585,7 @@ class Chrome(CDPMethods):
2579
2585
  def __init__(self, url=None, **kwargs):
2580
2586
  if not url:
2581
2587
  url = "about:blank"
2582
- loop = asyncio.new_event_loop()
2583
2588
  driver = cdp_util.start_sync(**kwargs)
2589
+ loop = asyncio.new_event_loop()
2584
2590
  page = loop.run_until_complete(driver.get(url))
2585
2591
  super().__init__(loop, page, driver)
@@ -18,10 +18,10 @@ By.TAG_NAME # "tag name"
18
18
  By.PARTIAL_LINK_TEXT # "partial link text"
19
19
  """
20
20
  import codecs
21
- import fasteners
22
21
  import os
23
22
  import time
24
23
  from contextlib import suppress
24
+ from filelock import FileLock
25
25
  from selenium.common.exceptions import ElementNotInteractableException
26
26
  from selenium.common.exceptions import ElementNotVisibleException
27
27
  from selenium.common.exceptions import NoAlertPresentException
@@ -1632,9 +1632,7 @@ def __switch_to_window(driver, window_handle, uc_lock=True):
1632
1632
  and driver._is_using_uc
1633
1633
  and uc_lock
1634
1634
  ):
1635
- gui_lock = fasteners.InterProcessLock(
1636
- constants.MultiBrowser.PYAUTOGUILOCK
1637
- )
1635
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
1638
1636
  with gui_lock:
1639
1637
  driver.switch_to.window(window_handle)
1640
1638
  else:
@@ -5,6 +5,7 @@ import requests
5
5
  import subprocess
6
6
  import sys
7
7
  import time
8
+ from filelock import FileLock
8
9
  import selenium.webdriver.chrome.service
9
10
  import selenium.webdriver.chrome.webdriver
10
11
  import selenium.webdriver.common.service
@@ -117,6 +118,7 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
117
118
  self.patcher = None
118
119
  import fasteners
119
120
  from seleniumbase.fixtures import constants
121
+ from seleniumbase.fixtures import shared_utils
120
122
  if patch_driver:
121
123
  uc_lock = fasteners.InterProcessLock(
122
124
  constants.MultiBrowser.DRIVER_FIXING_LOCK
@@ -284,10 +286,11 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
284
286
  options.binary_location, *options.arguments
285
287
  )
286
288
  else:
287
- gui_lock = fasteners.InterProcessLock(
288
- constants.MultiBrowser.PYAUTOGUILOCK
289
- )
289
+ gui_lock = FileLock(constants.MultiBrowser.PYAUTOGUILOCK)
290
290
  with gui_lock:
291
+ shared_utils.make_writable(
292
+ constants.MultiBrowser.PYAUTOGUILOCK
293
+ )
291
294
  browser = subprocess.Popen(
292
295
  [options.binary_location, *options.arguments],
293
296
  stdin=subprocess.PIPE,
@@ -5,6 +5,7 @@ import secrets
5
5
  import sys
6
6
  import tempfile
7
7
  import zipfile
8
+ from contextlib import suppress
8
9
  from seleniumbase.config import settings
9
10
  from typing import Union, List, Optional
10
11
 
@@ -82,6 +83,14 @@ class Config:
82
83
  self._custom_data_dir = False
83
84
  else:
84
85
  self.user_data_dir = user_data_dir
86
+ profile = os.path.join(self.user_data_dir, "Default")
87
+ preferences_file = os.path.join(profile, "Preferences")
88
+ preferences = get_default_preferences()
89
+ if not os.path.exists(profile):
90
+ with suppress(Exception):
91
+ os.makedirs(profile)
92
+ with open(preferences_file, "w") as f:
93
+ f.write(preferences)
85
94
  if not browser_executable_path:
86
95
  browser_executable_path = find_chrome_executable()
87
96
  self._browser_args = browser_args
@@ -270,9 +279,25 @@ def is_root():
270
279
  return ctypes.windll.shell32.IsUserAnAdmin() != 0
271
280
 
272
281
 
282
+ def get_default_preferences():
283
+ return (
284
+ """{"credentials_enable_service": false,
285
+ "password_manager_enabled": false,
286
+ "password_manager_leak_detection": false}"""
287
+ )
288
+
289
+
273
290
  def temp_profile_dir():
274
291
  """Generate a temp dir (path)"""
275
292
  path = os.path.normpath(tempfile.mkdtemp(prefix="uc_"))
293
+ profile = os.path.join(path, "Default")
294
+ preferences_file = os.path.join(profile, "Preferences")
295
+ preferences = get_default_preferences()
296
+ if not os.path.exists(profile):
297
+ with suppress(Exception):
298
+ os.makedirs(profile)
299
+ with open(preferences_file, "w") as f:
300
+ f.write(preferences)
276
301
  return path
277
302
 
278
303
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: seleniumbase
3
- Version: 4.41.7
3
+ Version: 4.41.9
4
4
  Summary: A complete web automation framework for end-to-end testing.
5
5
  Home-page: https://github.com/seleniumbase/SeleniumBase
6
6
  Author: Michael Mintz
@@ -143,7 +143,7 @@ Requires-Dist: allure-python-commons>=2.13.5; extra == "allure"
143
143
  Requires-Dist: allure-behave>=2.13.5; extra == "allure"
144
144
  Provides-Extra: coverage
145
145
  Requires-Dist: coverage>=7.6.1; python_version < "3.9" and extra == "coverage"
146
- Requires-Dist: coverage>=7.10.6; python_version >= "3.9" and extra == "coverage"
146
+ Requires-Dist: coverage>=7.10.7; python_version >= "3.9" and extra == "coverage"
147
147
  Requires-Dist: pytest-cov>=5.0.0; python_version < "3.9" and extra == "coverage"
148
148
  Requires-Dist: pytest-cov>=7.0.0; python_version >= "3.9" and extra == "coverage"
149
149
  Provides-Extra: flake8
@@ -275,7 +275,7 @@ Dynamic: summary
275
275
 
276
276
  --------
277
277
 
278
- <p align="left">📗 For performing a Google Search without hitting the "unusual traffic" page, you can use SeleniumBase UC Mode. Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py">SeleniumBase/examples/raw_google.py</a>, which exports the search results into different formats (PDF, HTML, PNG):</p>
278
+ <p align="left">📗 For performing a Google Search without hitting the "unusual traffic" page, you can use SeleniumBase UC Mode.<br />Here's <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py">SeleniumBase/examples/raw_google.py</a>, which exports results into different formats (PDF, HTML, PNG):</p>
279
279
 
280
280
  ```python
281
281
  from seleniumbase import SB
@@ -295,7 +295,7 @@ with SB(test=True, uc=True) as sb:
295
295
 
296
296
  > `python raw_google.py`
297
297
 
298
- <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py"><img src="https://seleniumbase.github.io/cdn/img/google_sb_result.png" alt="SeleniumBase on Google" title="SeleniumBase on Google" width="440" /></a>
298
+ <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_google.py"><img src="https://seleniumbase.github.io/cdn/img/google_sb_result.png" alt="SeleniumBase on Google" title="SeleniumBase on Google" width="480" /></a>
299
299
 
300
300
  --------
301
301
 
@@ -102,7 +102,7 @@ coverage>=7.6.1
102
102
  pytest-cov>=5.0.0
103
103
 
104
104
  [coverage:python_version >= "3.9"]
105
- coverage>=7.10.6
105
+ coverage>=7.10.7
106
106
  pytest-cov>=7.0.0
107
107
 
108
108
  [flake8]
@@ -237,7 +237,7 @@ setup(
237
237
  # Usage: coverage run -m pytest; coverage html; coverage report
238
238
  "coverage": [
239
239
  'coverage>=7.6.1;python_version<"3.9"',
240
- 'coverage>=7.10.6;python_version>="3.9"',
240
+ 'coverage>=7.10.7;python_version>="3.9"',
241
241
  'pytest-cov>=5.0.0;python_version<"3.9"',
242
242
  'pytest-cov>=7.0.0;python_version>="3.9"',
243
243
  ],
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes