Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[py] added decorator for handling deprecations. #12432

Closed
Closed
Show file tree
Hide file tree
Changes from 2 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
31 changes: 31 additions & 0 deletions py/selenium/deprecated.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from warnings import warn
sandeepsuryaprasad marked this conversation as resolved.
Show resolved Hide resolved

removed_from_version = "4.12"
sandeepsuryaprasad marked this conversation as resolved.
Show resolved Hide resolved


def deprecated_function(message):
"""decorator to log deprecation warning messgaes for deprecated methods."""

def _deprecated_function(func):
def wrapper(*args, **kwargs):
sandeepsuryaprasad marked this conversation as resolved.
Show resolved Hide resolved
warn(f"{message}: will be removed from {removed_from_version}", DeprecationWarning, stacklevel=2)
return func(*args, **kwargs)

return wrapper

return _deprecated_function


def deprecated_attributes(*attrs, message):
def _deprecated_attributes(func):
def wrapper(*args, **kwargs):
sandeepsuryaprasad marked this conversation as resolved.
Show resolved Hide resolved
result = func(*args, **kwargs)
for attr in attrs:
_attr = getattr(args[0], attr, None)
if _attr:
sandeepsuryaprasad marked this conversation as resolved.
Show resolved Hide resolved
warn(f"'{message}': will be removed from {removed_from_version}", DeprecationWarning, stacklevel=2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does stacklevel=2 play nice with a decorator (especially one with args?) in terms of the stack in the output? would need to double check

return result

return wrapper

return _deprecated_attributes
16 changes: 5 additions & 11 deletions py/selenium/webdriver/chromium/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@

import base64
import os
import warnings
from typing import BinaryIO
from typing import List
from typing import Union

from selenium.deprecated import deprecated_function
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.common.options import ArgOptions

Expand Down Expand Up @@ -139,18 +139,17 @@ def add_experimental_option(self, name: str, value: Union[str, int, dict, List[s
self._experimental_options[name] = value

@property
@deprecated_function("headless property is deprecated, instead check for '--headless' in arguments")
def headless(self) -> bool:
"""
:Returns: True if the headless argument is set, else False
"""
warnings.warn(
"headless property is deprecated, instead check for '--headless' in arguments",
DeprecationWarning,
stacklevel=2,
)
return "--headless" in self._arguments

@headless.setter
@deprecated_function(
"headless property is deprecated, instead use add_argument('--headless') or add_argument('--headless=new')"
)
def headless(self, value: bool) -> None:
"""Sets the headless argument Old headless uses a non-production
browser and is set with `--headless`
Expand All @@ -160,11 +159,6 @@ def headless(self, value: bool) -> None:
:Args:
value: boolean value indicating to set the headless option
"""
warnings.warn(
"headless property is deprecated, instead use add_argument('--headless') or add_argument('--headless=new')",
DeprecationWarning,
stacklevel=2,
)
args = {"--headless"}

if not isinstance(value, bool):
Expand Down
7 changes: 3 additions & 4 deletions py/selenium/webdriver/chromium/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
# specific language governing permissions and limitations
# under the License.
import typing
import warnings

from selenium.common import InvalidArgumentException
from selenium.deprecated import deprecated_attributes
from selenium.types import SubprocessStdAlias
from selenium.webdriver.common import service

Expand All @@ -33,6 +33,7 @@ class ChromiumService(service.Service):
:param env: (Optional) Mapping of environment variables for the new process, defaults to `os.environ`.
"""

@deprecated_attributes("log_path", message="log_path has been deprecated, please use log_output")
def __init__(
self,
executable_path: str = None,
Expand All @@ -45,9 +46,7 @@ def __init__(
) -> None:
self.service_args = service_args or []
self.log_output = log_output
if log_path is not None:
warnings.warn("log_path has been deprecated, please use log_output", DeprecationWarning, stacklevel=2)
self.log_output = log_path
self.log_output = log_path

if "--append-log" in self.service_args or "--readable-timestamp" in self.service_args:
if isinstance(self.log_output, str):
Expand Down
11 changes: 4 additions & 7 deletions py/selenium/webdriver/edge/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
# specific language governing permissions and limitations
# under the License.
import typing
import warnings

from selenium.deprecated import deprecated_attributes
from selenium.types import SubprocessStdAlias
from selenium.webdriver.chromium import service

Expand All @@ -34,6 +34,9 @@ class Service(service.ChromiumService):
:param env: (Optional) Mapping of environment variables for the new process, defaults to `os.environ`.
"""

@deprecated_attributes(
"verbose", message="verbose=True is deprecated. Use `service_args=['--verbose', ...]` instead."
)
def __init__(
self,
executable_path: str = None,
Expand All @@ -46,13 +49,7 @@ def __init__(
**kwargs,
) -> None:
self.service_args = service_args or []

if verbose:
warnings.warn(
"verbose=True is deprecated. Use `service_args=['--verbose', ...]` instead.",
DeprecationWarning,
stacklevel=2,
)
self.service_args.append("--verbose")

super().__init__(
Expand Down
5 changes: 2 additions & 3 deletions py/selenium/webdriver/firefox/firefox_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from xml.dom import minidom

from selenium.common.exceptions import WebDriverException
from selenium.deprecated import deprecated_function

WEBDRIVER_EXT = "webdriver.xpi"
WEBDRIVER_PREFERENCES = "webdriver_prefs.json"
Expand All @@ -43,6 +44,7 @@ class FirefoxProfile:
ANONYMOUS_PROFILE_NAME = "WEBDRIVER_ANONYMOUS_PROFILE"
DEFAULT_PREFERENCES = None

@deprecated_function("firefox_profile has been deprecated, please use an Options object")
def __init__(self, profile_directory=None):
"""Initialises a new instance of a Firefox Profile.

Expand All @@ -53,9 +55,6 @@ def __init__(self, profile_directory=None):
This defaults to None and will create a new
directory when object is created.
"""
warnings.warn(
"firefox_profile has been deprecated, please use an Options object", DeprecationWarning, stacklevel=2
)
if not FirefoxProfile.DEFAULT_PREFERENCES:
with open(
os.path.join(os.path.dirname(__file__), WEBDRIVER_PREFERENCES), encoding="utf-8"
Expand Down
23 changes: 7 additions & 16 deletions py/selenium/webdriver/firefox/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
# specific language governing permissions and limitations
# under the License.
import typing
import warnings
from typing import Union

from selenium.deprecated import deprecated_function
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.common.options import ArgOptions
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
Expand Down Expand Up @@ -81,49 +81,40 @@ def set_preference(self, name: str, value: Union[str, int, bool]):
self._preferences[name] = value

@property
@deprecated_function("Getting a profile has been deprecated.")
def profile(self) -> FirefoxProfile:
"""
:Returns: The Firefox profile to use.
"""
if self._profile:
warnings.warn("Getting a profile has been deprecated.", DeprecationWarning, stacklevel=2)
return self._profile

@profile.setter
@deprecated_function(
"Setting a profile has been deprecated. Please use the set_preference and install_addons methods"
)
def profile(self, new_profile: Union[str, FirefoxProfile]) -> None:
"""Sets location of the browser profile to use, either by string or
``FirefoxProfile``."""
warnings.warn(
"Setting a profile has been deprecated. Please use the set_preference and install_addons methods",
DeprecationWarning,
stacklevel=2,
)
if not isinstance(new_profile, FirefoxProfile):
new_profile = FirefoxProfile(new_profile)
self._profile = new_profile

@property
@deprecated_function("headless property is deprecated, instead check for '-headless' in arguments")
def headless(self) -> bool:
"""
:Returns: True if the headless argument is set, else False
"""
warnings.warn(
"headless property is deprecated, instead check for '-headless' in arguments",
DeprecationWarning,
stacklevel=2,
)
return "-headless" in self._arguments

@headless.setter
@deprecated_function("headless property is deprecated, instead use add_argument('-headless')")
def headless(self, value: bool) -> None:
"""Sets the headless argument.

Args:
value: boolean value indicating to set the headless option
"""
warnings.warn(
"headless property is deprecated, instead use add_argument('-headless')", DeprecationWarning, stacklevel=2
)
if not isinstance(value, bool):
raise TypeError("value must be a boolean")
if value:
Expand Down
5 changes: 3 additions & 2 deletions py/selenium/webdriver/firefox/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import warnings
from typing import List

from selenium.deprecated import deprecated_attributes
from selenium.types import SubprocessStdAlias
from selenium.webdriver.common import service
from selenium.webdriver.common import utils
Expand All @@ -35,6 +36,7 @@ class Service(service.Service):
:param env: (Optional) Mapping of environment variables for the new process, defaults to `os.environ`.
"""

@deprecated_attributes("log_path", message="log_path has been deprecated, please use log_output")
def __init__(
self,
executable_path: str = None,
Expand All @@ -46,8 +48,7 @@ def __init__(
**kwargs,
) -> None:
self.service_args = service_args or []
if log_path is not None:
warnings.warn("log_path has been deprecated, please use log_output", DeprecationWarning, stacklevel=2)
if log_path:
log_output = open(log_path, "a+", encoding="utf-8")

if log_path is None and log_output is None:
Expand Down
4 changes: 2 additions & 2 deletions py/selenium/webdriver/ie/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,17 @@
# specific language governing permissions and limitations
# under the License.
import typing
import warnings
from typing import List

from selenium.deprecated import deprecated_attributes
from selenium.types import SubprocessStdAlias
from selenium.webdriver.common import service


class Service(service.Service):
"""Object that manages the starting and stopping of the IEDriver."""

@deprecated_attributes("log_path", message="log_file has been deprecated, please use log_output")
def __init__(
self,
executable_path: str = None,
Expand Down Expand Up @@ -53,7 +54,6 @@ def __init__(
if log_level:
self.service_args.append(f"--log-level={log_level}")
if log_file:
warnings.warn("log_file has been deprecated, please use log_output", DeprecationWarning, stacklevel=2)
self.service_args.append(f"--log-file={log_file}")

super().__init__(
Expand Down
3 changes: 2 additions & 1 deletion py/selenium/webdriver/remote/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from selenium.common.exceptions import NoSuchCookieException
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import WebDriverException
from selenium.deprecated import deprecated_function
from selenium.webdriver.common.by import By
from selenium.webdriver.common.html5.application_cache import ApplicationCache
from selenium.webdriver.common.options import BaseOptions
Expand Down Expand Up @@ -769,9 +770,9 @@ def find_elements(self, by=By.ID, value: Optional[str] = None) -> List[WebElemen
return self.execute(Command.FIND_ELEMENTS, {"using": by, "value": value})["value"] or []

@property
@deprecated_function("desired_capabilities is deprecated. Please call capabilities.")
def desired_capabilities(self) -> dict:
"""returns the drivers current desired capabilities being used."""
warnings.warn("desired_capabilities is deprecated. Please call capabilities.", DeprecationWarning, stacklevel=2)
return self.caps

@property
Expand Down
6 changes: 2 additions & 4 deletions py/selenium/webdriver/safari/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
# under the License.

import typing
import warnings

from selenium.deprecated import deprecated_attributes
from selenium.webdriver.common import service


Expand All @@ -32,6 +32,7 @@ class Service(service.Service):
:param env: (Optional) Mapping of environment variables for the new process, defaults to `os.environ`.
"""

@deprecated_attributes("quiet", message="quiet is no longer needed to supress output")
def __init__(
self,
executable_path: str = None,
Expand All @@ -43,9 +44,6 @@ def __init__(
**kwargs,
) -> None:
self.service_args = service_args or []
if quiet is not None:
warnings.warn("quiet is no longer needed to supress output", DeprecationWarning, stacklevel=2)

self._reuse_service = reuse_service
super().__init__(
executable=executable_path,
Expand Down
12 changes: 4 additions & 8 deletions py/selenium/webdriver/safari/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
# under the License.

import http.client as http_client
import warnings

from selenium.common.exceptions import WebDriverException
from selenium.deprecated import deprecated_attributes
from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver

from ..common.driver_finder import DriverFinder
Expand All @@ -30,6 +30,9 @@
class WebDriver(RemoteWebDriver):
"""Controls the SafariDriver and allows you to drive the browser."""

@deprecated_attributes(
"reuse_service", message="reuse_service has been deprecated, please use the Service class to set it"
)
def __init__(
self,
reuse_service=False,
Expand All @@ -47,13 +50,6 @@ def __init__(
- options - Instance of ``options.Options``.
- service - Service object for handling the browser driver if you need to pass extra details
"""
if reuse_service:
warnings.warn(
"reuse_service has been deprecated, please use the Service class to set it",
DeprecationWarning,
stacklevel=2,
)

self.service = service if service else Service()
options = options if options else Options()

Expand Down