diff --git a/examples/tour_examples/bootstrap_google_tour.py b/examples/tour_examples/bootstrap_google_tour.py index 76906af7711..4219e39fb15 100644 --- a/examples/tour_examples/bootstrap_google_tour.py +++ b/examples/tour_examples/bootstrap_google_tour.py @@ -61,11 +61,18 @@ def test_google_tour(self): self.add_tour_step( "Or click here to zoom out.", "#widget-zoom-out", alignment="left" ) - self.add_tour_step( - "Use the Menu button to see more options.", - 'button[jsaction*="settings.open;"]', - alignment="right", - ) + if self.is_element_visible('button[jsaction*="settings.open;"]'): + self.add_tour_step( + "Use the Menu button to see more options.", + 'button[jsaction*="settings.open;"]', + alignment="right", + ) + elif self.is_element_visible('button[jsaction="navigationrail.more"]'): + self.add_tour_step( + "Use the Menu button to see more options.", + 'button[jsaction="navigationrail.more"]', + alignment="right", + ) self.add_tour_step( "Or click here to see more Google apps.", '[title="Google apps"]', diff --git a/examples/tour_examples/bootstrap_xkcd_tour.py b/examples/tour_examples/bootstrap_xkcd_tour.py index 7bb59d56e0f..ff7bc1a3fe5 100644 --- a/examples/tour_examples/bootstrap_xkcd_tour.py +++ b/examples/tour_examples/bootstrap_xkcd_tour.py @@ -16,5 +16,5 @@ def test_bootstrap_tour(self): self.add_tour_step("Learn about the author here.", 'a[rel="author"]') self.add_tour_step("Click for a random comic.", 'a[href*="/random/"]') self.add_tour_step("Thanks for taking this tour!") - self.export_tour(filename="bootstrap_xkcd_tour.js") # Exports the tour - self.play_tour() # Plays the tour + self.export_tour(filename="bootstrap_xkcd_tour.js") + self.play_tour() diff --git a/examples/tour_examples/driverjs_maps_tour.py b/examples/tour_examples/driverjs_maps_tour.py index 103b8da76fe..db7765dd533 100644 --- a/examples/tour_examples/driverjs_maps_tour.py +++ b/examples/tour_examples/driverjs_maps_tour.py @@ -37,11 +37,18 @@ def test_create_tour(self): self.add_tour_step( "Or click here to zoom out.", "#widget-zoom-out", alignment="left" ) - self.add_tour_step( - "Use the Menu button to see more options.", - 'button[jsaction*="settings.open;"]', - alignment="right", - ) + if self.is_element_visible('button[jsaction*="settings.open;"]'): + self.add_tour_step( + "Use the Menu button to see more options.", + 'button[jsaction*="settings.open;"]', + alignment="right", + ) + elif self.is_element_visible('button[jsaction="navigationrail.more"]'): + self.add_tour_step( + "Use the Menu button to see more options.", + 'button[jsaction="navigationrail.more"]', + alignment="right", + ) self.add_tour_step( "Or click here to see more Google apps.", '[title="Google apps"]', diff --git a/examples/tour_examples/google_tour.py b/examples/tour_examples/google_tour.py index 4fdb5153a43..10b422ac8ca 100644 --- a/examples/tour_examples/google_tour.py +++ b/examples/tour_examples/google_tour.py @@ -69,11 +69,18 @@ def test_google_tour(self): self.add_tour_step( "Or click here to zoom out.", "#widget-zoom-out", alignment="left" ) - self.add_tour_step( - "Use the Menu button to see more options.", - 'button[jsaction*="settings.open;"]', - alignment="right", - ) + if self.is_element_visible('button[jsaction*="settings.open;"]'): + self.add_tour_step( + "Use the Menu button to see more options.", + 'button[jsaction*="settings.open;"]', + alignment="right", + ) + elif self.is_element_visible('button[jsaction="navigationrail.more"]'): + self.add_tour_step( + "Use the Menu button to see more options.", + 'button[jsaction="navigationrail.more"]', + alignment="right", + ) self.add_tour_step( "Or click here to see more Google apps.", '[title="Google apps"]', diff --git a/examples/tour_examples/hopscotch_google_tour.py b/examples/tour_examples/hopscotch_google_tour.py index 321b1b2fe53..3647c757469 100644 --- a/examples/tour_examples/hopscotch_google_tour.py +++ b/examples/tour_examples/hopscotch_google_tour.py @@ -61,11 +61,18 @@ def test_google_tour(self): self.add_tour_step( "Or click here to zoom out.", "#widget-zoom-out", alignment="left" ) - self.add_tour_step( - "Use the Menu button to see more options.", - 'button[jsaction*="settings.open;"]', - alignment="right", - ) + if self.is_element_visible('button[jsaction*="settings.open;"]'): + self.add_tour_step( + "Use the Menu button to see more options.", + 'button[jsaction*="settings.open;"]', + alignment="right", + ) + elif self.is_element_visible('button[jsaction="navigationrail.more"]'): + self.add_tour_step( + "Use the Menu button to see more options.", + 'button[jsaction="navigationrail.more"]', + alignment="right", + ) self.add_tour_step( "Or click here to see more Google apps.", '[title="Google apps"]', diff --git a/examples/tour_examples/introjs_google_tour.py b/examples/tour_examples/introjs_google_tour.py index 0eeb3d1d56a..f69635e6a31 100644 --- a/examples/tour_examples/introjs_google_tour.py +++ b/examples/tour_examples/introjs_google_tour.py @@ -62,11 +62,18 @@ def test_google_tour(self): self.add_tour_step( "Or click here to zoom out.", "#widget-zoom-out", alignment="left" ) - self.add_tour_step( - "Use the Menu button to see more options.", - 'button[jsaction*="settings.open;"]', - alignment="right", - ) + if self.is_element_visible('button[jsaction*="settings.open;"]'): + self.add_tour_step( + "Use the Menu button to see more options.", + 'button[jsaction*="settings.open;"]', + alignment="right", + ) + elif self.is_element_visible('button[jsaction="navigationrail.more"]'): + self.add_tour_step( + "Use the Menu button to see more options.", + 'button[jsaction="navigationrail.more"]', + alignment="right", + ) self.add_tour_step( "Or click here to see more Google apps.", '[title="Google apps"]', diff --git a/examples/tour_examples/maps_introjs_tour.py b/examples/tour_examples/maps_introjs_tour.py index 1448bee6cab..d073d764e08 100644 --- a/examples/tour_examples/maps_introjs_tour.py +++ b/examples/tour_examples/maps_introjs_tour.py @@ -37,11 +37,18 @@ def test_google_maps_tour(self): self.add_tour_step( "Or click here to zoom out.", "#widget-zoom-out", alignment="left" ) - self.add_tour_step( - "Use the Menu button to see more options.", - 'button[jsaction*="settings.open;"]', - alignment="right", - ) + if self.is_element_visible('button[jsaction*="settings.open;"]'): + self.add_tour_step( + "Use the Menu button to see more options.", + 'button[jsaction*="settings.open;"]', + alignment="right", + ) + elif self.is_element_visible('button[jsaction="navigationrail.more"]'): + self.add_tour_step( + "Use the Menu button to see more options.", + 'button[jsaction="navigationrail.more"]', + alignment="right", + ) self.add_tour_step( "Or click here to see more Google apps.", '[title="Google apps"]', diff --git a/examples/tour_examples/shepherd_google_tour.py b/examples/tour_examples/shepherd_google_tour.py index fbc925a8ccb..bc660d6ff53 100644 --- a/examples/tour_examples/shepherd_google_tour.py +++ b/examples/tour_examples/shepherd_google_tour.py @@ -65,11 +65,18 @@ def test_google_tour(self): alignment="left", theme="light", ) - self.add_tour_step( - "Use the Menu button to see more options.", - 'button[jsaction*="settings.open;"]', - alignment="right", - ) + if self.is_element_visible('button[jsaction*="settings.open;"]'): + self.add_tour_step( + "Use the Menu button to see more options.", + 'button[jsaction*="settings.open;"]', + alignment="right", + ) + elif self.is_element_visible('button[jsaction="navigationrail.more"]'): + self.add_tour_step( + "Use the Menu button to see more options.", + 'button[jsaction="navigationrail.more"]', + alignment="right", + ) self.add_tour_step( "Or click here to see more Google apps.", '[title="Google apps"]', diff --git a/examples/tour_examples/xkcd_tour.py b/examples/tour_examples/xkcd_tour.py index 16948ca2d7b..e89daf137c3 100644 --- a/examples/tour_examples/xkcd_tour.py +++ b/examples/tour_examples/xkcd_tour.py @@ -17,5 +17,5 @@ def test_create_tour(self): self.add_tour_step("Click here for the license.", 'a[rel="license"]') self.add_tour_step("Click for a random comic.", 'a[href*="/random/"]') self.add_tour_step("Thanks for taking this tour!") - self.export_tour(filename="xkcd_tour.js") # Exports the tour - self.play_tour() # Plays the tour + self.export_tour(filename="xkcd_tour.js") + self.play_tour() diff --git a/mkdocs.yml b/mkdocs.yml index 10cf2fc46ef..5ed0e3d9a75 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -130,6 +130,7 @@ nav: - 🎞️ Presenter Demo: https://seleniumbase.io/other/presenter.html - 📊 Chart Maker Demo: https://seleniumbase.io/other/chart_presentation.html - ⚙️ Python Virtual Envs: https://seleniumbase.io/other/py_virtual_envs.html + - 🔰 Fundamentals Demo: https://seleniumbase.io/other/fundamentals.html - Demo Pages: - 🍵 Coffee Cart (Test App): https://seleniumbase.io/coffee/ - 📑 Demo Page (Test Page): https://seleniumbase.io/demo_page diff --git a/mkdocs_build/requirements.txt b/mkdocs_build/requirements.txt index b87fe716a72..d229a08ae8e 100644 --- a/mkdocs_build/requirements.txt +++ b/mkdocs_build/requirements.txt @@ -13,8 +13,8 @@ Jinja2==3.1.2 click==8.1.3 ghp-import==2.1.0 readme-renderer==37.3 -pymdown-extensions==9.10 -importlib-metadata==6.1.0 +pymdown-extensions==9.11 +importlib-metadata==6.2.0 pipdeptree==2.7.0 bleach==6.0.0 lunr==0.6.2 @@ -27,7 +27,7 @@ cssselect2==0.7.0 tinycss2==1.2.1 defusedxml==0.7.1 mkdocs==1.4.2 -mkdocs-material==9.1.4 +mkdocs-material==9.1.6 mkdocs-exclude-search==0.6.5 mkdocs-simple-hooks==0.1.5 mkdocs-material-extensions==1.1.1 diff --git a/requirements.txt b/requirements.txt index 21c5a9e0ee4..946ef330061 100755 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ pip>=23.0.1;python_version>="3.7" packaging>=21.3;python_version<"3.7" packaging>=23.0;python_version>="3.7" setuptools>=59.6.0;python_version<"3.7" -setuptools>=67.6.0;python_version>="3.7" +setuptools>=67.6.1;python_version>="3.7" keyring>=23.4.1;python_version<"3.8" keyring>=23.13.1;python_version>="3.8" tomli>=1.2.3;python_version<"3.7" @@ -17,10 +17,11 @@ attrs>=22.2.0;python_version>="3.7" PyYAML>=6.0 certifi>=2022.12.7 filelock>=3.4.1;python_version<"3.7" -filelock>=3.10.7;python_version>="3.7" +filelock>=3.11.0;python_version>="3.7" platformdirs>=2.4.0;python_version<"3.7" platformdirs>=3.2.0;python_version>="3.7" pyparsing>=3.0.7;python_version<"3.7" +pyparsing>=3.0.9;python_version>="3.7" zipp==3.6.0;python_version<"3.7" zipp>=3.15.0;python_version>="3.7" more-itertools==8.14.0;python_version<"3.7" @@ -42,7 +43,6 @@ h11==0.14.0;python_version>="3.7" outcome==1.2.0;python_version>="3.7" trio==0.22.0;python_version>="3.7" trio-websocket==0.10.2;python_version>="3.7" -websockets==10.4;python_version>="3.7" pyopenssl==23.1.1;python_version>="3.7" wsproto==1.2.0;python_version>="3.7" selenium==3.141.0;python_version<"3.7" @@ -59,7 +59,7 @@ iniconfig==2.0.0;python_version>="3.7" pluggy==1.0.0 py==1.11.0 pytest==7.0.1;python_version<"3.7" -pytest==7.2.2;python_version>="3.7" +pytest==7.3.0;python_version>="3.7" pytest-forked==1.4.0;python_version<"3.7" pytest-forked==1.6.0;python_version>="3.7" pytest-html==2.0.1 @@ -76,7 +76,7 @@ sbvirtualdisplay==1.2.0 behave==1.2.6 soupsieve==2.3.2.post1;python_version<"3.7" soupsieve==2.4;python_version>="3.7" -beautifulsoup4==4.12.0 +beautifulsoup4==4.12.2 cryptography==36.0.2;python_version<"3.7" cryptography==40.0.1;python_version>="3.7" pygments==2.14.0 @@ -103,7 +103,7 @@ rich==13.3.3;python_version>="3.7" # ("pip install -r requirements.txt" also installs this, but "pip install -e ." won't.) coverage==6.2;python_version<"3.7" -coverage==7.2.2;python_version>="3.7" +coverage==7.2.3;python_version>="3.7" pytest-cov==4.0.0 flake8==5.0.4;python_version<"3.9" flake8==6.0.0;python_version>="3.9" diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py index c4b6d5eae3e..4448a51f927 100755 --- a/seleniumbase/__version__.py +++ b/seleniumbase/__version__.py @@ -1,2 +1,2 @@ # seleniumbase package -__version__ = "4.13.21" +__version__ = "4.13.22" diff --git a/seleniumbase/core/browser_launcher.py b/seleniumbase/core/browser_launcher.py index ac468a3c7de..42d12b7e6ee 100644 --- a/seleniumbase/core/browser_launcher.py +++ b/seleniumbase/core/browser_launcher.py @@ -711,6 +711,14 @@ def _set_chrome_options( chromium_arg_item = "-" + chromium_arg_item else: chromium_arg_item = "--" + chromium_arg_item + if "remote-debugging-port=" in chromium_arg_item: + try: + # Extra processing for UC Mode + chrome_options._remote_debugging_port = int( + chromium_arg_item.split("remote-debugging-port=")[1] + ) + except Exception: + pass if len(chromium_arg_item) >= 3: chrome_options.add_argument(chromium_arg_item) if devtools and not headless: diff --git a/seleniumbase/core/tour_helper.py b/seleniumbase/core/tour_helper.py index 94ef564b0ea..f2929950e73 100644 --- a/seleniumbase/core/tour_helper.py +++ b/seleniumbase/core/tour_helper.py @@ -1,7 +1,5 @@ -""" -This module contains methods for running website tours. -These helper methods SHOULD NOT be called directly from tests. -""" +"""This module contains methods for running website tours. +These helper methods SHOULD NOT be called directly from tests.""" import os import re import textwrap @@ -70,7 +68,6 @@ def activate_driverjs(driver): var driverjs2 = Driver.name; """ - activate_bootstrap(driver) js_utils.wait_for_ready_state_complete(driver) js_utils.wait_for_angularjs(driver) js_utils.add_css_style(driver, backdrop_style) @@ -115,7 +112,6 @@ def activate_hopscotch(driver): var hops = hopscotch.isActive; """ - activate_bootstrap(driver) js_utils.wait_for_ready_state_complete(driver) js_utils.wait_for_angularjs(driver) js_utils.add_css_style(driver, backdrop_style) @@ -169,7 +165,6 @@ def activate_introjs(driver): var intro2 = introJs(); """ - activate_bootstrap(driver) js_utils.wait_for_ready_state_complete(driver) js_utils.wait_for_angularjs(driver) js_utils.add_css_style(driver, backdrop_style) @@ -218,7 +213,6 @@ def activate_shepherd(driver): sh_style = style_sheet.get_sh_style_test() backdrop_style = style_sheet.get_sh_backdrop_style() - activate_bootstrap(driver) js_utils.wait_for_ready_state_complete(driver) js_utils.wait_for_angularjs(driver) js_utils.add_css_style(driver, backdrop_style) @@ -269,6 +263,13 @@ def play_shepherd_tour(driver, tour_steps, msg_dur, name=None, interval=0): // Start the tour tour.start(); $tour = tour;""" + instructions += """ + document.body.addEventListener('keyup', function (event) { + if (event.key === 'PageUp' || event.key === 'ArrowLeft') { + Shepherd.activeTour.back(); } + if (event.key === 'PageDown' || event.key === 'ArrowRight') { + Shepherd.activeTour.next(); } + })""" autoplay = False if interval and interval > 0: autoplay = True @@ -302,6 +303,16 @@ def play_shepherd_tour(driver, tour_steps, msg_dur, name=None, interval=0): "" % selector ) driver.execute_script(instructions) + try: + page_actions.wait_for_element_visible( + driver, "a.tour-button-right", by="css selector", timeout=1.2 + ) + except Exception: + pass + try: + driver.execute_script('document.activeElement.blur();') + except Exception: + pass tour_on = True if autoplay: start_ms = time.time() * 1000.0 @@ -404,7 +415,6 @@ def play_bootstrap_tour( tour.restart(); // Save for later $tour = tour;""" - if interval and interval > 0: if interval < 1: interval = 1 @@ -412,10 +422,8 @@ def play_bootstrap_tour( instructions = instructions.replace( "duration: 0,", "duration: %s," % interval ) - if not is_bootstrap_activated(driver): activate_bootstrap(driver) - if len(tour_steps[name]) > 1: try: if "element: " in tour_steps[name][1]: @@ -441,9 +449,18 @@ def play_bootstrap_tour( "Exiting due to failure on first tour step!" "" % selector ) - driver.execute_script(instructions) tour_on = True + try: + page_actions.wait_for_element_visible( + driver, ".tour-tour", by="css selector", timeout=1.2 + ) + except Exception: + pass + try: + driver.execute_script('document.activeElement.blur();') + except Exception: + pass while tour_on: try: time.sleep(0.01) @@ -451,7 +468,7 @@ def play_bootstrap_tour( result = driver.execute_script("return $tour.ended()") else: page_actions.wait_for_element_present( - driver, ".tour-tour", by="css selector", timeout=0.65 + driver, ".tour-tour", by="css selector", timeout=0.48 ) result = False except Exception: @@ -467,7 +484,7 @@ def play_bootstrap_tour( result = driver.execute_script("return $tour.ended()") else: page_actions.wait_for_element_present( - driver, ".tour-tour", by="css selector", timeout=0.65 + driver, ".tour-tour", by="css selector", timeout=0.48 ) result = False if result is False: @@ -492,6 +509,11 @@ def play_driverjs_tour( // Start the tour! tour.start(); $tour = tour;""" + instructions += """ + document.body.addEventListener('keyup', function (event) { + if (event.key === 'PageUp') { $tour.movePrevious(); } + if (event.key === 'PageDown') { $tour.moveNext(); } + })""" autoplay = False if interval and interval > 0: autoplay = True @@ -619,6 +641,13 @@ def play_hopscotch_tour( // Start the tour! hopscotch.startTour(tour); $tour = hopscotch;""" + instructions += """ + document.body.addEventListener('keyup', function (event) { + if (event.key === 'PageUp' || event.key === 'ArrowLeft') { + $tour.prevStep(); } + if (event.key === 'PageDown' || event.key === 'ArrowRight') { + $tour.nextStep(); } + })""" autoplay = False if interval and interval > 0: autoplay = True @@ -656,6 +685,16 @@ def play_hopscotch_tour( ) driver.execute_script(instructions) + try: + page_actions.wait_for_element_visible( + driver, "button.hopscotch-next", by="css selector", timeout=1.2 + ) + except Exception: + pass + try: + driver.execute_script('document.activeElement.blur();') + except Exception: + pass tour_on = True if autoplay: start_ms = time.time() * 1000.0 @@ -751,6 +790,11 @@ def play_introjs_tour( // Start the tour startIntro(); """ + instructions += """ + document.body.addEventListener('keyup', function (event) { + if (event.key === 'PageUp') { $tour.previousStep(); } + if (event.key === 'PageDown') { $tour.nextStep(); } + })""" autoplay = False if interval and interval > 0: autoplay = True diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py index d1a3ad14917..efec33f9d82 100644 --- a/seleniumbase/fixtures/base_case.py +++ b/seleniumbase/fixtures/base_case.py @@ -309,8 +309,18 @@ def open(self, url): if self.undetectable: self.__uc_frame_layer = 0 if self.demo_mode: - if not js_utils.is_jquery_activated(self.driver): - js_utils.add_js_link(self.driver, constants.JQuery.MIN_JS) + if ( + self.driver.current_url.startswith("http") + or self.driver.current_url.startswith("file") + or self.driver.current_url.startswith("data") + ): + if not js_utils.is_jquery_activated(self.driver): + try: + js_utils.add_js_link( + self.driver, constants.JQuery.MIN_JS + ) + except Exception: + pass self.__demo_mode_pause_if_active() def get(self, url): @@ -6440,12 +6450,15 @@ def save_element_as_image_file( file.write(element_png) # Add a text overlay if given if type(overlay_text) is str and len(overlay_text) > 0: - try: - from PIL import Image, ImageDraw - except Exception: - shared_utils.pip_install("Pillow") - from PIL import Image, ImageDraw - + pip_find_lock = fasteners.InterProcessLock( + constants.PipInstall.FINDLOCK + ) + with pip_find_lock: + try: + from PIL import Image, ImageDraw + except Exception: + shared_utils.pip_install("Pillow") + from PIL import Image, ImageDraw text_rows = overlay_text.split("\n") len_text_rows = len(text_rows) max_width = 0 diff --git a/seleniumbase/fixtures/constants.py b/seleniumbase/fixtures/constants.py index 40c4f84e6dd..0dc5cf0a13e 100644 --- a/seleniumbase/fixtures/constants.py +++ b/seleniumbase/fixtures/constants.py @@ -208,7 +208,7 @@ class PrettifyJS: class Reveal: LIB = "https://cdn.jsdelivr.net/npm/reveal.js" VER = "3.8.0" - MIN_CSS = "%s@%s/css/reveal.css" % (LIB, VER) + MIN_CSS = "%s@%s/css/reveal.min.css" % (LIB, VER) SERIF_MIN_CSS = "%s@%s/css/theme/serif.min.css" % (LIB, VER) WHITE_MIN_CSS = "%s@%s/css/theme/white.min.css" % (LIB, VER) BLACK_MIN_CSS = "%s@%s/css/theme/black.min.css" % (LIB, VER) @@ -240,7 +240,8 @@ class BootstrapTour: LIB = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-tour" VER = "0.12.0" MIN_CSS = "%s/%s/css/bootstrap-tour-standalone.min.css" % (LIB, VER) - MIN_JS = "%s/%s/js/bootstrap-tour-standalone.min.js" % (LIB, VER) + # MIN_JS = "%s/%s/js/bootstrap-tour-standalone.min.js" % (LIB, VER) + MIN_JS = "https://seleniumbase.github.io/cdn/js/bootstraptour.min.js" class DriverJS: diff --git a/seleniumbase/undetected/__init__.py b/seleniumbase/undetected/__init__.py index b427a4ee019..4d00e5e74dc 100644 --- a/seleniumbase/undetected/__init__.py +++ b/seleniumbase/undetected/__init__.py @@ -134,13 +134,15 @@ def __init__( options = ChromeOptions() try: if hasattr(options, "_session") and options._session is not None: - # Prevent reuse of options + # Prevent reuse of options raise RuntimeError("you cannot reuse the ChromeOptions object") except AttributeError: pass options._session = self - debug_port = selenium.webdriver.common.service.utils.free_port() debug_host = "127.0.0.1" + debug_port = 9222 + if hasattr(options, "_remote_debugging_port"): + debug_port = options._remote_debugging_port if not options.debugger_address: options.debugger_address = "%s:%d" % (debug_host, debug_port) if enable_cdp_events: diff --git a/seleniumbase/undetected/cdp.py b/seleniumbase/undetected/cdp.py index 9e814c2e9f2..92e48cf41ac 100644 --- a/seleniumbase/undetected/cdp.py +++ b/seleniumbase/undetected/cdp.py @@ -1,7 +1,10 @@ #!/usr/bin/env python3 +import fasteners import json import logging import requests +from seleniumbase.fixtures import constants +from seleniumbase.fixtures import shared_utils log = logging.getLogger(__name__) @@ -75,8 +78,15 @@ def tab_close_last_opened(self): return self.post(self.endpoints["close"].format(id=opentabs[-1]["id"])) async def send(self, method, params): - import websockets - + pip_find_lock = fasteners.InterProcessLock( + constants.PipInstall.FINDLOCK + ) + with pip_find_lock: + try: + import websockets + except Exception: + shared_utils.pip_install("websockets") + import websockets self._reqid += 1 async with websockets.connect(self.wsurl) as ws: await ws.send( diff --git a/setup.py b/setup.py index ecbc323452a..584baf79202 100755 --- a/setup.py +++ b/setup.py @@ -127,7 +127,7 @@ 'packaging>=21.3;python_version<"3.7"', 'packaging>=23.0;python_version>="3.7"', 'setuptools>=59.6.0;python_version<"3.7"', - 'setuptools>=67.6.0;python_version>="3.7"', + 'setuptools>=67.6.1;python_version>="3.7"', 'keyring>=23.4.1;python_version<"3.8"', 'keyring>=23.13.1;python_version>="3.8"', 'tomli>=1.2.3;python_version<"3.7"', @@ -141,10 +141,11 @@ "PyYAML>=6.0", "certifi>=2022.12.7", 'filelock>=3.4.1;python_version<"3.7"', - 'filelock>=3.10.7;python_version>="3.7"', + 'filelock>=3.11.0;python_version>="3.7"', 'platformdirs>=2.4.0;python_version<"3.7"', 'platformdirs>=3.2.0;python_version>="3.7"', 'pyparsing>=3.0.7;python_version<"3.7"', + 'pyparsing>=3.0.9;python_version>="3.7"', 'zipp==3.6.0;python_version<"3.7"', 'zipp>=3.15.0;python_version>="3.7"', 'more-itertools==8.14.0;python_version<"3.7"', @@ -166,7 +167,6 @@ 'outcome==1.2.0;python_version>="3.7"', 'trio==0.22.0;python_version>="3.7"', 'trio-websocket==0.10.2;python_version>="3.7"', - 'websockets==10.4;python_version>="3.7"', 'pyopenssl==23.1.1;python_version>="3.7"', 'wsproto==1.2.0;python_version>="3.7"', 'selenium==3.141.0;python_version<"3.7"', @@ -183,7 +183,7 @@ "pluggy==1.0.0", "py==1.11.0", 'pytest==7.0.1;python_version<"3.7"', - 'pytest==7.2.2;python_version>="3.7"', + 'pytest==7.3.0;python_version>="3.7"', 'pytest-forked==1.4.0;python_version<"3.7"', 'pytest-forked==1.6.0;python_version>="3.7"', "pytest-html==2.0.1", # Newer ones had issues @@ -200,7 +200,7 @@ "behave==1.2.6", 'soupsieve==2.3.2.post1;python_version<"3.7"', 'soupsieve==2.4;python_version>="3.7"', - "beautifulsoup4==4.12.0", + "beautifulsoup4==4.12.2", 'cryptography==36.0.2;python_version<"3.7"', 'cryptography==40.0.1;python_version>="3.7"', "pygments==2.14.0", @@ -239,7 +239,7 @@ # Usage: coverage run -m pytest; coverage html; coverage report "coverage": [ 'coverage==6.2;python_version<"3.7"', - 'coverage==7.2.2;python_version>="3.7"', + 'coverage==7.2.3;python_version>="3.7"', "pytest-cov==4.0.0", ], # pip install -e .[flake8] @@ -268,7 +268,7 @@ # pip install -e .[pillow] "pillow": [ 'Pillow==8.4.0;python_version<"3.7"', - 'Pillow==9.4.0;python_version>="3.7"', + 'Pillow==9.5.0;python_version>="3.7"', ], # pip install -e .[psutil] "psutil": [ @@ -277,7 +277,6 @@ # pip install -e .[selenium-wire] "selenium-wire": [ 'selenium-wire==5.1.0;python_version>="3.7"', - 'pyparsing==3.0.9;python_version>="3.7"', 'Brotli==1.0.9;python_version>="3.7"', 'blinker==1.5;python_version>="3.7"', 'h2==4.1.0;python_version>="3.7"',