diff --git a/mkdocs_build/requirements.txt b/mkdocs_build/requirements.txt index 492b7ff975e..def6e314b11 100644 --- a/mkdocs_build/requirements.txt +++ b/mkdocs_build/requirements.txt @@ -6,7 +6,7 @@ pymdown-extensions>=10.15 pipdeptree>=2.26.1 python-dateutil>=2.8.2 Markdown==3.8 -click==8.2.0 +click==8.2.1 ghp-import==2.1.0 watchdog==6.0.0 cairocffi==1.7.1 @@ -14,7 +14,7 @@ pathspec==0.12.1 Babel==2.17.0 paginate==0.5.7 mkdocs==1.6.1 -mkdocs-material==9.6.13 +mkdocs-material==9.6.14 mkdocs-exclude-search==0.6.6 mkdocs-simple-hooks==0.1.5 mkdocs-material-extensions==1.3.1 diff --git a/requirements.txt b/requirements.txt index 0447e777129..f104aedf4e8 100755 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ pip>=25.0.1;python_version<"3.9" pip>=25.1.1;python_version>="3.9" packaging>=25.0 setuptools~=70.2;python_version<"3.10" -setuptools>=80.4.0;python_version>="3.10" +setuptools>=80.8.0;python_version>="3.10" wheel>=0.45.1 attrs>=25.3.0 certifi>=2025.4.26 @@ -51,7 +51,8 @@ cssselect==1.3.0;python_version>="3.9" sortedcontainers==2.4.0 execnet==2.1.1 iniconfig==2.1.0 -pluggy==1.5.0 +pluggy==1.5.0;python_version<"3.9" +pluggy==1.6.0;python_version>="3.9" pytest==8.3.5 pytest-html==4.0.2 pytest-metadata==3.1.1 @@ -73,7 +74,7 @@ rich>=14.0.0,<15 # ("pip install -r requirements.txt" also installs this, but "pip install -e ." won't.) coverage>=7.6.1;python_version<"3.9" -coverage>=7.8.0;python_version>="3.9" +coverage>=7.8.1;python_version>="3.9" pytest-cov>=5.0.0;python_version<"3.9" pytest-cov>=6.1.1;python_version>="3.9" flake8==5.0.4;python_version<"3.9" diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py index 326851e4780..608255c7e2a 100755 --- a/seleniumbase/__version__.py +++ b/seleniumbase/__version__.py @@ -1,2 +1,2 @@ # seleniumbase package -__version__ = "4.38.2" +__version__ = "4.38.3" diff --git a/seleniumbase/core/browser_launcher.py b/seleniumbase/core/browser_launcher.py index f4e44bc6963..eb30a46053e 100644 --- a/seleniumbase/core/browser_launcher.py +++ b/seleniumbase/core/browser_launcher.py @@ -404,7 +404,7 @@ def uc_special_open_if_cf( special = True if status_str == "403" or status_str == "429": time.sleep(0.06) # Forbidden / Blocked! (Wait first!) - if special: + if special and not hasattr(driver, "cdp_base"): time.sleep(0.05) with driver: driver.execute_script('window.open("%s","_blank");' % url) @@ -472,9 +472,12 @@ def uc_open_with_tab(driver, url): time.sleep(0.3) return if (url.startswith("http:") or url.startswith("https:")): - with driver: - driver.execute_script('window.open("%s","_blank");' % url) - driver.close() + if not hasattr(driver, "cdp_base"): + with driver: + driver.execute_script('window.open("%s","_blank");' % url) + driver.close() + else: + driver.cdp.open(url) page_actions.switch_to_window(driver, driver.window_handles[-1], 2) else: driver.default_get(url) # The original one @@ -492,9 +495,12 @@ def uc_open_with_reconnect(driver, url, reconnect_time=None): reconnect_time = constants.UC.RECONNECT_TIME if (url.startswith("http:") or url.startswith("https:")): script = 'window.open("%s","_blank");' % url - driver.execute_script(script) - time.sleep(0.05) - driver.close() + if not hasattr(driver, "cdp_base"): + driver.execute_script(script) + time.sleep(0.05) + driver.close() + else: + driver.cdp.open(url) if reconnect_time == "disconnect": driver.disconnect() time.sleep(0.008) diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py index 6d727227206..8ddb9ab5f3a 100644 --- a/seleniumbase/fixtures/base_case.py +++ b/seleniumbase/fixtures/base_case.py @@ -7678,10 +7678,13 @@ def assert_downloaded_file(self, file, timeout=None, browser=False): break time.sleep(1) if not found and not os.path.exists(downloaded_file_path): + plural = "s" + if timeout == 1: + plural = "" message = ( "File {%s} was not found in the downloads folder {%s} " - "after %s seconds! (Or the download didn't complete!)" - % (file, df, timeout) + "after %s second%s! (Or the download didn't complete!)" + % (file, df, timeout, plural) ) page_actions.timeout_exception("NoSuchFileException", message) if self.recorder_mode and self.__current_url_is_recordable(): @@ -7735,10 +7738,13 @@ def assert_downloaded_file_regex(self, regex, timeout=None, browser=False): break time.sleep(1) if not found: + plural = "s" + if timeout == 1: + plural = "" message = ( "Regex {%s} was not found in the downloads folder {%s} " - "after %s seconds! (Or the download didn't complete!)" - % (regex, df, timeout) + "after %s second%s! (Or the download didn't complete!)" + % (regex, df, timeout, plural) ) page_actions.timeout_exception("NoSuchFileException", message) if self.demo_mode: @@ -8262,7 +8268,10 @@ def is_connected(self): In CDP Mode, the CDP-Driver controls the web browser. The CDP-Driver can be connected while WebDriver isn't. """ - return self.driver.is_connected() + if hasattr(self.driver, "is_connected"): + return self.driver.is_connected() + else: + return True def is_chromium(self): """Return True if the browser is Chrome or Edge.""" @@ -10174,9 +10183,13 @@ def wait_for_link_text_present(self, link_text, timeout=None): if now_ms >= stop_ms: break time.sleep(0.2) - message = "Link text {%s} was not found after %s seconds!" % ( + plural = "s" + if timeout == 1: + plural = "" + message = "Link text {%s} was not found after %s second%s!" % ( link_text, timeout, + plural, ) page_actions.timeout_exception("LinkTextNotFoundException", message) @@ -10199,9 +10212,12 @@ def wait_for_partial_link_text_present(self, link_text, timeout=None): if now_ms >= stop_ms: break time.sleep(0.2) + plural = "s" + if timeout == 1: + plural = "" message = ( - "Partial Link text {%s} was not found after %s seconds!" - "" % (link_text, timeout) + "Partial Link text {%s} was not found after %s second%s!" + "" % (link_text, timeout, plural) ) page_actions.timeout_exception("LinkTextNotFoundException", message) @@ -14409,9 +14425,12 @@ def __get_shadow_element( if must_be_visible and is_present: error = "not visible" the_exception = "ElementNotVisibleException" + plural = "s" + if timeout == 1: + plural = "" msg = ( - "Shadow DOM Element {%s} was %s after %s seconds!" - % (selector_chain, error, timeout) + "Shadow DOM Element {%s} was %s after %s second%s!" + % (selector_chain, error, timeout, plural) ) page_actions.timeout_exception(the_exception, msg) return element diff --git a/seleniumbase/undetected/cdp_driver/tab.py b/seleniumbase/undetected/cdp_driver/tab.py index 95f6f77ab75..b0b9dc0fa3c 100644 --- a/seleniumbase/undetected/cdp_driver/tab.py +++ b/seleniumbase/undetected/cdp_driver/tab.py @@ -493,6 +493,8 @@ async def find_elements_by_text( search_id, nresult = await self.send( cdp.dom.perform_search(text, True) ) + if not nresult: + return [] if nresult: node_ids = await self.send( cdp.dom.get_search_results(search_id, 0, nresult) @@ -584,6 +586,8 @@ async def find_element_by_text( search_id, nresult = await self.send( cdp.dom.perform_search(text, True) ) + if not nresult: + return node_ids = await self.send( cdp.dom.get_search_results(search_id, 0, nresult) ) diff --git a/setup.py b/setup.py index bf9a5da2433..ffa6e4ced1a 100755 --- a/setup.py +++ b/setup.py @@ -151,7 +151,7 @@ 'pip>=25.1.1;python_version>="3.9"', 'packaging>=25.0', 'setuptools~=70.2;python_version<"3.10"', # Newer ones had issues - 'setuptools>=80.4.0;python_version>="3.10"', + 'setuptools>=80.8.0;python_version>="3.10"', 'wheel>=0.45.1', 'attrs>=25.3.0', "certifi>=2025.4.26", @@ -200,7 +200,8 @@ "sortedcontainers==2.4.0", 'execnet==2.1.1', 'iniconfig==2.1.0', - 'pluggy==1.5.0', + 'pluggy==1.5.0;python_version<"3.9"', + 'pluggy==1.6.0;python_version>="3.9"', 'pytest==8.3.5', "pytest-html==4.0.2", # Newer ones had issues 'pytest-metadata==3.1.1', @@ -231,7 +232,7 @@ # Usage: coverage run -m pytest; coverage html; coverage report "coverage": [ 'coverage>=7.6.1;python_version<"3.9"', - 'coverage>=7.8.0;python_version>="3.9"', + 'coverage>=7.8.1;python_version>="3.9"', 'pytest-cov>=5.0.0;python_version<"3.9"', 'pytest-cov>=6.1.1;python_version>="3.9"', ], @@ -264,7 +265,7 @@ 'pdfminer.six==20250324;python_version<"3.9"', 'pdfminer.six==20250506;python_version>="3.9"', 'cryptography==39.0.2;python_version<"3.9"', - 'cryptography==44.0.3;python_version>="3.9"', + 'cryptography==45.0.2;python_version>="3.9"', 'cffi==1.17.1', "pycparser==2.22", ],