seleniumbase 4.32.5a1__py3-none-any.whl → 4.32.7__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.
- seleniumbase/__version__.py +1 -1
- seleniumbase/core/browser_launcher.py +11 -1
- seleniumbase/core/sb_cdp.py +203 -0
- seleniumbase/undetected/__init__.py +3 -2
- seleniumbase/undetected/cdp_driver/cdp_util.py +124 -1
- {seleniumbase-4.32.5a1.dist-info → seleniumbase-4.32.7.dist-info}/METADATA +5 -4
- {seleniumbase-4.32.5a1.dist-info → seleniumbase-4.32.7.dist-info}/RECORD +11 -11
- {seleniumbase-4.32.5a1.dist-info → seleniumbase-4.32.7.dist-info}/WHEEL +1 -1
- {seleniumbase-4.32.5a1.dist-info → seleniumbase-4.32.7.dist-info}/LICENSE +0 -0
- {seleniumbase-4.32.5a1.dist-info → seleniumbase-4.32.7.dist-info}/entry_points.txt +0 -0
- {seleniumbase-4.32.5a1.dist-info → seleniumbase-4.32.7.dist-info}/top_level.txt +0 -0
seleniumbase/__version__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
# seleniumbase package
|
2
|
-
__version__ = "4.32.
|
2
|
+
__version__ = "4.32.7"
|
@@ -588,6 +588,7 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
588
588
|
cdp.find_elements_by_text = CDPM.find_elements_by_text
|
589
589
|
cdp.select = CDPM.select
|
590
590
|
cdp.select_all = CDPM.select_all
|
591
|
+
cdp.find_elements = CDPM.find_elements
|
591
592
|
cdp.click_link = CDPM.click_link
|
592
593
|
cdp.tile_windows = CDPM.tile_windows
|
593
594
|
cdp.get_all_cookies = CDPM.get_all_cookies
|
@@ -619,6 +620,8 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
619
620
|
cdp.reset_window_size = CDPM.reset_window_size
|
620
621
|
cdp.set_locale = CDPM.set_locale
|
621
622
|
cdp.set_attributes = CDPM.set_attributes
|
623
|
+
cdp.gui_click_x_y = CDPM.gui_click_x_y
|
624
|
+
cdp.gui_click_element = CDPM.gui_click_element
|
622
625
|
cdp.internalize_links = CDPM.internalize_links
|
623
626
|
cdp.get_window = CDPM.get_window
|
624
627
|
cdp.get_element_attributes = CDPM.get_element_attributes
|
@@ -655,6 +658,8 @@ def uc_open_with_cdp_mode(driver, url=None):
|
|
655
658
|
cdp.assert_element_visible = CDPM.assert_element
|
656
659
|
cdp.assert_text = CDPM.assert_text
|
657
660
|
cdp.assert_exact_text = CDPM.assert_exact_text
|
661
|
+
cdp.scroll_down = CDPM.scroll_down
|
662
|
+
cdp.scroll_up = CDPM.scroll_up
|
658
663
|
cdp.save_screenshot = CDPM.save_screenshot
|
659
664
|
cdp.page = page # async world
|
660
665
|
cdp.driver = driver.cdp_base # async world
|
@@ -2123,6 +2128,10 @@ def _set_chrome_options(
|
|
2123
2128
|
binary_loc = detect_b_ver.get_binary_location(br_app, True)
|
2124
2129
|
if os.path.exists(binary_loc):
|
2125
2130
|
binary_location = binary_loc
|
2131
|
+
elif os.path.exists("/usr/bin/google-chrome-stable"):
|
2132
|
+
binary_location = "/usr/bin/google-chrome-stable"
|
2133
|
+
elif os.path.exists("/usr/bin/google-chrome"):
|
2134
|
+
binary_location = "/usr/bin/google-chrome"
|
2126
2135
|
extra_disabled_features = []
|
2127
2136
|
if chromium_arg:
|
2128
2137
|
# Can be a comma-separated list of Chromium args or a list
|
@@ -2218,12 +2227,13 @@ def _set_chrome_options(
|
|
2218
2227
|
)
|
2219
2228
|
):
|
2220
2229
|
chrome_options.add_argument("--no-pings")
|
2221
|
-
chrome_options.add_argument("--disable-popup-blocking")
|
2222
2230
|
chrome_options.add_argument("--homepage=chrome://version/")
|
2223
2231
|
chrome_options.add_argument("--animation-duration-scale=0")
|
2224
2232
|
chrome_options.add_argument("--wm-window-animations-disabled")
|
2225
2233
|
chrome_options.add_argument("--enable-privacy-sandbox-ads-apis")
|
2226
2234
|
chrome_options.add_argument("--disable-background-timer-throttling")
|
2235
|
+
# Prevent new tabs opened by Selenium from being blocked:
|
2236
|
+
chrome_options.add_argument("--disable-popup-blocking")
|
2227
2237
|
# Skip remaining options that trigger anti-bot services
|
2228
2238
|
return chrome_options
|
2229
2239
|
chrome_options.add_argument("--test-type")
|
seleniumbase/core/sb_cdp.py
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
"""Add CDP methods to extend the driver"""
|
2
|
+
import fasteners
|
2
3
|
import math
|
3
4
|
import os
|
4
5
|
import re
|
6
|
+
import sys
|
5
7
|
import time
|
6
8
|
from contextlib import suppress
|
7
9
|
from seleniumbase import config as sb_config
|
@@ -239,6 +241,9 @@ class CDPMethods():
|
|
239
241
|
self.__slow_mode_pause_if_set()
|
240
242
|
return updated_elements
|
241
243
|
|
244
|
+
def find_elements(self, selector, timeout=settings.SMALL_TIMEOUT):
|
245
|
+
return self.select_all(selector, timeout=timeout)
|
246
|
+
|
242
247
|
def click_link(self, link_text):
|
243
248
|
self.find_elements_by_text(link_text, "a")[0].click()
|
244
249
|
|
@@ -835,6 +840,194 @@ class CDPMethods():
|
|
835
840
|
with suppress(Exception):
|
836
841
|
self.loop.run_until_complete(self.page.evaluate(js_code))
|
837
842
|
|
843
|
+
def __verify_pyautogui_has_a_headed_browser(self):
|
844
|
+
"""PyAutoGUI requires a headed browser so that it can
|
845
|
+
focus on the correct element when performing actions."""
|
846
|
+
driver = self.driver
|
847
|
+
if hasattr(driver, "cdp_base"):
|
848
|
+
driver = driver.cdp_base
|
849
|
+
if driver.config.headless:
|
850
|
+
raise Exception(
|
851
|
+
"PyAutoGUI can't be used in headless mode!"
|
852
|
+
)
|
853
|
+
|
854
|
+
def __install_pyautogui_if_missing(self):
|
855
|
+
self.__verify_pyautogui_has_a_headed_browser()
|
856
|
+
driver = self.driver
|
857
|
+
if hasattr(driver, "cdp_base"):
|
858
|
+
driver = driver.cdp_base
|
859
|
+
pip_find_lock = fasteners.InterProcessLock(
|
860
|
+
constants.PipInstall.FINDLOCK
|
861
|
+
)
|
862
|
+
with pip_find_lock: # Prevent issues with multiple processes
|
863
|
+
try:
|
864
|
+
import pyautogui
|
865
|
+
with suppress(Exception):
|
866
|
+
use_pyautogui_ver = constants.PyAutoGUI.VER
|
867
|
+
if pyautogui.__version__ != use_pyautogui_ver:
|
868
|
+
del pyautogui
|
869
|
+
shared_utils.pip_install(
|
870
|
+
"pyautogui", version=use_pyautogui_ver
|
871
|
+
)
|
872
|
+
import pyautogui
|
873
|
+
except Exception:
|
874
|
+
print("\nPyAutoGUI required! Installing now...")
|
875
|
+
shared_utils.pip_install(
|
876
|
+
"pyautogui", version=constants.PyAutoGUI.VER
|
877
|
+
)
|
878
|
+
try:
|
879
|
+
import pyautogui
|
880
|
+
except Exception:
|
881
|
+
if (
|
882
|
+
shared_utils.is_linux()
|
883
|
+
and (not sb_config.headed or sb_config.xvfb)
|
884
|
+
and not driver.config.headless
|
885
|
+
):
|
886
|
+
from sbvirtualdisplay import Display
|
887
|
+
xvfb_width = 1366
|
888
|
+
xvfb_height = 768
|
889
|
+
if (
|
890
|
+
hasattr(sb_config, "_xvfb_width")
|
891
|
+
and sb_config._xvfb_width
|
892
|
+
and isinstance(sb_config._xvfb_width, int)
|
893
|
+
and hasattr(sb_config, "_xvfb_height")
|
894
|
+
and sb_config._xvfb_height
|
895
|
+
and isinstance(sb_config._xvfb_height, int)
|
896
|
+
):
|
897
|
+
xvfb_width = sb_config._xvfb_width
|
898
|
+
xvfb_height = sb_config._xvfb_height
|
899
|
+
if xvfb_width < 1024:
|
900
|
+
xvfb_width = 1024
|
901
|
+
sb_config._xvfb_width = xvfb_width
|
902
|
+
if xvfb_height < 768:
|
903
|
+
xvfb_height = 768
|
904
|
+
sb_config._xvfb_height = xvfb_height
|
905
|
+
with suppress(Exception):
|
906
|
+
xvfb_display = Display(
|
907
|
+
visible=True,
|
908
|
+
size=(xvfb_width, xvfb_height),
|
909
|
+
backend="xvfb",
|
910
|
+
use_xauth=True,
|
911
|
+
)
|
912
|
+
xvfb_display.start()
|
913
|
+
|
914
|
+
def __get_configured_pyautogui(self, pyautogui_copy):
|
915
|
+
if (
|
916
|
+
shared_utils.is_linux()
|
917
|
+
and hasattr(pyautogui_copy, "_pyautogui_x11")
|
918
|
+
and "DISPLAY" in os.environ.keys()
|
919
|
+
):
|
920
|
+
if (
|
921
|
+
hasattr(sb_config, "_pyautogui_x11_display")
|
922
|
+
and sb_config._pyautogui_x11_display
|
923
|
+
and hasattr(pyautogui_copy._pyautogui_x11, "_display")
|
924
|
+
and (
|
925
|
+
sb_config._pyautogui_x11_display
|
926
|
+
== pyautogui_copy._pyautogui_x11._display
|
927
|
+
)
|
928
|
+
):
|
929
|
+
pass
|
930
|
+
else:
|
931
|
+
import Xlib.display
|
932
|
+
pyautogui_copy._pyautogui_x11._display = (
|
933
|
+
Xlib.display.Display(os.environ['DISPLAY'])
|
934
|
+
)
|
935
|
+
sb_config._pyautogui_x11_display = (
|
936
|
+
pyautogui_copy._pyautogui_x11._display
|
937
|
+
)
|
938
|
+
return pyautogui_copy
|
939
|
+
|
940
|
+
def __gui_click_x_y(self, x, y, timeframe=0.25, uc_lock=False):
|
941
|
+
self.__install_pyautogui_if_missing()
|
942
|
+
import pyautogui
|
943
|
+
pyautogui = self.__get_configured_pyautogui(pyautogui)
|
944
|
+
screen_width, screen_height = pyautogui.size()
|
945
|
+
if x < 0 or y < 0 or x > screen_width or y > screen_height:
|
946
|
+
raise Exception(
|
947
|
+
"PyAutoGUI cannot click on point (%s, %s)"
|
948
|
+
" outside screen. (Width: %s, Height: %s)"
|
949
|
+
% (x, y, screen_width, screen_height)
|
950
|
+
)
|
951
|
+
if uc_lock:
|
952
|
+
gui_lock = fasteners.InterProcessLock(
|
953
|
+
constants.MultiBrowser.PYAUTOGUILOCK
|
954
|
+
)
|
955
|
+
with gui_lock: # Prevent issues with multiple processes
|
956
|
+
pyautogui.moveTo(x, y, timeframe, pyautogui.easeOutQuad)
|
957
|
+
if timeframe >= 0.25:
|
958
|
+
time.sleep(0.056) # Wait if moving at human-speed
|
959
|
+
if "--debug" in sys.argv:
|
960
|
+
print(" <DEBUG> pyautogui.click(%s, %s)" % (x, y))
|
961
|
+
pyautogui.click(x=x, y=y)
|
962
|
+
else:
|
963
|
+
# Called from a method where the gui_lock is already active
|
964
|
+
pyautogui.moveTo(x, y, timeframe, pyautogui.easeOutQuad)
|
965
|
+
if timeframe >= 0.25:
|
966
|
+
time.sleep(0.056) # Wait if moving at human-speed
|
967
|
+
if "--debug" in sys.argv:
|
968
|
+
print(" <DEBUG> pyautogui.click(%s, %s)" % (x, y))
|
969
|
+
pyautogui.click(x=x, y=y)
|
970
|
+
|
971
|
+
def gui_click_x_y(self, x, y, timeframe=0.25):
|
972
|
+
gui_lock = fasteners.InterProcessLock(
|
973
|
+
constants.MultiBrowser.PYAUTOGUILOCK
|
974
|
+
)
|
975
|
+
with gui_lock: # Prevent issues with multiple processes
|
976
|
+
self.__install_pyautogui_if_missing()
|
977
|
+
import pyautogui
|
978
|
+
pyautogui = self.__get_configured_pyautogui(pyautogui)
|
979
|
+
width_ratio = 1.0
|
980
|
+
if (
|
981
|
+
shared_utils.is_windows()
|
982
|
+
and (
|
983
|
+
not hasattr(sb_config, "_saved_width_ratio")
|
984
|
+
or not sb_config._saved_width_ratio
|
985
|
+
)
|
986
|
+
):
|
987
|
+
window_rect = self.get_window_rect()
|
988
|
+
width = window_rect["width"]
|
989
|
+
height = window_rect["height"]
|
990
|
+
win_x = window_rect["x"]
|
991
|
+
win_y = window_rect["y"]
|
992
|
+
if (
|
993
|
+
hasattr(sb_config, "_saved_width_ratio")
|
994
|
+
and sb_config._saved_width_ratio
|
995
|
+
):
|
996
|
+
width_ratio = sb_config._saved_width_ratio
|
997
|
+
else:
|
998
|
+
scr_width = pyautogui.size().width
|
999
|
+
self.maximize()
|
1000
|
+
win_width = self.get_window_size()["width"]
|
1001
|
+
width_ratio = round(float(scr_width) / float(win_width), 2)
|
1002
|
+
width_ratio += 0.01
|
1003
|
+
if width_ratio < 0.45 or width_ratio > 2.55:
|
1004
|
+
width_ratio = 1.01
|
1005
|
+
sb_config._saved_width_ratio = width_ratio
|
1006
|
+
self.set_window_rect(win_x, win_y, width, height)
|
1007
|
+
self.bring_active_window_to_front()
|
1008
|
+
elif (
|
1009
|
+
shared_utils.is_windows()
|
1010
|
+
and hasattr(sb_config, "_saved_width_ratio")
|
1011
|
+
and sb_config._saved_width_ratio
|
1012
|
+
):
|
1013
|
+
width_ratio = sb_config._saved_width_ratio
|
1014
|
+
self.bring_active_window_to_front()
|
1015
|
+
if shared_utils.is_windows():
|
1016
|
+
x = x * width_ratio
|
1017
|
+
y = y * width_ratio
|
1018
|
+
self.__gui_click_x_y(x, y, timeframe=timeframe, uc_lock=False)
|
1019
|
+
return
|
1020
|
+
self.bring_active_window_to_front()
|
1021
|
+
self.__gui_click_x_y(x, y, timeframe=timeframe, uc_lock=False)
|
1022
|
+
|
1023
|
+
def gui_click_element(self, selector, timeframe=0.25):
|
1024
|
+
self.__slow_mode_pause_if_set()
|
1025
|
+
x, y = self.get_gui_element_center(selector)
|
1026
|
+
self.__add_light_pause()
|
1027
|
+
self.gui_click_x_y(x, y, timeframe=timeframe)
|
1028
|
+
self.__slow_mode_pause_if_set()
|
1029
|
+
self.loop.run_until_complete(self.page.wait())
|
1030
|
+
|
838
1031
|
def internalize_links(self):
|
839
1032
|
"""All `target="_blank"` links become `target="_self"`.
|
840
1033
|
This prevents those links from opening in a new tab."""
|
@@ -938,6 +1131,16 @@ class CDPMethods():
|
|
938
1131
|
% (text, element.text_all, selector)
|
939
1132
|
)
|
940
1133
|
|
1134
|
+
def scroll_down(self, amount=25):
|
1135
|
+
self.loop.run_until_complete(
|
1136
|
+
self.page.scroll_down(amount)
|
1137
|
+
)
|
1138
|
+
|
1139
|
+
def scroll_up(self, amount=25):
|
1140
|
+
self.loop.run_until_complete(
|
1141
|
+
self.page.scroll_up(amount)
|
1142
|
+
)
|
1143
|
+
|
941
1144
|
def save_screenshot(self, name, folder=None, selector=None):
|
942
1145
|
filename = name
|
943
1146
|
if folder:
|
@@ -497,8 +497,9 @@ class Chrome(selenium.webdriver.chrome.webdriver.WebDriver):
|
|
497
497
|
pass
|
498
498
|
if hasattr(self, "service") and getattr(self.service, "process", None):
|
499
499
|
logger.debug("Stopping webdriver service")
|
500
|
-
|
501
|
-
|
500
|
+
with suppress(Exception):
|
501
|
+
self.stop_client()
|
502
|
+
self.service.stop()
|
502
503
|
with suppress(Exception):
|
503
504
|
if self.reactor and isinstance(self.reactor, Reactor):
|
504
505
|
logger.debug("Shutting down Reactor")
|
@@ -1,10 +1,16 @@
|
|
1
1
|
"""CDP-Driver is based on NoDriver"""
|
2
2
|
from __future__ import annotations
|
3
3
|
import asyncio
|
4
|
+
import fasteners
|
4
5
|
import logging
|
6
|
+
import os
|
5
7
|
import time
|
6
8
|
import types
|
7
9
|
import typing
|
10
|
+
from contextlib import suppress
|
11
|
+
from seleniumbase import config as sb_config
|
12
|
+
from seleniumbase.config import settings
|
13
|
+
from seleniumbase.fixtures import constants
|
8
14
|
from seleniumbase.fixtures import shared_utils
|
9
15
|
from typing import Optional, List, Union, Callable
|
10
16
|
from .element import Element
|
@@ -15,9 +21,120 @@ from .tab import Tab
|
|
15
21
|
import mycdp as cdp
|
16
22
|
|
17
23
|
logger = logging.getLogger(__name__)
|
24
|
+
IS_LINUX = shared_utils.is_linux()
|
18
25
|
T = typing.TypeVar("T")
|
19
26
|
|
20
27
|
|
28
|
+
def __activate_standard_virtual_display():
|
29
|
+
from sbvirtualdisplay import Display
|
30
|
+
width = settings.HEADLESS_START_WIDTH
|
31
|
+
height = settings.HEADLESS_START_HEIGHT
|
32
|
+
with suppress(Exception):
|
33
|
+
_xvfb_display = Display(
|
34
|
+
visible=0, size=(width, height)
|
35
|
+
)
|
36
|
+
_xvfb_display.start()
|
37
|
+
sb_config._virtual_display = _xvfb_display
|
38
|
+
sb_config.headless_active = True
|
39
|
+
|
40
|
+
|
41
|
+
def __activate_virtual_display_as_needed(
|
42
|
+
headless, headed, xvfb, xvfb_metrics
|
43
|
+
):
|
44
|
+
"""This is only needed on Linux."""
|
45
|
+
if IS_LINUX and (not headed or xvfb):
|
46
|
+
from sbvirtualdisplay import Display
|
47
|
+
pip_find_lock = fasteners.InterProcessLock(
|
48
|
+
constants.PipInstall.FINDLOCK
|
49
|
+
)
|
50
|
+
with pip_find_lock: # Prevent issues with multiple processes
|
51
|
+
if not headless:
|
52
|
+
import Xlib.display
|
53
|
+
try:
|
54
|
+
_xvfb_width = None
|
55
|
+
_xvfb_height = None
|
56
|
+
if xvfb_metrics:
|
57
|
+
with suppress(Exception):
|
58
|
+
metrics_string = xvfb_metrics
|
59
|
+
metrics_string = metrics_string.replace(" ", "")
|
60
|
+
metrics_list = metrics_string.split(",")[0:2]
|
61
|
+
_xvfb_width = int(metrics_list[0])
|
62
|
+
_xvfb_height = int(metrics_list[1])
|
63
|
+
# The minimum width,height is: 1024,768
|
64
|
+
if _xvfb_width < 1024:
|
65
|
+
_xvfb_width = 1024
|
66
|
+
sb_config._xvfb_width = _xvfb_width
|
67
|
+
if _xvfb_height < 768:
|
68
|
+
_xvfb_height = 768
|
69
|
+
sb_config._xvfb_height = _xvfb_height
|
70
|
+
xvfb = True
|
71
|
+
if not _xvfb_width:
|
72
|
+
_xvfb_width = 1366
|
73
|
+
if not _xvfb_height:
|
74
|
+
_xvfb_height = 768
|
75
|
+
_xvfb_display = Display(
|
76
|
+
visible=True,
|
77
|
+
size=(_xvfb_width, _xvfb_height),
|
78
|
+
backend="xvfb",
|
79
|
+
use_xauth=True,
|
80
|
+
)
|
81
|
+
_xvfb_display.start()
|
82
|
+
if "DISPLAY" not in os.environ.keys():
|
83
|
+
print(
|
84
|
+
"\nX11 display failed! Will use regular xvfb!"
|
85
|
+
)
|
86
|
+
__activate_standard_virtual_display()
|
87
|
+
except Exception as e:
|
88
|
+
if hasattr(e, "msg"):
|
89
|
+
print("\n" + str(e.msg))
|
90
|
+
else:
|
91
|
+
print(e)
|
92
|
+
print("\nX11 display failed! Will use regular xvfb!")
|
93
|
+
__activate_standard_virtual_display()
|
94
|
+
return
|
95
|
+
pyautogui_is_installed = False
|
96
|
+
try:
|
97
|
+
import pyautogui
|
98
|
+
with suppress(Exception):
|
99
|
+
use_pyautogui_ver = constants.PyAutoGUI.VER
|
100
|
+
if pyautogui.__version__ != use_pyautogui_ver:
|
101
|
+
del pyautogui # To get newer ver
|
102
|
+
shared_utils.pip_install(
|
103
|
+
"pyautogui", version=use_pyautogui_ver
|
104
|
+
)
|
105
|
+
import pyautogui
|
106
|
+
pyautogui_is_installed = True
|
107
|
+
except Exception:
|
108
|
+
message = (
|
109
|
+
"PyAutoGUI is required for UC Mode on Linux! "
|
110
|
+
"Installing now..."
|
111
|
+
)
|
112
|
+
print("\n" + message)
|
113
|
+
shared_utils.pip_install(
|
114
|
+
"pyautogui", version=constants.PyAutoGUI.VER
|
115
|
+
)
|
116
|
+
import pyautogui
|
117
|
+
pyautogui_is_installed = True
|
118
|
+
if (
|
119
|
+
pyautogui_is_installed
|
120
|
+
and hasattr(pyautogui, "_pyautogui_x11")
|
121
|
+
):
|
122
|
+
try:
|
123
|
+
pyautogui._pyautogui_x11._display = (
|
124
|
+
Xlib.display.Display(os.environ['DISPLAY'])
|
125
|
+
)
|
126
|
+
sb_config._pyautogui_x11_display = (
|
127
|
+
pyautogui._pyautogui_x11._display
|
128
|
+
)
|
129
|
+
except Exception as e:
|
130
|
+
if hasattr(e, "msg"):
|
131
|
+
print("\n" + str(e.msg))
|
132
|
+
else:
|
133
|
+
print(e)
|
134
|
+
else:
|
135
|
+
__activate_standard_virtual_display()
|
136
|
+
|
137
|
+
|
21
138
|
async def start(
|
22
139
|
config: Optional[Config] = None,
|
23
140
|
*,
|
@@ -27,11 +144,14 @@ async def start(
|
|
27
144
|
guest: Optional[bool] = False,
|
28
145
|
browser_executable_path: Optional[PathLike] = None,
|
29
146
|
browser_args: Optional[List[str]] = None,
|
147
|
+
xvfb_metrics: Optional[List[str]] = None, # "Width,Height" for Linux
|
30
148
|
sandbox: Optional[bool] = True,
|
31
149
|
lang: Optional[str] = None,
|
32
150
|
host: Optional[str] = None,
|
33
151
|
port: Optional[int] = None,
|
34
|
-
|
152
|
+
xvfb: Optional[int] = None, # Use a special virtual display on Linux
|
153
|
+
headed: Optional[bool] = None, # Override default Xvfb mode on Linux
|
154
|
+
expert: Optional[bool] = None, # Open up closed Shadow-root elements
|
35
155
|
**kwargs: Optional[dict],
|
36
156
|
) -> Browser:
|
37
157
|
"""
|
@@ -73,6 +193,9 @@ async def start(
|
|
73
193
|
(For example, ensuring shadow-root is always in "open" mode.)
|
74
194
|
:type expert: bool
|
75
195
|
"""
|
196
|
+
if IS_LINUX and not headless and not headed and not xvfb:
|
197
|
+
xvfb = True # The default setting on Linux
|
198
|
+
__activate_virtual_display_as_needed(headless, headed, xvfb, xvfb_metrics)
|
76
199
|
if not config:
|
77
200
|
config = Config(
|
78
201
|
user_data_dir,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: seleniumbase
|
3
|
-
Version: 4.32.
|
3
|
+
Version: 4.32.7
|
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
|
@@ -92,7 +92,7 @@ Requires-Dist: trio==0.27.0
|
|
92
92
|
Requires-Dist: trio-websocket==0.11.1
|
93
93
|
Requires-Dist: wsproto==1.2.0
|
94
94
|
Requires-Dist: websocket-client==1.8.0
|
95
|
-
Requires-Dist: selenium==4.
|
95
|
+
Requires-Dist: selenium==4.26.1
|
96
96
|
Requires-Dist: cssselect==1.2.0
|
97
97
|
Requires-Dist: sortedcontainers==2.4.0
|
98
98
|
Requires-Dist: execnet==2.1.1
|
@@ -112,7 +112,7 @@ Requires-Dist: beautifulsoup4==4.12.3
|
|
112
112
|
Requires-Dist: pyotp==2.9.0
|
113
113
|
Requires-Dist: markdown-it-py==3.0.0
|
114
114
|
Requires-Dist: mdurl==0.1.2
|
115
|
-
Requires-Dist: rich==13.9.
|
115
|
+
Requires-Dist: rich==13.9.4
|
116
116
|
Requires-Dist: python-xlib==0.33; platform_system == "Linux"
|
117
117
|
Requires-Dist: pyreadline3>=3.5.3; platform_system == "Windows"
|
118
118
|
Requires-Dist: setuptools~=70.2; python_version < "3.10"
|
@@ -124,9 +124,10 @@ Requires-Dist: allure-pytest>=2.13.5; extra == "allure"
|
|
124
124
|
Requires-Dist: allure-python-commons>=2.13.5; extra == "allure"
|
125
125
|
Requires-Dist: allure-behave>=2.13.5; extra == "allure"
|
126
126
|
Provides-Extra: coverage
|
127
|
-
Requires-Dist: pytest-cov>=5.0.0; extra == "coverage"
|
128
127
|
Requires-Dist: coverage>=7.6.1; python_version < "3.9" and extra == "coverage"
|
128
|
+
Requires-Dist: pytest-cov>=5.0.0; python_version < "3.9" and extra == "coverage"
|
129
129
|
Requires-Dist: coverage>=7.6.4; python_version >= "3.9" and extra == "coverage"
|
130
|
+
Requires-Dist: pytest-cov>=6.0.0; python_version >= "3.9" and extra == "coverage"
|
130
131
|
Provides-Extra: flake8
|
131
132
|
Requires-Dist: mccabe==0.7.0; extra == "flake8"
|
132
133
|
Requires-Dist: flake8==5.0.4; python_version < "3.9" and extra == "flake8"
|
@@ -3,7 +3,7 @@ sbase/__main__.py,sha256=G0bVB1-DM4PGwQ1KyOupaWCs4ePbChZNNWuX2htim5U,647
|
|
3
3
|
sbase/steps.py,sha256=bKT_u5bJkKzYWEuAXi9NVVRYYxQRCM1_YJUrNFFRVPY,42865
|
4
4
|
seleniumbase/__init__.py,sha256=OtJh8nGKL4xtZpw8KPqmn7Q6R-86t4cWUDyVF5MbMTo,2398
|
5
5
|
seleniumbase/__main__.py,sha256=dn1p6dgCchmcH1zzTzzQvFwwdQQqnTGH6ULV9m4hv24,654
|
6
|
-
seleniumbase/__version__.py,sha256=
|
6
|
+
seleniumbase/__version__.py,sha256=OKPw6_xuqPFIHXuQ5lc-BDAB67jpMQ_dqtgnJNg8uL8,46
|
7
7
|
seleniumbase/behave/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
seleniumbase/behave/behave_helper.py,sha256=elkl8P9eLulRAioLstE9baYNM9N_PHBmAOcajX-pH_Y,24198
|
9
9
|
seleniumbase/behave/behave_sb.py,sha256=-hza7Nx2U41mSObYiPMi48v3JlPh3sJO3yzP0kqZ1Gk,59174
|
@@ -36,7 +36,7 @@ seleniumbase/console_scripts/sb_print.py,sha256=tNy-bMDgwHJO3bZxMpmo9weSE8uhbH0C
|
|
36
36
|
seleniumbase/console_scripts/sb_recorder.py,sha256=1oAA4wFzVboNhIFDwJLD3jgy9RuoavywKQG7R67bNZE,10908
|
37
37
|
seleniumbase/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
38
38
|
seleniumbase/core/application_manager.py,sha256=e_0sjtI8cjY5BNyZj1QBR0j6_oCScxGmSXYEpcYwuZE,576
|
39
|
-
seleniumbase/core/browser_launcher.py,sha256=
|
39
|
+
seleniumbase/core/browser_launcher.py,sha256=90omfhV8Q1-ki6Vend1j99C00LKFTKoNTYI4CwooOVk,216914
|
40
40
|
seleniumbase/core/capabilities_parser.py,sha256=meIS2uHapTCq2ldfNAToC7r0cKmZDRXuYNKExM1GHDY,6038
|
41
41
|
seleniumbase/core/colored_traceback.py,sha256=DrRWfg7XEnKcgY59Xj7Jdk09H-XqHYBSUpB-DiZt6iY,2020
|
42
42
|
seleniumbase/core/create_db_tables.sql,sha256=VWPtrdiW_HQ6yETHjqTu-VIrTwvd8I8o1NfBeaVSHpU,972
|
@@ -50,7 +50,7 @@ seleniumbase/core/proxy_helper.py,sha256=cXhu8ErK9Vjdm82RMaQj7hEq_yUWizSp6LyiD50
|
|
50
50
|
seleniumbase/core/recorder_helper.py,sha256=fNGjbapXmEsht54x1o6Igk198QdnPxDDnjUOzQxNhNQ,25055
|
51
51
|
seleniumbase/core/report_helper.py,sha256=AIl6Qava2yW1uSzbLpJBlPlYDz0KE-rVhogh8hsGWBo,12201
|
52
52
|
seleniumbase/core/s3_manager.py,sha256=bkeI8I4y19ebWuQG1oEZV5qJbotC6eN8vin31OCNWJk,3521
|
53
|
-
seleniumbase/core/sb_cdp.py,sha256=
|
53
|
+
seleniumbase/core/sb_cdp.py,sha256=ZuK55SpMu199j0ZI1tJCip8ruM7YR2FH0m0hsATxbxY,43260
|
54
54
|
seleniumbase/core/sb_driver.py,sha256=-k4vHwMnuiBIkdVInTtJA-IDLrgQfyMhNxSHMIsjepw,11623
|
55
55
|
seleniumbase/core/session_helper.py,sha256=s9zD3PVZEWVzG2h81cCUskbNWLfdjC_LwwQjKptHCak,558
|
56
56
|
seleniumbase/core/settings_parser.py,sha256=KokVXpCiGZhJ-D4Bo-hizPz5r-iefzWoiTANu9zNaq4,7504
|
@@ -106,7 +106,7 @@ seleniumbase/translate/portuguese.py,sha256=x3P4qxp56UiI41GoaL7JbUvFRYsgXU1EKjTg
|
|
106
106
|
seleniumbase/translate/russian.py,sha256=TyN9n0b4GRWDEYnHRGw1rfNAscdDmP3F3Y3aySM3C7s,27978
|
107
107
|
seleniumbase/translate/spanish.py,sha256=hh3xgW1Pq122SHYVvJAxFaXhFrjniOVncVbJbfWqOUM,25528
|
108
108
|
seleniumbase/translate/translator.py,sha256=wPhZH6e5NhmebYL1kP2eGxUcVy1gfTb6XCH8ATEPpxE,49238
|
109
|
-
seleniumbase/undetected/__init__.py,sha256=
|
109
|
+
seleniumbase/undetected/__init__.py,sha256=yBUsi4T79yUVxg9yKuDdjeCP85tMiaVBpjarTniBDTQ,23002
|
110
110
|
seleniumbase/undetected/cdp.py,sha256=RLpwZnhUvmK9tgXcZIBBQedwk2q7Jj_EXZkmzI8WUqk,4023
|
111
111
|
seleniumbase/undetected/dprocess.py,sha256=83EV8ZHJWHG1TSUv9JNClBhdgiBXlkCc6mJ--HsoP3k,1681
|
112
112
|
seleniumbase/undetected/options.py,sha256=BoNuwhrG7oOvuLvTwkvsWCF36pMkS1tHCG-XpP4_EkI,3001
|
@@ -116,7 +116,7 @@ seleniumbase/undetected/webelement.py,sha256=_s6evgUkdWJpwOnzX4qR9i796PoVbz3txlz
|
|
116
116
|
seleniumbase/undetected/cdp_driver/__init__.py,sha256=c0TjMwPfVFyoqYOJ7PQ-Jln_L_dpN3ebHyaD-juQoM0,64
|
117
117
|
seleniumbase/undetected/cdp_driver/_contradict.py,sha256=6thDYeoEGiC7Q3tXLgoD_AhxecCFnATzBSjNympyRHA,3184
|
118
118
|
seleniumbase/undetected/cdp_driver/browser.py,sha256=mGmpWuR206yYJoBPTNslru8CbEpQuvvIHdjBylSkoKg,30020
|
119
|
-
seleniumbase/undetected/cdp_driver/cdp_util.py,sha256=
|
119
|
+
seleniumbase/undetected/cdp_driver/cdp_util.py,sha256=Erfb62fzpvGr0QIIJOiqvGkyoyBakHOIwgbrQ7dqUgM,16625
|
120
120
|
seleniumbase/undetected/cdp_driver/config.py,sha256=Rjvde7V-XJ0ihZdTmOmHEVWSuDWm3SprQ3njg8SN3Go,12087
|
121
121
|
seleniumbase/undetected/cdp_driver/connection.py,sha256=HnwXlD4rawGzCyiGR3Shr4iaK7KTncvSqs3CXxCZM_8,23266
|
122
122
|
seleniumbase/undetected/cdp_driver/element.py,sha256=9oD9GxguctunrlHV3lWXlZgb9cNEjD5x03Oy84OqyVA,39631
|
@@ -135,9 +135,9 @@ seleniumbase/utilities/selenium_grid/start-grid-hub.bat,sha256=Ftq-GrAKRYH2ssDPr
|
|
135
135
|
seleniumbase/utilities/selenium_grid/start-grid-hub.sh,sha256=KADv0RUHONLL2_I443QFK8PryBpDmKn5Gy0s4o0vDSM,106
|
136
136
|
seleniumbase/utilities/selenium_ide/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
137
137
|
seleniumbase/utilities/selenium_ide/convert_ide.py,sha256=pZFnqEJQEKZPyNFjkLD29s2HPQgCrWW9XJWpCPhWOoM,31691
|
138
|
-
seleniumbase-4.32.
|
139
|
-
seleniumbase-4.32.
|
140
|
-
seleniumbase-4.32.
|
141
|
-
seleniumbase-4.32.
|
142
|
-
seleniumbase-4.32.
|
143
|
-
seleniumbase-4.32.
|
138
|
+
seleniumbase-4.32.7.dist-info/LICENSE,sha256=odSYtWibXBnQ1gBg6CnDZ82n8kLF_if5-2nbqnEyD8k,1085
|
139
|
+
seleniumbase-4.32.7.dist-info/METADATA,sha256=HIdMgaVZC17OSFsh2a811ES3MZEIgfbjlXgnhyjbDZg,86380
|
140
|
+
seleniumbase-4.32.7.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
141
|
+
seleniumbase-4.32.7.dist-info/entry_points.txt,sha256=CNrh2EKNaHYEhO6pP1RJyVLB99LkDDYX7TnUK8xfjqk,623
|
142
|
+
seleniumbase-4.32.7.dist-info/top_level.txt,sha256=4N97aBOQ8ETCnDnokBsWb07lJfTaq3C1ZzYRxvLMxqU,19
|
143
|
+
seleniumbase-4.32.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|