From bd92005dae1cfb89aec116081ab70a057a536050 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Thu, 27 Feb 2025 21:02:15 +0100 Subject: [PATCH 1/4] Drop Backward Compatibility for `user_id` in `send_gift` --- telegram/_bot.py | 16 +++++------ telegram/ext/_extbot.py | 4 +-- tests/auxil/bot_method_checks.py | 3 --- tests/test_chat.py | 10 +------ tests/test_gifts.py | 44 +++---------------------------- tests/test_official/exceptions.py | 3 --- tests/test_user.py | 10 +------ 7 files changed, 15 insertions(+), 75 deletions(-) diff --git a/telegram/_bot.py b/telegram/_bot.py index e645738a5b9..a9a688add13 100644 --- a/telegram/_bot.py +++ b/telegram/_bot.py @@ -9855,13 +9855,13 @@ async def get_available_gifts( async def send_gift( self, - user_id: Optional[int] = None, - gift_id: Union[str, Gift] = None, # type: ignore + gift_id: Union[str, Gift], text: Optional[str] = None, text_parse_mode: ODVInput[str] = DEFAULT_NONE, text_entities: Optional[Sequence["MessageEntity"]] = None, pay_for_upgrade: Optional[bool] = None, chat_id: Optional[Union[str, int]] = None, + user_id: Optional[int] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, write_timeout: ODVInput[float] = DEFAULT_NONE, @@ -9873,15 +9873,18 @@ async def send_gift( The gift can't be converted to Telegram Stars by the receiver. .. versionadded:: 21.8 + .. versionchanged:: NEXT.VERSION + Bot API 8.3 made :paramref:`user_id` optional. In version NEXT.VERSION, the methods + signature was changed accordingly. Args: + gift_id (:obj:`str` | :class:`~telegram.Gift`): Identifier of the gift or a + :class:`~telegram.Gift` object user_id (:obj:`int`, optional): Required if :paramref:`chat_id` is not specified. Unique identifier of the target user that will receive the gift. .. versionchanged:: NEXT.VERSION Now optional. - gift_id (:obj:`str` | :class:`~telegram.Gift`): Identifier of the gift or a - :class:`~telegram.Gift` object chat_id (:obj:`int` | :obj:`str`, optional): Required if :paramref:`user_id` is not specified. |chat_id_channel| It will receive the gift. @@ -9912,11 +9915,6 @@ async def send_gift( Raises: :class:`telegram.error.TelegramError` """ - # TODO: Remove when stability policy allows, tags: deprecated NEXT.VERSION - # also we should raise a deprecation warnung if anything is passed by - # position since it will be moved, not sure how - if gift_id is None: - raise TypeError("Missing required argument `gift_id`.") data: JSONDict = { "user_id": user_id, "gift_id": gift_id.id if isinstance(gift_id, Gift) else gift_id, diff --git a/telegram/ext/_extbot.py b/telegram/ext/_extbot.py index f77cfbf631b..20a72917074 100644 --- a/telegram/ext/_extbot.py +++ b/telegram/ext/_extbot.py @@ -4476,13 +4476,13 @@ async def get_available_gifts( async def send_gift( self, - user_id: Optional[int] = None, - gift_id: Union[str, Gift] = None, # type: ignore + gift_id: Union[str, Gift], text: Optional[str] = None, text_parse_mode: ODVInput[str] = DEFAULT_NONE, text_entities: Optional[Sequence["MessageEntity"]] = None, pay_for_upgrade: Optional[bool] = None, chat_id: Optional[Union[str, int]] = None, + user_id: Optional[int] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, write_timeout: ODVInput[float] = DEFAULT_NONE, diff --git a/tests/auxil/bot_method_checks.py b/tests/auxil/bot_method_checks.py index 610f49478ac..8e3179ea944 100644 --- a/tests/auxil/bot_method_checks.py +++ b/tests/auxil/bot_method_checks.py @@ -351,9 +351,6 @@ def build_kwargs( allow_sending_without_reply=manually_passed_value, quote_parse_mode=manually_passed_value, ) - # TODO remove when gift_id isnt marked as optional anymore, tags: deprecated NEXT.VERSION - elif name == "gift_id": - kws[name] = "GIFT-ID" return kws diff --git a/tests/test_chat.py b/tests/test_chat.py index 4f6acccb434..f53a0fdd2fe 100644 --- a/tests/test_chat.py +++ b/tests/test_chat.py @@ -1330,15 +1330,7 @@ async def make_assertion_channel(*_, **kwargs): and kwargs["text_entities"] == "text_entities" ) - # TODO discuss if better way exists - # tags: deprecated NEXT.VERSION - with pytest.raises( - Exception, - match="Default for argument gift_id does not match the default of the Bot method.", - ): - assert check_shortcut_signature( - Chat.send_gift, Bot.send_gift, ["user_id", "chat_id"], [] - ) + assert check_shortcut_signature(Chat.send_gift, Bot.send_gift, ["user_id", "chat_id"], []) assert await check_shortcut_call( chat.send_gift, chat.get_bot(), "send_gift", ["user_id", "chat_id"] ) diff --git a/tests/test_gifts.py b/tests/test_gifts.py index 3d4b064c8a4..3b3ef52cb39 100644 --- a/tests/test_gifts.py +++ b/tests/test_gifts.py @@ -135,40 +135,8 @@ def test_equality(self, gift): ], ids=["string", "Gift"], ) - async def test_send_gift(self, offline_bot, gift, monkeypatch): - # We can't send actual gifts, so we just check that the correct parameters are passed - text_entities = [ - MessageEntity(MessageEntity.TEXT_LINK, 0, 4, "url"), - MessageEntity(MessageEntity.BOLD, 5, 9), - ] - - async def make_assertion(url, request_data: RequestData, *args, **kwargs): - user_id = request_data.parameters["user_id"] == "user_id" - gift_id = request_data.parameters["gift_id"] == "gift_id" - text = request_data.parameters["text"] == "text" - text_parse_mode = request_data.parameters["text_parse_mode"] == "text_parse_mode" - tes = request_data.parameters["text_entities"] == [ - me.to_dict() for me in text_entities - ] - pay_for_upgrade = request_data.parameters["pay_for_upgrade"] is True - - return user_id and gift_id and text and text_parse_mode and tes and pay_for_upgrade - - monkeypatch.setattr(offline_bot.request, "post", make_assertion) - assert await offline_bot.send_gift( - "user_id", - gift, - "text", - text_parse_mode="text_parse_mode", - text_entities=text_entities, - pay_for_upgrade=True, - ) - @pytest.mark.parametrize("id_name", ["user_id", "chat_id"]) - async def test_send_gift_user_chat_id(self, offline_bot, gift, monkeypatch, id_name): - # Only here because we have to temporarily mark gift_id as optional. - # tags: deprecated NEXT.VERSION - + async def test_send_gift(self, offline_bot, gift, monkeypatch, id_name): # We can't send actual gifts, so we just check that the correct parameters are passed text_entities = [ MessageEntity(MessageEntity.TEXT_LINK, 0, 4, "url"), @@ -177,7 +145,7 @@ async def test_send_gift_user_chat_id(self, offline_bot, gift, monkeypatch, id_n async def make_assertion(url, request_data: RequestData, *args, **kwargs): received_id = request_data.parameters[id_name] == id_name - gift_id = request_data.parameters["gift_id"] == "some_id" + gift_id = request_data.parameters["gift_id"] == "gift_id" text = request_data.parameters["text"] == "text" text_parse_mode = request_data.parameters["text_parse_mode"] == "text_parse_mode" tes = request_data.parameters["text_entities"] == [ @@ -189,18 +157,14 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): monkeypatch.setattr(offline_bot.request, "post", make_assertion) assert await offline_bot.send_gift( - gift_id=gift, - text="text", + gift, + "text", text_parse_mode="text_parse_mode", text_entities=text_entities, pay_for_upgrade=True, **{id_name: id_name}, ) - async def test_send_gift_without_gift_id(self, offline_bot): - with pytest.raises(TypeError, match="Missing required argument `gift_id`."): - await offline_bot.send_gift() - @pytest.mark.parametrize("default_bot", [{"parse_mode": "Markdown"}], indirect=True) @pytest.mark.parametrize( ("passed_value", "expected_value"), diff --git a/tests/test_official/exceptions.py b/tests/test_official/exceptions.py index 9ada2569dca..b26f4cd3191 100644 --- a/tests/test_official/exceptions.py +++ b/tests/test_official/exceptions.py @@ -103,9 +103,6 @@ class ParamTypeCheckingExceptions: "EncryptedPassportElement": { "data": str, # actual: Union[IdDocumentData, PersonalDetails, ResidentialAddress] }, - # TODO: Deprecated and will be corrected (and removed) in next major PTB - # version: - "send_gift": {"gift_id": str}, # actual: Non optional } # param names ignored in the param type checking in classes for the `tg.Defaults` case. diff --git a/tests/test_user.py b/tests/test_user.py index 0102aa18824..b7ea5f8bd26 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -731,15 +731,7 @@ async def make_assertion(*_, **kwargs): and kwargs["text_entities"] == "text_entities" ) - # TODO discuss if better way exists - # tags: deprecated NEXT.VERSION - with pytest.raises( - Exception, - match="Default for argument gift_id does not match the default of the Bot method.", - ): - assert check_shortcut_signature( - user.send_gift, Bot.send_gift, ["user_id", "chat_id"], [] - ) + assert check_shortcut_signature(user.send_gift, Bot.send_gift, ["user_id", "chat_id"], []) assert await check_shortcut_call( user.send_gift, user.get_bot(), "send_gift", ["chat_id", "user_id"] ) From 87e4ddf52ca2c66bdb211a10235b3c15f944d94a Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Sat, 1 Mar 2025 12:39:50 +0100 Subject: [PATCH 2/4] Fix test-official --- tests/test_official/exceptions.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/test_official/exceptions.py b/tests/test_official/exceptions.py index b26f4cd3191..5e0800970f0 100644 --- a/tests/test_official/exceptions.py +++ b/tests/test_official/exceptions.py @@ -19,7 +19,7 @@ """This module contains exceptions to our API compared to the official API.""" import datetime as dtm -from telegram import Animation, Audio, Document, PhotoSize, Sticker, Video, VideoNote, Voice +from telegram import Animation, Audio, Document, Gift, PhotoSize, Sticker, Video, VideoNote, Voice from tests.test_official.helpers import _get_params_base IGNORED_OBJECTS = ("ResponseParameters",) @@ -47,8 +47,7 @@ class ParamTypeCheckingExceptions: "animation": Animation, "voice": Voice, "sticker": Sticker, - # TODO: Deprecated and will be corrected (and readded) in next major bot API release: - # "gift_id": Gift, + "gift_id": Gift, }, "(delete|set)_sticker.*": { "sticker$": Sticker, @@ -200,8 +199,6 @@ def ptb_ignored_params(object_name: str) -> set[str]: "send_venue": {"latitude", "longitude", "title", "address"}, "send_contact": {"phone_number", "first_name"}, # ----> - # here for backwards compatibility. Todo: remove on next bot api release - "send_gift": {"gift_id"}, } From 754b2c43d536fd1e28ec3ba3878eeb9a7db1c651 Mon Sep 17 00:00:00 2001 From: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com> Date: Fri, 11 Apr 2025 16:17:18 +0000 Subject: [PATCH 3/4] Add chango fragment for PR #4692 --- changes/unreleased/4692.dVZs28GuwTFnNJdWkvPbNv.toml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 changes/unreleased/4692.dVZs28GuwTFnNJdWkvPbNv.toml diff --git a/changes/unreleased/4692.dVZs28GuwTFnNJdWkvPbNv.toml b/changes/unreleased/4692.dVZs28GuwTFnNJdWkvPbNv.toml new file mode 100644 index 00000000000..48d1d7d8a5b --- /dev/null +++ b/changes/unreleased/4692.dVZs28GuwTFnNJdWkvPbNv.toml @@ -0,0 +1,6 @@ +breaking = "Drop Backward Compatibility for `user_id` in `send_gift`" +features = "Drop Backward Compatibility for `user_id` in `send_gift`" +[[pull_requests]] +uid = "4692" +author_uid = "Bibo-Joshi" +closes_threads = [] From 659b93bc05a85bea8908a4020af51aa6afcfd361 Mon Sep 17 00:00:00 2001 From: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com> Date: Fri, 11 Apr 2025 18:58:52 +0200 Subject: [PATCH 4/4] Elaborate chango fragment --- changes/unreleased/4692.dVZs28GuwTFnNJdWkvPbNv.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/changes/unreleased/4692.dVZs28GuwTFnNJdWkvPbNv.toml b/changes/unreleased/4692.dVZs28GuwTFnNJdWkvPbNv.toml index 48d1d7d8a5b..aebbd7e67c1 100644 --- a/changes/unreleased/4692.dVZs28GuwTFnNJdWkvPbNv.toml +++ b/changes/unreleased/4692.dVZs28GuwTFnNJdWkvPbNv.toml @@ -1,5 +1,4 @@ -breaking = "Drop Backward Compatibility for `user_id` in `send_gift`" -features = "Drop Backward Compatibility for `user_id` in `send_gift`" +breaking = "Drop backward compatibility for `user_id` in `send_gift` by updating the order of parameters. Please adapt your code accordingly or use keyword arguments." [[pull_requests]] uid = "4692" author_uid = "Bibo-Joshi"