From a529619d7999af98d157fdeaa46dc8eee77948e1 Mon Sep 17 00:00:00 2001 From: Martin Winks <50446230+uwinx@users.noreply.github.com> Date: Thu, 10 Sep 2020 23:34:20 +0400 Subject: [PATCH] hotfix(updates): CHOSEN_INLINE_RESULT is a correct API-term (#415) * hotfix(updates): CHOSEN_INLINE_RESULT is a correct API-term * feat(utils): deprecated descriptor deprecate CHOSEN_INLINE_QUERY and always return CHOSEN_INLINE_RESULT instead of incorrect value * fix(tests): remove example from test * fix(utils): use stacklevel=3 level on which descriptor is being called --- aiogram/types/update.py | 10 +++++++-- aiogram/utils/deprecated.py | 35 ++++++++++++++++++++++++++++- tests/test_utils/test_deprecated.py | 14 ++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 tests/test_utils/test_deprecated.py diff --git a/aiogram/types/update.py b/aiogram/types/update.py index 2146cb9d..9d1afacc 100644 --- a/aiogram/types/update.py +++ b/aiogram/types/update.py @@ -9,7 +9,7 @@ from .message import Message from .poll import Poll, PollAnswer from .pre_checkout_query import PreCheckoutQuery from .shipping_query import ShippingQuery -from ..utils import helper +from ..utils import helper, deprecated class Update(base.TelegramObject): @@ -55,9 +55,15 @@ class AllowedUpdates(helper.Helper): CHANNEL_POST = helper.ListItem() # channel_post EDITED_CHANNEL_POST = helper.ListItem() # edited_channel_post INLINE_QUERY = helper.ListItem() # inline_query - CHOSEN_INLINE_QUERY = helper.ListItem() # chosen_inline_result + CHOSEN_INLINE_RESULT = helper.ListItem() # chosen_inline_result CALLBACK_QUERY = helper.ListItem() # callback_query SHIPPING_QUERY = helper.ListItem() # shipping_query PRE_CHECKOUT_QUERY = helper.ListItem() # pre_checkout_query POLL = helper.ListItem() # poll POLL_ANSWER = helper.ListItem() # poll_answer + + CHOSEN_INLINE_QUERY = deprecated.DeprecatedReadOnlyClassVar( + "`CHOSEN_INLINE_QUERY` is a deprecated value for allowed update. " + "Use `CHOSEN_INLINE_RESULT`", + new_value_getter=lambda cls: cls.CHOSEN_INLINE_RESULT, + ) diff --git a/aiogram/utils/deprecated.py b/aiogram/utils/deprecated.py index 83a9034c..6d0d7ee3 100644 --- a/aiogram/utils/deprecated.py +++ b/aiogram/utils/deprecated.py @@ -2,7 +2,7 @@ import asyncio import inspect import warnings import functools -from typing import Callable +from typing import Callable, Generic, TypeVar, Type, Optional def deprecated(reason, stacklevel=2) -> Callable: @@ -129,3 +129,36 @@ def renamed_argument(old_name: str, new_name: str, until_version: str, stackleve return wrapped return decorator + + +_VT = TypeVar("_VT") +_OwnerCls = TypeVar("_OwnerCls") + + +class DeprecatedReadOnlyClassVar(Generic[_OwnerCls, _VT]): + """ + DeprecatedReadOnlyClassVar[Owner, ValueType] + + :param warning_message: Warning message when getter gets called + :param new_value_getter: Any callable with (owner_class: Type[Owner]) -> ValueType + signature that will be executed + + Usage example: + + >>> class MyClass: + ... some_attribute: DeprecatedReadOnlyClassVar[MyClass, int] = \ + ... DeprecatedReadOnlyClassVar( + ... "Warning message.", lambda owner: 15) + ... + >>> MyClass.some_attribute # does warning.warn with `Warning message` and returns 15 in the current case + """ + + __slots__ = "_new_value_getter", "_warning_message" + + def __init__(self, warning_message: str, new_value_getter: Callable[[_OwnerCls], _VT]): + self._warning_message = warning_message + self._new_value_getter = new_value_getter + + def __get__(self, instance: Optional[_OwnerCls], owner: Type[_OwnerCls]): + warn_deprecated(self._warning_message, stacklevel=3) + return self._new_value_getter(owner) diff --git a/tests/test_utils/test_deprecated.py b/tests/test_utils/test_deprecated.py new file mode 100644 index 00000000..114d6810 --- /dev/null +++ b/tests/test_utils/test_deprecated.py @@ -0,0 +1,14 @@ +import pytest + +from aiogram.utils.deprecated import DeprecatedReadOnlyClassVar + + +def test_DeprecatedReadOnlyClassVarCD(): + assert DeprecatedReadOnlyClassVar.__slots__ == ("_new_value_getter", "_warning_message") + + new_value_of_deprecated_cls_cd = "mpa" + pseudo_owner_cls = type("OpekaCla$$", (), {}) + deprecated_cd = DeprecatedReadOnlyClassVar("mopekaa", lambda owner: new_value_of_deprecated_cls_cd) + + with pytest.warns(DeprecationWarning): + assert deprecated_cd.__get__(None, pseudo_owner_cls) == new_value_of_deprecated_cls_cd