seleniumbase 4.32.1__py3-none-any.whl → 4.32.2__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/fixtures/base_case.py +87 -49
- seleniumbase/plugins/driver_manager.py +13 -4
- seleniumbase/plugins/sb_manager.py +0 -24
- seleniumbase/undetected/cdp_driver/__init__.py +1 -0
- seleniumbase/undetected/cdp_driver/_contradict.py +110 -0
- seleniumbase/undetected/cdp_driver/browser.py +830 -0
- seleniumbase/undetected/cdp_driver/cdp_util.py +317 -0
- seleniumbase/undetected/cdp_driver/config.py +322 -0
- seleniumbase/undetected/cdp_driver/connection.py +625 -0
- seleniumbase/undetected/cdp_driver/element.py +1150 -0
- seleniumbase/undetected/cdp_driver/tab.py +1319 -0
- {seleniumbase-4.32.1.dist-info → seleniumbase-4.32.2.dist-info}/METADATA +1 -1
- {seleniumbase-4.32.1.dist-info → seleniumbase-4.32.2.dist-info}/RECORD +18 -10
- {seleniumbase-4.32.1.dist-info → seleniumbase-4.32.2.dist-info}/LICENSE +0 -0
- {seleniumbase-4.32.1.dist-info → seleniumbase-4.32.2.dist-info}/WHEEL +0 -0
- {seleniumbase-4.32.1.dist-info → seleniumbase-4.32.2.dist-info}/entry_points.txt +0 -0
- {seleniumbase-4.32.1.dist-info → seleniumbase-4.32.2.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.2"
|
@@ -4090,6 +4090,88 @@ class BaseCase(unittest.TestCase):
|
|
4090
4090
|
"Browser: {%s} is not a valid browser option. "
|
4091
4091
|
"Valid options = {%s}" % (browser, valid_browsers)
|
4092
4092
|
)
|
4093
|
+
# Fix Chrome-130 issues by creating a user-data-dir in advance
|
4094
|
+
if (
|
4095
|
+
undetectable
|
4096
|
+
and (
|
4097
|
+
not user_data_dir
|
4098
|
+
or not os.path.exists(user_data_dir)
|
4099
|
+
or not any(os.scandir(user_data_dir))
|
4100
|
+
)
|
4101
|
+
and self.browser == "chrome"
|
4102
|
+
):
|
4103
|
+
import tempfile
|
4104
|
+
if not user_data_dir:
|
4105
|
+
user_data_dir = os.path.normpath(tempfile.mkdtemp())
|
4106
|
+
self.user_data_dir = user_data_dir
|
4107
|
+
sb_config.user_data_dir = user_data_dir
|
4108
|
+
try:
|
4109
|
+
decoy_driver = browser_launcher.get_driver(
|
4110
|
+
browser_name=browser_name,
|
4111
|
+
headless=headless,
|
4112
|
+
locale_code=locale_code,
|
4113
|
+
use_grid=use_grid,
|
4114
|
+
protocol=protocol,
|
4115
|
+
servername=servername,
|
4116
|
+
port=port,
|
4117
|
+
proxy_string=proxy_string,
|
4118
|
+
proxy_bypass_list=proxy_bypass_list,
|
4119
|
+
proxy_pac_url=proxy_pac_url,
|
4120
|
+
multi_proxy=multi_proxy,
|
4121
|
+
user_agent=user_agent,
|
4122
|
+
cap_file=cap_file,
|
4123
|
+
cap_string=cap_string,
|
4124
|
+
recorder_ext=recorder_ext,
|
4125
|
+
disable_cookies=disable_cookies,
|
4126
|
+
disable_js=disable_js,
|
4127
|
+
disable_csp=disable_csp,
|
4128
|
+
enable_ws=enable_ws,
|
4129
|
+
enable_sync=enable_sync,
|
4130
|
+
use_auto_ext=use_auto_ext,
|
4131
|
+
undetectable=undetectable,
|
4132
|
+
uc_cdp_events=uc_cdp_events,
|
4133
|
+
uc_subprocess=uc_subprocess,
|
4134
|
+
log_cdp_events=log_cdp_events,
|
4135
|
+
no_sandbox=no_sandbox,
|
4136
|
+
disable_gpu=disable_gpu,
|
4137
|
+
headless1=headless1,
|
4138
|
+
headless2=True,
|
4139
|
+
incognito=incognito,
|
4140
|
+
guest_mode=guest_mode,
|
4141
|
+
dark_mode=dark_mode,
|
4142
|
+
devtools=devtools,
|
4143
|
+
remote_debug=remote_debug,
|
4144
|
+
enable_3d_apis=enable_3d_apis,
|
4145
|
+
swiftshader=swiftshader,
|
4146
|
+
ad_block_on=ad_block_on,
|
4147
|
+
host_resolver_rules=host_resolver_rules,
|
4148
|
+
block_images=block_images,
|
4149
|
+
do_not_track=do_not_track,
|
4150
|
+
chromium_arg=chromium_arg,
|
4151
|
+
firefox_arg=firefox_arg,
|
4152
|
+
firefox_pref=firefox_pref,
|
4153
|
+
user_data_dir=user_data_dir,
|
4154
|
+
extension_zip=extension_zip,
|
4155
|
+
extension_dir=extension_dir,
|
4156
|
+
disable_features=disable_features,
|
4157
|
+
binary_location=binary_location,
|
4158
|
+
driver_version=driver_version,
|
4159
|
+
page_load_strategy=page_load_strategy,
|
4160
|
+
use_wire=use_wire,
|
4161
|
+
external_pdf=external_pdf,
|
4162
|
+
test_id=test_id,
|
4163
|
+
mobile_emulator=is_mobile,
|
4164
|
+
device_width=d_width,
|
4165
|
+
device_height=d_height,
|
4166
|
+
device_pixel_ratio=d_p_r,
|
4167
|
+
browser=browser_name,
|
4168
|
+
)
|
4169
|
+
time.sleep(0.555)
|
4170
|
+
except Exception:
|
4171
|
+
pass
|
4172
|
+
finally:
|
4173
|
+
with suppress(Exception):
|
4174
|
+
decoy_driver.quit()
|
4093
4175
|
# Launch a web browser
|
4094
4176
|
new_driver = browser_launcher.get_driver(
|
4095
4177
|
browser_name=browser_name,
|
@@ -4435,7 +4517,12 @@ class BaseCase(unittest.TestCase):
|
|
4435
4517
|
"""Loads the page cookies from the "saved_cookies" folder."""
|
4436
4518
|
cookies = self.get_saved_cookies(name)
|
4437
4519
|
self.wait_for_ready_state_complete()
|
4520
|
+
origin = self.get_origin()
|
4521
|
+
trim_origin = origin.split("://")[-1]
|
4438
4522
|
for cookie in cookies:
|
4523
|
+
if "domain" in cookie:
|
4524
|
+
if cookie["domain"] not in origin:
|
4525
|
+
cookie["domain"] = trim_origin
|
4439
4526
|
if "expiry" in cookie:
|
4440
4527
|
del cookie["expiry"]
|
4441
4528
|
self.driver.add_cookie(cookie)
|
@@ -4656,30 +4743,6 @@ class BaseCase(unittest.TestCase):
|
|
4656
4743
|
if hasattr(self.driver, "_is_using_uc") and self.driver._is_using_uc:
|
4657
4744
|
self.driver.uc_open_with_cdp_mode(url)
|
4658
4745
|
else:
|
4659
|
-
# Fix Chrome-130 issues by creating a user-data-dir in advance
|
4660
|
-
if (
|
4661
|
-
(
|
4662
|
-
not self.user_data_dir
|
4663
|
-
or not os.path.exists(self.user_data_dir)
|
4664
|
-
)
|
4665
|
-
and self.browser == "chrome"
|
4666
|
-
):
|
4667
|
-
import tempfile
|
4668
|
-
user_data_dir = os.path.normpath(tempfile.mkdtemp())
|
4669
|
-
self.user_data_dir = user_data_dir
|
4670
|
-
sb_config.user_data_dir = user_data_dir
|
4671
|
-
try:
|
4672
|
-
driver = self.get_new_driver(
|
4673
|
-
user_data_dir=user_data_dir,
|
4674
|
-
undetectable=True,
|
4675
|
-
headless2=True,
|
4676
|
-
)
|
4677
|
-
time.sleep(0.555)
|
4678
|
-
except Exception:
|
4679
|
-
pass
|
4680
|
-
finally:
|
4681
|
-
with suppress(Exception):
|
4682
|
-
driver.quit()
|
4683
4746
|
self.get_new_driver(undetectable=True)
|
4684
4747
|
self.driver.uc_open_with_cdp_mode(url)
|
4685
4748
|
self.cdp = self.driver.cdp
|
@@ -14941,31 +15004,6 @@ class BaseCase(unittest.TestCase):
|
|
14941
15004
|
self.__js_start_time = int(time.time() * 1000.0)
|
14942
15005
|
else:
|
14943
15006
|
# Launch WebDriver for both pytest and pynose
|
14944
|
-
|
14945
|
-
# Fix Chrome-130 issues by creating a user-data-dir in advance
|
14946
|
-
if (
|
14947
|
-
self.undetectable
|
14948
|
-
and (
|
14949
|
-
not self.user_data_dir
|
14950
|
-
or not os.path.exists(self.user_data_dir)
|
14951
|
-
)
|
14952
|
-
and self.browser == "chrome"
|
14953
|
-
):
|
14954
|
-
import tempfile
|
14955
|
-
user_data_dir = os.path.normpath(tempfile.mkdtemp())
|
14956
|
-
self.user_data_dir = user_data_dir
|
14957
|
-
sb_config.user_data_dir = user_data_dir
|
14958
|
-
try:
|
14959
|
-
driver = self.get_new_driver(
|
14960
|
-
user_data_dir=user_data_dir,
|
14961
|
-
headless2=True,
|
14962
|
-
)
|
14963
|
-
time.sleep(0.555)
|
14964
|
-
except Exception:
|
14965
|
-
pass
|
14966
|
-
finally:
|
14967
|
-
with suppress(Exception):
|
14968
|
-
driver.quit()
|
14969
15007
|
self.driver = self.get_new_driver(
|
14970
15008
|
browser=self.browser,
|
14971
15009
|
headless=self.headless,
|
@@ -792,12 +792,21 @@ def Driver(
|
|
792
792
|
from seleniumbase.core import browser_launcher
|
793
793
|
|
794
794
|
# Fix Chrome-130 issues by creating a user-data-dir in advance
|
795
|
-
if
|
795
|
+
if (
|
796
|
+
undetectable
|
797
|
+
and (
|
798
|
+
not user_data_dir
|
799
|
+
or not os.path.exists(user_data_dir)
|
800
|
+
or not any(os.scandir(user_data_dir))
|
801
|
+
)
|
802
|
+
and browser == "chrome"
|
803
|
+
):
|
796
804
|
import tempfile
|
797
805
|
import time
|
798
|
-
|
799
|
-
|
800
|
-
|
806
|
+
if not user_data_dir:
|
807
|
+
user_data_dir = (
|
808
|
+
os.path.normpath(tempfile.mkdtemp())
|
809
|
+
)
|
801
810
|
try:
|
802
811
|
decoy_driver = browser_launcher.get_driver(
|
803
812
|
browser_name=browser_name,
|
@@ -1212,30 +1212,6 @@ def SB(
|
|
1212
1212
|
if not sb_config.multi_proxy:
|
1213
1213
|
proxy_helper.remove_proxy_zip_if_present()
|
1214
1214
|
start_time = time.time()
|
1215
|
-
saved_headless2 = headless2
|
1216
|
-
|
1217
|
-
# Fix Chrome-130 issues by creating a user-data-dir in advance
|
1218
|
-
if undetectable and not user_data_dir and browser == "chrome":
|
1219
|
-
import tempfile
|
1220
|
-
user_data_dir = (
|
1221
|
-
os.path.normpath(tempfile.mkdtemp())
|
1222
|
-
)
|
1223
|
-
sb.user_data_dir = user_data_dir
|
1224
|
-
sb_config.user_data_dir = user_data_dir
|
1225
|
-
try:
|
1226
|
-
decoy = sb
|
1227
|
-
decoy.headless2 = True
|
1228
|
-
decoy.setUp()
|
1229
|
-
decoy.sleep(0.555)
|
1230
|
-
except Exception:
|
1231
|
-
pass
|
1232
|
-
finally:
|
1233
|
-
try:
|
1234
|
-
decoy.tearDown()
|
1235
|
-
except Exception:
|
1236
|
-
pass
|
1237
|
-
sb.headless2 = saved_headless2
|
1238
|
-
|
1239
1215
|
sb.setUp()
|
1240
1216
|
test_passed = True # This can change later
|
1241
1217
|
teardown_exception = None
|
@@ -0,0 +1 @@
|
|
1
|
+
from seleniumbase.undetected.cdp_driver import cdp_util # noqa
|
@@ -0,0 +1,110 @@
|
|
1
|
+
import warnings as _warnings
|
2
|
+
from collections.abc import Mapping as _Mapping, Sequence as _Sequence
|
3
|
+
import logging
|
4
|
+
|
5
|
+
__logger__ = logging.getLogger(__name__)
|
6
|
+
__all__ = ["cdict", "ContraDict"]
|
7
|
+
|
8
|
+
|
9
|
+
def cdict(*args, **kwargs):
|
10
|
+
"""Factory function"""
|
11
|
+
return ContraDict(*args, **kwargs)
|
12
|
+
|
13
|
+
|
14
|
+
class ContraDict(dict):
|
15
|
+
"""
|
16
|
+
Directly inherited from dict.
|
17
|
+
Accessible by attribute. o.x == o['x']
|
18
|
+
This works also for all corner cases.
|
19
|
+
Native json.dumps and json.loads work with it.
|
20
|
+
|
21
|
+
Names like "keys", "update", "values" etc won't overwrite the methods,
|
22
|
+
but will just be available using dict lookup notation obj['items']
|
23
|
+
instead of obj.items.
|
24
|
+
|
25
|
+
All key names are converted to snake_case.
|
26
|
+
Hyphen's (-), dot's (.) or whitespaces are replaced by underscore (_).
|
27
|
+
Autocomplete works even if the objects comes from a list.
|
28
|
+
Recursive action. Dict assignments will be converted too.
|
29
|
+
"""
|
30
|
+
__module__ = None
|
31
|
+
|
32
|
+
def __init__(self, *args, **kwargs):
|
33
|
+
super().__init__()
|
34
|
+
silent = kwargs.pop("silent", False)
|
35
|
+
_ = dict(*args, **kwargs)
|
36
|
+
|
37
|
+
super().__setattr__("__dict__", self)
|
38
|
+
for k, v in _.items():
|
39
|
+
_check_key(k, self, False, silent)
|
40
|
+
super().__setitem__(k, _wrap(self.__class__, v))
|
41
|
+
|
42
|
+
def __setitem__(self, key, value):
|
43
|
+
super().__setitem__(key, _wrap(self.__class__, value))
|
44
|
+
|
45
|
+
def __setattr__(self, key, value):
|
46
|
+
super().__setitem__(key, _wrap(self.__class__, value))
|
47
|
+
|
48
|
+
def __getattribute__(self, attribute):
|
49
|
+
if attribute in self:
|
50
|
+
return self[attribute]
|
51
|
+
if not _check_key(attribute, self, True, silent=True):
|
52
|
+
return getattr(super(), attribute)
|
53
|
+
return object.__getattribute__(self, attribute)
|
54
|
+
|
55
|
+
|
56
|
+
def _wrap(cls, v):
|
57
|
+
if isinstance(v, _Mapping):
|
58
|
+
v = cls(v)
|
59
|
+
elif isinstance(v, _Sequence) and not isinstance(
|
60
|
+
v, (str, bytes, bytearray, set, tuple)
|
61
|
+
):
|
62
|
+
v = list([_wrap(cls, x) for x in v])
|
63
|
+
return v
|
64
|
+
|
65
|
+
|
66
|
+
_warning_names = (
|
67
|
+
"items",
|
68
|
+
"keys",
|
69
|
+
"values",
|
70
|
+
"update",
|
71
|
+
"clear",
|
72
|
+
"copy",
|
73
|
+
"fromkeys",
|
74
|
+
"get",
|
75
|
+
"items",
|
76
|
+
"keys",
|
77
|
+
"pop",
|
78
|
+
"popitem",
|
79
|
+
"setdefault",
|
80
|
+
"update",
|
81
|
+
"values",
|
82
|
+
"class",
|
83
|
+
)
|
84
|
+
|
85
|
+
_warning_names_message = """\n\
|
86
|
+
While creating a ContraDict object, a key offending key name '{0}'
|
87
|
+
has been found, which might behave unexpected.
|
88
|
+
You will only be able to look it up using key,
|
89
|
+
eg. myobject['{0}']. myobject.{0} will not work with that name."""
|
90
|
+
|
91
|
+
|
92
|
+
def _check_key(
|
93
|
+
key: str, mapping: _Mapping, boolean: bool = False, silent=False
|
94
|
+
):
|
95
|
+
"""Checks `key` and warns if needed.
|
96
|
+
:param key:
|
97
|
+
:param boolean: return True or False instead of passthrough
|
98
|
+
"""
|
99
|
+
e = None
|
100
|
+
if not isinstance(key, (str,)):
|
101
|
+
if boolean:
|
102
|
+
return True
|
103
|
+
return key
|
104
|
+
if key.lower() in _warning_names or any(_ in key for _ in ("-", ".")):
|
105
|
+
if not silent:
|
106
|
+
_warnings.warn(_warning_names_message.format(key))
|
107
|
+
e = True
|
108
|
+
if not boolean:
|
109
|
+
return key
|
110
|
+
return not e
|