Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/cdp_mode/playwright/raw_clearcote_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
sb.select_option_by_text("select", "Mouse")
sb.click('button:contains("Run the audit")')
sb.sleep(6)
sb.assert_element("div.text-successText", timeout=8)
sb.assert_element("div.text-successText", timeout=10)
try:
sb.assert_text("100", "div.text-successText", timeout=5)
sb.highlight('div.text-successText:contains("100")')
Expand Down
2 changes: 1 addition & 1 deletion examples/cdp_mode/raw_cdp_clearcote.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
sb.select_option_by_text("select", "Mouse")
sb.click('button:contains("Run the audit")')
sb.sleep(6)
sb.assert_element("div.text-successText", timeout=8)
sb.assert_element("div.text-successText", timeout=10)
try:
sb.assert_text("100", "div.text-successText", timeout=5)
sb.highlight('div.text-successText:contains("100")')
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pip>=26.0.1;python_version<"3.10"
pip>=26.2;python_version>="3.10"
packaging>=26.2
pip>=26.2.1;python_version>="3.10"
packaging>=26.3
setuptools~=70.2;python_version<"3.10"
setuptools>=83.0.0;python_version>="3.10"
wheel>=0.47.0
Expand Down
2 changes: 1 addition & 1 deletion seleniumbase/__version__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# seleniumbase package
__version__ = "4.51.9"
__version__ = "4.51.10"
78 changes: 78 additions & 0 deletions seleniumbase/core/nest_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,84 @@ def _get_event_loop(stacklevel=3):
asyncio.Future = asyncio.futures._CFuture = asyncio.futures.Future = (
asyncio.futures._PyFuture
)

# -----------------------------------------------------------------
# Python 3.14+ FIX: Hybrid Task Visibility.
# Playwright background loops natively run _CTasks.
# Patched loops run _PyTasks.
# We must keep both environments synchronized and visible to current_task()
if sys.version_info >= (3, 14, 0):
_c_current_task = asyncio.current_task
_c_all_tasks = asyncio.all_tasks
_c_swap_current_task = (
getattr(asyncio.tasks, "_swap_current_task", None)
)

def _patched_current_task(loop=None):
# 1. Check C-level state (finds Playwright / Extension tasks)
t = _c_current_task(loop)
if t is not None:
return t
# 2. Check pure-Python state (finds patched nest_asyncio tasks)
if hasattr(asyncio.tasks, "_py_current_task"):
return asyncio.tasks._py_current_task(loop)
return None

def _patched_all_tasks(loop=None):
tasks = _c_all_tasks(loop) or set()
if hasattr(asyncio.tasks, "_py_all_tasks"):
tasks.update(asyncio.tasks._py_all_tasks(loop) or set())
return tasks

def _patched_swap_current_task(loop, task):
old_c = None
if _c_swap_current_task is not None:
try:
old_c = _c_swap_current_task(loop, None)
except (KeyError, RuntimeError):
pass

old_py = None
if hasattr(asyncio.tasks, "_py_swap_current_task"):
try:
old_py = asyncio.tasks._py_swap_current_task(loop, None)
except (KeyError, RuntimeError):
pass

if task is not None:
if _c_swap_current_task is not None:
try:
_c_swap_current_task(loop, task)
except (TypeError, ValueError):
pass
if hasattr(asyncio.tasks, "_py_swap_current_task"):
try:
asyncio.tasks._py_swap_current_task(loop, task)
except (TypeError, ValueError):
pass

return old_c or old_py

asyncio.tasks.current_task = _patched_current_task
asyncio.current_task = _patched_current_task
asyncio.tasks.all_tasks = _patched_all_tasks
asyncio.all_tasks = _patched_all_tasks
if _c_swap_current_task is not None:
asyncio.tasks._swap_current_task = _patched_swap_current_task

for func in (
"_enter_task",
"_leave_task",
"_register_task",
"_unregister_task",
"_register_eager_task",
"_unregister_eager_task",
):
py_func = f"_py{func}"
if hasattr(asyncio.tasks, py_func):
setattr(asyncio.tasks, func, getattr(asyncio.tasks, py_func))
# -----------------------------------------------------------------

asyncio.get_event_loop = _get_event_loop
events._get_event_loop = events.get_event_loop = asyncio.get_event_loop
asyncio.run = run
Expand Down
4 changes: 2 additions & 2 deletions seleniumbase/undetected/cdp_driver/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ async def mouse_click_async(
asyncio.create_task(self.flash_async(0.25))'''
with suppress(Exception):
await self.mouse_move_async()
await asyncio.sleep(random.uniform(0.0035, 0.0048))
await asyncio.sleep(random.uniform(0.0036, 0.0046))
x = center[0] + random.uniform(-0.85, 0.85)
y = center[1] + random.uniform(-0.85, 0.85)
asyncio.create_task(
Expand All @@ -546,7 +546,7 @@ async def mouse_click_async(
)
if not timeframe or timeframe <= 0:
# If 0 (or less), hold for a small amount of time
await asyncio.sleep(random.uniform(0.0126, 0.0152))
await asyncio.sleep(random.uniform(0.0142, 0.0152))
x += random.uniform(-0.12, 0.12)
y += random.uniform(-0.12, 0.12)
else:
Expand Down
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@
python_requires=">=3.9",
install_requires=[
'pip>=26.0.1;python_version<"3.10"',
'pip>=26.2;python_version>="3.10"',
'packaging>=26.2',
'pip>=26.2.1;python_version>="3.10"',
'packaging>=26.3',
'setuptools~=70.2;python_version<"3.10"', # Newer ones had issues
'setuptools>=83.0.0;python_version>="3.10"',
'wheel>=0.47.0',
Expand Down Expand Up @@ -278,7 +278,7 @@
'pdfminer.six==20260107;python_version>="3.10"',
'cryptography==50.0.0',
'cffi==2.0.0;python_version<"3.10"',
'cffi==2.1.0;python_version>="3.10"',
'cffi==2.1.1;python_version>="3.10"',
'pycparser==2.23;python_version<"3.10"',
'pycparser==3.0;python_version>="3.10"',
],
Expand Down