Skip to content
18 changes: 15 additions & 3 deletions py/selenium/webdriver/chrome/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@


from collections.abc import Mapping
from typing import Optional
from typing import Optional, Sequence

from selenium.types import SubprocessStdAlias
from selenium.webdriver.chromium import service
Expand All @@ -29,7 +29,7 @@ class Service(service.ChromiumService):

:param executable_path: install path of the chromedriver executable, defaults to `chromedriver`.
:param port: Port for the service to run on, defaults to 0 where the operating system will decide.
:param service_args: (Optional) List of args to be passed to the subprocess when launching the executable.
:param service_args: (Optional) Sequence of args to be passed to the subprocess when launching the executable.
:param log_output: (Optional) int representation of STDOUT/DEVNULL, any IO instance or String path to file.
:param env: (Optional) Mapping of environment variables for the new process, defaults to `os.environ`.
"""
Expand All @@ -38,11 +38,13 @@ def __init__(
self,
executable_path: Optional[str] = None,
port: int = 0,
service_args: Optional[list[str]] = None,
service_args: Optional[Sequence[str]] = None,
log_output: Optional[SubprocessStdAlias] = None,
env: Optional[Mapping[str, str]] = None,
**kwargs,
) -> None:
self._service_args = service_args or []

super().__init__(
executable_path=executable_path,
port=port,
Expand All @@ -51,3 +53,13 @@ def __init__(
env=env,
**kwargs,
)

@property
def service_args(self) -> Sequence[str]:
return self._service_args

@service_args.setter
def service_args(self, value: Sequence[str]):
if isinstance(value, str) or not isinstance(value, Sequence):
raise TypeError("service_args must be a sequence")
self._service_args = list(value)
23 changes: 17 additions & 6 deletions py/selenium/webdriver/chromium/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

from collections.abc import Mapping
from io import IOBase
from typing import Optional
from typing import Optional, Sequence

from selenium.types import SubprocessStdAlias
from selenium.webdriver.common import service
Expand All @@ -28,7 +29,7 @@ class ChromiumService(service.Service):

:param executable_path: install path of the executable.
:param port: Port for the service to run on, defaults to 0 where the operating system will decide.
:param service_args: (Optional) List of args to be passed to the subprocess when launching the executable.
:param service_args: (Optional) Sequence of args to be passed to the subprocess when launching the executable.
:param log_output: (Optional) int representation of STDOUT/DEVNULL, any IO instance or String path to file.
:param env: (Optional) Mapping of environment variables for the new process, defaults to `os.environ`.
:param driver_path_env_key: (Optional) Environment variable to use to get the path to the driver executable.
Expand All @@ -38,17 +39,17 @@ def __init__(
self,
executable_path: Optional[str] = None,
port: int = 0,
service_args: Optional[list[str]] = None,
service_args: Optional[Sequence[str]] = None,
log_output: Optional[SubprocessStdAlias] = None,
env: Optional[Mapping[str, str]] = None,
driver_path_env_key: Optional[str] = None,
**kwargs,
) -> None:
self.service_args = service_args or []
self._service_args = list(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}")
self._service_args.append(f"--log-path={log_output}")
self.log_output: Optional[IOBase] = None
elif isinstance(log_output, IOBase):
self.log_output = log_output
Expand All @@ -65,4 +66,14 @@ def __init__(
)

def command_line_args(self) -> list[str]:
return [f"--port={self.port}"] + self.service_args
return [f"--port={self.port}"] + self._service_args

@property
def service_args(self) -> Sequence[str]:
return self._service_args

@service_args.setter
def service_args(self, value: Sequence[str]):
if isinstance(value, str) or not isinstance(value, Sequence):
raise TypeError("service_args must be a sequence")
self._service_args = list(value)
1 change: 1 addition & 0 deletions py/selenium/webdriver/common/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

import errno
import logging
import os
Expand Down
18 changes: 14 additions & 4 deletions py/selenium/webdriver/edge/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# under the License.

from collections.abc import Mapping
from typing import Optional
from typing import Optional, Sequence

from selenium.types import SubprocessStdAlias
from selenium.webdriver.chromium import service
Expand All @@ -29,7 +29,7 @@ class Service(service.ChromiumService):
:param executable_path: install path of the msedgedriver executable, defaults to `msedgedriver`.
:param port: Port for the service to run on, defaults to 0 where the operating system will decide.
:param log_output: (Optional) int representation of STDOUT/DEVNULL, any IO instance or String path to file.
:param service_args: (Optional) List of args to be passed to the subprocess when launching the executable.
:param service_args: (Optional) Sequence of args to be passed to the subprocess when launching the executable.
:param env: (Optional) Mapping of environment variables for the new process, defaults to `os.environ`.
:param driver_path_env_key: (Optional) Environment variable to use to get the path to the driver executable.
"""
Expand All @@ -39,12 +39,12 @@ def __init__(
executable_path: Optional[str] = None,
port: int = 0,
log_output: Optional[SubprocessStdAlias] = None,
service_args: Optional[list[str]] = None,
service_args: Optional[Sequence[str]] = None,
env: Optional[Mapping[str, str]] = None,
driver_path_env_key: Optional[str] = None,
**kwargs,
) -> None:
self.service_args = service_args or []
self._service_args = list(service_args or [])
driver_path_env_key = driver_path_env_key or "SE_EDGEDRIVER"

super().__init__(
Expand All @@ -56,3 +56,13 @@ def __init__(
driver_path_env_key=driver_path_env_key,
**kwargs,
)

@property
def service_args(self) -> Sequence[str]:
return self._service_args

@service_args.setter
def service_args(self, value: Sequence[str]):
if isinstance(value, str) or not isinstance(value, Sequence):
raise TypeError("service_args must be a sequence")
self._service_args = list(value)
27 changes: 19 additions & 8 deletions py/selenium/webdriver/firefox/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

from collections.abc import Mapping
from typing import Optional
from typing import Optional, Sequence

from selenium.types import SubprocessStdAlias
from selenium.webdriver.common import service, utils
Expand All @@ -27,7 +28,7 @@ class Service(service.Service):

:param executable_path: install path of the geckodriver executable, defaults to `geckodriver`.
:param port: Port for the service to run on, defaults to 0 where the operating system will decide.
:param service_args: (Optional) List of args to be passed to the subprocess when launching the executable.
:param service_args: (Optional) Sequence of args to be passed to the subprocess when launching the executable.
:param log_output: (Optional) int representation of STDOUT/DEVNULL, any IO instance or String path to file.
:param env: (Optional) Mapping of environment variables for the new process, defaults to `os.environ`.
:param driver_path_env_key: (Optional) Environment variable to use to get the path to the driver executable.
Expand All @@ -37,13 +38,13 @@ def __init__(
self,
executable_path: Optional[str] = None,
port: int = 0,
service_args: Optional[list[str]] = None,
service_args: Optional[Sequence[str]] = None,
log_output: Optional[SubprocessStdAlias] = None,
env: Optional[Mapping[str, str]] = None,
driver_path_env_key: Optional[str] = None,
**kwargs,
) -> None:
self.service_args = service_args or []
self._service_args = list(service_args or [])
driver_path_env_key = driver_path_env_key or "SE_GECKODRIVER"

super().__init__(
Expand All @@ -56,9 +57,19 @@ def __init__(
)

# Set a port for CDP
if "--connect-existing" not in self.service_args:
self.service_args.append("--websocket-port")
self.service_args.append(f"{utils.free_port()}")
if "--connect-existing" not in self._service_args:
self._service_args.append("--websocket-port")
self._service_args.append(f"{utils.free_port()}")

def command_line_args(self) -> list[str]:
return ["--port", f"{self.port}"] + self.service_args
return ["--port", f"{self.port}"] + self._service_args

@property
def service_args(self) -> Sequence[str]:
return self._service_args

@service_args.setter
def service_args(self, value: Sequence[str]):
if isinstance(value, str) or not isinstance(value, Sequence):
raise TypeError("service_args must be a sequence")
self._service_args = list(value)
31 changes: 22 additions & 9 deletions py/selenium/webdriver/ie/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from typing import Optional

from typing import Optional, Sequence

from selenium.types import SubprocessStdAlias
from selenium.webdriver.common import service
Expand All @@ -28,7 +29,7 @@ def __init__(
executable_path: Optional[str] = None,
port: int = 0,
host: Optional[str] = None,
service_args: Optional[list[str]] = None,
service_args: Optional[Sequence[str]] = None,
log_level: Optional[str] = None,
log_output: Optional[SubprocessStdAlias] = None,
driver_path_env_key: Optional[str] = None,
Expand All @@ -39,19 +40,21 @@ def __init__(
:Args:
- executable_path : Path to the IEDriver
- port : Port the service is running on
- host : IP address the service port is bound
- log_level : Level of logging of service, may be "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE".
Default is "FATAL".
- host : (Optional) IP address the service port is bound
- service_args: (Optional) Sequence of args to be passed to the subprocess when launching the executable.
- log_level : (Optional) Level of logging of service, may be "FATAL", "ERROR", "WARN", "INFO", "DEBUG",
"TRACE". Default is "FATAL".
- log_output: (Optional) int representation of STDOUT/DEVNULL, any IO instance or String path to file.
Default is "stdout".
- driver_path_env_key: (Optional) Environment variable to use to get the path to the driver executable.
"""
self.service_args = service_args or []
self._service_args = list(service_args or [])
driver_path_env_key = driver_path_env_key or "SE_IEDRIVER"

if host:
self.service_args.append(f"--host={host}")
self._service_args.append(f"--host={host}")
if log_level:
self.service_args.append(f"--log-level={log_level}")
self._service_args.append(f"--log-level={log_level}")

super().__init__(
executable_path=executable_path,
Expand All @@ -62,4 +65,14 @@ def __init__(
)

def command_line_args(self) -> list[str]:
return [f"--port={self.port}"] + self.service_args
return [f"--port={self.port}"] + self._service_args

@property
def service_args(self) -> Sequence[str]:
return self._service_args

@service_args.setter
def service_args(self, value: Sequence[str]):
if isinstance(value, str) or not isinstance(value, Sequence):
raise TypeError("service_args must be a sequence")
self._service_args = list(value)
23 changes: 16 additions & 7 deletions py/selenium/webdriver/safari/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@
# specific language governing permissions and limitations
# under the License.


from collections.abc import Mapping
from typing import Optional
from typing import Optional, Sequence

from selenium.webdriver.common import service

Expand All @@ -28,7 +27,7 @@ class Service(service.Service):

:param executable_path: install path of the safaridriver executable, defaults to `/usr/bin/safaridriver`.
:param port: Port for the service to run on, defaults to 0 where the operating system will decide.
:param service_args: (Optional) List of args to be passed to the subprocess when launching the executable.
:param service_args: (Optional) Sequence of args to be passed to the subprocess when launching the executable.
:param env: (Optional) Mapping of environment variables for the new process, defaults to `os.environ`.
:param enable_logging: (Optional) Enable logging of the service. Logs can be located at
`~/Library/Logs/com.apple.WebDriver/`
Expand All @@ -39,18 +38,18 @@ def __init__(
self,
executable_path: Optional[str] = None,
port: int = 0,
service_args: Optional[list[str]] = None,
service_args: Optional[Sequence[str]] = None,
env: Optional[Mapping[str, str]] = None,
reuse_service=False,
enable_logging: bool = False,
driver_path_env_key: Optional[str] = None,
**kwargs,
) -> None:
self.service_args = service_args or []
self._service_args = list(service_args or [])
driver_path_env_key = driver_path_env_key or "SE_SAFARIDRIVER"

if enable_logging:
self.service_args.append("--diagnose")
self._service_args.append("--diagnose")

self.reuse_service = reuse_service
super().__init__(
Expand All @@ -62,7 +61,7 @@ def __init__(
)

def command_line_args(self) -> list[str]:
return ["-p", f"{self.port}"] + self.service_args
return ["-p", f"{self.port}"] + self._service_args

@property
def service_url(self) -> str:
Expand All @@ -78,3 +77,13 @@ def reuse_service(self, reuse: bool) -> None:
if not isinstance(reuse, bool):
raise TypeError("reuse must be a boolean")
self._reuse_service = reuse

@property
def service_args(self) -> Sequence[str]:
return self._service_args

@service_args.setter
def service_args(self, value: Sequence[str]):
if isinstance(value, str) or not isinstance(value, Sequence):
raise TypeError("service_args must be a sequence")
self._service_args = list(value)
Loading