Skip to content

Commit 8d37f15

Browse files
authored
Merge pull request #3707 from seleniumbase/cdp-mode-patch-45
CDP Mode: Patch 45
2 parents 54e76c8 + fb4d472 commit 8d37f15

File tree

9 files changed

+88
-86
lines changed

9 files changed

+88
-86
lines changed

mkdocs_build/requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Minimum Python version: 3.9 (for generating docs only)
33

44
regex>=2024.11.6
5-
pymdown-extensions>=10.14.3
5+
pymdown-extensions>=10.15
66
pipdeptree>=2.26.1
77
python-dateutil>=2.8.2
88
Markdown==3.8

requirements.txt

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
pip>=25.0.1
1+
pip>=25.0.1;python_version<"3.9"
2+
pip>=25.1;python_version>="3.9"
23
packaging>=25.0
34
setuptools~=70.2;python_version<"3.10"
4-
setuptools>=79.0.1;python_version>="3.10"
5+
setuptools>=80.0.0;python_version>="3.10"
56
wheel>=0.45.1
67
attrs>=25.3.0
7-
certifi>=2025.1.31
8+
certifi>=2025.4.26
89
exceptiongroup>=1.2.2
910
websockets~=13.1;python_version<"3.9"
1011
websockets>=15.0.1;python_version>="3.9"

seleniumbase/__version__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# seleniumbase package
2-
__version__ = "4.37.7"
2+
__version__ = "4.37.8"

seleniumbase/core/browser_launcher.py

+4
Original file line numberDiff line numberDiff line change
@@ -546,12 +546,15 @@ def uc_open_with_cdp_mode(driver, url=None):
546546
headless = False
547547
headed = None
548548
xvfb = None
549+
binary_location = None
549550
if hasattr(sb_config, "headless"):
550551
headless = sb_config.headless
551552
if hasattr(sb_config, "headed"):
552553
headed = sb_config.headed
553554
if hasattr(sb_config, "xvfb"):
554555
xvfb = sb_config.xvfb
556+
if hasattr(sb_config, "binary_location"):
557+
binary_location = sb_config.binary_location
555558

556559
loop = asyncio.new_event_loop()
557560
asyncio.set_event_loop(loop)
@@ -562,6 +565,7 @@ def uc_open_with_cdp_mode(driver, url=None):
562565
headless=headless,
563566
headed=headed,
564567
xvfb=xvfb,
568+
browser_executable_path=binary_location,
565569
)
566570
)
567571
loop.run_until_complete(driver.cdp_base.wait(0))

seleniumbase/plugins/sb_manager.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1234,7 +1234,8 @@ def SB(
12341234
sb._has_failure = False # This may change
12351235

12361236
with suppress(Exception):
1237-
stack_base = traceback.format_stack()[0].split(os.sep)[-1]
1237+
stack_base = traceback.format_stack()[0].split("with SB(")[0]
1238+
stack_base = stack_base.split(os.sep)[-1]
12381239
test_base = stack_base.split(", in ")[0]
12391240
filename = test_base.split('"')[0]
12401241
methodname = ".line_" + test_base.split(", line ")[-1]
@@ -1251,7 +1252,8 @@ def SB(
12511252
c1 = colorama.Fore.GREEN
12521253
b1 = colorama.Style.BRIGHT
12531254
cr = colorama.Style.RESET_ALL
1254-
stack_base = traceback.format_stack()[0].split(os.sep)[-1]
1255+
stack_base = traceback.format_stack()[0].split("with SB(")[0]
1256+
stack_base = stack_base.split(os.sep)[-1]
12551257
test_name = stack_base.split(", in ")[0].replace('", line ', ":")
12561258
test_name += ":SB"
12571259
start_text = "=== {%s} starts ===" % test_name

seleniumbase/undetected/cdp_driver/browser.py

+50-75
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,8 @@ def deconstruct_browser():
4646
logger.debug(
4747
"Problem removing data dir %s\n"
4848
"Consider checking whether it's there "
49-
"and remove it by hand\nerror: %s",
50-
_.config.user_data_dir,
51-
e,
49+
"and remove it by hand\nerror: %s"
50+
% (_.config.user_data_dir, e)
5251
)
5352
break
5453
time.sleep(0.15)
@@ -190,7 +189,7 @@ async def wait(self, time: Union[float, int] = 1) -> Browser:
190189

191190
sleep = wait
192191
"""Alias for wait"""
193-
def _handle_target_update(
192+
async def _handle_target_update(
194193
self,
195194
event: Union[
196195
cdp.target.TargetInfoChanged,
@@ -224,21 +223,21 @@ def _handle_target_update(
224223
current_tab.target = target_info
225224
elif isinstance(event, cdp.target.TargetCreated):
226225
target_info: cdp.target.TargetInfo = event.target_info
227-
from .tab import Tab
228-
229-
new_target = Tab(
230-
(
231-
f"ws://{self.config.host}:{self.config.port}"
232-
f"/devtools/{target_info.type_ or 'page'}"
233-
f"/{target_info.target_id}"
234-
),
235-
target=target_info,
236-
browser=self,
237-
)
238-
self.targets.append(new_target)
239-
logger.debug(
240-
"Target #%d created => %s", len(self.targets), new_target
226+
websocket_url = (
227+
f"ws://{self.config.host}:{self.config.port}"
228+
f"/devtools/{target_info.type_ or 'page'}"
229+
f"/{target_info.target_id}"
241230
)
231+
async with tab.Tab(
232+
websocket_url=websocket_url,
233+
target=target_info,
234+
browser=self
235+
) as new_target:
236+
self.targets.append(new_target)
237+
logger.debug(
238+
"Target #%d created => %s"
239+
% (len(self.targets), new_target)
240+
)
242241
elif isinstance(event, cdp.target.TargetDestroyed):
243242
current_tab = next(
244243
filter(
@@ -287,62 +286,42 @@ async def get(
287286
connection: tab.Tab = next(
288287
filter(lambda item: item.type_ == "page", self.targets)
289288
)
290-
if hasattr(sb_config, "_cdp_locale") and sb_config._cdp_locale:
291-
await connection.send(cdp.page.navigate("about:blank"))
292-
if (
293-
hasattr(sb_config, "_cdp_user_agent")
294-
and sb_config._cdp_user_agent
295-
):
296-
pass
297-
elif (
298-
hasattr(sb_config, "_cdp_platform")
299-
and sb_config._cdp_platform
300-
):
301-
pass
302-
else:
303-
await connection.set_locale(sb_config._cdp_locale)
304-
if hasattr(sb_config, "_cdp_timezone") and sb_config._cdp_timezone:
305-
await connection.send(cdp.page.navigate("about:blank"))
306-
await connection.set_timezone(sb_config._cdp_timezone)
289+
_cdp_timezone = None
290+
_cdp_user_agent = ""
291+
_cdp_locale = None
292+
_cdp_platform = None
293+
_cdp_geolocation = None
294+
if (
295+
hasattr(sb_config, "_cdp_timezone") and sb_config._cdp_timezone
296+
):
297+
_cdp_timezone = sb_config._cdp_timezone
307298
if (
308299
hasattr(sb_config, "_cdp_user_agent")
309300
and sb_config._cdp_user_agent
310301
):
311-
await connection.send(cdp.page.navigate("about:blank"))
312-
if hasattr(sb_config, "_cdp_locale") and sb_config._cdp_locale:
313-
_cdp_platform = None
314-
if (
315-
hasattr(sb_config, "_cdp_platform")
316-
and sb_config._cdp_platform
317-
):
318-
_cdp_platform = sb_config._cdp_platform
319-
await connection.set_user_agent(
320-
sb_config._cdp_user_agent,
321-
sb_config._cdp_locale,
322-
_cdp_platform,
323-
)
324-
else:
325-
await connection.set_user_agent(sb_config._cdp_user_agent)
326-
elif (
327-
hasattr(sb_config, "_cdp_platform") and sb_config._cdp_platform
328-
):
329-
await connection.send(cdp.page.navigate("about:blank"))
330-
if hasattr(sb_config, "_cdp_locale") and sb_config._cdp_locale:
331-
_cdp_platform = sb_config._cdp_platform
332-
await connection.set_user_agent(
333-
accept_language=sb_config._cdp_locale,
334-
platform=_cdp_platform,
335-
)
336-
else:
337-
await connection.set_user_agent(
338-
platform=sb_config._cdp_platform
339-
)
302+
_cdp_user_agent = sb_config._cdp_user_agent
303+
if hasattr(sb_config, "_cdp_locale") and sb_config._cdp_locale:
304+
_cdp_locale = sb_config._cdp_locale
305+
if hasattr(sb_config, "_cdp_platform") and sb_config._cdp_platform:
306+
_cdp_platform = sb_config._cdp_platform
340307
if (
341308
hasattr(sb_config, "_cdp_geolocation")
342309
and sb_config._cdp_geolocation
343310
):
311+
_cdp_geolocation = sb_config._cdp_geolocation
312+
if _cdp_timezone:
313+
await connection.send(cdp.page.navigate("about:blank"))
314+
await connection.set_timezone(_cdp_timezone)
315+
if _cdp_user_agent or _cdp_locale or _cdp_platform:
316+
await connection.send(cdp.page.navigate("about:blank"))
317+
await connection.set_user_agent(
318+
user_agent=_cdp_user_agent,
319+
accept_language=_cdp_locale,
320+
platform=_cdp_platform,
321+
)
322+
if _cdp_geolocation:
344323
await connection.send(cdp.page.navigate("about:blank"))
345-
await connection.set_geolocation(sb_config._cdp_geolocation)
324+
await connection.set_geolocation(_cdp_geolocation)
346325
# Use the tab to navigate to new url
347326
frame_id, loader_id, *_ = await connection.send(
348327
cdp.page.navigate(url)
@@ -376,8 +355,8 @@ async def start(self=None) -> Browser:
376355
self.config.port = util.free_port()
377356
if not connect_existing:
378357
logger.debug(
379-
"BROWSER EXECUTABLE PATH: %s",
380-
self.config.browser_executable_path,
358+
"BROWSER EXECUTABLE PATH: %s"
359+
% self.config.browser_executable_path,
381360
)
382361
if not pathlib.Path(self.config.browser_executable_path).exists():
383362
raise FileNotFoundError(
@@ -782,10 +761,8 @@ async def save(self, file: PathLike = ".session.dat", pattern: str = ".*"):
782761
for cookie in cookies:
783762
for match in pattern.finditer(str(cookie.__dict__)):
784763
logger.debug(
785-
"Saved cookie for matching pattern '%s' => (%s: %s)",
786-
pattern.pattern,
787-
cookie.name,
788-
cookie.value,
764+
"Saved cookie for matching pattern '%s' => (%s: %s)"
765+
% (pattern.pattern, cookie.name, cookie.value)
789766
)
790767
included_cookies.append(cookie)
791768
break
@@ -822,10 +799,8 @@ async def load(self, file: PathLike = ".session.dat", pattern: str = ".*"):
822799
for match in pattern.finditer(str(cookie.__dict__)):
823800
included_cookies.append(cookie)
824801
logger.debug(
825-
"Loaded cookie for matching pattern '%s' => (%s: %s)",
826-
pattern.pattern,
827-
cookie.name,
828-
cookie.value,
802+
"Loaded cookie for matching pattern '%s' => (%s: %s)"
803+
% (pattern.pattern, cookie.name, cookie.value)
829804
)
830805
break
831806
await connection.send(cdp.network.set_cookies(included_cookies))

seleniumbase/undetected/cdp_driver/cdp_util.py

+5
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,11 @@ async def start(
325325
ad_block_dir = os.path.join(DOWNLOADS_FOLDER, "ad_block")
326326
__unzip_to_new_folder(ad_block_zip, ad_block_dir)
327327
extension_dir = __add_chrome_ext_dir(extension_dir, ad_block_dir)
328+
if (
329+
"binary_location" in kwargs
330+
and not browser_executable_path
331+
):
332+
browser_executable_path = kwargs["binary_location"]
328333
if not config:
329334
config = Config(
330335
user_data_dir,

seleniumbase/undetected/cdp_driver/tab.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import pathlib
77
import urllib.parse
88
import warnings
9+
from seleniumbase import config as sb_config
910
from typing import Dict, List, Union, Optional, Tuple
1011
from . import browser as cdp_browser
1112
from . import element
@@ -137,6 +138,14 @@ def __init__(
137138
self._dom = None
138139
self._window_id = None
139140

141+
async def __aenter__(self):
142+
return self
143+
144+
async def __aexit__(self, exc_type, exc_val, exc_tb):
145+
await self.aclose()
146+
if exc_type and exc_val:
147+
raise exc_type(exc_val)
148+
140149
@property
141150
def inspector_url(self):
142151
"""
@@ -348,7 +357,12 @@ async def get(
348357
if new_window and not new_tab:
349358
new_tab = True
350359
if new_tab:
351-
return await self.browser.get(url, new_tab, new_window)
360+
if hasattr(sb_config, "incognito") and sb_config.incognito:
361+
return await self.browser.get(
362+
url, new_tab=False, new_window=True
363+
)
364+
else:
365+
return await self.browser.get(url, new_tab, new_window)
352366
else:
353367
frame_id, loader_id, *_ = await self.send(cdp.page.navigate(url))
354368
await self

setup.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,14 @@
147147
],
148148
python_requires=">=3.8",
149149
install_requires=[
150-
'pip>=25.0.1',
150+
'pip>=25.0.1;python_version<"3.9"',
151+
'pip>=25.1;python_version>="3.9"',
151152
'packaging>=25.0',
152153
'setuptools~=70.2;python_version<"3.10"', # Newer ones had issues
153-
'setuptools>=79.0.1;python_version>="3.10"',
154+
'setuptools>=80.0.0;python_version>="3.10"',
154155
'wheel>=0.45.1',
155156
'attrs>=25.3.0',
156-
"certifi>=2025.1.31",
157+
"certifi>=2025.4.26",
157158
"exceptiongroup>=1.2.2",
158159
'websockets~=13.1;python_version<"3.9"',
159160
'websockets>=15.0.1;python_version>="3.9"',

0 commit comments

Comments
 (0)