seleniumbase 4.43.1__py3-none-any.whl → 4.43.3__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 seleniumbase might be problematic. Click here for more details.

Files changed (42) hide show
  1. seleniumbase/__version__.py +1 -1
  2. seleniumbase/behave/behave_sb.py +7 -7
  3. seleniumbase/console_scripts/sb_caseplans.py +3 -3
  4. seleniumbase/console_scripts/sb_mkchart.py +1 -1
  5. seleniumbase/console_scripts/sb_mkdir.py +21 -21
  6. seleniumbase/console_scripts/sb_mkfile.py +1 -1
  7. seleniumbase/console_scripts/sb_mkpres.py +1 -1
  8. seleniumbase/console_scripts/sb_mkrec.py +1 -1
  9. seleniumbase/console_scripts/sb_objectify.py +4 -4
  10. seleniumbase/console_scripts/sb_print.py +1 -1
  11. seleniumbase/core/browser_launcher.py +82 -5
  12. seleniumbase/core/detect_b_ver.py +214 -8
  13. seleniumbase/core/log_helper.py +4 -4
  14. seleniumbase/core/report_helper.py +6 -4
  15. seleniumbase/core/sb_cdp.py +52 -6
  16. seleniumbase/core/tour_helper.py +1 -1
  17. seleniumbase/drivers/atlas_drivers/__init__.py +0 -0
  18. seleniumbase/drivers/brave_drivers/__init__.py +0 -0
  19. seleniumbase/drivers/comet_drivers/__init__.py +0 -0
  20. seleniumbase/drivers/opera_drivers/__init__.py +0 -0
  21. seleniumbase/fixtures/constants.py +29 -0
  22. seleniumbase/fixtures/js_utils.py +14 -2
  23. seleniumbase/fixtures/page_utils.py +13 -7
  24. seleniumbase/plugins/basic_test_info.py +2 -2
  25. seleniumbase/plugins/driver_manager.py +114 -0
  26. seleniumbase/plugins/page_source.py +2 -2
  27. seleniumbase/plugins/pytest_plugin.py +148 -21
  28. seleniumbase/plugins/sb_manager.py +118 -1
  29. seleniumbase/plugins/selenium_plugin.py +123 -0
  30. seleniumbase/translate/translator.py +2 -2
  31. seleniumbase/undetected/cdp_driver/cdp_util.py +56 -38
  32. seleniumbase/undetected/cdp_driver/connection.py +1 -0
  33. seleniumbase/utilities/selenium_grid/download_selenium_server.py +1 -1
  34. seleniumbase/utilities/selenium_grid/grid_hub.py +1 -1
  35. seleniumbase/utilities/selenium_grid/grid_node.py +2 -2
  36. seleniumbase/utilities/selenium_ide/convert_ide.py +2 -2
  37. {seleniumbase-4.43.1.dist-info → seleniumbase-4.43.3.dist-info}/METADATA +6 -2
  38. {seleniumbase-4.43.1.dist-info → seleniumbase-4.43.3.dist-info}/RECORD +42 -38
  39. {seleniumbase-4.43.1.dist-info → seleniumbase-4.43.3.dist-info}/WHEEL +0 -0
  40. {seleniumbase-4.43.1.dist-info → seleniumbase-4.43.3.dist-info}/entry_points.txt +0 -0
  41. {seleniumbase-4.43.1.dist-info → seleniumbase-4.43.3.dist-info}/licenses/LICENSE +0 -0
  42. {seleniumbase-4.43.1.dist-info → seleniumbase-4.43.3.dist-info}/top_level.txt +0 -0
@@ -1,2 +1,2 @@
1
1
  # seleniumbase package
2
- __version__ = "4.43.1"
2
+ __version__ = "4.43.3"
@@ -1216,24 +1216,24 @@ def _create_dashboard_assets_():
1216
1216
  add_pytest_style_css = True
1217
1217
  if os.path.exists(pytest_style_css):
1218
1218
  existing_pytest_style = None
1219
- with open(pytest_style_css, "r") as f:
1219
+ with open(pytest_style_css, mode="r") as f:
1220
1220
  existing_pytest_style = f.read()
1221
1221
  if existing_pytest_style == get_pytest_style():
1222
1222
  add_pytest_style_css = False
1223
1223
  if add_pytest_style_css:
1224
- out_file = open(pytest_style_css, "w+", encoding="utf-8")
1224
+ out_file = open(pytest_style_css, mode="w+", encoding="utf-8")
1225
1225
  out_file.writelines(get_pytest_style())
1226
1226
  out_file.close()
1227
1227
  live_js_file = os.path.join(assets_folder, "live.js")
1228
1228
  add_live_js_file = True
1229
1229
  if os.path.exists(live_js_file):
1230
1230
  existing_live_js = None
1231
- with open(live_js_file, "r") as f:
1231
+ with open(live_js_file, mode="r") as f:
1232
1232
  existing_live_js = f.read()
1233
1233
  if existing_live_js == live_js:
1234
1234
  add_live_js_file = False
1235
1235
  if add_live_js_file:
1236
- out_file = open(live_js_file, "w+", encoding="utf-8")
1236
+ out_file = open(live_js_file, mode="w+", encoding="utf-8")
1237
1237
  out_file.writelines(live_js)
1238
1238
  out_file.close()
1239
1239
 
@@ -1306,7 +1306,7 @@ def _perform_behave_unconfigure_():
1306
1306
  # Part 1: Finalizing the dashboard / integrating html report
1307
1307
  if os.path.exists(dashboard_path):
1308
1308
  the_html_d = None
1309
- with open(dashboard_path, "r", encoding="utf-8") as f:
1309
+ with open(dashboard_path, mode="r", encoding="utf-8") as f:
1310
1310
  the_html_d = f.read()
1311
1311
  if sb_config._multithreaded and "-c" in sys.argv:
1312
1312
  # Threads have "-c" in sys.argv, except for the last
@@ -1317,7 +1317,7 @@ def _perform_behave_unconfigure_():
1317
1317
  if os.path.exists(pie_path):
1318
1318
  import json
1319
1319
 
1320
- with open(pie_path, "r") as f:
1320
+ with open(pie_path, mode="r") as f:
1321
1321
  dash_pie = f.read().strip()
1322
1322
  sb_config._saved_dashboard_pie = json.loads(dash_pie)
1323
1323
  # If the test run doesn't complete by itself, stop refresh
@@ -1326,7 +1326,7 @@ def _perform_behave_unconfigure_():
1326
1326
  the_html_d = the_html_d.replace(find_it_3, swap_with_3)
1327
1327
  the_html_d = the_html_d.replace(find_it_4, swap_with_4)
1328
1328
  the_html_d += stamp
1329
- with open(dashboard_path, "w", encoding="utf-8") as f:
1329
+ with open(dashboard_path, mode="w", encoding="utf-8") as f:
1330
1330
  f.write(the_html_d) # Finalize the dashboard
1331
1331
  except KeyboardInterrupt:
1332
1332
  pass
@@ -134,7 +134,7 @@ def generate_case_plan_boilerplates(
134
134
  file_name = case_id
135
135
  file_path = os.path.join(full_folder_path, file_name)
136
136
  if not os.path.exists(file_path):
137
- out_file = open(file_path, "w+", "utf-8")
137
+ out_file = open(file_path, mode="w+", encoding="utf-8")
138
138
  out_file.writelines("\r\n".join(data))
139
139
  out_file.close()
140
140
  new_plans += 1
@@ -182,7 +182,7 @@ def view_summary_of_existing_case_plans(root, tests):
182
182
  else:
183
183
  case_path = os.path.join(folder_path, "case_plans", case_id)
184
184
  if os.path.exists(case_path):
185
- f = open(case_path, "r")
185
+ f = open(case_path, mode="r")
186
186
  case_data = f.read()
187
187
  f.close()
188
188
  case_data_storage.append(case_data)
@@ -315,7 +315,7 @@ def view_summary_of_existing_case_plans(root, tests):
315
315
  full_plan = plan_head
316
316
 
317
317
  file_path = "case_summary.md"
318
- file = open(file_path, "w+", "utf-8")
318
+ file = open(file_path, mode="w+", encoding="utf-8")
319
319
  file.writelines("\r\n".join(full_plan))
320
320
  file.close()
321
321
 
@@ -253,7 +253,7 @@ def main():
253
253
  continue
254
254
  new_data.append(line)
255
255
  data = new_data
256
- file = open(file_path, "w+", "utf-8")
256
+ file = open(file_path, mode="w+", encoding="utf-8")
257
257
  file.writelines("\r\n".join(data))
258
258
  file.close()
259
259
  if " " not in file_name:
@@ -113,7 +113,7 @@ def main():
113
113
  data.append(seleniumbase_req)
114
114
  data.append("")
115
115
  file_path = "%s/%s" % (dir_name, "requirements.txt")
116
- file = open(file_path, "w+", "utf-8")
116
+ file = open(file_path, mode="w+", encoding="utf-8")
117
117
  file.writelines("\r\n".join(data))
118
118
  file.close()
119
119
 
@@ -151,7 +151,7 @@ def main():
151
151
  data.append(" production: custom marker")
152
152
  data.append("")
153
153
  file_path = "%s/%s" % (dir_name, "pytest.ini")
154
- file = open(file_path, "w+", "utf-8")
154
+ file = open(file_path, mode="w+", encoding="utf-8")
155
155
  file.writelines("\r\n".join(data))
156
156
  file.close()
157
157
 
@@ -168,14 +168,14 @@ def main():
168
168
  data.append("show_skipped=false")
169
169
  data.append("show_timings=false")
170
170
  file_path = "%s/%s" % (dir_name, "setup.cfg")
171
- file = open(file_path, "w+", "utf-8")
171
+ file = open(file_path, mode="w+", encoding="utf-8")
172
172
  file.writelines("\r\n".join(data))
173
173
  file.close()
174
174
 
175
175
  data = []
176
176
  data.append("")
177
177
  file_path = "%s/%s" % (dir_name, "__init__.py")
178
- file = open(file_path, "w+", "utf-8")
178
+ file = open(file_path, mode="w+", encoding="utf-8")
179
179
  file.writelines("\r\n".join(data))
180
180
  file.close()
181
181
 
@@ -311,7 +311,7 @@ def main():
311
311
  data.append("temp_*/")
312
312
  data.append("node_modules")
313
313
  file_path = "%s/%s" % (dir_name, ".gitignore")
314
- file = open(file_path, "w+", "utf-8")
314
+ file = open(file_path, mode="w+", encoding="utf-8")
315
315
  file.writelines("\r\n".join(data))
316
316
  file.close()
317
317
 
@@ -323,7 +323,7 @@ def main():
323
323
  data.append(" ├── requirements.txt")
324
324
  data.append(" └── setup.cfg")
325
325
  file_path = "%s/%s" % (dir_name, "outline.rst")
326
- file = open(file_path, "w+", "utf-8")
326
+ file = open(file_path, mode="w+", encoding="utf-8")
327
327
  file.writelines("\r\n".join(data))
328
328
  file.close()
329
329
  os.system("sbase print %s -n" % file_path)
@@ -367,7 +367,7 @@ def main():
367
367
  data.append(' self.assert_element("div#login_button_container")')
368
368
  data.append("")
369
369
  file_path = "%s/%s" % (dir_name, "my_first_test.py")
370
- file = open(file_path, "w+", "utf-8")
370
+ file = open(file_path, mode="w+", encoding="utf-8")
371
371
  file.writelines("\r\n".join(data))
372
372
  file.close()
373
373
 
@@ -460,7 +460,7 @@ def main():
460
460
  data.append(' self.assert_text("SeleniumBase", "h2")')
461
461
  data.append("")
462
462
  file_path = "%s/%s" % (dir_name, "test_demo_site.py")
463
- file = open(file_path, "w+", "utf-8")
463
+ file = open(file_path, mode="w+", encoding="utf-8")
464
464
  file.writelines("\r\n".join(data))
465
465
  file.close()
466
466
 
@@ -499,7 +499,7 @@ def main():
499
499
  data.append(' self.assert_title_contains(title_text)')
500
500
  data.append("")
501
501
  file_path = "%s/%s" % (dir_name, "parameterized_test.py")
502
- file = open(file_path, "w+", "utf-8")
502
+ file = open(file_path, mode="w+", encoding="utf-8")
503
503
  file.writelines("\r\n".join(data))
504
504
  file.close()
505
505
 
@@ -509,7 +509,7 @@ def main():
509
509
  data = []
510
510
  data.append("")
511
511
  file_path = "%s/%s" % (dir_name_2, "__init__.py")
512
- file = open(file_path, "w+", "utf-8")
512
+ file = open(file_path, mode="w+", encoding="utf-8")
513
513
  file.writelines("\r\n".join(data))
514
514
  file.close()
515
515
 
@@ -544,7 +544,7 @@ def main():
544
544
  data.append(" pass")
545
545
  data.append("")
546
546
  file_path = "%s/%s" % (dir_name_2, "base_test_case.py")
547
- file = open(file_path, "w+", "utf-8")
547
+ file = open(file_path, mode="w+", encoding="utf-8")
548
548
  file.writelines("\r\n".join(data))
549
549
  file.close()
550
550
 
@@ -553,7 +553,7 @@ def main():
553
553
  data.append(' html = "html"')
554
554
  data.append("")
555
555
  file_path = "%s/%s" % (dir_name_2, "page_objects.py")
556
- file = open(file_path, "w+", "utf-8")
556
+ file = open(file_path, mode="w+", encoding="utf-8")
557
557
  file.writelines("\r\n".join(data))
558
558
  file.close()
559
559
 
@@ -569,7 +569,7 @@ def main():
569
569
  data.append(" self.assert_element(Page.html)")
570
570
  data.append("")
571
571
  file_path = "%s/%s" % (dir_name_2, "boilerplate_test.py")
572
- file = open(file_path, "w+", "utf-8")
572
+ file = open(file_path, mode="w+", encoding="utf-8")
573
573
  file.writelines("\r\n".join(data))
574
574
  file.close()
575
575
 
@@ -593,7 +593,7 @@ def main():
593
593
  data.append(' DataPage().add_input_text(self, "Goodbye!")')
594
594
  data.append("")
595
595
  file_path = "%s/%s" % (dir_name_2, "classic_obj_test.py")
596
- file = open(file_path, "w+", "utf-8")
596
+ file = open(file_path, mode="w+", encoding="utf-8")
597
597
  file.writelines("\r\n".join(data))
598
598
  file.close()
599
599
 
@@ -613,7 +613,7 @@ def main():
613
613
  data.append(' DataPage().add_input_text(sb, "Goodbye!")')
614
614
  data.append("")
615
615
  file_path = "%s/%s" % (dir_name_2, "sb_fixture_test.py")
616
- file = open(file_path, "w+", "utf-8")
616
+ file = open(file_path, mode="w+", encoding="utf-8")
617
617
  file.writelines("\r\n".join(data))
618
618
  file.close()
619
619
 
@@ -623,7 +623,7 @@ def main():
623
623
  data = []
624
624
  data.append("")
625
625
  file_path = "%s/%s" % (dir_name_3, "__init__.py")
626
- file = open(file_path, "w+", "utf-8")
626
+ file = open(file_path, mode="w+", encoding="utf-8")
627
627
  file.writelines("\r\n".join(data))
628
628
  file.close()
629
629
 
@@ -651,7 +651,7 @@ def main():
651
651
  )
652
652
  data.append("")
653
653
  file_path = "%s/%s" % (dir_name_3, "google_test.py")
654
- file = open(file_path, "w+", "utf-8")
654
+ file = open(file_path, mode="w+", encoding="utf-8")
655
655
  file.writelines("\r\n".join(data))
656
656
  file.close()
657
657
 
@@ -669,7 +669,7 @@ def main():
669
669
  data.append(' search_results = "div#center_col"')
670
670
  data.append("")
671
671
  file_path = "%s/%s" % (dir_name_3, "google_objects.py")
672
- file = open(file_path, "w+", "utf-8")
672
+ file = open(file_path, mode="w+", encoding="utf-8")
673
673
  file.writelines("\r\n".join(data))
674
674
  file.close()
675
675
 
@@ -701,7 +701,7 @@ def main():
701
701
  data.append(' self.assert_element("div#login_button_container")')
702
702
  data.append("")
703
703
  file_path = "%s/%s" % (dir_name_3, "swag_labs_test.py")
704
- file = open(file_path, "w+", "utf-8")
704
+ file = open(file_path, mode="w+", encoding="utf-8")
705
705
  file.writelines("\r\n".join(data))
706
706
  file.close()
707
707
 
@@ -728,7 +728,7 @@ def main():
728
728
  data.append(' sb.assert_element("div#login_button_container")')
729
729
  data.append("")
730
730
  file_path = "%s/%s" % (dir_name_3, "sb_swag_test.py")
731
- file = open(file_path, "w+", "utf-8")
731
+ file = open(file_path, mode="w+", encoding="utf-8")
732
732
  file.writelines("\r\n".join(data))
733
733
  file.close()
734
734
 
@@ -755,7 +755,7 @@ def main():
755
755
  data.append(" ├── sb_swag_test.py")
756
756
  data.append(" └── swag_labs_test.py")
757
757
  file_path = "%s/%s" % (dir_name, "outline.rst")
758
- file = open(file_path, "w+", "utf-8")
758
+ file = open(file_path, mode="w+", encoding="utf-8")
759
759
  file.writelines("\r\n".join(data))
760
760
  file.close()
761
761
  if " " not in file_path:
@@ -412,7 +412,7 @@ def main():
412
412
  continue
413
413
  new_data.append(line)
414
414
  data = new_data
415
- file = open(file_path, "w+", "utf-8")
415
+ file = open(file_path, mode="w+", encoding="utf-8")
416
416
  file.writelines("\r\n".join(data))
417
417
  file.close()
418
418
  if " " not in file_name:
@@ -272,7 +272,7 @@ def main():
272
272
  continue
273
273
  new_data.append(line)
274
274
  data = new_data
275
- file = open(file_path, "w+", "utf-8")
275
+ file = open(file_path, mode="w+", encoding="utf-8")
276
276
  file.writelines("\r\n".join(data))
277
277
  file.close()
278
278
  if " " not in file_name:
@@ -239,7 +239,7 @@ def main():
239
239
  d2.append("")
240
240
  data = d2
241
241
 
242
- file = open(file_path, "w+", "utf-8")
242
+ file = open(file_path, mode="w+", encoding="utf-8")
243
243
  file.writelines("\r\n".join(data))
244
244
  file.close()
245
245
  success = (
@@ -135,7 +135,7 @@ def create_objects_file(selector_list_dict=None):
135
135
  data.append(' html = "html"')
136
136
  data.append("")
137
137
  file_path = PAGE_OBJECTS_FILE
138
- file = open(file_path, "w+", "utf-8")
138
+ file = open(file_path, mode="w+", encoding="utf-8")
139
139
  file.writelines("\r\n".join(data))
140
140
  file.close()
141
141
  if not selector_list_dict:
@@ -149,7 +149,7 @@ def scan_objects_file():
149
149
  create_objects_file()
150
150
 
151
151
  page_selectors = {}
152
- with open(PAGE_OBJECTS_FILE, "r", encoding="utf-8") as f:
152
+ with open(PAGE_OBJECTS_FILE, mode="r", encoding="utf-8") as f:
153
153
  all_code = f.read()
154
154
 
155
155
  var_names = []
@@ -3089,7 +3089,7 @@ def main(shell_command):
3089
3089
  "Expecting: %s\n" % (seleniumbase_file, expected_arg)
3090
3090
  )
3091
3091
 
3092
- with open(seleniumbase_file, "r", encoding="utf-8") as f:
3092
+ with open(seleniumbase_file, mode="r", encoding="utf-8") as f:
3093
3093
  all_code = f.read()
3094
3094
  if "def test_" not in all_code:
3095
3095
  raise Exception(
@@ -3188,7 +3188,7 @@ def main(shell_command):
3188
3188
  # Create SeleniumBase test file
3189
3189
  base_file_name = seleniumbase_file.split(".py")[0]
3190
3190
  converted_file_name = base_file_name + ".py" # Change end to make a copy
3191
- out_file = open(converted_file_name, "w+", encoding="utf-8")
3191
+ out_file = open(converted_file_name, mode="w+", encoding="utf-8")
3192
3192
  out_file.writelines(seleniumbase_code)
3193
3193
  out_file.close()
3194
3194
  print('\n>>> ["%s"] was updated!\n' % converted_file_name)
@@ -123,7 +123,7 @@ def main():
123
123
 
124
124
  all_code = None
125
125
  with open(
126
- file_to_print, "r+", encoding="utf-8", errors="ignore"
126
+ file_to_print, mode="r+", encoding="utf-8", errors="ignore"
127
127
  ) as f:
128
128
  all_code = f.read()
129
129
  all_code = all_code.replace("\t", " ")
@@ -28,6 +28,10 @@ from seleniumbase import decorators
28
28
  from seleniumbase import drivers # webdriver storage folder for SeleniumBase
29
29
  from seleniumbase.drivers import cft_drivers # chrome-for-testing
30
30
  from seleniumbase.drivers import chs_drivers # chrome-headless-shell
31
+ from seleniumbase.drivers import opera_drivers # still uses chromedriver
32
+ from seleniumbase.drivers import brave_drivers # still uses chromedriver
33
+ from seleniumbase.drivers import comet_drivers # still uses chromedriver
34
+ from seleniumbase.drivers import atlas_drivers # still uses chromedriver
31
35
  from seleniumbase import extensions # browser extensions storage folder
32
36
  from seleniumbase.config import settings
33
37
  from seleniumbase.core import detect_b_ver
@@ -44,6 +48,10 @@ urllib3.disable_warnings()
44
48
  DRIVER_DIR = os.path.dirname(os.path.realpath(drivers.__file__))
45
49
  DRIVER_DIR_CFT = os.path.dirname(os.path.realpath(cft_drivers.__file__))
46
50
  DRIVER_DIR_CHS = os.path.dirname(os.path.realpath(chs_drivers.__file__))
51
+ DRIVER_DIR_OPERA = os.path.dirname(os.path.realpath(opera_drivers.__file__))
52
+ DRIVER_DIR_BRAVE = os.path.dirname(os.path.realpath(brave_drivers.__file__))
53
+ DRIVER_DIR_COMET = os.path.dirname(os.path.realpath(comet_drivers.__file__))
54
+ DRIVER_DIR_ATLAS = os.path.dirname(os.path.realpath(atlas_drivers.__file__))
47
55
  # Make sure that the SeleniumBase DRIVER_DIR is at the top of the System PATH
48
56
  # (Changes to the System PATH with os.environ only last during the test run)
49
57
  if not os.environ["PATH"].startswith(DRIVER_DIR):
@@ -1218,8 +1226,8 @@ def uc_gui_click_x_y(driver, x, y, timeframe=0.25):
1218
1226
  driver.cdp.minimize()
1219
1227
  driver.cdp.set_window_rect(win_x, win_y, width, height)
1220
1228
  if IS_WINDOWS:
1221
- x = x * width_ratio
1222
- y = y * width_ratio
1229
+ x = x * (width_ratio + 0.03)
1230
+ y = y * (width_ratio - 0.03)
1223
1231
  _uc_gui_click_x_y(driver, x, y, timeframe=timeframe, uc_lock=False)
1224
1232
  return
1225
1233
  with suppress(Exception):
@@ -1260,7 +1268,7 @@ def _uc_gui_click_captcha(
1260
1268
  ctype=None,
1261
1269
  ):
1262
1270
  cdp_mode_on_at_start = __is_cdp_swap_needed(driver)
1263
- if cdp_mode_on_at_start and (not ctype or ctype == "cf_t"):
1271
+ if cdp_mode_on_at_start:
1264
1272
  return driver.cdp.gui_click_captcha()
1265
1273
  _on_a_captcha_page = None
1266
1274
  if ctype == "cf_t":
@@ -1952,6 +1960,15 @@ def get_valid_binary_names_for_browser(browser):
1952
1960
  raise Exception("Invalid combination for OS browser binaries!")
1953
1961
 
1954
1962
 
1963
+ def _special_binary_exists(location, name):
1964
+ filename = str(location).split("/")[-1].split("\\")[-1]
1965
+ return (
1966
+ location
1967
+ and str(name).lower() in filename.lower()
1968
+ and os.path.exists(location)
1969
+ )
1970
+
1971
+
1955
1972
  def _repair_chromedriver(chrome_options, headless_options, mcv=None):
1956
1973
  if mcv:
1957
1974
  subprocess.check_call(
@@ -2011,7 +2028,7 @@ def _mark_driver_repaired():
2011
2028
  file_path = os.path.join(abs_path, driver_repaired_lock)
2012
2029
  if not os.path.exists(DOWNLOADS_FOLDER):
2013
2030
  os.makedirs(DOWNLOADS_FOLDER)
2014
- out_file = open(file_path, "w+", encoding="utf-8")
2031
+ out_file = open(file_path, mode="w+", encoding="utf-8")
2015
2032
  out_file.writelines("")
2016
2033
  out_file.close()
2017
2034
 
@@ -2396,6 +2413,19 @@ def _set_chrome_options(
2396
2413
  and not recorder_ext
2397
2414
  and (not extension_zip and not extension_dir)
2398
2415
  ):
2416
+ if (
2417
+ binary_location
2418
+ and isinstance(binary_location, str)
2419
+ and (
2420
+ binary_location.lower().endswith("comet")
2421
+ or binary_location.lower().endswith("comet.exe")
2422
+ or binary_location.lower().endswith("atlas")
2423
+ or binary_location.lower().endswith("atlas.exe")
2424
+ )
2425
+ ):
2426
+ # AI browsers don't like Incognito / Guest Mode
2427
+ incognito = False
2428
+ guest_mode = False
2399
2429
  if incognito:
2400
2430
  # Use Chrome's Incognito Mode
2401
2431
  # Incognito Mode prevents Chrome extensions from loading,
@@ -2947,6 +2977,14 @@ def get_driver(
2947
2977
  and sb_config.binary_location == "chs"
2948
2978
  ):
2949
2979
  driver_dir = DRIVER_DIR_CHS
2980
+ if _special_binary_exists(binary_location, "opera"):
2981
+ driver_dir = DRIVER_DIR_OPERA
2982
+ if _special_binary_exists(binary_location, "brave"):
2983
+ driver_dir = DRIVER_DIR_BRAVE
2984
+ if _special_binary_exists(binary_location, "comet"):
2985
+ driver_dir = DRIVER_DIR_COMET
2986
+ if _special_binary_exists(binary_location, "atlas"):
2987
+ driver_dir = DRIVER_DIR_ATLAS
2950
2988
  if (
2951
2989
  hasattr(sb_config, "settings")
2952
2990
  and hasattr(sb_config.settings, "NEW_DRIVER_DIR")
@@ -3906,6 +3944,18 @@ def get_local_driver(
3906
3944
  ):
3907
3945
  special_chrome = True
3908
3946
  driver_dir = DRIVER_DIR_CHS
3947
+ if _special_binary_exists(binary_location, "opera"):
3948
+ special_chrome = True
3949
+ driver_dir = DRIVER_DIR_OPERA
3950
+ if _special_binary_exists(binary_location, "brave"):
3951
+ special_chrome = True
3952
+ driver_dir = DRIVER_DIR_BRAVE
3953
+ if _special_binary_exists(binary_location, "comet"):
3954
+ special_chrome = True
3955
+ driver_dir = DRIVER_DIR_COMET
3956
+ if _special_binary_exists(binary_location, "atlas"):
3957
+ special_chrome = True
3958
+ driver_dir = DRIVER_DIR_ATLAS
3909
3959
  if (
3910
3960
  hasattr(sb_config, "settings")
3911
3961
  and hasattr(sb_config.settings, "NEW_DRIVER_DIR")
@@ -4743,6 +4793,27 @@ def get_local_driver(
4743
4793
  )
4744
4794
  return extend_driver(driver)
4745
4795
  elif browser_name == constants.Browser.GOOGLE_CHROME:
4796
+ set_chromium = None
4797
+ if _special_binary_exists(binary_location, "opera"):
4798
+ set_chromium = "opera"
4799
+ local_chromedriver = DRIVER_DIR_OPERA + "/chromedriver"
4800
+ if IS_WINDOWS:
4801
+ local_chromedriver = DRIVER_DIR_OPERA + "/chromedriver.exe"
4802
+ if _special_binary_exists(binary_location, "brave"):
4803
+ set_chromium = "brave"
4804
+ local_chromedriver = DRIVER_DIR_BRAVE + "/chromedriver"
4805
+ if IS_WINDOWS:
4806
+ local_chromedriver = DRIVER_DIR_BRAVE + "/chromedriver.exe"
4807
+ if _special_binary_exists(binary_location, "comet"):
4808
+ set_chromium = "comet"
4809
+ local_chromedriver = DRIVER_DIR_COMET + "/chromedriver"
4810
+ if IS_WINDOWS:
4811
+ local_chromedriver = DRIVER_DIR_COMET + "/chromedriver.exe"
4812
+ if _special_binary_exists(binary_location, "atlas"):
4813
+ set_chromium = "atlas"
4814
+ local_chromedriver = DRIVER_DIR_ATLAS + "/chromedriver"
4815
+ if IS_WINDOWS:
4816
+ local_chromedriver = DRIVER_DIR_ATLAS + "/chromedriver.exe"
4746
4817
  try:
4747
4818
  chrome_options = _set_chrome_options(
4748
4819
  browser_name,
@@ -4864,6 +4935,12 @@ def get_local_driver(
4864
4935
  major_chrome_version = None
4865
4936
  if major_chrome_version:
4866
4937
  use_version = major_chrome_version
4938
+ if (
4939
+ set_chromium == "opera"
4940
+ and use_version.isnumeric()
4941
+ and int(use_version) < 130
4942
+ ):
4943
+ use_version = "130" # Special case
4867
4944
  ch_driver_version = None
4868
4945
  path_chromedriver = chromedriver_on_path()
4869
4946
  if os.path.exists(local_chromedriver):
@@ -4881,7 +4958,7 @@ def get_local_driver(
4881
4958
  ch_driver_version = output
4882
4959
  if driver_version == "keep":
4883
4960
  driver_version = ch_driver_version
4884
- elif path_chromedriver:
4961
+ elif path_chromedriver and not set_chromium:
4885
4962
  try:
4886
4963
  make_driver_executable_if_not(path_chromedriver)
4887
4964
  except Exception as e: