Deprecate binary sensor device class constants (#105736)

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
This commit is contained in:
Robert Resch 2023-12-19 12:45:32 +01:00 committed by GitHub
parent c64c1c8f08
commit a4ccd6e13b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 302 additions and 33 deletions

View file

@ -3,10 +3,11 @@ from __future__ import annotations
from collections.abc import Callable
from contextlib import suppress
from enum import Enum
import functools
import inspect
import logging
from typing import Any, ParamSpec, TypeVar
from typing import Any, NamedTuple, ParamSpec, TypeVar
from homeassistant.core import HomeAssistant, async_get_hass
from homeassistant.exceptions import HomeAssistantError
@ -153,7 +154,25 @@ def _print_deprecation_warning(
verb: str,
breaks_in_ha_version: str | None,
) -> None:
logger = logging.getLogger(obj.__module__)
_print_deprecation_warning_internal(
obj.__name__,
obj.__module__,
replacement,
description,
verb,
breaks_in_ha_version,
)
def _print_deprecation_warning_internal(
obj_name: str,
module_name: str,
replacement: str,
description: str,
verb: str,
breaks_in_ha_version: str | None,
) -> None:
logger = logging.getLogger(module_name)
if breaks_in_ha_version:
breaks_in = f" which will be removed in HA Core {breaks_in_ha_version}"
else:
@ -163,7 +182,7 @@ def _print_deprecation_warning(
except MissingIntegrationFrame:
logger.warning(
"%s is a deprecated %s%s. Use %s instead",
obj.__name__,
obj_name,
description,
breaks_in,
replacement,
@ -183,7 +202,7 @@ def _print_deprecation_warning(
"%s was %s from %s, this is a deprecated %s%s. Use %s instead,"
" please %s"
),
obj.__name__,
obj_name,
verb,
integration_frame.integration,
description,
@ -194,10 +213,69 @@ def _print_deprecation_warning(
else:
logger.warning(
"%s was %s from %s, this is a deprecated %s%s. Use %s instead",
obj.__name__,
obj_name,
verb,
integration_frame.integration,
description,
breaks_in,
replacement,
)
class DeprecatedConstant(NamedTuple):
"""Deprecated constant."""
value: Any
replacement: str
breaks_in_ha_version: str | None
class DeprecatedConstantEnum(NamedTuple):
"""Deprecated constant."""
enum: Enum
breaks_in_ha_version: str | None
def check_if_deprecated_constant(name: str, module_globals: dict[str, Any]) -> Any:
"""Check if the not found name is a deprecated constant.
If it is, print a deprecation warning and return the value of the constant.
Otherwise raise AttributeError.
"""
module_name = module_globals.get("__name__")
logger = logging.getLogger(module_name)
if (deprecated_const := module_globals.get(f"_DEPRECATED_{name}")) is None:
raise AttributeError(f"Module {module_name!r} has no attribute {name!r}")
if isinstance(deprecated_const, DeprecatedConstant):
value = deprecated_const.value
replacement = deprecated_const.replacement
breaks_in_ha_version = deprecated_const.breaks_in_ha_version
elif isinstance(deprecated_const, DeprecatedConstantEnum):
value = deprecated_const.enum.value
replacement = (
f"{deprecated_const.enum.__class__.__name__}.{deprecated_const.enum.name}"
)
breaks_in_ha_version = deprecated_const.breaks_in_ha_version
else:
msg = (
f"Value of _DEPRECATED_{name!r} is an instance of {type(deprecated_const)} "
"but an instance of DeprecatedConstant or DeprecatedConstantEnum is required"
)
logger.debug(msg)
# PEP 562 -- Module __getattr__ and __dir__
# specifies that __getattr__ should raise AttributeError if the attribute is not
# found.
# https://peps.python.org/pep-0562/#specification
raise AttributeError(msg) # noqa: TRY004
_print_deprecation_warning_internal(
name,
module_name or __name__,
replacement,
"constant",
"used",
breaks_in_ha_version,
)
return value