Skip to content
Open
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
20 changes: 20 additions & 0 deletions py/selenium/webdriver/chrome/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chromium.webdriver import ChromiumDriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.remote.client_config import ClientConfig


class WebDriver(ChromiumDriver):
Expand All @@ -31,6 +32,7 @@ def __init__(
options: Optional[Options] = None,
service: Optional[Service] = None,
keep_alive: bool = True,
client_config: Optional[ClientConfig] = None,
) -> None:
"""Creates a new instance of the chrome driver.

Expand All @@ -40,6 +42,23 @@ def __init__(
options: This takes an instance of ChromeOptions.
service: Service object for handling the browser driver if you need to pass extra details.
keep_alive: Whether to configure ChromeRemoteConnection to use HTTP keep-alive.
This parameter is ignored if client_config is provided.
client_config: ClientConfig instance for advanced HTTP/WebSocket configuration.
If provided, takes precedence over individual parameters like keep_alive.

Example:
Basic usage::

driver = webdriver.Chrome()

With custom config::

from selenium.webdriver.remote.client_config import ClientConfig
config = ClientConfig(
remote_server_addr="http://localhost:9515",
websocket_timeout=10
)
driver = webdriver.Chrome(client_config=config)
"""
service = service if service else Service()
options = options if options else Options()
Expand All @@ -50,4 +69,5 @@ def __init__(
options=options,
service=service,
keep_alive=keep_alive,
client_config=client_config,
)
11 changes: 11 additions & 0 deletions py/selenium/webdriver/chromium/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
from selenium.webdriver.chromium.remote_connection import ChromiumRemoteConnection
from selenium.webdriver.chromium.service import ChromiumService
from selenium.webdriver.common.driver_finder import DriverFinder
from selenium.webdriver.common.utils import normalize_local_driver_config
from selenium.webdriver.remote.client_config import ClientConfig
from selenium.webdriver.remote.command import Command
from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver

Expand All @@ -35,6 +37,7 @@ def __init__(
options: Optional[ChromiumOptions] = None,
service: Optional[ChromiumService] = None,
keep_alive: bool = True,
client_config: Optional[ClientConfig] = None,
) -> None:
"""Create a new WebDriver instance, start the service, and create new ChromiumDriver instance.

Expand All @@ -44,6 +47,9 @@ def __init__(
options: This takes an instance of ChromiumOptions.
service: Service object for handling the browser driver if you need to pass extra details.
keep_alive: Whether to configure ChromiumRemoteConnection to use HTTP keep-alive.
This parameter is ignored if client_config is provided.
client_config: ClientConfig instance for advanced HTTP/WebSocket configuration.
If provided, takes precedence over individual parameters like keep_alive.
"""
self.service = service if service else ChromiumService()
options = options if options else ChromiumOptions()
Expand All @@ -56,12 +62,17 @@ def __init__(
self.service.path = self.service.env_path() or finder.get_driver_path()
self.service.start()

client_config = normalize_local_driver_config(
self.service.service_url, user_config=client_config, keep_alive=keep_alive, timeout=120
)

executor = ChromiumRemoteConnection(
remote_server_addr=self.service.service_url,
browser_name=browser_name,
vendor_prefix=vendor_prefix,
keep_alive=keep_alive,
ignore_proxy=options._ignore_local_proxy,
client_config=client_config,
)

try:
Expand Down
16 changes: 16 additions & 0 deletions py/selenium/webdriver/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

from selenium.types import AnyKey
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.remote.client_config import ClientConfig

_is_connectable_exceptions = (socket.error, ConnectionResetError)

Expand Down Expand Up @@ -164,3 +165,18 @@ def keys_to_typing(value: Iterable[AnyKey]) -> list[str]:
else:
characters.extend(val)
return characters


def normalize_local_driver_config(
service_url: str, user_config: Optional[ClientConfig] = None, **defaults
) -> ClientConfig:
"""Creates a ClientConfig for local drivers."""
if user_config is None:
return ClientConfig(remote_server_addr=service_url, **defaults)

# Programmatically copy attributes to avoid brittleness
config_args = {
key.lstrip("_"): value for key, value in vars(user_config).items()
}
config_args["remote_server_addr"] = service_url
return ClientConfig(**config_args)
18 changes: 17 additions & 1 deletion py/selenium/webdriver/edge/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.edge.options import Options
from selenium.webdriver.edge.service import Service
from selenium.webdriver.remote.client_config import ClientConfig


class WebDriver(ChromiumDriver):
Expand All @@ -31,6 +32,7 @@ def __init__(
options: Optional[Options] = None,
service: Optional[Service] = None,
keep_alive: bool = True,
client_config: Optional[ClientConfig] = None,
) -> None:
"""Creates a new instance of the edge driver.

Expand All @@ -41,7 +43,20 @@ def __init__(
service: Service object for handling the browser driver if you need
to pass extra details.
keep_alive: Whether to configure EdgeRemoteConnection to use HTTP
keep-alive.
keep-alive. This parameter is ignored if client_config is provided.
client_config: ClientConfig instance for advanced HTTP/WebSocket configuration.
If provided, takes precedence over individual parameters like keep_alive.

Example:
Basic usage::

driver = webdriver.Edge()

With custom config::

from selenium.webdriver.remote.client_config import ClientConfig
config = ClientConfig(websocket_timeout=10)
driver = webdriver.Edge(client_config=config)
"""
service = service if service else Service()
options = options if options else Options()
Expand All @@ -52,4 +67,5 @@ def __init__(
options=options,
service=service,
keep_alive=keep_alive,
client_config=client_config,
)
22 changes: 22 additions & 0 deletions py/selenium/webdriver/firefox/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
from typing import Optional

from selenium.webdriver.common.driver_finder import DriverFinder
from selenium.webdriver.common.utils import normalize_local_driver_config
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.remote_connection import FirefoxRemoteConnection
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.remote.client_config import ClientConfig
from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver


Expand All @@ -40,13 +42,28 @@ def __init__(
options: Optional[Options] = None,
service: Optional[Service] = None,
keep_alive: bool = True,
client_config: Optional[ClientConfig] = None,
) -> None:
"""Create a new instance of the Firefox driver, start the service, and create new instance.

Args:
options: Instance of ``options.Options``.
service: (Optional) service instance for managing the starting and stopping of the driver.
keep_alive: Whether to configure remote_connection.RemoteConnection to use HTTP keep-alive.
This parameter is ignored if client_config is provided.
client_config: ClientConfig instance for advanced HTTP/WebSocket configuration.
If provided, takes precedence over individual parameters like keep_alive.

Example:
Basic usage::

driver = webdriver.Firefox()

With custom config::

from selenium.webdriver.remote.client_config import ClientConfig
config = ClientConfig(websocket_timeout=10)
driver = webdriver.Firefox(client_config=config)
"""
self.service = service if service else Service()
options = options if options else Options()
Expand All @@ -59,10 +76,15 @@ def __init__(
self.service.path = self.service.env_path() or finder.get_driver_path()
self.service.start()

client_config = normalize_local_driver_config(
self.service.service_url, user_config=client_config, keep_alive=keep_alive, timeout=120
)

executor = FirefoxRemoteConnection(
remote_server_addr=self.service.service_url,
keep_alive=keep_alive,
ignore_proxy=options._ignore_local_proxy,
client_config=client_config,
)

try:
Expand Down
21 changes: 20 additions & 1 deletion py/selenium/webdriver/ie/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from typing import Optional

from selenium.webdriver.common.driver_finder import DriverFinder
from selenium.webdriver.common.utils import normalize_local_driver_config
from selenium.webdriver.ie.options import Options
from selenium.webdriver.ie.service import Service
from selenium.webdriver.remote.client_config import ClientConfig
Expand All @@ -33,6 +34,7 @@ def __init__(
options: Optional[Options] = None,
service: Optional[Service] = None,
keep_alive: bool = True,
client_config: Optional[ClientConfig] = None,
) -> None:
"""Creates a new instance of the Ie driver.

Expand All @@ -42,14 +44,31 @@ def __init__(
options: IE Options instance, providing additional IE options
service: (Optional) service instance for managing the starting and stopping of the driver.
keep_alive: Whether to configure RemoteConnection to use HTTP keep-alive.
This parameter is ignored if client_config is provided.
client_config: ClientConfig instance for advanced HTTP/WebSocket configuration.
If provided, takes precedence over individual parameters like keep_alive.

Example:
Basic usage::

driver = webdriver.Ie()

With custom config::

from selenium.webdriver.remote.client_config import ClientConfig
config = ClientConfig(websocket_timeout=10)
driver = webdriver.Ie(client_config=config)
"""
self.service = service if service else Service()
options = options if options else Options()

self.service.path = self.service.env_path() or DriverFinder(self.service, options).get_driver_path()
self.service.start()

client_config = ClientConfig(remote_server_addr=self.service.service_url, keep_alive=keep_alive, timeout=120)
client_config = normalize_local_driver_config(
self.service.service_url, user_config=client_config, keep_alive=keep_alive, timeout=120
)

executor = RemoteConnection(
ignore_proxy=options._ignore_local_proxy,
client_config=client_config,
Expand Down
2 changes: 1 addition & 1 deletion py/selenium/webdriver/remote/client_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class ClientConfig:

def __init__(
self,
remote_server_addr: str,
remote_server_addr: Optional[str] = None,
keep_alive: Optional[bool] = True,
proxy: Optional[Proxy] = Proxy(raw={"proxyType": ProxyType.SYSTEM}),
ignore_certificates: Optional[bool] = False,
Expand Down
24 changes: 23 additions & 1 deletion py/selenium/webdriver/safari/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.driver_finder import DriverFinder
from selenium.webdriver.common.utils import normalize_local_driver_config
from selenium.webdriver.remote.client_config import ClientConfig
from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver
from selenium.webdriver.safari.options import Options
from selenium.webdriver.safari.remote_connection import SafariRemoteConnection
Expand All @@ -30,17 +32,32 @@ class WebDriver(RemoteWebDriver):

def __init__(
self,
keep_alive=True,
keep_alive: bool = True,
options: Optional[Options] = None,
service: Optional[Service] = None,
client_config: Optional[ClientConfig] = None,
) -> None:
"""Create a new Safari driver instance and launch or find a running safaridriver service.

Args:
keep_alive: Whether to configure SafariRemoteConnection to use
HTTP keep-alive. Defaults to True.
This parameter is ignored if client_config is provided.
options: Instance of ``options.Options``.
service: Service object for handling the browser driver if you need to pass extra details
client_config: ClientConfig instance for advanced HTTP/WebSocket configuration.
If provided, takes precedence over individual parameters like keep_alive.

Example:
Basic usage::

driver = webdriver.Safari()

With custom config::

from selenium.webdriver.remote.client_config import ClientConfig
config = ClientConfig(websocket_timeout=10)
driver = webdriver.Safari(client_config=config)
"""
self.service = service if service else Service()
options = options if options else Options()
Expand All @@ -50,10 +67,15 @@ def __init__(
if not self.service.reuse_service:
self.service.start()

client_config = normalize_local_driver_config(
self.service.service_url, user_config=client_config, keep_alive=keep_alive, timeout=120
)

executor = SafariRemoteConnection(
remote_server_addr=self.service.service_url,
keep_alive=keep_alive,
ignore_proxy=options._ignore_local_proxy,
client_config=client_config,
)

try:
Expand Down
Loading