From 1f606f967150817d73d98b4da81a60eda8acef46 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 8 Dec 2025 22:52:16 -0500 Subject: [PATCH 1/6] Fix issue with passing options to new tabs in CDP Mode --- seleniumbase/core/sb_cdp.py | 6 ++++-- seleniumbase/fixtures/base_case.py | 18 +++++++++--------- seleniumbase/undetected/cdp_driver/browser.py | 15 ++++++++++----- seleniumbase/undetected/cdp_driver/tab.py | 2 +- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/seleniumbase/core/sb_cdp.py b/seleniumbase/core/sb_cdp.py index 8e3e7ac03fb..aad1d27ad0c 100644 --- a/seleniumbase/core/sb_cdp.py +++ b/seleniumbase/core/sb_cdp.py @@ -1182,13 +1182,15 @@ def switch_to_window(self, window): def switch_to_newest_window(self): self.switch_to_tab(-1) - def open_new_tab(self, url=None, switch_to=True): + def open_new_tab(self, url=None, switch_to=True, **kwargs): driver = self.driver if not isinstance(url, str): url = "about:blank" if hasattr(driver, "cdp_base"): try: - self.loop.run_until_complete(self.page.get(url, new_tab=True)) + self.loop.run_until_complete( + self.page.get(url, new_tab=True, **kwargs) + ) except Exception: original_targets = self.loop.run_until_complete( self.page.send(mycdp.target.get_targets()) diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py index 425ab1b00d6..447ef349646 100644 --- a/seleniumbase/fixtures/base_case.py +++ b/seleniumbase/fixtures/base_case.py @@ -221,11 +221,11 @@ def test_example(self): [sys.executable, "-m", "pytest", file, "-s", *all_args] ) - def open(self, url): + def open(self, url, **kwargs): """Navigates the current browser window to the specified page.""" self.__check_scope() if self.__is_cdp_swap_needed(): - self.cdp.open(url) + self.cdp.open(url, **kwargs) return elif ( getattr(self.driver, "_is_using_uc", None) @@ -235,14 +235,14 @@ def open(self, url): # Auth in UC Mode requires CDP Mode # (and now we're always forcing it) logging.info("open() in UC Mode now always activates CDP Mode.") - self.activate_cdp_mode(url) + self.activate_cdp_mode(url, **kwargs) return elif ( getattr(self.driver, "_is_using_uc", None) and getattr(self.driver, "_is_using_cdp", None) ): self.disconnect() - self.cdp.open(url) + self.cdp.open(url, **kwargs) return self._check_browser() if self.__needs_minimum_wait(): @@ -3960,7 +3960,7 @@ def set_content_to_parent_frame(self): Reverts self.set_content_to_frame().""" self.set_content_to_default(nested=True) - def open_new_window(self, switch_to=True): + def open_new_window(self, switch_to=True, **kwargs): """Opens a new browser tab/window and switches to it by default.""" url = None if self.__looks_like_a_page_url(str(switch_to)): @@ -3969,14 +3969,14 @@ def open_new_window(self, switch_to=True): url = switch_to switch_to = True if self.__is_cdp_swap_needed(): - self.cdp.open_new_tab(url=url, switch_to=switch_to) + self.cdp.open_new_tab(url=url, switch_to=switch_to, **kwargs) return elif ( getattr(self.driver, "_is_using_uc", None) and getattr(self.driver, "_is_using_cdp", None) ): self.disconnect() - self.cdp.open_new_tab(url=url, switch_to=switch_to) + self.cdp.open_new_tab(url=url, switch_to=switch_to, **kwargs) return self.wait_for_ready_state_complete() if switch_to: @@ -9264,9 +9264,9 @@ def reload_page(self): """Same as self.refresh_page()""" self.refresh_page() - def open_new_tab(self, switch_to=True): + def open_new_tab(self, switch_to=True, **kwargs): """Same as self.open_new_window()""" - self.open_new_window(switch_to=switch_to) + self.open_new_window(switch_to=switch_to, **kwargs) def switch_to_tab(self, tab, timeout=None): """Same as self.switch_to_window() diff --git a/seleniumbase/undetected/cdp_driver/browser.py b/seleniumbase/undetected/cdp_driver/browser.py index 364b0d56ffc..58e7fc96434 100644 --- a/seleniumbase/undetected/cdp_driver/browser.py +++ b/seleniumbase/undetected/cdp_driver/browser.py @@ -333,11 +333,16 @@ async def get( ) connection.browser = self else: - # First tab from browser.tabs - connection: tab.Tab = next( - filter(lambda item: item.type_ == "page", self.targets) - ) - await connection.sleep(0.005) + try: + # Most recently opened tab + connection = self.targets[-1] + await connection.sleep(0.005) + except Exception: + # First tab from browser.tabs + connection: tab.Tab = next( + filter(lambda item: item.type_ == "page", self.targets) + ) + await connection.sleep(0.005) _cdp_timezone = None _cdp_user_agent = "" _cdp_locale = None diff --git a/seleniumbase/undetected/cdp_driver/tab.py b/seleniumbase/undetected/cdp_driver/tab.py index d99827229e6..a594bf26453 100644 --- a/seleniumbase/undetected/cdp_driver/tab.py +++ b/seleniumbase/undetected/cdp_driver/tab.py @@ -371,7 +371,7 @@ async def get( return self else: return await self.browser.get( - url, new_tab, new_window, **kwargs + url, new_tab=False, new_window=False, **kwargs ) async def open(self, url="about:blank"): From 759dd9ba7fd2f62ba6a587907939d954d1cb5cea Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 8 Dec 2025 22:53:07 -0500 Subject: [PATCH 2/6] Add method to CDP Mode --- seleniumbase/undetected/cdp_driver/tab.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/seleniumbase/undetected/cdp_driver/tab.py b/seleniumbase/undetected/cdp_driver/tab.py index a594bf26453..97ebbdf6662 100644 --- a/seleniumbase/undetected/cdp_driver/tab.py +++ b/seleniumbase/undetected/cdp_driver/tab.py @@ -1458,6 +1458,9 @@ async def get_gui_element_rect(self, selector, timeout=5): async def get_title(self): return await self.evaluate("document.title") + async def get_current_url(self): + return await self.evaluate("window.location.href") + async def send_keys(self, selector, text, timeout=5): element = await self.find(selector, timeout=timeout) await element.send_keys_async(text) From f08b984c21b44115c7460f2c08ebc953cb2c26a7 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 8 Dec 2025 23:00:45 -0500 Subject: [PATCH 3/6] Update CDP Mode examples --- examples/cdp_mode/raw_async.py | 23 ++++++++++++----------- examples/cdp_mode/raw_basic_async.py | 1 + examples/cdp_mode/raw_cookies_async.py | 9 +++------ examples/cdp_mode/raw_mobile_async.py | 7 ++----- examples/cdp_mode/raw_multi_async.py | 6 ++---- 5 files changed, 20 insertions(+), 26 deletions(-) diff --git a/examples/cdp_mode/raw_async.py b/examples/cdp_mode/raw_async.py index fc193aadb58..745070feb4b 100644 --- a/examples/cdp_mode/raw_async.py +++ b/examples/cdp_mode/raw_async.py @@ -7,18 +7,19 @@ async def main(): url = "seleniumbase.io/simple/login" - driver = await cdp_driver.start_async(incognito=True) - page = await driver.get(url) - print(await page.evaluate("document.title")) - element = await page.select("#username") - await element.send_keys_async("demo_user") - element = await page.select("#password") - await element.send_keys_async("secret_pass") - element = await page.select("#log-in") - await element.click_async() - time.sleep(1) + driver = await cdp_driver.start_async() + page = await driver.get(url, lang="en") + print(await page.get_title()) + await page.type("#username", "demo_user") + await page.type("#password", "secret_pass") + await page.click("#log-in") + print(await page.get_title()) element = await page.select("h1") assert element.text == "Welcome!" + top_nav = await page.select("div.topnav") + links = await top_nav.query_selector_all_async("a") + for nav_item in links: + print(nav_item.text) driver.stop() if __name__ == "__main__": @@ -26,7 +27,7 @@ async def main(): loop = asyncio.new_event_loop() loop.run_until_complete(main()) - # Call everything without using async / await + # An example of wrapping all async calls with event loops driver = cdp_driver.start_sync() page = loop.run_until_complete(driver.get("about:blank")) loop.run_until_complete(page.set_locale("en")) diff --git a/examples/cdp_mode/raw_basic_async.py b/examples/cdp_mode/raw_basic_async.py index af21373db96..5c3c1f6c536 100644 --- a/examples/cdp_mode/raw_basic_async.py +++ b/examples/cdp_mode/raw_basic_async.py @@ -18,6 +18,7 @@ async def main(): links = await top_nav.query_selector_all_async("a") for nav_item in links: print(nav_item.text) + driver.stop() if __name__ == "__main__": # Call an async function with awaited methods diff --git a/examples/cdp_mode/raw_cookies_async.py b/examples/cdp_mode/raw_cookies_async.py index e581feb5b18..aef54198d2b 100644 --- a/examples/cdp_mode/raw_cookies_async.py +++ b/examples/cdp_mode/raw_cookies_async.py @@ -9,12 +9,9 @@ async def get_login_cookies(): url = "https://www.saucedemo.com" driver = await cdp_driver.start_async(incognito=True) page = await driver.get(url) - element = await page.select("#user-name") - await element.send_keys_async("standard_user") - element = await page.select("#password") - await element.send_keys_async("secret_sauce") - element = await page.select('input[type="submit"]') - await element.click_async() + await page.type("#user-name", "standard_user") + await page.type("#password", "secret_sauce") + await page.click('input[type="submit"]') cookies = await driver.cookies.get_all() driver.stop() return cookies diff --git a/examples/cdp_mode/raw_mobile_async.py b/examples/cdp_mode/raw_mobile_async.py index 2c99ff7d3f4..dd1fc72d9f5 100644 --- a/examples/cdp_mode/raw_mobile_async.py +++ b/examples/cdp_mode/raw_mobile_async.py @@ -15,17 +15,14 @@ async def main(): ) page = await driver.get(url, lang="en") time.sleep(3) - try: - element = await page.select('[style*="grid"] div div', timeout=1) - await element.mouse_click_with_offset_async(32, 28) - except Exception: - pass # Maybe CAPTCHA was already bypassed + await page.solve_captcha() element = await page.select('label[for="user_login"]') await element.flash_async(duration=1.5, color="44EE44") time.sleep(1) element = await page.select('[data-testid="sign-in-button"]') await element.flash_async(duration=2, color="44EE44") time.sleep(2) + driver.stop() if __name__ == "__main__": # Call an async function with awaited methods diff --git a/examples/cdp_mode/raw_multi_async.py b/examples/cdp_mode/raw_multi_async.py index 638af36a066..d7363f0768b 100644 --- a/examples/cdp_mode/raw_multi_async.py +++ b/examples/cdp_mode/raw_multi_async.py @@ -11,10 +11,8 @@ async def main(url): page = await driver.get(url) await page.set_window_rect(randint(4, 600), randint(8, 410), 860, 500) await page.sleep(0.5) - field = await page.select("input") - await field.send_keys_async("Text") - button = await page.select("button") - await button.click_async() + await page.type("input", "Text") + await page.click("button") await page.sleep(2) driver.stop() From cfe11392b4dfe2c48c4c050c588f3ace5a13627d Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 8 Dec 2025 23:02:11 -0500 Subject: [PATCH 4/6] Update the documentation --- README.md | 17 ++--- examples/cdp_mode/ReadMe.md | 126 ++++++++++++++++++-------------- help_docs/ReadMe.md | 2 + help_docs/cdp_mode_methods.md | 126 ++++++++++++++++++-------------- help_docs/js_package_manager.md | 4 +- 5 files changed, 151 insertions(+), 124 deletions(-) diff --git a/README.md b/README.md index e7a3bdb1870..d58547ac827 100755 --- a/README.md +++ b/README.md @@ -24,11 +24,11 @@ 🌠 Scripts | 📱 Mobile
-📘 APIs | - 🔠 Formats | +📘 API | + 🔠 Syntaxes | 🔴 Recorder | 📊 Dashboard | -🗾 Locales | +🗾 Locale | đŸ’ģ Farm
đŸŽ–ī¸ GUI | @@ -39,18 +39,17 @@ 🌐 Grid
đŸ‘ī¸ How | -🚝 Migrate | -đŸ—‚ī¸ CasePlans | -â™ģī¸ Template | -đŸ§Ŧ Hybrid | +🚝 Migration | +🎭 Stealthy Playwright | +🛂 MasterQA | 🚎 Tours
🤖 CI/CD | đŸ•šī¸ JSMgr | 🌏 Translator | đŸŽžī¸ Presenter | -🛂 Dialog | -đŸ–ŧī¸ Visual +đŸ–ŧī¸ Visual | +đŸ—‚ī¸ CPlans

diff --git a/examples/cdp_mode/ReadMe.md b/examples/cdp_mode/ReadMe.md index 601254a1630..b2f4b6d990f 100644 --- a/examples/cdp_mode/ReadMe.md +++ b/examples/cdp_mode/ReadMe.md @@ -620,63 +620,77 @@ sb.driver.stop() ### 🐙 CDP Mode Async API / Methods +Initialization: + +```python +from seleniumbase import cdp_driver + +driver = await cdp_driver.start_async() +tab = await driver.get(url, **kwargs) +``` + +Methods: (Sometimes `tab` is named `page` in examples) + ```python -await get(url="about:blank") -await open(url="about:blank") -await find(text, best_match=False, timeout=10) # `text` can be a selector -await find_all(text, timeout=10) # `text` can be a selector -await select(selector, timeout=10) -await select_all(selector, timeout=10, include_frames=False) -await query_selector(selector) -await query_selector_all(selector) -await find_element_by_text(text, best_match=False) -await find_elements_by_text(text) -await reload(ignore_cache=True, script_to_evaluate_on_load=None) -await evaluate(expression) -await js_dumps(obj_name) -await back() -await forward() -await get_window() -await get_content() -await maximize() -await minimize() -await fullscreen() -await medimize() -await set_window_size(left=0, top=0, width=1280, height=1024) -await set_window_rect(left=0, top=0, width=1280, height=1024) -await activate() -await bring_to_front() -await set_window_state(left=0, top=0, width=1280, height=720, state="normal") -await get_navigation_history() -await open_external_inspector() # Open a separate browser for debugging -await close() -await scroll_down(amount=25) -await scroll_up(amount=25) -await wait_for(selector="", text="", timeout=10) -await download_file(url, filename=None) -await save_screenshot(filename="auto", format="png", full_page=False) -await print_to_pdf(filename="auto") -await set_download_path(path) -await get_all_linked_sources() -await get_all_urls(absolute=True) -await get_html() -await get_page_source() -await is_element_present(selector) -await is_element_visible(selector) -await get_element_rect(selector, timeout=5) # (relative to window) -await get_window_rect() -await get_gui_element_rect(selector, timeout=5) # (relative to screen) -await get_title() -await send_keys(selector, text, timeout=5) -await type(selector, text, timeout=5) -await click(selector, timeout=5) -await click_with_offset(selector, x, y, center=False, timeout=5) -await solve_captcha() -await click_captcha() # Same as solve_captcha() -await get_document() -await get_flattened_document() -await get_local_storage() -await set_local_storage(items) +await tab.get(url="about:blank") +await tab.open(url="about:blank") +await tab.find(text, best_match=False, timeout=10) # text can be selector +await tab.find_all(text, timeout=10) # text can be selector +await tab.select(selector, timeout=10) +await tab.select_all(selector, timeout=10, include_frames=False) +await tab.query_selector(selector) +await tab.query_selector_all(selector) +await tab.find_element_by_text(text, best_match=False) +await tab.find_elements_by_text(text) +await tab.reload(ignore_cache=True, script_to_evaluate_on_load=None) +await tab.evaluate(expression) +await tab.js_dumps(obj_name) +await tab.back() +await tab.forward() +await tab.get_window() +await tab.get_content() +await tab.maximize() +await tab.minimize() +await tab.fullscreen() +await tab.medimize() +await tab.set_window_size(left=0, top=0, width=1280, height=1024) +await tab.set_window_rect(left=0, top=0, width=1280, height=1024) +await tab.activate() +await tab.bring_to_front() +await tab.set_window_state( + left=0, top=0, width=1280, height=720, state="normal") +await tab.get_navigation_history() +await tab.open_external_inspector() # Open separate browser for debugging +await tab.close() +await tab.scroll_down(amount=25) +await tab.scroll_up(amount=25) +await tab.wait_for(selector="", text="", timeout=10) +await tab.download_file(url, filename=None) +await tab.save_screenshot( + filename="auto", format="png", full_page=False) +await tab.print_to_pdf(filename="auto") +await tab.set_download_path(path) +await tab.get_all_linked_sources() +await tab.get_all_urls(absolute=True) +await tab.get_html() +await tab.get_page_source() +await tab.is_element_present(selector) +await tab.is_element_visible(selector) +await tab.get_element_rect(selector, timeout=5) # (window-based) +await tab.get_window_rect() +await tab.get_gui_element_rect(selector, timeout=5) # (screen-based) +await tab.get_title() +await tab.get_current_url() +await tab.send_keys(selector, text, timeout=5) +await tab.type(selector, text, timeout=5) +await tab.click(selector, timeout=5) +await tab.click_with_offset(selector, x, y, center=False, timeout=5) +await tab.solve_captcha() +await tab.click_captcha() # Same as solve_captcha() +await tab.get_document() +await tab.get_flattened_document() +await tab.get_local_storage() +await tab.set_local_storage(items) ``` -------- diff --git a/help_docs/ReadMe.md b/help_docs/ReadMe.md index be492e5b389..bea3acf8d6d 100644 --- a/help_docs/ReadMe.md +++ b/help_docs/ReadMe.md @@ -35,6 +35,8 @@ 🔴 Recorder | đŸ’ģ Device Farm
+🎭 Stealthy Playwright Mode +
đŸŽžī¸ Slides | đŸ“ļ Chart Maker
diff --git a/help_docs/cdp_mode_methods.md b/help_docs/cdp_mode_methods.md index 8fba1e994d6..741391aeb14 100644 --- a/help_docs/cdp_mode_methods.md +++ b/help_docs/cdp_mode_methods.md @@ -258,63 +258,77 @@ sb.driver.stop() ### 🐙 CDP Mode Async API / Methods +Initialization: + +```python +from seleniumbase import cdp_driver + +driver = await cdp_driver.start_async() +tab = await driver.get(url, **kwargs) +``` + +Methods: (Sometimes `tab` is named `page` in examples) + ```python -await get(url="about:blank") -await open(url="about:blank") -await find(text, best_match=False, timeout=10) # `text` can be a selector -await find_all(text, timeout=10) # `text` can be a selector -await select(selector, timeout=10) -await select_all(selector, timeout=10, include_frames=False) -await query_selector(selector) -await query_selector_all(selector) -await find_element_by_text(text, best_match=False) -await find_elements_by_text(text) -await reload(ignore_cache=True, script_to_evaluate_on_load=None) -await evaluate(expression) -await js_dumps(obj_name) -await back() -await forward() -await get_window() -await get_content() -await maximize() -await minimize() -await fullscreen() -await medimize() -await set_window_size(left=0, top=0, width=1280, height=1024) -await set_window_rect(left=0, top=0, width=1280, height=1024) -await activate() -await bring_to_front() -await set_window_state(left=0, top=0, width=1280, height=720, state="normal") -await get_navigation_history() -await open_external_inspector() # Open a separate browser for debugging -await close() -await scroll_down(amount=25) -await scroll_up(amount=25) -await wait_for(selector="", text="", timeout=10) -await download_file(url, filename=None) -await save_screenshot(filename="auto", format="png", full_page=False) -await print_to_pdf(filename="auto") -await set_download_path(path) -await get_all_linked_sources() -await get_all_urls(absolute=True) -await get_html() -await get_page_source() -await is_element_present(selector) -await is_element_visible(selector) -await get_element_rect(selector, timeout=5) # (relative to window) -await get_window_rect() -await get_gui_element_rect(selector, timeout=5) # (relative to screen) -await get_title() -await send_keys(selector, text, timeout=5) -await type(selector, text, timeout=5) -await click(selector, timeout=5) -await click_with_offset(selector, x, y, center=False, timeout=5) -await solve_captcha() -await click_captcha() # Same as solve_captcha() -await get_document() -await get_flattened_document() -await get_local_storage() -await set_local_storage(items) +await tab.get(url="about:blank") +await tab.open(url="about:blank") +await tab.find(text, best_match=False, timeout=10) # text can be selector +await tab.find_all(text, timeout=10) # text can be selector +await tab.select(selector, timeout=10) +await tab.select_all(selector, timeout=10, include_frames=False) +await tab.query_selector(selector) +await tab.query_selector_all(selector) +await tab.find_element_by_text(text, best_match=False) +await tab.find_elements_by_text(text) +await tab.reload(ignore_cache=True, script_to_evaluate_on_load=None) +await tab.evaluate(expression) +await tab.js_dumps(obj_name) +await tab.back() +await tab.forward() +await tab.get_window() +await tab.get_content() +await tab.maximize() +await tab.minimize() +await tab.fullscreen() +await tab.medimize() +await tab.set_window_size(left=0, top=0, width=1280, height=1024) +await tab.set_window_rect(left=0, top=0, width=1280, height=1024) +await tab.activate() +await tab.bring_to_front() +await tab.set_window_state( + left=0, top=0, width=1280, height=720, state="normal") +await tab.get_navigation_history() +await tab.open_external_inspector() # Open separate browser for debugging +await tab.close() +await tab.scroll_down(amount=25) +await tab.scroll_up(amount=25) +await tab.wait_for(selector="", text="", timeout=10) +await tab.download_file(url, filename=None) +await tab.save_screenshot( + filename="auto", format="png", full_page=False) +await tab.print_to_pdf(filename="auto") +await tab.set_download_path(path) +await tab.get_all_linked_sources() +await tab.get_all_urls(absolute=True) +await tab.get_html() +await tab.get_page_source() +await tab.is_element_present(selector) +await tab.is_element_visible(selector) +await tab.get_element_rect(selector, timeout=5) # (window-based) +await tab.get_window_rect() +await tab.get_gui_element_rect(selector, timeout=5) # (screen-based) +await tab.get_title() +await tab.get_current_url() +await tab.send_keys(selector, text, timeout=5) +await tab.type(selector, text, timeout=5) +await tab.click(selector, timeout=5) +await tab.click_with_offset(selector, x, y, center=False, timeout=5) +await tab.solve_captcha() +await tab.click_captcha() # Same as solve_captcha() +await tab.get_document() +await tab.get_flattened_document() +await tab.get_local_storage() +await tab.set_local_storage(items) ``` -------- diff --git a/help_docs/js_package_manager.md b/help_docs/js_package_manager.md index eeade9efb5e..f58773dc5d4 100644 --- a/help_docs/js_package_manager.md +++ b/help_docs/js_package_manager.md @@ -53,7 +53,7 @@ self.add_js_link(js_link)

đŸ•šī¸ This example loads the IntroJS JavaScript library:

```python -self.add_js_link("https://cdnjs.cloudflare.com/ajax/libs/intro.js/2.9.3/intro.min.js") +self.add_js_link("https://cdn.jsdelivr.net/npm/intro.js@5.1.0/intro.min.js") ```
đŸ•šī¸ You can load any JS package this way as long as you know the URL.
@@ -133,8 +133,6 @@ pytest test_dialog_boxes.py -[](https://github.com/seleniumbase/SeleniumBase/) -
To learn more about SeleniumBase, check out the Docs Site:
SeleniumBase.io Docs From c934bea10a5dfd3b0f8dc713c2598e30b08c1d0f Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 8 Dec 2025 23:03:01 -0500 Subject: [PATCH 5/6] Refresh coverage --- requirements.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 4c692cdfffc..60227ffd1f3 100755 --- a/requirements.txt +++ b/requirements.txt @@ -76,7 +76,7 @@ rich>=14.2.0,<15 # ("pip install -r requirements.txt" also installs this, but "pip install -e ." won't.) coverage>=7.10.7;python_version<"3.10" -coverage>=7.12.0;python_version>="3.10" +coverage>=7.13.0;python_version>="3.10" pytest-cov>=7.0.0 flake8==7.3.0 mccabe==0.7.0 diff --git a/setup.py b/setup.py index 85cd8e79776..1b6ec808fb4 100755 --- a/setup.py +++ b/setup.py @@ -233,7 +233,7 @@ # Usage: coverage run -m pytest; coverage html; coverage report "coverage": [ 'coverage>=7.10.7;python_version<"3.10"', - 'coverage>=7.12.0;python_version>="3.10"', + 'coverage>=7.13.0;python_version>="3.10"', 'pytest-cov>=7.0.0', ], # pip install -e .[flake8] From 5752ebb23355e90b38d4ce92e58c275c30a31ed7 Mon Sep 17 00:00:00 2001 From: Michael Mintz Date: Mon, 8 Dec 2025 23:03:17 -0500 Subject: [PATCH 6/6] Version 4.45.1 --- seleniumbase/__version__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py index 0a8dac81b9b..505895bdc30 100755 --- a/seleniumbase/__version__.py +++ b/seleniumbase/__version__.py @@ -1,2 +1,2 @@ # seleniumbase package -__version__ = "4.45.0" +__version__ = "4.45.1"