Skip to content
Merged
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
3 changes: 2 additions & 1 deletion py/generate_api_module_listing.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
file containing a listing of all modules in separate sections.
The `api.rst` file is later used by `sphinx-autogen` to generate
sphinx autodoc stub pages used in the Python API documentation.
See `py/tox.ini` for how it is invoked."""
See `py/tox.ini` for how it is invoked.
"""

import os
import site
Expand Down
19 changes: 18 additions & 1 deletion py/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,26 @@ respect-gitignore = true
target-version = "py39"

[tool.ruff.lint]
extend-select = ["E4", "E7", "E9", "F", "I", "E501", "RUF022", "TID252"]
extend-select = ["D", "E4", "E7", "E9", "F", "I", "E501", "RUF022", "TID252"]
fixable = ["ALL"]
# remove these as we cleanup docstrings
extend-ignore = [
"D100", # Missing docstring in public module
"D101", # Missing docstring in public class
"D102", # Missing docstring in public method
"D103", # Missing docstring in public function
"D104", # Missing docstring in public package
"D105", # Missing docstring in magic method
"D107", # Missing docstring in `__init__`
"D205", # 1 blank line required between summary line and description
"D212", # Multi-line docstring summary should start at the first line
"D415", # First line should end with a period, question mark, or exclamation point
"D417", # Missing argument descriptions in the docstring for `__init__`
]

[tool.ruff.format]
docstring-code-format = true
docstring-code-line-length = 120

[tool.ruff.lint.pydocstyle]
convention = "google"
27 changes: 18 additions & 9 deletions py/selenium/common/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ class NoSuchAttributeException(WebDriverException):

class NoSuchShadowRootException(WebDriverException):
"""Thrown when trying to access the shadow root of an element when it does
not have a shadow root attached."""
not have a shadow root attached.
"""


class StaleElementReferenceException(WebDriverException):
Expand Down Expand Up @@ -175,7 +176,8 @@ def __init__(

class ElementNotInteractableException(InvalidElementStateException):
"""Thrown when an element is present in the DOM but interactions with that
element will hit another element due to paint order."""
element will hit another element due to paint order.
"""

def __init__(
self, msg: Optional[Any] = None, screen: Optional[str] = None, stacktrace: Optional[Sequence[str]] = None
Expand All @@ -194,7 +196,8 @@ class ElementNotSelectableException(InvalidElementStateException):

class InvalidCookieDomainException(WebDriverException):
"""Thrown when attempting to add a cookie under a different domain than the
current URL."""
current URL.
"""


class UnableToSetCookieException(WebDriverException):
Expand All @@ -207,7 +210,8 @@ class TimeoutException(WebDriverException):

class MoveTargetOutOfBoundsException(WebDriverException):
"""Thrown when the target provided to the `ActionsChains` move() method is
invalid, i.e. out of document."""
invalid, i.e. out of document.
"""


class UnexpectedTagNameException(WebDriverException):
Expand Down Expand Up @@ -254,7 +258,8 @@ class JavascriptException(WebDriverException):

class NoSuchCookieException(WebDriverException):
"""No cookie matching the given path name was found amongst the associated
cookies of the current browsing context's active document."""
cookies of the current browsing context's active document.
"""


class ScreenshotException(WebDriverException):
Expand All @@ -264,7 +269,8 @@ class ScreenshotException(WebDriverException):
class ElementClickInterceptedException(WebDriverException):
"""The Element Click command could not be completed because the element
receiving the events is obscuring the element that was requested to be
clicked."""
clicked.
"""

def __init__(
self, msg: Optional[Any] = None, screen: Optional[str] = None, stacktrace: Optional[Sequence[str]] = None
Expand All @@ -276,7 +282,8 @@ def __init__(

class InsecureCertificateException(WebDriverException):
"""Navigation caused the user agent to hit a certificate warning, which is
usually the result of an expired or invalid TLS certificate."""
usually the result of an expired or invalid TLS certificate.
"""


class InvalidCoordinatesException(WebDriverException):
Expand All @@ -285,7 +292,8 @@ class InvalidCoordinatesException(WebDriverException):

class InvalidSessionIdException(WebDriverException):
"""Occurs if the given session id is not in the list of active sessions,
meaning the session either does not exist or that it's not active."""
meaning the session either does not exist or that it's not active.
"""

def __init__(
self, msg: Optional[Any] = None, screen: Optional[str] = None, stacktrace: Optional[Sequence[str]] = None
Expand All @@ -308,7 +316,8 @@ def __init__(

class UnknownMethodException(WebDriverException):
"""The requested command matched a known URL but did not match any methods
for that URL."""
for that URL.
"""


class NoSuchDriverException(WebDriverException):
Expand Down
2 changes: 1 addition & 1 deletion py/selenium/webdriver/chromium/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def add_extension(self, extension: str) -> None:
extract it to the ChromeDriver.

Args:
extension: Path to the \\*.crx file.
extension: Path to the *.crx file.
"""
if extension:
extension_to_add = os.path.abspath(os.path.expanduser(extension))
Expand Down
4 changes: 2 additions & 2 deletions py/selenium/webdriver/chromium/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@

class ChromiumDriver(RemoteWebDriver):
"""Controls the WebDriver instance of ChromiumDriver and allows you to
drive the browser."""
drive the browser.
"""

def __init__(
self,
Expand All @@ -47,7 +48,6 @@ def __init__(
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.
"""

self.service = service if service else ChromiumService()
options = options if options else ChromiumOptions()

Expand Down
10 changes: 2 additions & 8 deletions py/selenium/webdriver/common/action_chains.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ def perform(self) -> None:

def reset_actions(self) -> None:
"""Clears actions that are already stored locally and on the remote
end."""
end.
"""
self.w3c_actions.clear_actions()
for device in self.w3c_actions.devices:
device.clear_actions()
Expand Down Expand Up @@ -235,7 +236,6 @@ def move_by_offset(self, xoffset: int, yoffset: int) -> ActionChains:
xoffset: X offset to move to, as a positive or negative integer.
yoffset: Y offset to move to, as a positive or negative integer.
"""

self.w3c_actions.pointer_action.move_by(xoffset, yoffset)
self.w3c_actions.key_action.pause()

Expand All @@ -247,7 +247,6 @@ def move_to_element(self, to_element: WebElement) -> ActionChains:
Args:
to_element: The WebElement to move to.
"""

self.w3c_actions.pointer_action.move_to(to_element)
self.w3c_actions.key_action.pause()

Expand All @@ -262,15 +261,13 @@ def move_to_element_with_offset(self, to_element: WebElement, xoffset: int, yoff
xoffset: X offset to move to, as a positive or negative integer.
yoffset: Y offset to move to, as a positive or negative integer.
"""

self.w3c_actions.pointer_action.move_to(to_element, int(xoffset), int(yoffset))
self.w3c_actions.key_action.pause()

return self

def pause(self, seconds: float | int) -> ActionChains:
"""Pause all inputs for the specified duration in seconds."""

self.w3c_actions.pointer_action.pause(seconds)
self.w3c_actions.key_action.pause(int(seconds))

Expand Down Expand Up @@ -325,7 +322,6 @@ def scroll_to_element(self, element: WebElement) -> ActionChains:
Args:
element: Which element to scroll into the viewport.
"""

self.w3c_actions.wheel_action.scroll(origin=element)
return self

Expand All @@ -337,7 +333,6 @@ def scroll_by_amount(self, delta_x: int, delta_y: int) -> ActionChains:
delta_x: Distance along X axis to scroll using the wheel. A negative value scrolls left.
delta_y: Distance along Y axis to scroll using the wheel. A negative value scrolls up.
"""

self.w3c_actions.wheel_action.scroll(delta_x=delta_x, delta_y=delta_y)
return self

Expand All @@ -356,7 +351,6 @@ def scroll_from_origin(self, scroll_origin: ScrollOrigin, delta_x: int, delta_y:
Raises:
MoveTargetOutOfBoundsException: If the origin with offset is outside the viewport.
"""

if not isinstance(scroll_origin, ScrollOrigin):
raise TypeError(f"Expected object of type ScrollOrigin, got: {type(scroll_origin)}")

Expand Down
1 change: 0 additions & 1 deletion py/selenium/webdriver/common/actions/input_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ def __init__(self, name: Optional[str] = None):
self.actions: list[Any] = []

def add_action(self, action: Any) -> None:
""""""
self.actions.append(action)

def clear_actions(self) -> None:
Expand Down
6 changes: 0 additions & 6 deletions py/selenium/webdriver/common/bidi/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ def _on_request(self, event_name, callback):
Returns:
int: callback id
"""

event = NetworkEvent(event_name)

def _callback(event_data):
Expand Down Expand Up @@ -155,7 +154,6 @@ def add_request_handler(self, event, callback, url_patterns=None, contexts=None)
Returns:
int: callback id
"""

try:
event_name = self.EVENTS[event]
phase_name = self.PHASES[event]
Expand Down Expand Up @@ -202,7 +200,6 @@ def remove_request_handler(self, event, callback_id):

def clear_request_handlers(self):
"""Clear all request handlers from the network."""

for event_name in self.subscriptions:
net_event = NetworkEvent(event_name)
for callback_id in self.subscriptions[event_name]:
Expand Down Expand Up @@ -270,7 +267,6 @@ def __init__(

def fail_request(self):
"""Fail this request."""

if not self.request_id:
raise ValueError("Request not found.")

Expand All @@ -279,7 +275,6 @@ def fail_request(self):

def continue_request(self, body=None, method=None, headers=None, cookies=None, url=None):
"""Continue after intercepting this request."""

if not self.request_id:
raise ValueError("Request not found.")

Expand Down Expand Up @@ -307,7 +302,6 @@ def _continue_with_auth(self, username=None, password=None):
Note:
If username or password is None, it attempts auth with no credentials.
"""

params = {}
params["request"] = self.request_id

Expand Down
1 change: 0 additions & 1 deletion py/selenium/webdriver/common/bidi/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,6 @@ def execute(self, script: str, *args) -> dict:
Raises:
WebDriverException: If the script execution fails.
"""

if self.driver is None:
raise WebDriverException("Driver reference is required for script execution")
browsing_context_id = self.driver.current_window_handle
Expand Down
3 changes: 0 additions & 3 deletions py/selenium/webdriver/common/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ async def mutation_events(self) -> AsyncGenerator[dict[str, Any], None]:
assert event["current_value"] == ""
assert event["old_value"] == "display:none;"
"""

page = self.cdp.get_session_context("page.enable")
await page.execute(self.devtools.page.enable())
runtime = self.cdp.get_session_context("runtime.enable")
Expand Down Expand Up @@ -105,7 +104,6 @@ async def add_js_error_listener(self) -> AsyncGenerator[dict[str, Any], None]:
assert bool(error)
assert error.exception_details.stack_trace.call_frames[0].function_name == "onmouseover"
"""

session = self.cdp.get_session_context("page.enable")
await session.execute(self.devtools.page.enable())
session = self.cdp.get_session_context("runtime.enable")
Expand All @@ -128,7 +126,6 @@ async def add_listener(self, event_type) -> AsyncGenerator[dict[str, Any], None]
driver.execute_script("console.log('I like cheese')")
assert messages["message"] == "I love cheese"
"""

from selenium.webdriver.common.bidi.console import Console

session = self.cdp.get_session_context("page.enable")
Expand Down
6 changes: 4 additions & 2 deletions py/selenium/webdriver/common/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,8 @@ def default_capabilities(self):

def ignore_local_proxy_environment_variables(self) -> None:
"""By calling this you will ignore HTTP_PROXY and HTTPS_PROXY from
being picked up and used."""
being picked up and used.
"""
self._ignore_local_proxy = True


Expand Down Expand Up @@ -409,7 +410,8 @@ def add_argument(self, argument: str) -> None:

def ignore_local_proxy_environment_variables(self) -> None:
"""By calling this you will ignore HTTP_PROXY and HTTPS_PROXY from
being picked up and used."""
being picked up and used.
"""
warnings.warn(
"using ignore_local_proxy_environment_variables in Options has been deprecated, "
"instead, create a Proxy instance with ProxyType.DIRECT to ignore proxy settings, "
Expand Down
3 changes: 2 additions & 1 deletion py/selenium/webdriver/common/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ def __set__(self, obj, value):

class Proxy:
"""Proxy contains information about proxy type and necessary proxy
settings."""
settings.
"""

proxyType = ProxyType.UNSPECIFIED
autodetect = False
Expand Down
2 changes: 0 additions & 2 deletions py/selenium/webdriver/common/selenium_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ def binary_paths(self, args: list) -> dict:
Returns:
Dictionary of assets and their path.
"""

args = [str(self._get_binary())] + args
if logger.getEffectiveLevel() == logging.DEBUG:
args.append("--debug")
Expand All @@ -65,7 +64,6 @@ def _get_binary() -> Path:
Raises:
WebDriverException: If the platform is unsupported.
"""

compiled_path = Path(__file__).parent.joinpath("selenium-manager")
exe = sysconfig.get_config_var("EXE")
if exe is not None:
Expand Down
7 changes: 4 additions & 3 deletions py/selenium/webdriver/common/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,14 @@ def assert_process_still_running(self) -> None:

def is_connectable(self) -> bool:
"""Establishes a socket connection to determine if the service running
on the port is accessible."""
on the port is accessible.
"""
return utils.is_connectable(self.port)

def send_remote_shutdown_command(self) -> None:
"""Dispatch an HTTP request to the shutdown endpoint for the service in
an attempt to stop it."""
an attempt to stop it.
"""
try:
request.urlopen(f"{self.service_url}/shutdown")
except URLError:
Expand All @@ -142,7 +144,6 @@ def send_remote_shutdown_command(self) -> None:

def stop(self) -> None:
"""Stops the service."""

if self.log_output not in {PIPE, subprocess.DEVNULL}:
if isinstance(self.log_output, IOBase):
self.log_output.close()
Expand Down
1 change: 0 additions & 1 deletion py/selenium/webdriver/common/timeouts.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ def __init__(self, implicit_wait: float = 0, page_load: float = 0, script: float
script: Number of seconds to wait for an asynchronous script to
finish execution before throwing an error.
"""

self._implicit_wait = self._convert(implicit_wait)
self._page_load = self._convert(page_load)
self._script = self._convert(script)
Expand Down
Loading