Path: blob/trunk/py/selenium/webdriver/common/options.py
4007 views
# Licensed to the Software Freedom Conservancy (SFC) under one1# or more contributor license agreements. See the NOTICE file2# distributed with this work for additional information3# regarding copyright ownership. The SFC licenses this file4# to you under the Apache License, Version 2.0 (the5# "License"); you may not use this file except in compliance6# with the License. You may obtain a copy of the License at7#8# http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing,11# software distributed under the License is distributed on an12# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13# KIND, either express or implied. See the License for the14# specific language governing permissions and limitations15# under the License.1617import warnings18from abc import ABCMeta, abstractmethod19from enum import Enum2021from selenium.common.exceptions import InvalidArgumentException22from selenium.webdriver.common.proxy import Proxy232425class PageLoadStrategy(str, Enum):26"""Enum of possible page load strategies.2728Selenium support following strategies:29* normal (default) - waits for all resources to download30* eager - DOM access is ready, but other resources like images may still be loading31* none - does not block `WebDriver` at all3233Docs: https://www.selenium.dev/documentation/webdriver/drivers/options/#pageloadstrategy.34"""3536normal = "normal"37eager = "eager"38none = "none"394041class _BaseOptionsDescriptor:42def __init__(self, name):43self.name = name4445def __get__(self, obj, cls):46if self.name == "enableBidi":47# whether BiDi is or will be enabled48value = obj._caps.get("webSocketUrl")49return value is True or isinstance(value, str)50if self.name == "webSocketUrl":51# Return socket url or None if not created yet52value = obj._caps.get(self.name)53return None if not isinstance(value, str) else value54if self.name in ("acceptInsecureCerts", "strictFileInteractability", "setWindowRect", "se:downloadsEnabled"):55return obj._caps.get(self.name, False)56return obj._caps.get(self.name)5758def __set__(self, obj, value):59if self.name == "enableBidi":60obj.set_capability("webSocketUrl", value)61else:62obj.set_capability(self.name, value)636465class _PageLoadStrategyDescriptor:66"""Determines the point at which a navigation command is returned.6768See:69- https://w3c.github.io/webdriver/#dfn-table-of-page-load-strategies.7071Args:72strategy: the strategy corresponding to a document readiness state73"""7475def __init__(self, name):76self.name = name7778def __get__(self, obj, cls):79return obj._caps.get(self.name)8081def __set__(self, obj, value):82if value in ("normal", "eager", "none"):83obj.set_capability(self.name, value)84else:85raise ValueError("Strategy can only be one of the following: normal, eager, none")868788class _UnHandledPromptBehaviorDescriptor:89"""How the driver should respond when an alert is present and the command sent is not handling the alert.9091See:92- https://w3c.github.io/webdriver/#dfn-table-of-page-load-strategies:9394Args:95behavior: behavior to use when an alert is encountered9697Returns:98Values for implicit timeout, pageLoad timeout and script timeout if set (in milliseconds)99"""100101def __init__(self, name):102self.name = name103104def __get__(self, obj, cls):105return obj._caps.get(self.name)106107def __set__(self, obj, value):108if value in ("dismiss", "accept", "dismiss and notify", "accept and notify", "ignore"):109obj.set_capability(self.name, value)110else:111raise ValueError(112"Behavior can only be one of the following: dismiss, accept, dismiss and notify, "113"accept and notify, ignore"114)115116117class _TimeoutsDescriptor:118"""How long the driver should wait for actions to complete before returning an error.119120See:121- https://w3c.github.io/webdriver/#timeouts122123Args:124timeouts: values in milliseconds for implicit wait, page load and script timeout125126Returns:127Values for implicit timeout, pageLoad timeout and script timeout if set (in milliseconds)128"""129130def __init__(self, name):131self.name = name132133def __get__(self, obj, cls):134return obj._caps.get(self.name)135136def __set__(self, obj, value):137if all(x in ("implicit", "pageLoad", "script") for x in value.keys()):138obj.set_capability(self.name, value)139else:140raise ValueError("Timeout keys can only be one of the following: implicit, pageLoad, script")141142143class _ProxyDescriptor:144"""Descriptor for proxy property access.145146Returns:147Proxy if set, otherwise None.148"""149150def __init__(self, name):151self.name = name152153def __get__(self, obj, cls):154return obj._proxy155156def __set__(self, obj, value):157if not isinstance(value, Proxy):158raise InvalidArgumentException("Only Proxy objects can be passed in.")159obj._proxy = value160obj._caps[self.name] = value.to_capabilities()161162163class BaseOptions(metaclass=ABCMeta):164"""Base class for individual browser options."""165166browser_version = _BaseOptionsDescriptor("browserVersion")167"""Gets and Sets the version of the browser.168169Usage:170- Get: `self.browser_version`171- Set: `self.browser_version = value`172173Args:174value: str175176Returns:177str when getting, None when setting.178"""179180platform_name = _BaseOptionsDescriptor("platformName")181"""Gets and Sets name of the platform.182183Usage:184- Get: `self.platform_name`185- Set: `self.platform_name = value`186187Args:188value: str189190Returns:191str when getting, None when setting.192"""193194accept_insecure_certs = _BaseOptionsDescriptor("acceptInsecureCerts")195"""Gets and Set whether the session accepts insecure certificates.196197Usage:198- Get: `self.accept_insecure_certs`199- Set: `self.accept_insecure_certs = value`200201Args:202value: bool203204Returns:205bool when getting, None when setting.206"""207208strict_file_interactability = _BaseOptionsDescriptor("strictFileInteractability")209"""Gets and Sets whether session is about file interactability.210211Usage:212- Get: `self.strict_file_interactability`213- Set: `self.strict_file_interactability = value`214215Args:216value: bool217218Returns:219bool when getting, None when setting.220"""221222set_window_rect = _BaseOptionsDescriptor("setWindowRect")223"""Gets and Sets window size and position.224225Usage:226- Get: `self.set_window_rect`227- Set: `self.set_window_rect = value`228229Args:230value: bool231232Returns:233bool when getting, None when setting.234"""235236enable_bidi = _BaseOptionsDescriptor("enableBidi")237"""Gets and Set whether the session has WebDriverBiDi enabled.238239Usage:240- Get: `self.enable_bidi`241- Set: `self.enable_bidi = value`242243Args:244value: bool245246Returns:247bool when getting, None when setting.248"""249250page_load_strategy = _PageLoadStrategyDescriptor("pageLoadStrategy")251"""Gets and Sets page load strategy, the default is "normal".252253Usage:254- Get: `self.page_load_strategy`255- Set: `self.page_load_strategy = value`256257Args:258value: str259260Returns:261str when getting, None when setting.262"""263264unhandled_prompt_behavior = _UnHandledPromptBehaviorDescriptor("unhandledPromptBehavior")265"""Gets and Sets unhandled prompt behavior, the default is "dismiss and notify".266267Usage:268- Get: `self.unhandled_prompt_behavior`269- Set: `self.unhandled_prompt_behavior = value`270271Args:272value: str273274Returns:275str when getting, None when setting.276"""277278timeouts = _TimeoutsDescriptor("timeouts")279"""Gets and Sets implicit timeout, pageLoad timeout and script timeout if set (in milliseconds).280281Usage:282- Get: `self.timeouts`283- Set: `self.timeouts = value`284285Args:286value: dict287288Returns:289dict when getting, None when setting.290"""291292proxy = _ProxyDescriptor("proxy")293"""Sets and Gets Proxy.294295Usage:296- Get: `self.proxy`297- Set: `self.proxy = value`298299Args:300value: Proxy301302Returns:303Proxy when getting, None when setting.304"""305306enable_downloads = _BaseOptionsDescriptor("se:downloadsEnabled")307"""Gets and Sets whether session can download files.308309Usage:310- Get: `self.enable_downloads`311- Set: `self.enable_downloads = value`312313Args:314value: bool315316Returns:317bool when getting, None when setting.318"""319320web_socket_url = _BaseOptionsDescriptor("webSocketUrl")321"""Gets and Sets WebSocket URL.322323Usage:324- Get: `self.web_socket_url`325- Set: `self.web_socket_url = value`326327Args:328value: str329330Returns:331str when getting, None when setting.332"""333334def __init__(self) -> None:335super().__init__()336self._caps = self.default_capabilities337self._proxy = None338self.set_capability("pageLoadStrategy", PageLoadStrategy.normal)339self.mobile_options: dict[str, str] | None = None340self._ignore_local_proxy = False341342@property343def capabilities(self):344return self._caps345346def set_capability(self, name, value) -> None:347"""Sets a capability."""348self._caps[name] = value349350def enable_mobile(351self,352android_package: str | None = None,353android_activity: str | None = None,354device_serial: str | None = None,355) -> None:356"""Enables mobile browser use for browsers that support it.357358Args:359android_package: The name of the android package to start360android_activity: The name of the android activity361device_serial: The device serial number362"""363if not android_package:364raise AttributeError("android_package must be passed in")365self.mobile_options = {"androidPackage": android_package}366if android_activity:367self.mobile_options["androidActivity"] = android_activity368if device_serial:369self.mobile_options["androidDeviceSerial"] = device_serial370371@abstractmethod372def to_capabilities(self):373"""Convert options into capabilities dictionary."""374375@property376@abstractmethod377def default_capabilities(self):378"""Return minimal capabilities necessary as a dictionary."""379380def ignore_local_proxy_environment_variables(self) -> None:381"""Ignore HTTP_PROXY and HTTPS_PROXY environment variables."""382self._ignore_local_proxy = True383384385class ArgOptions(BaseOptions):386BINARY_LOCATION_ERROR = "Binary Location Must be a String"387# FedCM capability key388FEDCM_CAPABILITY = "fedcm:accounts"389390def __init__(self) -> None:391super().__init__()392self._arguments: list[str] = []393394@property395def arguments(self):396"""Returns a list of arguments needed for the browser."""397return self._arguments398399def add_argument(self, argument: str) -> None:400"""Adds an argument to the list.401402Args:403argument: Sets the arguments404"""405if argument:406self._arguments.append(argument)407else:408raise ValueError("argument can not be null")409410def ignore_local_proxy_environment_variables(self) -> None:411"""Ignore HTTP_PROXY and HTTPS_PROXY environment variables.412413This method is deprecated; use a Proxy instance with ProxyType.DIRECT instead.414"""415warnings.warn(416"using ignore_local_proxy_environment_variables in Options has been deprecated, "417"instead, create a Proxy instance with ProxyType.DIRECT to ignore proxy settings, "418"pass the proxy instance into a ClientConfig constructor, "419"pass the client config instance into the Webdriver constructor",420DeprecationWarning,421stacklevel=2,422)423424super().ignore_local_proxy_environment_variables()425426def to_capabilities(self):427return self._caps428429@property430def default_capabilities(self):431return {}432433434