Allow passing breaks_in_ha_version to deprecation helper decorators (#104985)

This commit is contained in:
Erik Montnemery 2023-12-04 11:52:10 +01:00 committed by GitHub
parent d8a6d864c0
commit db51a8e1f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 24 deletions

View File

@ -97,7 +97,7 @@ def get_deprecated(
def deprecated_class(
replacement: str,
replacement: str, *, breaks_in_ha_version: str | None = None
) -> Callable[[Callable[_P, _R]], Callable[_P, _R]]:
"""Mark class as deprecated and provide a replacement class to be used instead.
@ -111,7 +111,9 @@ def deprecated_class(
@functools.wraps(cls)
def deprecated_cls(*args: _P.args, **kwargs: _P.kwargs) -> _R:
"""Wrap for the original class."""
_print_deprecation_warning(cls, replacement, "class", "instantiated")
_print_deprecation_warning(
cls, replacement, "class", "instantiated", breaks_in_ha_version
)
return cls(*args, **kwargs)
return deprecated_cls
@ -120,7 +122,7 @@ def deprecated_class(
def deprecated_function(
replacement: str,
replacement: str, *, breaks_in_ha_version: str | None = None
) -> Callable[[Callable[_P, _R]], Callable[_P, _R]]:
"""Mark function as deprecated and provide a replacement to be used instead.
@ -134,7 +136,9 @@ def deprecated_function(
@functools.wraps(func)
def deprecated_func(*args: _P.args, **kwargs: _P.kwargs) -> _R:
"""Wrap for the original function."""
_print_deprecation_warning(func, replacement, "function", "called")
_print_deprecation_warning(
func, replacement, "function", "called", breaks_in_ha_version
)
return func(*args, **kwargs)
return deprecated_func
@ -147,15 +151,21 @@ def _print_deprecation_warning(
replacement: str,
description: str,
verb: str,
breaks_in_ha_version: str | None,
) -> None:
logger = logging.getLogger(obj.__module__)
if breaks_in_ha_version:
breaks_in = f" which will be removed in HA Core {breaks_in_ha_version}"
else:
breaks_in = ""
try:
integration_frame = get_integration_frame()
except MissingIntegrationFrame:
logger.warning(
"%s is a deprecated %s. Use %s instead",
"%s is a deprecated %s%s. Use %s instead",
obj.__name__,
description,
breaks_in,
replacement,
)
else:
@ -170,22 +180,24 @@ def _print_deprecation_warning(
)
logger.warning(
(
"%s was %s from %s, this is a deprecated %s. Use %s instead,"
"%s was %s from %s, this is a deprecated %s%s. Use %s instead,"
" please %s"
),
obj.__name__,
verb,
integration_frame.integration,
description,
breaks_in,
replacement,
report_issue,
)
else:
logger.warning(
"%s was %s from %s, this is a deprecated %s. Use %s instead",
"%s was %s from %s, this is a deprecated %s%s. Use %s instead",
obj.__name__,
verb,
integration_frame.integration,
description,
breaks_in,
replacement,
)

View File

@ -137,7 +137,7 @@ class FastSafeLoader(FastestAvailableSafeLoader, _LoaderMixin):
self.secrets = secrets
@deprecated_class("FastSafeLoader")
@deprecated_class("FastSafeLoader", breaks_in_ha_version="2024.6")
class SafeLoader(FastSafeLoader):
"""Provided for backwards compatibility. Logs when instantiated."""
@ -151,7 +151,7 @@ class PythonSafeLoader(yaml.SafeLoader, _LoaderMixin):
self.secrets = secrets
@deprecated_class("PythonSafeLoader")
@deprecated_class("PythonSafeLoader", breaks_in_ha_version="2024.6")
class SafeLineLoader(PythonSafeLoader):
"""Provided for backwards compatibility. Logs when instantiated."""

View File

@ -119,32 +119,52 @@ def test_deprecated_class(mock_get_logger) -> None:
assert len(mock_logger.warning.mock_calls) == 1
def test_deprecated_function(caplog: pytest.LogCaptureFixture) -> None:
@pytest.mark.parametrize(
("breaks_in_ha_version", "extra_msg"),
[
(None, ""),
("2099.1", " which will be removed in HA Core 2099.1"),
],
)
def test_deprecated_function(
caplog: pytest.LogCaptureFixture,
breaks_in_ha_version: str | None,
extra_msg: str,
) -> None:
"""Test deprecated_function decorator.
This tests the behavior when the calling integration is not known.
"""
@deprecated_function("new_function")
@deprecated_function("new_function", breaks_in_ha_version=breaks_in_ha_version)
def mock_deprecated_function():
pass
mock_deprecated_function()
assert (
"mock_deprecated_function is a deprecated function. Use new_function instead"
in caplog.text
)
f"mock_deprecated_function is a deprecated function{extra_msg}. "
"Use new_function instead"
) in caplog.text
@pytest.mark.parametrize(
("breaks_in_ha_version", "extra_msg"),
[
(None, ""),
("2099.1", " which will be removed in HA Core 2099.1"),
],
)
def test_deprecated_function_called_from_built_in_integration(
caplog: pytest.LogCaptureFixture,
breaks_in_ha_version: str | None,
extra_msg: str,
) -> None:
"""Test deprecated_function decorator.
This tests the behavior when the calling integration is built-in.
"""
@deprecated_function("new_function")
@deprecated_function("new_function", breaks_in_ha_version=breaks_in_ha_version)
def mock_deprecated_function():
pass
@ -170,14 +190,24 @@ def test_deprecated_function_called_from_built_in_integration(
):
mock_deprecated_function()
assert (
"mock_deprecated_function was called from hue, this is a deprecated function. "
"Use new_function instead" in caplog.text
)
"mock_deprecated_function was called from hue, "
f"this is a deprecated function{extra_msg}. "
"Use new_function instead"
) in caplog.text
@pytest.mark.parametrize(
("breaks_in_ha_version", "extra_msg"),
[
(None, ""),
("2099.1", " which will be removed in HA Core 2099.1"),
],
)
def test_deprecated_function_called_from_custom_integration(
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
breaks_in_ha_version: str | None,
extra_msg: str,
) -> None:
"""Test deprecated_function decorator.
@ -186,7 +216,7 @@ def test_deprecated_function_called_from_custom_integration(
mock_integration(hass, MockModule("hue"), built_in=False)
@deprecated_function("new_function")
@deprecated_function("new_function", breaks_in_ha_version=breaks_in_ha_version)
def mock_deprecated_function():
pass
@ -212,7 +242,8 @@ def test_deprecated_function_called_from_custom_integration(
):
mock_deprecated_function()
assert (
"mock_deprecated_function was called from hue, this is a deprecated function. "
"Use new_function instead, please report it to the author of the 'hue' custom "
"integration" in caplog.text
)
"mock_deprecated_function was called from hue, "
f"this is a deprecated function{extra_msg}. "
"Use new_function instead, please report it to the author of the "
"'hue' custom integration"
) in caplog.text

View File

@ -637,7 +637,7 @@ async def test_deprecated_loaders(
loader_class()
assert (
f"{loader_class.__name__} was instantiated from hue, this is a deprecated "
f"class. Use {new_class} instead"
f"class which will be removed in HA Core 2024.6. Use {new_class} instead"
) in caplog.text