Enable registering of legacy attributes without exact substitutes (#1438)
* Enable registering of legacy attributes without... ... exact substitutes. (See diff for an example.) * Take new callable instead of old name ... ... so we can ensure existence * Require old names to be passed as key words This is a lot simpler, less error prone, and works for all kinds of old names, not only those which are proper camelcase.
This commit is contained in:
parent
4678b12570
commit
54df350cda
@ -44,15 +44,21 @@ class DeprecatedNamesMixin:
|
|||||||
# attributes on the consuming class
|
# attributes on the consuming class
|
||||||
|
|
||||||
_deprecated_aliases: dict[str, str] = {}
|
_deprecated_aliases: dict[str, str] = {}
|
||||||
|
_deprecated_attributes: dict[str, tuple[str, str]] = {}
|
||||||
|
|
||||||
@no_type_check
|
@no_type_check
|
||||||
def __getattr__(self, name: str) -> Any:
|
def __getattr__(self, name: str) -> Any:
|
||||||
remapped = self._deprecated_aliases.get(name) or stringcase.snakecase(name)
|
if some_tuple := self._deprecated_attributes.get(name):
|
||||||
|
remapped, replacement = some_tuple
|
||||||
|
else:
|
||||||
|
replacement = remapped = self._deprecated_aliases.get(
|
||||||
|
name
|
||||||
|
) or stringcase.snakecase(name)
|
||||||
if remapped == name:
|
if remapped == name:
|
||||||
raise AttributeError
|
raise AttributeError
|
||||||
|
|
||||||
out = getattr(self, remapped)
|
out = getattr(self, remapped)
|
||||||
_print_warning(f"'{name}'", f"please use '{remapped}'")
|
_print_warning(f"'{name}'", f"please use '{replacement}'")
|
||||||
|
|
||||||
return out
|
return out
|
||||||
|
|
||||||
@ -67,6 +73,28 @@ class DeprecatedNamesMixin:
|
|||||||
"""
|
"""
|
||||||
cls._deprecated_aliases = {k: _target_to_string(v) for k, v in kwargs.items()}
|
cls._deprecated_aliases = {k: _target_to_string(v) for k, v in kwargs.items()}
|
||||||
|
|
||||||
|
@no_type_check
|
||||||
|
@classmethod
|
||||||
|
def register_deprecated_attributes(
|
||||||
|
cls,
|
||||||
|
**kwargs: tuple[DeprecatedAliasTarget, DeprecatedAliasTarget],
|
||||||
|
) -> None:
|
||||||
|
"""Manually add deprecated attributes without exact substitutes.
|
||||||
|
|
||||||
|
Pass a tuple of (alias, replacement), where alias is the attribute's new
|
||||||
|
name (by convention: snakecase, prepended with '_legacy_'), and
|
||||||
|
replacement is any callable to be used instead in new code.
|
||||||
|
Also note the docstring of `register_deprecated_aliases`.
|
||||||
|
|
||||||
|
E.g. given `def oldFunc(args): return new_func(additionalLogic(args))`,
|
||||||
|
rename `oldFunc` to `_legacy_old_func` and call
|
||||||
|
`register_deprecated_attributes(oldFunc=(_legacy_old_func, new_func))`.
|
||||||
|
"""
|
||||||
|
cls._deprecated_attributes = {
|
||||||
|
k: (_target_to_string(v[0]), _target_to_string(v[1]))
|
||||||
|
for k, v in kwargs.items()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def deprecated(replaced_by: Callable | None = None, info: str = "") -> Callable:
|
def deprecated(replaced_by: Callable | None = None, info: str = "") -> Callable:
|
||||||
"""Print a deprecation warning, telling users to use `replaced_by`, or show `doc`."""
|
"""Print a deprecation warning, telling users to use `replaced_by`, or show `doc`."""
|
||||||
|
Loading…
Reference in New Issue
Block a user