From 968c9dc1fad692122736ff61a2c8c4ca40f52f12 Mon Sep 17 00:00:00 2001 From: delta456 Date: Wed, 18 Sep 2024 17:30:10 +0530 Subject: [PATCH 1/6] use ENV variables for custom driver locations --- py/selenium/webdriver/chromium/service.py | 3 +++ py/selenium/webdriver/chromium/webdriver.py | 2 +- py/selenium/webdriver/common/service.py | 6 +++++- py/selenium/webdriver/edge/service.py | 3 +++ py/selenium/webdriver/firefox/service.py | 3 +++ py/selenium/webdriver/firefox/webdriver.py | 2 +- py/selenium/webdriver/ie/service.py | 4 ++++ py/selenium/webdriver/ie/webdriver.py | 2 +- py/selenium/webdriver/safari/service.py | 3 +++ py/selenium/webdriver/safari/webdriver.py | 2 +- 10 files changed, 25 insertions(+), 5 deletions(-) diff --git a/py/selenium/webdriver/chromium/service.py b/py/selenium/webdriver/chromium/service.py index fc7d165f2b8f0..3446c4fac1e7a 100644 --- a/py/selenium/webdriver/chromium/service.py +++ b/py/selenium/webdriver/chromium/service.py @@ -39,9 +39,11 @@ def __init__( service_args: typing.Optional[typing.List[str]] = None, log_output: SubprocessStdAlias = None, env: typing.Optional[typing.Mapping[str, str]] = None, + driver_path_env_key: str = None, **kwargs, ) -> None: self.service_args = service_args or [] + driver_path_env_key = driver_path_env_key or 'SE_CHROMEDRIVER' if isinstance(log_output, str): self.service_args.append(f"--log-path={log_output}") @@ -56,6 +58,7 @@ def __init__( port=port, env=env, log_output=self.log_output, + driver_path_env_key=driver_path_env_key, **kwargs, ) diff --git a/py/selenium/webdriver/chromium/webdriver.py b/py/selenium/webdriver/chromium/webdriver.py index 6fc3adeb4086d..6d8df2dcd1a0e 100644 --- a/py/selenium/webdriver/chromium/webdriver.py +++ b/py/selenium/webdriver/chromium/webdriver.py @@ -51,7 +51,7 @@ def __init__( options.binary_location = finder.get_browser_path() options.browser_version = None - self.service.path = finder.get_driver_path() + self.service.path = finder.get_driver_path() or self.service.env_path() self.service.start() executor = ChromiumRemoteConnection( diff --git a/py/selenium/webdriver/common/service.py b/py/selenium/webdriver/common/service.py index 829e4f43ad967..d3552aa6e3b95 100644 --- a/py/selenium/webdriver/common/service.py +++ b/py/selenium/webdriver/common/service.py @@ -25,7 +25,7 @@ from platform import system from subprocess import PIPE from time import sleep -from typing import cast +from typing import cast, Optional from urllib import request from urllib.error import URLError @@ -53,6 +53,7 @@ def __init__( port: int = 0, log_output: SubprocessStdAlias = None, env: typing.Optional[typing.Mapping[typing.Any, typing.Any]] = None, + driver_path_env_key: str = None, **kwargs, ) -> None: if isinstance(log_output, str): @@ -70,6 +71,7 @@ def __init__( self.popen_kw = kwargs.pop("popen_kw", {}) self.creation_flags = self.popen_kw.pop("creation_flags", 0) self.env = env or os.environ + self.DRIVER_PATH_ENV_KEY = driver_path_env_key @property def service_url(self) -> str: @@ -236,3 +238,5 @@ def _start_process(self, path: str) -> None: f"'{os.path.basename(self._path)}' executable may have wrong permissions." ) from err raise + def env_path(self) -> Optional[str]: + return os.getenv(self.DRIVER_PATH_ENV_KEY, None) diff --git a/py/selenium/webdriver/edge/service.py b/py/selenium/webdriver/edge/service.py index 7a9142ce75467..e8f73b5b75753 100644 --- a/py/selenium/webdriver/edge/service.py +++ b/py/selenium/webdriver/edge/service.py @@ -40,9 +40,11 @@ def __init__( log_output: SubprocessStdAlias = None, service_args: typing.Optional[typing.List[str]] = None, env: typing.Optional[typing.Mapping[str, str]] = None, + driver_path_env_key: str = None, **kwargs, ) -> None: self.service_args = service_args or [] + driver_path_env_key = driver_path_env_key or 'SE_EDGEDRIVER' super().__init__( executable_path=executable_path, @@ -50,5 +52,6 @@ def __init__( service_args=service_args, log_output=log_output, env=env, + driver_path_env_key=driver_path_env_key, **kwargs, ) diff --git a/py/selenium/webdriver/firefox/service.py b/py/selenium/webdriver/firefox/service.py index 4b25cc7b5304d..e34431480547e 100644 --- a/py/selenium/webdriver/firefox/service.py +++ b/py/selenium/webdriver/firefox/service.py @@ -40,15 +40,18 @@ def __init__( service_args: typing.Optional[typing.List[str]] = None, log_output: SubprocessStdAlias = None, env: typing.Optional[typing.Mapping[str, str]] = None, + driver_path_env_key: str = None, **kwargs, ) -> None: self.service_args = service_args or [] + driver_path_env_key = driver_path_env_key or "SE_GECKODRIVER" super().__init__( executable_path=executable_path, port=port, log_output=log_output, env=env, + driver_path_env_key=driver_path_env_key, **kwargs, ) diff --git a/py/selenium/webdriver/firefox/webdriver.py b/py/selenium/webdriver/firefox/webdriver.py index c04c2d4a7b458..e07fc984cf7a2 100644 --- a/py/selenium/webdriver/firefox/webdriver.py +++ b/py/selenium/webdriver/firefox/webdriver.py @@ -58,7 +58,7 @@ def __init__( options.binary_location = finder.get_browser_path() options.browser_version = None - self.service.path = finder.get_driver_path() + self.service.path = finder.get_driver_path() or self.service.env_path() self.service.start() executor = FirefoxRemoteConnection( diff --git a/py/selenium/webdriver/ie/service.py b/py/selenium/webdriver/ie/service.py index 4b0d7f0f3bd90..9b0a6029a1a89 100644 --- a/py/selenium/webdriver/ie/service.py +++ b/py/selenium/webdriver/ie/service.py @@ -32,6 +32,7 @@ def __init__( service_args: typing.Optional[typing.List[str]] = None, log_level: typing.Optional[str] = None, log_output: SubprocessStdAlias = None, + driver_path_env_key: str = None, **kwargs, ) -> None: """Creates a new instance of the Service. @@ -46,6 +47,8 @@ def __init__( Default is "stdout". """ self.service_args = service_args or [] + driver_path_env_key = driver_path_env_key or 'SE_IEDRIVER' + if host: self.service_args.append(f"--host={host}") if log_level: @@ -55,6 +58,7 @@ def __init__( executable_path=executable_path, port=port, log_output=log_output, + driver_path_env_key=driver_path_env_key, **kwargs, ) diff --git a/py/selenium/webdriver/ie/webdriver.py b/py/selenium/webdriver/ie/webdriver.py index 64bf79fe250dc..3ba349be2e3b5 100644 --- a/py/selenium/webdriver/ie/webdriver.py +++ b/py/selenium/webdriver/ie/webdriver.py @@ -46,7 +46,7 @@ def __init__( self.service = service if service else Service() options = options if options else Options() - self.service.path = DriverFinder(self.service, options).get_driver_path() + self.service.path = DriverFinder(self.service, options).get_driver_path() or self.service.env_path() self.service.start() executor = RemoteConnection( diff --git a/py/selenium/webdriver/safari/service.py b/py/selenium/webdriver/safari/service.py index 9728b877720c4..da2ed7fcfb8db 100644 --- a/py/selenium/webdriver/safari/service.py +++ b/py/selenium/webdriver/safari/service.py @@ -37,15 +37,18 @@ def __init__( service_args: typing.Optional[typing.List[str]] = None, env: typing.Optional[typing.Mapping[str, str]] = None, reuse_service=False, + driver_path_env_key: str = None, **kwargs, ) -> None: self.service_args = service_args or [] + driver_path_env_key = driver_path_env_key or 'SE_SAFARIDRIVER' self.reuse_service = reuse_service super().__init__( executable_path=executable_path, port=port, env=env, + driver_path_env_key=driver_path_env_key, **kwargs, ) diff --git a/py/selenium/webdriver/safari/webdriver.py b/py/selenium/webdriver/safari/webdriver.py index 259b2d82047bf..6051062648600 100644 --- a/py/selenium/webdriver/safari/webdriver.py +++ b/py/selenium/webdriver/safari/webdriver.py @@ -45,7 +45,7 @@ def __init__( self.service = service if service else Service() options = options if options else Options() - self.service.path = DriverFinder(self.service, options).get_driver_path() + self.service.path = DriverFinder(self.service, options).get_driver_path() or self.service.env_path() if not self.service.reuse_service: self.service.start() From 04ce8dfa82ef763e02e2f3eb5fc6c2638b02ae31 Mon Sep 17 00:00:00 2001 From: delta456 Date: Fri, 20 Sep 2024 17:11:02 +0530 Subject: [PATCH 2/6] use boolean operation correctly --- py/selenium/webdriver/chromium/webdriver.py | 2 +- py/selenium/webdriver/firefox/webdriver.py | 2 +- py/selenium/webdriver/ie/webdriver.py | 2 +- py/selenium/webdriver/safari/webdriver.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/py/selenium/webdriver/chromium/webdriver.py b/py/selenium/webdriver/chromium/webdriver.py index 6d8df2dcd1a0e..d7bf5c706a453 100644 --- a/py/selenium/webdriver/chromium/webdriver.py +++ b/py/selenium/webdriver/chromium/webdriver.py @@ -51,7 +51,7 @@ def __init__( options.binary_location = finder.get_browser_path() options.browser_version = None - self.service.path = finder.get_driver_path() or self.service.env_path() + self.service.path = self.service.env_path() or finder.get_driver_path() self.service.start() executor = ChromiumRemoteConnection( diff --git a/py/selenium/webdriver/firefox/webdriver.py b/py/selenium/webdriver/firefox/webdriver.py index e07fc984cf7a2..dd686d93923cc 100644 --- a/py/selenium/webdriver/firefox/webdriver.py +++ b/py/selenium/webdriver/firefox/webdriver.py @@ -58,7 +58,7 @@ def __init__( options.binary_location = finder.get_browser_path() options.browser_version = None - self.service.path = finder.get_driver_path() or self.service.env_path() + self.service.path = self.service.env_path() or finder.get_driver_path() self.service.start() executor = FirefoxRemoteConnection( diff --git a/py/selenium/webdriver/ie/webdriver.py b/py/selenium/webdriver/ie/webdriver.py index 3ba349be2e3b5..11c137e509fe7 100644 --- a/py/selenium/webdriver/ie/webdriver.py +++ b/py/selenium/webdriver/ie/webdriver.py @@ -46,7 +46,7 @@ def __init__( self.service = service if service else Service() options = options if options else Options() - self.service.path = DriverFinder(self.service, options).get_driver_path() or self.service.env_path() + self.service.path = self.service.env_path() or DriverFinder(self.service, options).get_driver_path() self.service.start() executor = RemoteConnection( diff --git a/py/selenium/webdriver/safari/webdriver.py b/py/selenium/webdriver/safari/webdriver.py index 6051062648600..2c37a4bd7abde 100644 --- a/py/selenium/webdriver/safari/webdriver.py +++ b/py/selenium/webdriver/safari/webdriver.py @@ -45,7 +45,7 @@ def __init__( self.service = service if service else Service() options = options if options else Options() - self.service.path = DriverFinder(self.service, options).get_driver_path() or self.service.env_path() + self.service.path = self.service.env_path() or DriverFinder(self.service, options).get_driver_path() if not self.service.reuse_service: self.service.start() From cfad1baf0719bd6fd16ae05f9ab9b0ee9a746f3b Mon Sep 17 00:00:00 2001 From: delta456 Date: Fri, 20 Sep 2024 18:24:03 +0530 Subject: [PATCH 3/6] add test --- py/selenium/webdriver/common/service.py | 2 +- .../firefox/firefox_service_tests.py | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/py/selenium/webdriver/common/service.py b/py/selenium/webdriver/common/service.py index d3552aa6e3b95..c651e569ee09f 100644 --- a/py/selenium/webdriver/common/service.py +++ b/py/selenium/webdriver/common/service.py @@ -65,13 +65,13 @@ def __init__( else: self.log_output = log_output - self._path = executable_path self.port = port or utils.free_port() # Default value for every python subprocess: subprocess.Popen(..., creationflags=0) self.popen_kw = kwargs.pop("popen_kw", {}) self.creation_flags = self.popen_kw.pop("creation_flags", 0) self.env = env or os.environ self.DRIVER_PATH_ENV_KEY = driver_path_env_key + self._path = self.env_path() or executable_path @property def service_url(self) -> str: diff --git a/py/test/selenium/webdriver/firefox/firefox_service_tests.py b/py/test/selenium/webdriver/firefox/firefox_service_tests.py index dde881c8141b9..fe3fd05e06239 100644 --- a/py/test/selenium/webdriver/firefox/firefox_service_tests.py +++ b/py/test/selenium/webdriver/firefox/firefox_service_tests.py @@ -16,6 +16,7 @@ # under the License. import os import subprocess +import pytest from selenium.webdriver import Firefox from selenium.webdriver.firefox.service import Service @@ -54,3 +55,27 @@ def test_log_output_as_stdout(capfd) -> None: out, err = capfd.readouterr() assert "geckodriver\tINFO\tListening" in out driver.quit() + +@pytest.fixture +def service(): + return Service() + +@pytest.mark.usefixtures("service") +class TestGeckoDriverService: + service_path = "/path/to/geckodriver" + + @pytest.fixture(autouse=True) + def setup_and_teardown(self): + os.environ['SE_GECKODRIVER'] = self.service_path + yield + os.environ.pop('SE_GECKODRIVER', None) + + def test_uses_path_from_env_variable(self, service): + assert 'geckodriver' in service.path + + def test_updates_path_after_setting_env_variable(self, service): + new_path = "/foo/bar" + os.environ['SE_GECKODRIVER'] = new_path + service.executable_path = self.service_path # Simulating the update + + assert 'geckodriver' in service.executable_path From 8ef8198bfc010705b7fb9588fbb3b0ec3cd43b73 Mon Sep 17 00:00:00 2001 From: delta456 Date: Mon, 23 Sep 2024 14:37:46 +0530 Subject: [PATCH 4/6] add chrome tests --- .../webdriver/chrome/chrome_service_tests.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/py/test/selenium/webdriver/chrome/chrome_service_tests.py b/py/test/selenium/webdriver/chrome/chrome_service_tests.py index 51c0252141773..389d3b78cae69 100644 --- a/py/test/selenium/webdriver/chrome/chrome_service_tests.py +++ b/py/test/selenium/webdriver/chrome/chrome_service_tests.py @@ -95,3 +95,27 @@ def test_log_output_null_default(driver, capfd) -> None: out, err = capfd.readouterr() assert "Starting ChromeDriver" not in out driver.quit() + +@pytest.fixture +def service(): + return Service() + +@pytest.mark.usefixtures("service") +class TestChromeDriverService: + service_path = "/path/to/chromedriver" + + @pytest.fixture(autouse=True) + def setup_and_teardown(self): + os.environ['SE_CHROMEDRIVER'] = self.service_path + yield + os.environ.pop('SE_CHROMEDRIVER', None) + + def test_uses_path_from_env_variable(self, service): + assert 'chromedriver' in service.path + + def test_updates_path_after_setting_env_variable(self, service): + new_path = "/foo/bar" + os.environ['SE_CHROMEDRIVER'] = new_path + service.executable_path = self.service_path # Simulating the update + + assert 'chromedriver' in service.executable_path From 2a63e2142ca2403bba2f242163f19cadd79df981 Mon Sep 17 00:00:00 2001 From: delta456 Date: Mon, 23 Sep 2024 14:49:12 +0530 Subject: [PATCH 5/6] format --- py/selenium/webdriver/chromium/service.py | 2 +- py/selenium/webdriver/common/service.py | 1 + py/selenium/webdriver/edge/service.py | 2 +- py/selenium/webdriver/ie/service.py | 2 +- py/selenium/webdriver/safari/service.py | 2 +- .../webdriver/chrome/chrome_service_tests.py | 12 +++++++----- .../webdriver/firefox/firefox_service_tests.py | 12 +++++++----- 7 files changed, 19 insertions(+), 14 deletions(-) diff --git a/py/selenium/webdriver/chromium/service.py b/py/selenium/webdriver/chromium/service.py index 3446c4fac1e7a..aebedec40f509 100644 --- a/py/selenium/webdriver/chromium/service.py +++ b/py/selenium/webdriver/chromium/service.py @@ -43,7 +43,7 @@ def __init__( **kwargs, ) -> None: self.service_args = service_args or [] - driver_path_env_key = driver_path_env_key or 'SE_CHROMEDRIVER' + driver_path_env_key = driver_path_env_key or "SE_CHROMEDRIVER" if isinstance(log_output, str): self.service_args.append(f"--log-path={log_output}") diff --git a/py/selenium/webdriver/common/service.py b/py/selenium/webdriver/common/service.py index c651e569ee09f..bfddbb78fc6ab 100644 --- a/py/selenium/webdriver/common/service.py +++ b/py/selenium/webdriver/common/service.py @@ -238,5 +238,6 @@ def _start_process(self, path: str) -> None: f"'{os.path.basename(self._path)}' executable may have wrong permissions." ) from err raise + def env_path(self) -> Optional[str]: return os.getenv(self.DRIVER_PATH_ENV_KEY, None) diff --git a/py/selenium/webdriver/edge/service.py b/py/selenium/webdriver/edge/service.py index e8f73b5b75753..698a917149de4 100644 --- a/py/selenium/webdriver/edge/service.py +++ b/py/selenium/webdriver/edge/service.py @@ -44,7 +44,7 @@ def __init__( **kwargs, ) -> None: self.service_args = service_args or [] - driver_path_env_key = driver_path_env_key or 'SE_EDGEDRIVER' + driver_path_env_key = driver_path_env_key or "SE_EDGEDRIVER" super().__init__( executable_path=executable_path, diff --git a/py/selenium/webdriver/ie/service.py b/py/selenium/webdriver/ie/service.py index 9b0a6029a1a89..b8fac381d9f35 100644 --- a/py/selenium/webdriver/ie/service.py +++ b/py/selenium/webdriver/ie/service.py @@ -47,7 +47,7 @@ def __init__( Default is "stdout". """ self.service_args = service_args or [] - driver_path_env_key = driver_path_env_key or 'SE_IEDRIVER' + driver_path_env_key = driver_path_env_key or "SE_IEDRIVER" if host: self.service_args.append(f"--host={host}") diff --git a/py/selenium/webdriver/safari/service.py b/py/selenium/webdriver/safari/service.py index da2ed7fcfb8db..3386198c893ac 100644 --- a/py/selenium/webdriver/safari/service.py +++ b/py/selenium/webdriver/safari/service.py @@ -41,7 +41,7 @@ def __init__( **kwargs, ) -> None: self.service_args = service_args or [] - driver_path_env_key = driver_path_env_key or 'SE_SAFARIDRIVER' + driver_path_env_key = driver_path_env_key or "SE_SAFARIDRIVER" self.reuse_service = reuse_service super().__init__( diff --git a/py/test/selenium/webdriver/chrome/chrome_service_tests.py b/py/test/selenium/webdriver/chrome/chrome_service_tests.py index 389d3b78cae69..c3b3360c939c4 100644 --- a/py/test/selenium/webdriver/chrome/chrome_service_tests.py +++ b/py/test/selenium/webdriver/chrome/chrome_service_tests.py @@ -96,26 +96,28 @@ def test_log_output_null_default(driver, capfd) -> None: assert "Starting ChromeDriver" not in out driver.quit() + @pytest.fixture def service(): return Service() + @pytest.mark.usefixtures("service") class TestChromeDriverService: service_path = "/path/to/chromedriver" @pytest.fixture(autouse=True) def setup_and_teardown(self): - os.environ['SE_CHROMEDRIVER'] = self.service_path + os.environ["SE_CHROMEDRIVER"] = self.service_path yield - os.environ.pop('SE_CHROMEDRIVER', None) + os.environ.pop("SE_CHROMEDRIVER", None) def test_uses_path_from_env_variable(self, service): - assert 'chromedriver' in service.path + assert "chromedriver" in service.path def test_updates_path_after_setting_env_variable(self, service): new_path = "/foo/bar" - os.environ['SE_CHROMEDRIVER'] = new_path + os.environ["SE_CHROMEDRIVER"] = new_path service.executable_path = self.service_path # Simulating the update - assert 'chromedriver' in service.executable_path + assert "chromedriver" in service.executable_path diff --git a/py/test/selenium/webdriver/firefox/firefox_service_tests.py b/py/test/selenium/webdriver/firefox/firefox_service_tests.py index fe3fd05e06239..553e5aeb33913 100644 --- a/py/test/selenium/webdriver/firefox/firefox_service_tests.py +++ b/py/test/selenium/webdriver/firefox/firefox_service_tests.py @@ -56,26 +56,28 @@ def test_log_output_as_stdout(capfd) -> None: assert "geckodriver\tINFO\tListening" in out driver.quit() + @pytest.fixture def service(): return Service() + @pytest.mark.usefixtures("service") class TestGeckoDriverService: service_path = "/path/to/geckodriver" @pytest.fixture(autouse=True) def setup_and_teardown(self): - os.environ['SE_GECKODRIVER'] = self.service_path + os.environ["SE_GECKODRIVER"] = self.service_path yield - os.environ.pop('SE_GECKODRIVER', None) + os.environ.pop("SE_GECKODRIVER", None) def test_uses_path_from_env_variable(self, service): - assert 'geckodriver' in service.path + assert "geckodriver" in service.path def test_updates_path_after_setting_env_variable(self, service): new_path = "/foo/bar" - os.environ['SE_GECKODRIVER'] = new_path + os.environ["SE_GECKODRIVER"] = new_path service.executable_path = self.service_path # Simulating the update - assert 'geckodriver' in service.executable_path + assert "geckodriver" in service.executable_path From 7e57ab747ceced9460709d59ec9d7d8bcd280e9a Mon Sep 17 00:00:00 2001 From: delta456 Date: Mon, 23 Sep 2024 15:00:17 +0530 Subject: [PATCH 6/6] format --- py/selenium/webdriver/common/service.py | 3 ++- py/test/selenium/webdriver/firefox/firefox_service_tests.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/py/selenium/webdriver/common/service.py b/py/selenium/webdriver/common/service.py index bfddbb78fc6ab..3afbced1a3e88 100644 --- a/py/selenium/webdriver/common/service.py +++ b/py/selenium/webdriver/common/service.py @@ -25,7 +25,8 @@ from platform import system from subprocess import PIPE from time import sleep -from typing import cast, Optional +from typing import Optional +from typing import cast from urllib import request from urllib.error import URLError diff --git a/py/test/selenium/webdriver/firefox/firefox_service_tests.py b/py/test/selenium/webdriver/firefox/firefox_service_tests.py index 553e5aeb33913..2a57d0341acee 100644 --- a/py/test/selenium/webdriver/firefox/firefox_service_tests.py +++ b/py/test/selenium/webdriver/firefox/firefox_service_tests.py @@ -16,6 +16,7 @@ # under the License. import os import subprocess + import pytest from selenium.webdriver import Firefox