Skip to content

Commit

Permalink
[py] Remove deprecated code in driver classes (#12030)
Browse files Browse the repository at this point in the history
* [py] remove chrome w3c warnings

* [py] this constant is always true for supported versions of Python

* [py] remove deprecations

* [py] Fixing linting issues

---------

Co-authored-by: Diego Molina <diemol@gmail.com>
Co-authored-by: Diego Molina <diemol@users.noreply.github.com>
  • Loading branch information
3 people committed Jun 1, 2023
1 parent abad15e commit 9f5801c
Show file tree
Hide file tree
Showing 17 changed files with 124 additions and 705 deletions.
5 changes: 1 addition & 4 deletions py/conftest.py
Expand Up @@ -27,7 +27,6 @@
import pytest

from selenium import webdriver
from selenium.webdriver import DesiredCapabilities

drivers = (
"chrome",
Expand Down Expand Up @@ -120,9 +119,7 @@ def fin():
if driver_class == "Chrome":
options = get_options(driver_class, request.config)
if driver_class == "Remote":
capabilities = DesiredCapabilities.FIREFOX.copy()
kwargs.update({"desired_capabilities": capabilities})
options = get_options("Firefox", request.config)
options = get_options("Firefox", request.config) or webdriver.FirefoxOptions()
if driver_class == "WebKitGTK":
options = get_options(driver_class, request.config)
if driver_class == "Edge":
Expand Down
64 changes: 11 additions & 53 deletions py/selenium/webdriver/chrome/webdriver.py
Expand Up @@ -14,84 +14,42 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import warnings

from selenium.webdriver.chromium.webdriver import ChromiumDriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.common.driver_finder import DriverFinder

from .options import Options
from .service import DEFAULT_EXECUTABLE_PATH
from .service import Service

DEFAULT_PORT = 0
DEFAULT_SERVICE_LOG_PATH = None
DEFAULT_KEEP_ALIVE = None


class WebDriver(ChromiumDriver):
"""Controls the ChromeDriver and allows you to drive the browser.
You will need to download the ChromeDriver executable from
http://chromedriver.storage.googleapis.com/index.html
"""
"""Controls the ChromeDriver and allows you to drive the browser."""

def __init__(
self,
executable_path=DEFAULT_EXECUTABLE_PATH,
port=DEFAULT_PORT,
options: Options = None,
service_args=None,
desired_capabilities=None,
service_log_path=DEFAULT_SERVICE_LOG_PATH,
chrome_options=None,
service: Service = None,
keep_alive=DEFAULT_KEEP_ALIVE,
keep_alive: bool = True,
) -> None:
"""Creates a new instance of the chrome driver. Starts the service and
then creates new instance of chrome driver.
:Args:
- executable_path - Deprecated: path to the executable. If the default is used it assumes the executable is in the $PATH
- port - Deprecated: port you would like the service to run, if left as 0, a free port will be found.
- options - this takes an instance of ChromeOptions
- service - Service object for handling the browser driver if you need to pass extra details
- service_args - Deprecated: List of args to pass to the driver service
- desired_capabilities - Deprecated: Dictionary object with non-browser specific
capabilities only, such as "proxy" or "loggingPref".
- service_log_path - Deprecated: Where to log information from the driver.
- keep_alive - Deprecated: Whether to configure ChromeRemoteConnection to use HTTP keep-alive.
- keep_alive - Whether to configure ChromeRemoteConnection to use HTTP keep-alive.
"""
if executable_path != "chromedriver":
warnings.warn(
"executable_path has been deprecated, please pass in a Service object", DeprecationWarning, stacklevel=2
)
if chrome_options:
warnings.warn("use options instead of chrome_options", DeprecationWarning, stacklevel=2)
options = chrome_options
if keep_alive != DEFAULT_KEEP_ALIVE:
warnings.warn(
"keep_alive has been deprecated, please pass in a Service object", DeprecationWarning, stacklevel=2
)
else:
keep_alive = True
if not options:
options = self.create_options()
if not service:
service = Service(executable_path, port, service_args, service_log_path)
service.path = DriverFinder.get_path(service, options)
self.service = service if service else Service()
self.options = options if options else Options()
self.keep_alive = keep_alive

self.service.path = DriverFinder.get_path(self.service, self.options)

super().__init__(
DesiredCapabilities.CHROME["browserName"],
"goog",
port,
options,
service_args,
desired_capabilities,
service_log_path,
service,
keep_alive,
self.options,
self.service,
self.keep_alive,
)

def create_options(self) -> Options:
return Options()
13 changes: 0 additions & 13 deletions py/selenium/webdriver/chromium/options.py
Expand Up @@ -132,8 +132,6 @@ def add_experimental_option(self, name: str, value: Union[str, int, dict, List[s
name: The experimental option name.
value: The option value.
"""
if name.lower() == "w3c" and (value == "false" or value is False):
warnings.warn(UserWarning("Manipulating `w3c` setting can have unintended consequences."), stacklevel=2)
self._experimental_options[name] = value

@property
Expand Down Expand Up @@ -176,17 +174,6 @@ def to_capabilities(self) -> dict:
"""
caps = self._caps
chrome_options = self.experimental_options.copy()
if "w3c" in chrome_options:
if chrome_options["w3c"]:
warnings.warn(
"Setting 'w3c: True' is redundant and will no longer be allowed", DeprecationWarning, stacklevel=2
)
else:
raise AttributeError(
"setting w3c to False is not allowed, "
"Please update to W3C Syntax: "
"https://www.selenium.dev/blog/2022/legacy-protocol-support/"
)
if self.mobile_options:
chrome_options.update(self.mobile_options)
chrome_options["extensions"] = self.extensions
Expand Down
73 changes: 10 additions & 63 deletions py/selenium/webdriver/chromium/webdriver.py
Expand Up @@ -15,19 +15,11 @@
# specific language governing permissions and limitations
# under the License.

import warnings

from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.chromium.remote_connection import ChromiumRemoteConnection
from selenium.webdriver.common.options import BaseOptions
from selenium.webdriver.common.options import ArgOptions
from selenium.webdriver.common.service import Service
from selenium.webdriver.edge.options import Options as EdgeOptions
from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver

DEFAULT_PORT = 0
DEFAULT_SERVICE_LOG_PATH = None
DEFAULT_KEEP_ALIVE = None


class ChromiumDriver(RemoteWebDriver):
"""Controls the WebDriver instance of ChromiumDriver and allows you to
Expand All @@ -37,67 +29,25 @@ def __init__(
self,
browser_name,
vendor_prefix,
port=DEFAULT_PORT,
options: BaseOptions = None,
service_args=None,
desired_capabilities=None,
service_log_path=DEFAULT_SERVICE_LOG_PATH,
service: Service = None,
keep_alive=DEFAULT_KEEP_ALIVE,
options: ArgOptions,
service: Service,
keep_alive=True,
) -> None:
"""Creates a new WebDriver instance of the ChromiumDriver. Starts the
service and then creates new WebDriver instance of ChromiumDriver.
:Args:
- browser_name - Browser name used when matching capabilities.
- vendor_prefix - Company prefix to apply to vendor-specific WebDriver extension commands.
- port - Deprecated: port you would like the service to run, if left as 0, a free port will be found.
- options - this takes an instance of ChromiumOptions
- service_args - Deprecated: List of args to pass to the driver service
- desired_capabilities - Deprecated: Dictionary object with non-browser specific
capabilities only, such as "proxy" or "loggingPref".
- service_log_path - Deprecated: Where to log information from the driver.
- keep_alive - Deprecated: Whether to configure ChromiumRemoteConnection to use HTTP keep-alive.
- 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.
"""
if desired_capabilities:
warnings.warn(
"desired_capabilities has been deprecated, please pass in a Service object",
DeprecationWarning,
stacklevel=2,
)
if port != DEFAULT_PORT:
warnings.warn("port has been deprecated, please pass in a Service object", DeprecationWarning, stacklevel=2)
self.port = port
if service_log_path != DEFAULT_SERVICE_LOG_PATH:
warnings.warn(
"service_log_path has been deprecated, please pass in a Service object",
DeprecationWarning,
stacklevel=2,
)
if keep_alive != DEFAULT_KEEP_ALIVE and type(self) == __class__:
warnings.warn(
"keep_alive has been deprecated, please pass in a Service object", DeprecationWarning, stacklevel=2
)
else:
keep_alive = True

self.vendor_prefix = vendor_prefix

_ignore_proxy = None
if not options:
options = self.create_options()

if desired_capabilities:
for key, value in desired_capabilities.items():
options.set_capability(key, value)

if options._ignore_local_proxy:
_ignore_proxy = options._ignore_local_proxy

if not service:
raise AttributeError("service cannot be None")

self.service = service
self.options = options

self.service.start()

try:
Expand All @@ -107,9 +57,9 @@ def __init__(
browser_name=browser_name,
vendor_prefix=vendor_prefix,
keep_alive=keep_alive,
ignore_proxy=_ignore_proxy,
ignore_proxy=self.options._ignore_local_proxy,
),
options=options,
options=self.options,
)
except Exception:
self.quit()
Expand Down Expand Up @@ -240,6 +190,3 @@ def quit(self) -> None:
pass
finally:
self.service.stop()

def create_options(self) -> BaseOptions:
return EdgeOptions() if self.vendor_prefix == "ms" else ChromeOptions()
7 changes: 2 additions & 5 deletions py/selenium/webdriver/common/service.py
Expand Up @@ -35,9 +35,6 @@
logger = logging.getLogger(__name__)


_HAS_NATIVE_DEVNULL = True


class Service(ABC):
"""The abstract base class for all service objects. Services typically
launch a child program in a new process as an interim process to
Expand All @@ -61,7 +58,7 @@ def __init__(
) -> None:
self._path = executable
self.port = port or utils.free_port()
self.log_file = open(os.devnull, "wb") if not _HAS_NATIVE_DEVNULL and log_file == DEVNULL else log_file
self.log_file = open(os.devnull, "wb") if not log_file == DEVNULL else log_file

This comment has been minimized.

Copy link
@jun66j5

jun66j5 Jun 29, 2023

The conditional expression is wrong.

-        self.log_file = open(os.devnull, "wb") if not log_file == DEVNULL else log_file
+        self.log_file = open(os.devnull, "wb") if log_file == DEVNULL else log_file

This comment has been minimized.

Copy link
@titusfortner

titusfortner Jun 29, 2023

Author Member

Yes, this was already fixed in trunk and will be available for the next release. Thanks.

self.start_error_message = start_error_message or ""
# Default value for every python subprocess: subprocess.Popen(..., creationflags=0)
self.popen_kw = kwargs.pop("popen_kw", {})
Expand Down Expand Up @@ -132,7 +129,7 @@ def send_remote_shutdown_command(self) -> None:

def stop(self) -> None:
"""Stops the service."""
if self.log_file != PIPE and not (self.log_file == DEVNULL and _HAS_NATIVE_DEVNULL):
if self.log_file != PIPE and not (self.log_file == DEVNULL):
try:
# Todo: Be explicit in what we are catching here.
if hasattr(self.log_file, "close"):
Expand Down
54 changes: 10 additions & 44 deletions py/selenium/webdriver/edge/webdriver.py
Expand Up @@ -14,76 +14,42 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import warnings

from selenium.webdriver.chromium.webdriver import ChromiumDriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.common.driver_finder import DriverFinder

from .options import Options
from .service import DEFAULT_EXECUTABLE_PATH
from .service import Service

DEFAULT_PORT = 0
DEFAULT_SERVICE_LOG_PATH = None


class WebDriver(ChromiumDriver):
"""Controls the Microsoft Edge driver and allows you to drive the browser.
You will need to download the MSEdgeDriver executable from
https://developer.microsoft.com/microsoft-edge/tools/webdriver/
"""
"""Controls the MDEdgeDriver and allows you to drive the browser."""

def __init__(
self,
executable_path=DEFAULT_EXECUTABLE_PATH,
port=DEFAULT_PORT,
options: Options = Options(),
service_args=None,
capabilities=None,
service_log_path=DEFAULT_SERVICE_LOG_PATH,
options: Options = None,
service: Service = None,
keep_alive=False,
verbose=False, # Todo: Why is this now unused?
keep_alive=True,
) -> None:
"""Creates a new instance of the edge driver. Starts the service and
then creates new instance of edge driver.
:Args:
- executable_path - Deprecated: path to the executable. If the default is used it assumes the executable is in the $PATH
- port - Deprecated: port you would like the service to run, if left as 0, a free port will be found.
- options - this takes an instance of EdgeOptions
- service_args - Deprecated: List of args to pass to the driver service
- capabilities - Deprecated: Dictionary object with non-browser specific
capabilities only, such as "proxy" or "loggingPref".
- service_log_path - Deprecated: Where to log information from the driver.
- 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.
- verbose - whether to set verbose logging in the service.
"""
if executable_path != "msedgedriver":
warnings.warn(
"executable_path has been deprecated, please pass in a Service object", DeprecationWarning, stacklevel=2
)
self.service = service if service else Service()
self.options = options if options else Options()
self.keep_alive = keep_alive

if not options:
options = self.create_options()
if not service:
service = Service(executable_path, port, service_args, service_log_path)
service.path = DriverFinder.get_path(service, options)
self.service.path = DriverFinder.get_path(self.service, self.options)

super().__init__(
DesiredCapabilities.EDGE["browserName"],
"ms",
port,
options,
service_args,
capabilities,
service_log_path,
service,
keep_alive,
self.options,
self.service,
self.keep_alive,
)

def create_options(self) -> Options:
return Options()

0 comments on commit 9f5801c

Please sign in to comment.