From 0ddd31638815478c2abbb91c4a9ab0331e95545b Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Sat, 26 Jun 2021 11:33:35 +1000 Subject: [PATCH] add a helper so we can get semi-automatic camelCase conversion --- pylib/.pylintrc | 3 +++ pylib/anki/BUILD.bazel | 1 + pylib/anki/_legacy.py | 43 ++++++++++++++++++++++++++++++++++++++++++ qt/mypy.ini | 2 ++ 4 files changed, 49 insertions(+) create mode 100644 pylib/anki/_legacy.py diff --git a/pylib/.pylintrc b/pylib/.pylintrc index d3fcc58c4..683ac5d40 100644 --- a/pylib/.pylintrc +++ b/pylib/.pylintrc @@ -43,3 +43,6 @@ disable= global-statement, protected-access, arguments-differ, + +[BASIC] +good-names = id \ No newline at end of file diff --git a/pylib/anki/BUILD.bazel b/pylib/anki/BUILD.bazel index 03c81721c..eac8d8acf 100644 --- a/pylib/anki/BUILD.bazel +++ b/pylib/anki/BUILD.bazel @@ -47,6 +47,7 @@ py_library( requirement("flask"), requirement("waitress"), requirement("markdown"), + requirement("stringcase"), ] + orjson_if_available(), ) diff --git a/pylib/anki/_legacy.py b/pylib/anki/_legacy.py new file mode 100644 index 000000000..3284f81c0 --- /dev/null +++ b/pylib/anki/_legacy.py @@ -0,0 +1,43 @@ +# Copyright: Ankitects Pty Ltd and contributors +# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + +from __future__ import annotations + +from typing import Any, Callable, Dict, Tuple, Union + +import stringcase + +VariableTarget = Tuple[Any, str] +DeprecatedAliasTarget = Union[Callable, VariableTarget] + + +def _target_to_string(target: DeprecatedAliasTarget) -> str: + if name := getattr(target, "__name__", None): + return name + else: + return target[1] # type: ignore + + +class DeprecatedNamesMixin: + "Expose instance methods/vars as camelCase for legacy callers." + + _deprecated_aliases: Dict[str, str] = {} + + def __getattr__(self, name: str) -> Any: + remapped = self._deprecated_aliases.get(name) or stringcase.snakecase(name) + if remapped == name: + raise AttributeError + + out = getattr(self, remapped) + print(f"please use {remapped} instead of {name} on {self}") + return out + + @classmethod + def register_deprecated_aliases(cls, **kwargs: DeprecatedAliasTarget) -> None: + """Manually add aliases that are not a simple transform. + + Either pass in a method, or a tuple of (variable, "variable"). The + latter is required because we want to ensure the provided arguments + are valid symbols, and we can't get a variable's name easily. + """ + cls._deprecated_aliases = {k: _target_to_string(v) for k, v in kwargs.items()} diff --git a/qt/mypy.ini b/qt/mypy.ini index 72f33a3a4..db40aba95 100644 --- a/qt/mypy.ini +++ b/qt/mypy.ini @@ -60,6 +60,8 @@ ignore_missing_imports = True ignore_missing_imports = True [mypy-socks] ignore_missing_imports = True +[mypy-stringcase] +ignore_missing_imports = True [mypy-aqt.forms.*] disallow_untyped_defs=false