From e25e5f0f70b36d94ba3b235f0fe5f6c7dfcaa163 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Sun, 29 Dec 2024 20:12:24 +0100 Subject: [PATCH 01/14] Get Started on Simplifying `de_json/list` --- telegram/_bot.py | 54 +++--- telegram/_botcommandscope.py | 7 +- telegram/_business.py | 49 ++---- telegram/_callbackquery.py | 12 +- telegram/_chatbackground.py | 29 +--- telegram/_chatboost.py | 51 ++---- telegram/_chatfullinfo.py | 35 ++-- telegram/_chatinvitelink.py | 10 +- telegram/_chatjoinrequest.py | 14 +- telegram/_chatlocation.py | 10 +- telegram/_chatmember.py | 10 +- telegram/_chatmemberupdated.py | 18 +- telegram/_chatpermissions.py | 7 +- telegram/_choseninlineresult.py | 12 +- telegram/_files/_basethumbedmedium.py | 10 +- telegram/_files/sticker.py | 23 +-- telegram/_files/venue.py | 8 +- telegram/_games/game.py | 13 +- telegram/_games/gamehighscore.py | 10 +- telegram/_gifts.py | 16 +- telegram/_giveaway.py | 31 +--- telegram/_inline/inlinekeyboardbutton.py | 20 +-- telegram/_inline/inlinekeyboardmarkup.py | 6 +- telegram/_inline/inlinequery.py | 12 +- telegram/_inline/inlinequeryresultsbutton.py | 9 +- .../_inline/inputinvoicemessagecontent.py | 11 +- telegram/_inline/preparedinlinemessage.py | 7 +- telegram/_keyboardbutton.py | 18 +- telegram/_keyboardbuttonrequest.py | 16 +- telegram/_menubutton.py | 20 +-- telegram/_message.py | 164 +++++++++--------- telegram/_messageentity.py | 10 +- telegram/_messageorigin.py | 14 +- telegram/_messagereactionupdated.py | 30 ++-- telegram/_paidmedia.py | 46 +---- telegram/_passport/credentials.py | 65 +++---- .../_passport/encryptedpassportelement.py | 50 +++--- telegram/_passport/passportdata.py | 13 +- telegram/_passport/passportfile.py | 15 +- telegram/_payment/orderinfo.py | 10 +- telegram/_payment/precheckoutquery.py | 12 +- telegram/_payment/shippingquery.py | 12 +- telegram/_payment/stars/affiliateinfo.py | 13 +- .../_payment/stars/revenuewithdrawalstate.py | 14 +- telegram/_payment/stars/startransactions.py | 22 +-- telegram/_payment/stars/transactionpartner.py | 44 ++--- telegram/_payment/successfulpayment.py | 10 +- telegram/_poll.py | 42 ++--- telegram/_proximityalerttriggered.py | 12 +- telegram/_reaction.py | 20 +-- telegram/_reply.py | 73 ++++---- telegram/_shared.py | 29 +--- telegram/_story.py | 5 +- telegram/_telegramobject.py | 22 +-- telegram/_update.py | 70 ++++---- telegram/_userprofilephotos.py | 7 +- telegram/_utils/argumentparsing.py | 76 +++++++- telegram/_videochat.py | 14 +- telegram/_webhookinfo.py | 7 +- 59 files changed, 573 insertions(+), 896 deletions(-) diff --git a/telegram/_bot.py b/telegram/_bot.py index 7b5b4b04f3d..956e560c277 100644 --- a/telegram/_bot.py +++ b/telegram/_bot.py @@ -901,7 +901,7 @@ async def get_me( api_kwargs=api_kwargs, ) self._bot_user = User.de_json(result, self) - return self._bot_user # type: ignore[return-value] + return self._bot_user async def send_message( self, @@ -3689,7 +3689,7 @@ async def save_prepared_inline_message( "allow_group_chats": allow_group_chats, "allow_channel_chats": allow_channel_chats, } - return PreparedInlineMessage.de_json( # type: ignore[return-value] + return PreparedInlineMessage.de_json( await self._post( "savePreparedInlineMessage", data, @@ -3744,7 +3744,7 @@ async def get_user_profile_photos( api_kwargs=api_kwargs, ) - return UserProfilePhotos.de_json(result, self) # type: ignore[return-value] + return UserProfilePhotos.de_json(result, self) async def get_file( self, @@ -3809,7 +3809,7 @@ async def get_file( if file_path and not is_local_file(file_path): result["file_path"] = f"{self._base_file_url}/{file_path}" - return File.de_json(result, self) # type: ignore[return-value] + return File.de_json(result, self) async def ban_chat_member( self, @@ -4729,7 +4729,7 @@ async def get_chat( api_kwargs=api_kwargs, ) - return ChatFullInfo.de_json(result, self) # type: ignore[return-value] + return ChatFullInfo.de_json(result, self) async def get_chat_administrators( self, @@ -4842,7 +4842,7 @@ async def get_chat_member( pool_timeout=pool_timeout, api_kwargs=api_kwargs, ) - return ChatMember.de_json(result, self) # type: ignore[return-value] + return ChatMember.de_json(result, self) async def set_chat_sticker_set( self, @@ -4937,7 +4937,7 @@ async def get_webhook_info( pool_timeout=pool_timeout, api_kwargs=api_kwargs, ) - return WebhookInfo.de_json(result, self) # type: ignore[return-value] + return WebhookInfo.de_json(result, self) async def set_game_score( self, @@ -5444,7 +5444,7 @@ async def answer_web_app_query( api_kwargs=api_kwargs, ) - return SentWebAppMessage.de_json(api_result, self) # type: ignore[return-value] + return SentWebAppMessage.de_json(api_result, self) async def restrict_chat_member( self, @@ -5858,7 +5858,7 @@ async def create_chat_invite_link( api_kwargs=api_kwargs, ) - return ChatInviteLink.de_json(result, self) # type: ignore[return-value] + return ChatInviteLink.de_json(result, self) async def edit_chat_invite_link( self, @@ -5937,7 +5937,7 @@ async def edit_chat_invite_link( api_kwargs=api_kwargs, ) - return ChatInviteLink.de_json(result, self) # type: ignore[return-value] + return ChatInviteLink.de_json(result, self) async def revoke_chat_invite_link( self, @@ -5984,7 +5984,7 @@ async def revoke_chat_invite_link( api_kwargs=api_kwargs, ) - return ChatInviteLink.de_json(result, self) # type: ignore[return-value] + return ChatInviteLink.de_json(result, self) async def approve_chat_join_request( self, @@ -6456,7 +6456,7 @@ async def get_sticker_set( pool_timeout=pool_timeout, api_kwargs=api_kwargs, ) - return StickerSet.de_json(result, self) # type: ignore[return-value] + return StickerSet.de_json(result, self) async def get_custom_emoji_stickers( self, @@ -6559,7 +6559,7 @@ async def upload_sticker_file( pool_timeout=pool_timeout, api_kwargs=api_kwargs, ) - return File.de_json(result, self) # type: ignore[return-value] + return File.de_json(result, self) async def add_sticker_to_set( self, @@ -7384,7 +7384,7 @@ async def stop_poll( pool_timeout=pool_timeout, api_kwargs=api_kwargs, ) - return Poll.de_json(result, self) # type: ignore[return-value] + return Poll.de_json(result, self) async def send_dice( self, @@ -7540,7 +7540,7 @@ async def get_my_default_administrator_rights( api_kwargs=api_kwargs, ) - return ChatAdministratorRights.de_json(result, self) # type: ignore[return-value] + return ChatAdministratorRights.de_json(result, self) async def set_my_default_administrator_rights( self, @@ -7950,7 +7950,7 @@ async def copy_message( pool_timeout=pool_timeout, api_kwargs=api_kwargs, ) - return MessageId.de_json(result, self) # type: ignore[return-value] + return MessageId.de_json(result, self) async def copy_messages( self, @@ -8101,7 +8101,7 @@ async def get_chat_menu_button( pool_timeout=pool_timeout, api_kwargs=api_kwargs, ) - return MenuButton.de_json(result, bot=self) # type: ignore[return-value] + return MenuButton.de_json(result, bot=self) async def create_invoice_link( self, @@ -8352,7 +8352,7 @@ async def create_forum_topic( pool_timeout=pool_timeout, api_kwargs=api_kwargs, ) - return ForumTopic.de_json(result, self) # type: ignore[return-value] + return ForumTopic.de_json(result, self) async def edit_forum_topic( self, @@ -8940,7 +8940,7 @@ async def get_my_description( """ data = {"language_code": language_code} - return BotDescription.de_json( # type: ignore[return-value] + return BotDescription.de_json( await self._post( "getMyDescription", data, @@ -8979,7 +8979,7 @@ async def get_my_short_description( """ data = {"language_code": language_code} - return BotShortDescription.de_json( # type: ignore[return-value] + return BotShortDescription.de_json( await self._post( "getMyShortDescription", data, @@ -9065,7 +9065,7 @@ async def get_my_name( """ data = {"language_code": language_code} - return BotName.de_json( # type: ignore[return-value] + return BotName.de_json( await self._post( "getMyName", data, @@ -9107,7 +9107,7 @@ async def get_user_chat_boosts( :class:`telegram.error.TelegramError` """ data: JSONDict = {"chat_id": chat_id, "user_id": user_id} - return UserChatBoosts.de_json( # type: ignore[return-value] + return UserChatBoosts.de_json( await self._post( "getUserChatBoosts", data, @@ -9231,7 +9231,7 @@ async def get_business_connection( :class:`telegram.error.TelegramError` """ data: JSONDict = {"business_connection_id": business_connection_id} - return BusinessConnection.de_json( # type: ignore[return-value] + return BusinessConnection.de_json( await self._post( "getBusinessConnection", data, @@ -9366,7 +9366,7 @@ async def get_star_transactions( data: JSONDict = {"offset": offset, "limit": limit} - return StarTransactions.de_json( # type: ignore[return-value] + return StarTransactions.de_json( await self._post( "getStarTransactions", data, @@ -9592,7 +9592,7 @@ async def create_chat_subscription_invite_link( api_kwargs=api_kwargs, ) - return ChatInviteLink.de_json(result, self) # type: ignore[return-value] + return ChatInviteLink.de_json(result, self) async def edit_chat_subscription_invite_link( self, @@ -9645,7 +9645,7 @@ async def edit_chat_subscription_invite_link( api_kwargs=api_kwargs, ) - return ChatInviteLink.de_json(result, self) # type: ignore[return-value] + return ChatInviteLink.de_json(result, self) async def get_available_gifts( self, @@ -9667,7 +9667,7 @@ async def get_available_gifts( Raises: :class:`telegram.error.TelegramError` """ - return Gifts.de_json( # type: ignore[return-value] + return Gifts.de_json( await self._post( "getAvailableGifts", read_timeout=read_timeout, diff --git a/telegram/_botcommandscope.py b/telegram/_botcommandscope.py index 8d068802ca0..7780e2fe3db 100644 --- a/telegram/_botcommandscope.py +++ b/telegram/_botcommandscope.py @@ -84,9 +84,7 @@ def __init__(self, type: str, *, api_kwargs: Optional[JSONDict] = None): self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["BotCommandScope"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BotCommandScope": """Converts JSON data to the appropriate :class:`BotCommandScope` object, i.e. takes care of selecting the correct subclass. @@ -104,9 +102,6 @@ def de_json( """ data = cls._parse_data(data) - if not data: - return None - _class_mapping: dict[str, type[BotCommandScope]] = { cls.DEFAULT: BotCommandScopeDefault, cls.ALL_PRIVATE_CHATS: BotCommandScopeAllPrivateChats, diff --git a/telegram/_business.py b/telegram/_business.py index 28075e9b580..24b800d13ea 100644 --- a/telegram/_business.py +++ b/telegram/_business.py @@ -27,7 +27,7 @@ from telegram._files.sticker import Sticker from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -106,20 +106,15 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["BusinessConnection"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessConnection": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["user"] = User.de_json(data.get("user"), bot) + data["user"] = de_json_wo(data.get("user"), User, bot) return super().de_json(data=data, bot=bot) @@ -177,16 +172,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["BusinessMessagesDeleted"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessMessagesDeleted": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["chat"] = Chat.de_json(data.get("chat"), bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) return super().de_json(data=data, bot=bot) @@ -236,16 +226,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["BusinessIntro"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessIntro": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["sticker"] = Sticker.de_json(data.get("sticker"), bot) + data["sticker"] = de_json_wo(data.get("sticker"), Sticker, bot) return super().de_json(data=data, bot=bot) @@ -290,16 +275,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["BusinessLocation"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessLocation": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["location"] = Location.de_json(data.get("location"), bot) + data["location"] = de_json_wo(data.get("location"), Location, bot) return super().de_json(data=data, bot=bot) @@ -439,17 +419,12 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["BusinessOpeningHours"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessOpeningHours": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["opening_hours"] = BusinessOpeningHoursInterval.de_list( - data.get("opening_hours"), bot + data["opening_hours"] = de_list_wo( + data.get("opening_hours"), BusinessOpeningHoursInterval, bot ) return super().de_json(data=data, bot=bot) diff --git a/telegram/_callbackquery.py b/telegram/_callbackquery.py index 9264feaaa8f..84f0dfd49b5 100644 --- a/telegram/_callbackquery.py +++ b/telegram/_callbackquery.py @@ -26,6 +26,7 @@ from telegram._message import MaybeInaccessibleMessage, Message from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.types import JSONDict, ODVInput, ReplyMarkup @@ -149,17 +150,12 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["CallbackQuery"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "CallbackQuery": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["from_user"] = User.de_json(data.pop("from", None), bot) - data["message"] = Message.de_json(data.get("message"), bot) + data["from_user"] = de_json_wo(data.pop("from", None), User, bot) + data["message"] = de_json_wo(data.get("message"), Message, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatbackground.py b/telegram/_chatbackground.py index 148c628039d..4d9f110b483 100644 --- a/telegram/_chatbackground.py +++ b/telegram/_chatbackground.py @@ -24,7 +24,7 @@ from telegram._files.document import Document from telegram._telegramobject import TelegramObject from telegram._utils import enum -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -79,15 +79,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["BackgroundFill"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BackgroundFill": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - _class_mapping: dict[str, type[BackgroundFill]] = { cls.SOLID: BackgroundFillSolid, cls.GRADIENT: BackgroundFillGradient, @@ -270,15 +265,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["BackgroundType"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BackgroundType": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - _class_mapping: dict[str, type[BackgroundType]] = { cls.FILL: BackgroundTypeFill, cls.WALLPAPER: BackgroundTypeWallpaper, @@ -290,10 +280,10 @@ def de_json( return _class_mapping[data.pop("type")].de_json(data=data, bot=bot) if "fill" in data: - data["fill"] = BackgroundFill.de_json(data.get("fill"), bot) + data["fill"] = de_json_wo(data.get("fill"), BackgroundFill, bot) if "document" in data: - data["document"] = Document.de_json(data.get("document"), bot) + data["document"] = de_json_wo(data.get("document"), Document, bot) return super().de_json(data=data, bot=bot) @@ -533,15 +523,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ChatBackground"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBackground": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["type"] = BackgroundType.de_json(data.get("type"), bot) + data["type"] = de_json_wo(data.get("type"), BackgroundType, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatboost.py b/telegram/_chatboost.py index 55c7cba8060..f2140323be4 100644 --- a/telegram/_chatboost.py +++ b/telegram/_chatboost.py @@ -26,7 +26,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -110,15 +110,10 @@ def __init__(self, source: str, *, api_kwargs: Optional[JSONDict] = None): self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ChatBoostSource"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoostSource": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - _class_mapping: dict[str, type[ChatBoostSource]] = { cls.PREMIUM: ChatBoostSourcePremium, cls.GIFT_CODE: ChatBoostSourceGiftCode, @@ -129,7 +124,7 @@ def de_json( return _class_mapping[data.pop("source")].de_json(data=data, bot=bot) if "user" in data: - data["user"] = User.de_json(data.get("user"), bot) + data["user"] = de_json_wo(data.get("user"), User, bot) return super().de_json(data=data, bot=bot) @@ -290,16 +285,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ChatBoost"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoost": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["source"] = ChatBoostSource.de_json(data.get("source"), bot) + data["source"] = de_json_wo(data.get("source"), ChatBoostSource, bot) loc_tzinfo = extract_tzinfo_from_defaults(bot) data["add_date"] = from_timestamp(data["add_date"], tzinfo=loc_tzinfo) data["expiration_date"] = from_timestamp(data["expiration_date"], tzinfo=loc_tzinfo) @@ -342,17 +332,12 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ChatBoostUpdated"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoostUpdated": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["chat"] = Chat.de_json(data.get("chat"), bot) - data["boost"] = ChatBoost.de_json(data.get("boost"), bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["boost"] = de_json_wo(data.get("boost"), ChatBoost, bot) return super().de_json(data=data, bot=bot) @@ -401,17 +386,12 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ChatBoostRemoved"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoostRemoved": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["chat"] = Chat.de_json(data.get("chat"), bot) - data["source"] = ChatBoostSource.de_json(data.get("source"), bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["source"] = de_json_wo(data.get("source"), ChatBoostSource, bot) loc_tzinfo = extract_tzinfo_from_defaults(bot) data["remove_date"] = from_timestamp(data["remove_date"], tzinfo=loc_tzinfo) @@ -450,15 +430,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["UserChatBoosts"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "UserChatBoosts": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["boosts"] = ChatBoost.de_list(data.get("boosts"), bot) + data["boosts"] = de_list_wo(data.get("boosts"), ChatBoost, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatfullinfo.py b/telegram/_chatfullinfo.py index 3f8dc301dba..f505b97bfc1 100644 --- a/telegram/_chatfullinfo.py +++ b/telegram/_chatfullinfo.py @@ -28,7 +28,7 @@ from telegram._chatpermissions import ChatPermissions from telegram._files.chatphoto import ChatPhoto from telegram._reaction import ReactionType -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -512,15 +512,10 @@ def __init__( self.can_send_paid_media: Optional[bool] = can_send_paid_media @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ChatFullInfo"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatFullInfo": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) @@ -528,7 +523,7 @@ def de_json( data.get("emoji_status_expiration_date"), tzinfo=loc_tzinfo ) - data["photo"] = ChatPhoto.de_json(data.get("photo"), bot) + data["photo"] = de_json_wo(data.get("photo"), ChatPhoto, bot) from telegram import ( # pylint: disable=import-outside-toplevel BusinessIntro, @@ -537,16 +532,20 @@ def de_json( Message, ) - data["pinned_message"] = Message.de_json(data.get("pinned_message"), bot) - data["permissions"] = ChatPermissions.de_json(data.get("permissions"), bot) - data["location"] = ChatLocation.de_json(data.get("location"), bot) - data["available_reactions"] = ReactionType.de_list(data.get("available_reactions"), bot) - data["birthdate"] = Birthdate.de_json(data.get("birthdate"), bot) - data["personal_chat"] = Chat.de_json(data.get("personal_chat"), bot) - data["business_intro"] = BusinessIntro.de_json(data.get("business_intro"), bot) - data["business_location"] = BusinessLocation.de_json(data.get("business_location"), bot) - data["business_opening_hours"] = BusinessOpeningHours.de_json( - data.get("business_opening_hours"), bot + data["pinned_message"] = de_json_wo(data.get("pinned_message"), Message, bot) + data["permissions"] = de_json_wo(data.get("permissions"), ChatPermissions, bot) + data["location"] = de_json_wo(data.get("location"), ChatLocation, bot) + data["available_reactions"] = de_list_wo( + data.get("available_reactions"), ReactionType, bot + ) + data["birthdate"] = de_json_wo(data.get("birthdate"), Birthdate, bot) + data["personal_chat"] = de_json_wo(data.get("personal_chat"), Chat, bot) + data["business_intro"] = de_json_wo(data.get("business_intro"), BusinessIntro, bot) + data["business_location"] = de_json_wo( + data.get("business_location"), BusinessLocation, bot + ) + data["business_opening_hours"] = de_json_wo( + data.get("business_opening_hours"), BusinessOpeningHours, bot ) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatinvitelink.py b/telegram/_chatinvitelink.py index fd85ea92808..9ccdf0aedcb 100644 --- a/telegram/_chatinvitelink.py +++ b/telegram/_chatinvitelink.py @@ -22,6 +22,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -177,19 +178,14 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ChatInviteLink"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatInviteLink": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["creator"] = User.de_json(data.get("creator"), bot) + data["creator"] = de_json_wo(data.get("creator"), User, bot) data["expire_date"] = from_timestamp(data.get("expire_date", None), tzinfo=loc_tzinfo) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatjoinrequest.py b/telegram/_chatjoinrequest.py index 9324e89a6df..3590a7e0747 100644 --- a/telegram/_chatjoinrequest.py +++ b/telegram/_chatjoinrequest.py @@ -24,6 +24,7 @@ from telegram._chatinvitelink import ChatInviteLink from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.types import JSONDict, ODVInput @@ -129,22 +130,17 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ChatJoinRequest"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatJoinRequest": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chat"] = Chat.de_json(data.get("chat"), bot) - data["from_user"] = User.de_json(data.pop("from", None), bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["from_user"] = de_json_wo(data.pop("from", None), User, bot) data["date"] = from_timestamp(data.get("date", None), tzinfo=loc_tzinfo) - data["invite_link"] = ChatInviteLink.de_json(data.get("invite_link"), bot) + data["invite_link"] = de_json_wo(data.get("invite_link"), ChatInviteLink, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatlocation.py b/telegram/_chatlocation.py index 04f9854a23a..a02824f4648 100644 --- a/telegram/_chatlocation.py +++ b/telegram/_chatlocation.py @@ -23,6 +23,7 @@ from telegram import constants from telegram._files.location import Location from telegram._telegramobject import TelegramObject +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -68,16 +69,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ChatLocation"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatLocation": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["location"] = Location.de_json(data.get("location"), bot) + data["location"] = de_json_wo(data.get("location"), Location, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatmember.py b/telegram/_chatmember.py index d1b4051e60b..af37a6d60d0 100644 --- a/telegram/_chatmember.py +++ b/telegram/_chatmember.py @@ -24,6 +24,7 @@ from telegram import constants from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -105,15 +106,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ChatMember"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatMember": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - _class_mapping: dict[str, type[ChatMember]] = { cls.OWNER: ChatMemberOwner, cls.ADMINISTRATOR: ChatMemberAdministrator, @@ -126,7 +122,7 @@ def de_json( if cls is ChatMember and data.get("status") in _class_mapping: return _class_mapping[data.pop("status")].de_json(data=data, bot=bot) - data["user"] = User.de_json(data.get("user"), bot) + data["user"] = de_json_wo(data.get("user"), User, bot) if "until_date" in data: # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) diff --git a/telegram/_chatmemberupdated.py b/telegram/_chatmemberupdated.py index cf71d772d06..676aba316a8 100644 --- a/telegram/_chatmemberupdated.py +++ b/telegram/_chatmemberupdated.py @@ -25,6 +25,7 @@ from telegram._chatmember import ChatMember from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -141,24 +142,19 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ChatMemberUpdated"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatMemberUpdated": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chat"] = Chat.de_json(data.get("chat"), bot) - data["from_user"] = User.de_json(data.pop("from", None), bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["from_user"] = de_json_wo(data.pop("from", None), User, bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["old_chat_member"] = ChatMember.de_json(data.get("old_chat_member"), bot) - data["new_chat_member"] = ChatMember.de_json(data.get("new_chat_member"), bot) - data["invite_link"] = ChatInviteLink.de_json(data.get("invite_link"), bot) + data["old_chat_member"] = de_json_wo(data.get("old_chat_member"), ChatMember, bot) + data["new_chat_member"] = de_json_wo(data.get("new_chat_member"), ChatMember, bot) + data["invite_link"] = de_json_wo(data.get("invite_link"), ChatInviteLink, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatpermissions.py b/telegram/_chatpermissions.py index c4e9e94b7a9..edc930034d6 100644 --- a/telegram/_chatpermissions.py +++ b/telegram/_chatpermissions.py @@ -231,15 +231,10 @@ def no_permissions(cls) -> "ChatPermissions": return cls(*(14 * (False,))) @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ChatPermissions"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatPermissions": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - api_kwargs = {} # This is a deprecated field that TG still returns for backwards compatibility # Let's filter it out to speed up the de-json process diff --git a/telegram/_choseninlineresult.py b/telegram/_choseninlineresult.py index 76380e95839..6efe1f95017 100644 --- a/telegram/_choseninlineresult.py +++ b/telegram/_choseninlineresult.py @@ -24,6 +24,7 @@ from telegram._files.location import Location from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -92,18 +93,13 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ChosenInlineResult"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChosenInlineResult": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # Required - data["from_user"] = User.de_json(data.pop("from", None), bot) + data["from_user"] = de_json_wo(data.pop("from", None), User, bot) # Optionals - data["location"] = Location.de_json(data.get("location"), bot) + data["location"] = de_json_wo(data.get("location"), Location, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_files/_basethumbedmedium.py b/telegram/_files/_basethumbedmedium.py index d0b66f35c20..2622a6a956a 100644 --- a/telegram/_files/_basethumbedmedium.py +++ b/telegram/_files/_basethumbedmedium.py @@ -21,6 +21,7 @@ from telegram._files._basemedium import _BaseMedium from telegram._files.photosize import PhotoSize +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -82,17 +83,14 @@ def __init__( @classmethod def de_json( - cls: type[ThumbedMT_co], data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional[ThumbedMT_co]: + cls: type[ThumbedMT_co], data: JSONDict, bot: Optional["Bot"] = None + ) -> ThumbedMT_co: """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # In case this wasn't already done by the subclass if not isinstance(data.get("thumbnail"), PhotoSize): - data["thumbnail"] = PhotoSize.de_json(data.get("thumbnail"), bot) + data["thumbnail"] = de_json_wo(data.get("thumbnail"), PhotoSize, bot) api_kwargs = {} # This is a deprecated field that TG still returns for backwards compatibility diff --git a/telegram/_files/sticker.py b/telegram/_files/sticker.py index 01ebf37e6ff..1cd24c8f1e5 100644 --- a/telegram/_files/sticker.py +++ b/telegram/_files/sticker.py @@ -26,7 +26,7 @@ from telegram._files.photosize import PhotoSize from telegram._telegramobject import TelegramObject from telegram._utils import enum -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -194,16 +194,13 @@ def __init__( """:const:`telegram.constants.StickerType.CUSTOM_EMOJI`""" @classmethod - def de_json(cls, data: Optional[JSONDict], bot: Optional["Bot"] = None) -> Optional["Sticker"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Sticker": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["thumbnail"] = PhotoSize.de_json(data.get("thumbnail"), bot) - data["mask_position"] = MaskPosition.de_json(data.get("mask_position"), bot) - data["premium_animation"] = File.de_json(data.get("premium_animation"), bot) + data["thumbnail"] = de_json_wo(data.get("thumbnail"), PhotoSize, bot) + data["mask_position"] = de_json_wo(data.get("mask_position"), MaskPosition, bot) + data["premium_animation"] = de_json_wo(data.get("premium_animation"), File, bot) api_kwargs = {} # This is a deprecated field that TG still returns for backwards compatibility @@ -306,15 +303,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["StickerSet"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "StickerSet": """See :meth:`telegram.TelegramObject.de_json`.""" - if not data: - return None - data["thumbnail"] = PhotoSize.de_json(data.get("thumbnail"), bot) - data["stickers"] = Sticker.de_list(data.get("stickers"), bot) + data["thumbnail"] = de_json_wo(data.get("thumbnail"), PhotoSize, bot) + data["stickers"] = de_list_wo(data.get("stickers"), Sticker, bot) api_kwargs = {} # These are deprecated fields that TG still returns for backwards compatibility diff --git a/telegram/_files/venue.py b/telegram/_files/venue.py index 443bd009c17..6d28a16914f 100644 --- a/telegram/_files/venue.py +++ b/telegram/_files/venue.py @@ -22,6 +22,7 @@ from telegram._files.location import Location from telegram._telegramobject import TelegramObject +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -103,13 +104,10 @@ def __init__( self._freeze() @classmethod - def de_json(cls, data: Optional[JSONDict], bot: Optional["Bot"] = None) -> Optional["Venue"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Venue": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["location"] = Location.de_json(data.get("location"), bot) + data["location"] = de_json_wo(data.get("location"), Location, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_games/game.py b/telegram/_games/game.py index efe30ea7f25..2d544e2c5b3 100644 --- a/telegram/_games/game.py +++ b/telegram/_games/game.py @@ -24,7 +24,7 @@ from telegram._files.photosize import PhotoSize from telegram._messageentity import MessageEntity from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.strings import TextEncoding from telegram._utils.types import JSONDict @@ -124,16 +124,13 @@ def __init__( self._freeze() @classmethod - def de_json(cls, data: Optional[JSONDict], bot: Optional["Bot"] = None) -> Optional["Game"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Game": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["photo"] = PhotoSize.de_list(data.get("photo"), bot) - data["text_entities"] = MessageEntity.de_list(data.get("text_entities"), bot) - data["animation"] = Animation.de_json(data.get("animation"), bot) + data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) + data["text_entities"] = de_list_wo(data.get("text_entities"), MessageEntity, bot) + data["animation"] = de_json_wo(data.get("animation"), Animation, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_games/gamehighscore.py b/telegram/_games/gamehighscore.py index 40f93fadd49..c2082d3f9dc 100644 --- a/telegram/_games/gamehighscore.py +++ b/telegram/_games/gamehighscore.py @@ -22,6 +22,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -61,15 +62,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["GameHighScore"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "GameHighScore": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["user"] = User.de_json(data.get("user"), bot) + data["user"] = de_json_wo(data.get("user"), User, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_gifts.py b/telegram/_gifts.py index 4aa5f5f604c..1b57ea97a1e 100644 --- a/telegram/_gifts.py +++ b/telegram/_gifts.py @@ -23,7 +23,7 @@ from telegram._files.sticker import Sticker from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -82,14 +82,11 @@ def __init__( self._freeze() @classmethod - def de_json(cls, data: Optional[JSONDict], bot: Optional["Bot"] = None) -> Optional["Gift"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Gift": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["sticker"] = Sticker.de_json(data.get("sticker"), bot) + data["sticker"] = de_json_wo(data.get("sticker"), Sticker, bot) return cls(**data) @@ -125,12 +122,9 @@ def __init__( self._freeze() @classmethod - def de_json(cls, data: Optional[JSONDict], bot: Optional["Bot"] = None) -> Optional["Gifts"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Gifts": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["gifts"] = Gift.de_list(data.get("gifts"), bot) + data["gifts"] = de_list_wo(data.get("gifts"), Gift, bot) return cls(**data) diff --git a/telegram/_giveaway.py b/telegram/_giveaway.py index ad2e6e0a6b7..0344b605cfc 100644 --- a/telegram/_giveaway.py +++ b/telegram/_giveaway.py @@ -24,7 +24,7 @@ from telegram._chat import Chat from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -137,19 +137,14 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["Giveaway"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Giveaway": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if data is None: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chats"] = tuple(Chat.de_list(data.get("chats"), bot)) + data["chats"] = tuple(de_list_wo(data.get("chats"), Chat, bot)) data["winners_selection_date"] = from_timestamp( data.get("winners_selection_date"), tzinfo=loc_tzinfo ) @@ -299,20 +294,15 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["GiveawayWinners"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "GiveawayWinners": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if data is None: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chat"] = Chat.de_json(data.get("chat"), bot) - data["winners"] = tuple(User.de_list(data.get("winners"), bot)) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["winners"] = tuple(de_list_wo(data.get("winners"), User, bot)) data["winners_selection_date"] = from_timestamp( data.get("winners_selection_date"), tzinfo=loc_tzinfo ) @@ -376,18 +366,13 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["GiveawayCompleted"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "GiveawayCompleted": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if data is None: - return None - # Unfortunately, this needs to be here due to cyclic imports from telegram._message import Message # pylint: disable=import-outside-toplevel - data["giveaway_message"] = Message.de_json(data.get("giveaway_message"), bot) + data["giveaway_message"] = de_json_wo(data.get("giveaway_message"), Message, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_inline/inlinekeyboardbutton.py b/telegram/_inline/inlinekeyboardbutton.py index 32edb655411..c2eaa2741be 100644 --- a/telegram/_inline/inlinekeyboardbutton.py +++ b/telegram/_inline/inlinekeyboardbutton.py @@ -26,6 +26,7 @@ from telegram._loginurl import LoginUrl from telegram._switchinlinequerychosenchat import SwitchInlineQueryChosenChat from telegram._telegramobject import TelegramObject +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict from telegram._webappinfo import WebAppInfo @@ -296,22 +297,17 @@ def _set_id_attrs(self) -> None: ) @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["InlineKeyboardButton"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "InlineKeyboardButton": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["login_url"] = LoginUrl.de_json(data.get("login_url"), bot) - data["web_app"] = WebAppInfo.de_json(data.get("web_app"), bot) - data["callback_game"] = CallbackGame.de_json(data.get("callback_game"), bot) - data["switch_inline_query_chosen_chat"] = SwitchInlineQueryChosenChat.de_json( - data.get("switch_inline_query_chosen_chat"), bot + data["login_url"] = de_json_wo(data.get("login_url"), LoginUrl, bot) + data["web_app"] = de_json_wo(data.get("web_app"), WebAppInfo, bot) + data["callback_game"] = de_json_wo(data.get("callback_game"), CallbackGame, bot) + data["switch_inline_query_chosen_chat"] = de_json_wo( + data.get("switch_inline_query_chosen_chat"), SwitchInlineQueryChosenChat, bot ) - data["copy_text"] = CopyTextButton.de_json(data.get("copy_text"), bot) + data["copy_text"] = de_json_wo(data.get("copy_text"), CopyTextButton, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_inline/inlinekeyboardmarkup.py b/telegram/_inline/inlinekeyboardmarkup.py index 406688f2d2f..5d47204bc2d 100644 --- a/telegram/_inline/inlinekeyboardmarkup.py +++ b/telegram/_inline/inlinekeyboardmarkup.py @@ -91,12 +91,8 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["InlineKeyboardMarkup"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "InlineKeyboardMarkup": """See :meth:`telegram.TelegramObject.de_json`.""" - if not data: - return None keyboard = [] for row in data["inline_keyboard"]: diff --git a/telegram/_inline/inlinequery.py b/telegram/_inline/inlinequery.py index f6a94e8f47e..273f6e02ca8 100644 --- a/telegram/_inline/inlinequery.py +++ b/telegram/_inline/inlinequery.py @@ -27,6 +27,7 @@ from telegram._inline.inlinequeryresultsbutton import InlineQueryResultsButton from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.types import JSONDict, ODVInput @@ -126,17 +127,12 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["InlineQuery"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "InlineQuery": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["from_user"] = User.de_json(data.pop("from", None), bot) - data["location"] = Location.de_json(data.get("location"), bot) + data["from_user"] = de_json_wo(data.pop("from", None), User, bot) + data["location"] = de_json_wo(data.get("location"), Location, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_inline/inlinequeryresultsbutton.py b/telegram/_inline/inlinequeryresultsbutton.py index ae0b404e1f8..78f7c588101 100644 --- a/telegram/_inline/inlinequeryresultsbutton.py +++ b/telegram/_inline/inlinequeryresultsbutton.py @@ -22,6 +22,7 @@ from telegram import constants from telegram._telegramobject import TelegramObject +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict from telegram._webappinfo import WebAppInfo @@ -97,14 +98,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["InlineQueryResultsButton"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "InlineQueryResultsButton": """See :meth:`telegram.TelegramObject.de_json`.""" - if not data: - return None - data["web_app"] = WebAppInfo.de_json(data.get("web_app"), bot) + data["web_app"] = de_json_wo(data.get("web_app"), WebAppInfo, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_inline/inputinvoicemessagecontent.py b/telegram/_inline/inputinvoicemessagecontent.py index 2ab896c8a5c..cd10ee49ac3 100644 --- a/telegram/_inline/inputinvoicemessagecontent.py +++ b/telegram/_inline/inputinvoicemessagecontent.py @@ -22,7 +22,7 @@ from telegram._inline.inputmessagecontent import InputMessageContent from telegram._payment.labeledprice import LabeledPrice -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_list_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -254,15 +254,10 @@ def __init__( ) @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["InputInvoiceMessageContent"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "InputInvoiceMessageContent": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["prices"] = LabeledPrice.de_list(data.get("prices"), bot) + data["prices"] = de_list_wo(data.get("prices"), LabeledPrice, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_inline/preparedinlinemessage.py b/telegram/_inline/preparedinlinemessage.py index 3f094d56bc8..2ed6d8d437f 100644 --- a/telegram/_inline/preparedinlinemessage.py +++ b/telegram/_inline/preparedinlinemessage.py @@ -67,15 +67,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["PreparedInlineMessage"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PreparedInlineMessage": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if data is None: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) data["expiration_date"] = from_timestamp(data.get("expiration_date"), tzinfo=loc_tzinfo) diff --git a/telegram/_keyboardbutton.py b/telegram/_keyboardbutton.py index ad08f2f98ad..2aa3bd12008 100644 --- a/telegram/_keyboardbutton.py +++ b/telegram/_keyboardbutton.py @@ -23,6 +23,7 @@ from telegram._keyboardbuttonpolltype import KeyboardButtonPollType from telegram._keyboardbuttonrequest import KeyboardButtonRequestChat, KeyboardButtonRequestUsers from telegram._telegramobject import TelegramObject +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict from telegram._webappinfo import WebAppInfo @@ -168,19 +169,16 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["KeyboardButton"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "KeyboardButton": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["request_poll"] = KeyboardButtonPollType.de_json(data.get("request_poll"), bot) - data["request_users"] = KeyboardButtonRequestUsers.de_json(data.get("request_users"), bot) - data["request_chat"] = KeyboardButtonRequestChat.de_json(data.get("request_chat"), bot) - data["web_app"] = WebAppInfo.de_json(data.get("web_app"), bot) + data["request_poll"] = de_json_wo(data.get("request_poll"), KeyboardButtonPollType, bot) + data["request_users"] = de_json_wo( + data.get("request_users"), KeyboardButtonRequestUsers, bot + ) + data["request_chat"] = de_json_wo(data.get("request_chat"), KeyboardButtonRequestChat, bot) + data["web_app"] = de_json_wo(data.get("web_app"), WebAppInfo, bot) api_kwargs = {} # This is a deprecated field that TG still returns for backwards compatibility diff --git a/telegram/_keyboardbuttonrequest.py b/telegram/_keyboardbuttonrequest.py index 4416952112e..f905cba9f94 100644 --- a/telegram/_keyboardbuttonrequest.py +++ b/telegram/_keyboardbuttonrequest.py @@ -22,6 +22,7 @@ from telegram._chatadministratorrights import ChatAdministratorRights from telegram._telegramobject import TelegramObject +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -257,20 +258,15 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["KeyboardButtonRequestChat"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "KeyboardButtonRequestChat": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["user_administrator_rights"] = ChatAdministratorRights.de_json( - data.get("user_administrator_rights"), bot + data["user_administrator_rights"] = de_json_wo( + data.get("user_administrator_rights"), ChatAdministratorRights, bot ) - data["bot_administrator_rights"] = ChatAdministratorRights.de_json( - data.get("bot_administrator_rights"), bot + data["bot_administrator_rights"] = de_json_wo( + data.get("bot_administrator_rights"), ChatAdministratorRights, bot ) return super().de_json(data=data, bot=bot) diff --git a/telegram/_menubutton.py b/telegram/_menubutton.py index 3df50fd3f8b..af410d97cbc 100644 --- a/telegram/_menubutton.py +++ b/telegram/_menubutton.py @@ -22,6 +22,7 @@ from telegram import constants from telegram._telegramobject import TelegramObject from telegram._utils import enum +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict from telegram._webappinfo import WebAppInfo @@ -69,9 +70,7 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["MenuButton"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MenuButton": """Converts JSON data to the appropriate :class:`MenuButton` object, i.e. takes care of selecting the correct subclass. @@ -89,12 +88,6 @@ def de_json( """ data = cls._parse_data(data) - if data is None: - return None - - if not data and cls is MenuButton: - return None - _class_mapping: dict[str, type[MenuButton]] = { cls.COMMANDS: MenuButtonCommands, cls.WEB_APP: MenuButtonWebApp, @@ -172,16 +165,11 @@ def __init__(self, text: str, web_app: WebAppInfo, *, api_kwargs: Optional[JSOND self._id_attrs = (self.type, self.text, self.web_app) @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["MenuButtonWebApp"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MenuButtonWebApp": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["web_app"] = WebAppInfo.de_json(data.get("web_app"), bot) + data["web_app"] = de_json_wo(data.get("web_app"), WebAppInfo, bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] diff --git a/telegram/_message.py b/telegram/_message.py index f56acfeb134..989cfb66867 100644 --- a/telegram/_message.py +++ b/telegram/_message.py @@ -65,7 +65,7 @@ from telegram._story import Story from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.defaultvalue import DEFAULT_NONE, DefaultValue from telegram._utils.entities import parse_message_entities, parse_message_entity @@ -191,9 +191,6 @@ def _de_json( """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - if cls is MaybeInaccessibleMessage: if data["date"] == 0: return InaccessibleMessage.de_json(data=data, bot=bot) @@ -208,7 +205,7 @@ def _de_json( else: data["date"] = from_timestamp(data["date"], tzinfo=loc_tzinfo) - data["chat"] = Chat.de_json(data.get("chat"), bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs) @@ -1251,83 +1248,92 @@ def link(self) -> Optional[str]: return None @classmethod - def de_json(cls, data: Optional[JSONDict], bot: Optional["Bot"] = None) -> Optional["Message"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Message": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["from_user"] = User.de_json(data.pop("from", None), bot) - data["sender_chat"] = Chat.de_json(data.get("sender_chat"), bot) - data["entities"] = MessageEntity.de_list(data.get("entities"), bot) - data["caption_entities"] = MessageEntity.de_list(data.get("caption_entities"), bot) - data["reply_to_message"] = Message.de_json(data.get("reply_to_message"), bot) + data["from_user"] = de_json_wo(data.pop("from", None), User, bot) + data["sender_chat"] = de_json_wo(data.get("sender_chat"), Chat, bot) + data["entities"] = de_list_wo(data.get("entities"), MessageEntity, bot) + data["caption_entities"] = de_list_wo(data.get("caption_entities"), MessageEntity, bot) + data["reply_to_message"] = de_json_wo(data.get("reply_to_message"), Message, bot) data["edit_date"] = from_timestamp(data.get("edit_date"), tzinfo=loc_tzinfo) - data["audio"] = Audio.de_json(data.get("audio"), bot) - data["document"] = Document.de_json(data.get("document"), bot) - data["animation"] = Animation.de_json(data.get("animation"), bot) - data["game"] = Game.de_json(data.get("game"), bot) - data["photo"] = PhotoSize.de_list(data.get("photo"), bot) - data["sticker"] = Sticker.de_json(data.get("sticker"), bot) - data["story"] = Story.de_json(data.get("story"), bot) - data["video"] = Video.de_json(data.get("video"), bot) - data["voice"] = Voice.de_json(data.get("voice"), bot) - data["video_note"] = VideoNote.de_json(data.get("video_note"), bot) - data["contact"] = Contact.de_json(data.get("contact"), bot) - data["location"] = Location.de_json(data.get("location"), bot) - data["venue"] = Venue.de_json(data.get("venue"), bot) - data["new_chat_members"] = User.de_list(data.get("new_chat_members"), bot) - data["left_chat_member"] = User.de_json(data.get("left_chat_member"), bot) - data["new_chat_photo"] = PhotoSize.de_list(data.get("new_chat_photo"), bot) - data["message_auto_delete_timer_changed"] = MessageAutoDeleteTimerChanged.de_json( - data.get("message_auto_delete_timer_changed"), bot + data["audio"] = de_json_wo(data.get("audio"), Audio, bot) + data["document"] = de_json_wo(data.get("document"), Document, bot) + data["animation"] = de_json_wo(data.get("animation"), Animation, bot) + data["game"] = de_json_wo(data.get("game"), Game, bot) + data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) + data["sticker"] = de_json_wo(data.get("sticker"), Sticker, bot) + data["story"] = de_json_wo(data.get("story"), Story, bot) + data["video"] = de_json_wo(data.get("video"), Video, bot) + data["voice"] = de_json_wo(data.get("voice"), Voice, bot) + data["video_note"] = de_json_wo(data.get("video_note"), VideoNote, bot) + data["contact"] = de_json_wo(data.get("contact"), Contact, bot) + data["location"] = de_json_wo(data.get("location"), Location, bot) + data["venue"] = de_json_wo(data.get("venue"), Venue, bot) + data["new_chat_members"] = de_list_wo(data.get("new_chat_members"), User, bot) + data["left_chat_member"] = de_json_wo(data.get("left_chat_member"), User, bot) + data["new_chat_photo"] = de_list_wo(data.get("new_chat_photo"), PhotoSize, bot) + data["message_auto_delete_timer_changed"] = de_json_wo( + data.get("message_auto_delete_timer_changed"), MessageAutoDeleteTimerChanged, bot + ) + data["pinned_message"] = de_json_wo( + data.get("pinned_message"), MaybeInaccessibleMessage, bot + ) + data["invoice"] = de_json_wo(data.get("invoice"), Invoice, bot) + data["successful_payment"] = de_json_wo( + data.get("successful_payment"), SuccessfulPayment, bot ) - data["pinned_message"] = MaybeInaccessibleMessage.de_json(data.get("pinned_message"), bot) - data["invoice"] = Invoice.de_json(data.get("invoice"), bot) - data["successful_payment"] = SuccessfulPayment.de_json(data.get("successful_payment"), bot) - data["passport_data"] = PassportData.de_json(data.get("passport_data"), bot) - data["poll"] = Poll.de_json(data.get("poll"), bot) - data["dice"] = Dice.de_json(data.get("dice"), bot) - data["via_bot"] = User.de_json(data.get("via_bot"), bot) - data["proximity_alert_triggered"] = ProximityAlertTriggered.de_json( - data.get("proximity_alert_triggered"), bot + data["passport_data"] = de_json_wo(data.get("passport_data"), PassportData, bot) + data["poll"] = de_json_wo(data.get("poll"), Poll, bot) + data["dice"] = de_json_wo(data.get("dice"), Dice, bot) + data["via_bot"] = de_json_wo(data.get("via_bot"), User, bot) + data["proximity_alert_triggered"] = de_json_wo( + data.get("proximity_alert_triggered"), ProximityAlertTriggered, bot ) - data["reply_markup"] = InlineKeyboardMarkup.de_json(data.get("reply_markup"), bot) - data["video_chat_scheduled"] = VideoChatScheduled.de_json( - data.get("video_chat_scheduled"), bot + data["reply_markup"] = de_json_wo(data.get("reply_markup"), InlineKeyboardMarkup, bot) + data["video_chat_scheduled"] = de_json_wo( + data.get("video_chat_scheduled"), VideoChatScheduled, bot ) - data["video_chat_started"] = VideoChatStarted.de_json(data.get("video_chat_started"), bot) - data["video_chat_ended"] = VideoChatEnded.de_json(data.get("video_chat_ended"), bot) - data["video_chat_participants_invited"] = VideoChatParticipantsInvited.de_json( - data.get("video_chat_participants_invited"), bot + data["video_chat_started"] = de_json_wo( + data.get("video_chat_started"), VideoChatStarted, bot ) - data["web_app_data"] = WebAppData.de_json(data.get("web_app_data"), bot) - data["forum_topic_closed"] = ForumTopicClosed.de_json(data.get("forum_topic_closed"), bot) - data["forum_topic_created"] = ForumTopicCreated.de_json( - data.get("forum_topic_created"), bot + data["video_chat_ended"] = de_json_wo(data.get("video_chat_ended"), VideoChatEnded, bot) + data["video_chat_participants_invited"] = de_json_wo( + data.get("video_chat_participants_invited"), VideoChatParticipantsInvited, bot ) - data["forum_topic_reopened"] = ForumTopicReopened.de_json( - data.get("forum_topic_reopened"), bot + data["web_app_data"] = de_json_wo(data.get("web_app_data"), WebAppData, bot) + data["forum_topic_closed"] = de_json_wo( + data.get("forum_topic_closed"), ForumTopicClosed, bot ) - data["forum_topic_edited"] = ForumTopicEdited.de_json(data.get("forum_topic_edited"), bot) - data["general_forum_topic_hidden"] = GeneralForumTopicHidden.de_json( - data.get("general_forum_topic_hidden"), bot + data["forum_topic_created"] = de_json_wo( + data.get("forum_topic_created"), ForumTopicCreated, bot ) - data["general_forum_topic_unhidden"] = GeneralForumTopicUnhidden.de_json( - data.get("general_forum_topic_unhidden"), bot + data["forum_topic_reopened"] = de_json_wo( + data.get("forum_topic_reopened"), ForumTopicReopened, bot ) - data["write_access_allowed"] = WriteAccessAllowed.de_json( - data.get("write_access_allowed"), bot + data["forum_topic_edited"] = de_json_wo( + data.get("forum_topic_edited"), ForumTopicEdited, bot ) - data["users_shared"] = UsersShared.de_json(data.get("users_shared"), bot) - data["chat_shared"] = ChatShared.de_json(data.get("chat_shared"), bot) - data["chat_background_set"] = ChatBackground.de_json(data.get("chat_background_set"), bot) - data["paid_media"] = PaidMediaInfo.de_json(data.get("paid_media"), bot) - data["refunded_payment"] = RefundedPayment.de_json(data.get("refunded_payment"), bot) + data["general_forum_topic_hidden"] = de_json_wo( + data.get("general_forum_topic_hidden"), GeneralForumTopicHidden, bot + ) + data["general_forum_topic_unhidden"] = de_json_wo( + data.get("general_forum_topic_unhidden"), GeneralForumTopicUnhidden, bot + ) + data["write_access_allowed"] = de_json_wo( + data.get("write_access_allowed"), WriteAccessAllowed, bot + ) + data["users_shared"] = de_json_wo(data.get("users_shared"), UsersShared, bot) + data["chat_shared"] = de_json_wo(data.get("chat_shared"), ChatShared, bot) + data["chat_background_set"] = de_json_wo( + data.get("chat_background_set"), ChatBackground, bot + ) + data["paid_media"] = de_json_wo(data.get("paid_media"), PaidMediaInfo, bot) + data["refunded_payment"] = de_json_wo(data.get("refunded_payment"), RefundedPayment, bot) # Unfortunately, this needs to be here due to cyclic imports from telegram._giveaway import ( # pylint: disable=import-outside-toplevel @@ -1344,19 +1350,21 @@ def de_json(cls, data: Optional[JSONDict], bot: Optional["Bot"] = None) -> Optio TextQuote, ) - data["giveaway"] = Giveaway.de_json(data.get("giveaway"), bot) - data["giveaway_completed"] = GiveawayCompleted.de_json(data.get("giveaway_completed"), bot) - data["giveaway_created"] = GiveawayCreated.de_json(data.get("giveaway_created"), bot) - data["giveaway_winners"] = GiveawayWinners.de_json(data.get("giveaway_winners"), bot) - data["link_preview_options"] = LinkPreviewOptions.de_json( - data.get("link_preview_options"), bot + data["giveaway"] = de_json_wo(data.get("giveaway"), Giveaway, bot) + data["giveaway_completed"] = de_json_wo( + data.get("giveaway_completed"), GiveawayCompleted, bot + ) + data["giveaway_created"] = de_json_wo(data.get("giveaway_created"), GiveawayCreated, bot) + data["giveaway_winners"] = de_json_wo(data.get("giveaway_winners"), GiveawayWinners, bot) + data["link_preview_options"] = de_json_wo( + data.get("link_preview_options"), LinkPreviewOptions, bot ) - data["external_reply"] = ExternalReplyInfo.de_json(data.get("external_reply"), bot) - data["quote"] = TextQuote.de_json(data.get("quote"), bot) - data["forward_origin"] = MessageOrigin.de_json(data.get("forward_origin"), bot) - data["reply_to_story"] = Story.de_json(data.get("reply_to_story"), bot) - data["boost_added"] = ChatBoostAdded.de_json(data.get("boost_added"), bot) - data["sender_business_bot"] = User.de_json(data.get("sender_business_bot"), bot) + data["external_reply"] = de_json_wo(data.get("external_reply"), ExternalReplyInfo, bot) + data["quote"] = de_json_wo(data.get("quote"), TextQuote, bot) + data["forward_origin"] = de_json_wo(data.get("forward_origin"), MessageOrigin, bot) + data["reply_to_story"] = de_json_wo(data.get("reply_to_story"), Story, bot) + data["boost_added"] = de_json_wo(data.get("boost_added"), ChatBoostAdded, bot) + data["sender_business_bot"] = de_json_wo(data.get("sender_business_bot"), User, bot) api_kwargs = {} # This is a deprecated field that TG still returns for backwards compatibility diff --git a/telegram/_messageentity.py b/telegram/_messageentity.py index 2fa5953d56d..c0f933de8a3 100644 --- a/telegram/_messageentity.py +++ b/telegram/_messageentity.py @@ -27,6 +27,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.strings import TextEncoding from telegram._utils.types import JSONDict @@ -137,16 +138,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["MessageEntity"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageEntity": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["user"] = User.de_json(data.get("user"), bot) + data["user"] = de_json_wo(data.get("user"), User, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_messageorigin.py b/telegram/_messageorigin.py index 61f18f67cc6..91a5732d551 100644 --- a/telegram/_messageorigin.py +++ b/telegram/_messageorigin.py @@ -25,6 +25,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -94,17 +95,12 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["MessageOrigin"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageOrigin": """Converts JSON data to the appropriate :class:`MessageOrigin` object, i.e. takes care of selecting the correct subclass. """ data = cls._parse_data(data) - if not data: - return None - _class_mapping: dict[str, type[MessageOrigin]] = { cls.USER: MessageOriginUser, cls.HIDDEN_USER: MessageOriginHiddenUser, @@ -118,13 +114,13 @@ def de_json( data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) if "sender_user" in data: - data["sender_user"] = User.de_json(data.get("sender_user"), bot) + data["sender_user"] = de_json_wo(data.get("sender_user"), User, bot) if "sender_chat" in data: - data["sender_chat"] = Chat.de_json(data.get("sender_chat"), bot) + data["sender_chat"] = de_json_wo(data.get("sender_chat"), Chat, bot) if "chat" in data: - data["chat"] = Chat.de_json(data.get("chat"), bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_messagereactionupdated.py b/telegram/_messagereactionupdated.py index 1d4b7d4d29f..5eb5c42a809 100644 --- a/telegram/_messagereactionupdated.py +++ b/telegram/_messagereactionupdated.py @@ -25,7 +25,7 @@ from telegram._reaction import ReactionCount, ReactionType from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -86,21 +86,16 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["MessageReactionCountUpdated"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageReactionCountUpdated": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["chat"] = Chat.de_json(data.get("chat"), bot) - data["reactions"] = ReactionCount.de_list(data.get("reactions"), bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["reactions"] = de_list_wo(data.get("reactions"), ReactionCount, bot) return super().de_json(data=data, bot=bot) @@ -187,23 +182,18 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["MessageReactionUpdated"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageReactionUpdated": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["chat"] = Chat.de_json(data.get("chat"), bot) - data["old_reaction"] = ReactionType.de_list(data.get("old_reaction"), bot) - data["new_reaction"] = ReactionType.de_list(data.get("new_reaction"), bot) - data["user"] = User.de_json(data.get("user"), bot) - data["actor_chat"] = Chat.de_json(data.get("actor_chat"), bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["old_reaction"] = de_list_wo(data.get("old_reaction"), ReactionType, bot) + data["new_reaction"] = de_list_wo(data.get("new_reaction"), ReactionType, bot) + data["user"] = de_json_wo(data.get("user"), User, bot) + data["actor_chat"] = de_json_wo(data.get("actor_chat"), Chat, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_paidmedia.py b/telegram/_paidmedia.py index c3ab1e22eaf..1337e6f1df0 100644 --- a/telegram/_paidmedia.py +++ b/telegram/_paidmedia.py @@ -27,7 +27,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -75,9 +75,7 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["PaidMedia"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PaidMedia": """Converts JSON data to the appropriate :class:`PaidMedia` object, i.e. takes care of selecting the correct subclass. @@ -91,12 +89,6 @@ def de_json( """ data = cls._parse_data(data) - if data is None: - return None - - if not data and cls is PaidMedia: - return None - _class_mapping: dict[str, type[PaidMedia]] = { cls.PREVIEW: PaidMediaPreview, cls.PHOTO: PaidMediaPhoto, @@ -185,15 +177,10 @@ def __init__( self._id_attrs = (self.type, self.photo) @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["PaidMediaPhoto"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PaidMediaPhoto": data = cls._parse_data(data) - if not data: - return None - - data["photo"] = PhotoSize.de_list(data.get("photo"), bot=bot) + data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] @@ -231,15 +218,10 @@ def __init__( self._id_attrs = (self.type, self.video) @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["PaidMediaVideo"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PaidMediaVideo": data = cls._parse_data(data) - if not data: - return None - - data["video"] = Video.de_json(data.get("video"), bot=bot) + data["video"] = de_json_wo(data.get("video"), Video, bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] @@ -280,15 +262,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["PaidMediaInfo"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PaidMediaInfo": data = cls._parse_data(data) - if not data: - return None - - data["paid_media"] = PaidMedia.de_list(data.get("paid_media"), bot=bot) + data["paid_media"] = de_list_wo(data.get("paid_media"), PaidMedia, bot) return super().de_json(data=data, bot=bot) @@ -329,13 +306,8 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["PaidMediaPurchased"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PaidMediaPurchased": data = cls._parse_data(data) - if not data: - return None - data["from_user"] = User.de_json(data=data.pop("from"), bot=bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_passport/credentials.py b/telegram/_passport/credentials.py index 17e44595abc..607b973538c 100644 --- a/telegram/_passport/credentials.py +++ b/telegram/_passport/credentials.py @@ -39,7 +39,7 @@ CRYPTO_INSTALLED = False from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.strings import TextEncoding from telegram._utils.types import JSONDict from telegram.error import PassportDecryptionError @@ -207,7 +207,7 @@ def decrypted_data(self) -> "Credentials": decrypt_json(self.decrypted_secret, b64decode(self.hash), b64decode(self.data)), self.get_bot(), ) - return self._decrypted_data # type: ignore[return-value] + return self._decrypted_data class Credentials(TelegramObject): @@ -234,16 +234,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["Credentials"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Credentials": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["secure_data"] = SecureData.de_json(data.get("secure_data"), bot=bot) + data["secure_data"] = de_json_wo(data.get("secure_data"), SecureData, bot) return super().de_json(data=data, bot=bot) @@ -346,30 +341,25 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["SecureData"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "SecureData": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["temporary_registration"] = SecureValue.de_json( - data.get("temporary_registration"), bot=bot + data["temporary_registration"] = de_json_wo( + data.get("temporary_registration"), SecureValue, bot ) - data["passport_registration"] = SecureValue.de_json( - data.get("passport_registration"), bot=bot + data["passport_registration"] = de_json_wo( + data.get("passport_registration"), SecureValue, bot ) - data["rental_agreement"] = SecureValue.de_json(data.get("rental_agreement"), bot=bot) - data["bank_statement"] = SecureValue.de_json(data.get("bank_statement"), bot=bot) - data["utility_bill"] = SecureValue.de_json(data.get("utility_bill"), bot=bot) - data["address"] = SecureValue.de_json(data.get("address"), bot=bot) - data["identity_card"] = SecureValue.de_json(data.get("identity_card"), bot=bot) - data["driver_license"] = SecureValue.de_json(data.get("driver_license"), bot=bot) - data["internal_passport"] = SecureValue.de_json(data.get("internal_passport"), bot=bot) - data["passport"] = SecureValue.de_json(data.get("passport"), bot=bot) - data["personal_details"] = SecureValue.de_json(data.get("personal_details"), bot=bot) + data["rental_agreement"] = de_json_wo(data.get("rental_agreement"), SecureValue, bot) + data["bank_statement"] = de_json_wo(data.get("bank_statement"), SecureValue, bot) + data["utility_bill"] = de_json_wo(data.get("utility_bill"), SecureValue, bot) + data["address"] = de_json_wo(data.get("address"), SecureValue, bot) + data["identity_card"] = de_json_wo(data.get("identity_card"), SecureValue, bot) + data["driver_license"] = de_json_wo(data.get("driver_license"), SecureValue, bot) + data["internal_passport"] = de_json_wo(data.get("internal_passport"), SecureValue, bot) + data["passport"] = de_json_wo(data.get("passport"), SecureValue, bot) + data["personal_details"] = de_json_wo(data.get("personal_details"), SecureValue, bot) return super().de_json(data=data, bot=bot) @@ -454,21 +444,16 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["SecureValue"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "SecureValue": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["data"] = DataCredentials.de_json(data.get("data"), bot=bot) - data["front_side"] = FileCredentials.de_json(data.get("front_side"), bot=bot) - data["reverse_side"] = FileCredentials.de_json(data.get("reverse_side"), bot=bot) - data["selfie"] = FileCredentials.de_json(data.get("selfie"), bot=bot) - data["files"] = FileCredentials.de_list(data.get("files"), bot=bot) - data["translation"] = FileCredentials.de_list(data.get("translation"), bot=bot) + data["data"] = de_json_wo(data.get("data"), DataCredentials, bot) + data["front_side"] = de_json_wo(data.get("front_side"), FileCredentials, bot) + data["reverse_side"] = de_json_wo(data.get("reverse_side"), FileCredentials, bot) + data["selfie"] = de_json_wo(data.get("selfie"), FileCredentials, bot) + data["files"] = de_list_wo(data.get("files"), FileCredentials, bot) + data["translation"] = de_list_wo(data.get("translation"), FileCredentials, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_passport/encryptedpassportelement.py b/telegram/_passport/encryptedpassportelement.py index 5bb764c9fc1..dc020896dbe 100644 --- a/telegram/_passport/encryptedpassportelement.py +++ b/telegram/_passport/encryptedpassportelement.py @@ -25,7 +25,13 @@ from telegram._passport.data import IdDocumentData, PersonalDetails, ResidentialAddress from telegram._passport.passportfile import PassportFile from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import ( + de_json_decrypted_wo, + de_json_wo, + de_list_decrypted_wo, + de_list_wo, + parse_sequence_arg, +) from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -194,27 +200,22 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["EncryptedPassportElement"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "EncryptedPassportElement": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["files"] = PassportFile.de_list(data.get("files"), bot) or None - data["front_side"] = PassportFile.de_json(data.get("front_side"), bot) - data["reverse_side"] = PassportFile.de_json(data.get("reverse_side"), bot) - data["selfie"] = PassportFile.de_json(data.get("selfie"), bot) - data["translation"] = PassportFile.de_list(data.get("translation"), bot) or None + data["files"] = de_list_wo(data.get("files"), PassportFile, bot) or None + data["front_side"] = de_json_wo(data.get("front_side"), PassportFile, bot) + data["reverse_side"] = de_json_wo(data.get("reverse_side"), PassportFile, bot) + data["selfie"] = de_json_wo(data.get("selfie"), PassportFile, bot) + data["translation"] = de_list_wo(data.get("translation"), PassportFile, bot) or None return super().de_json(data=data, bot=bot) @classmethod def de_json_decrypted( - cls, data: Optional[JSONDict], bot: Optional["Bot"], credentials: "Credentials" - ) -> Optional["EncryptedPassportElement"]: + cls, data: JSONDict, bot: Optional["Bot"], credentials: "Credentials" + ) -> "EncryptedPassportElement": """Variant of :meth:`telegram.TelegramObject.de_json` that also takes into account passport credentials. @@ -234,8 +235,6 @@ def de_json_decrypted( :class:`telegram.EncryptedPassportElement`: """ - if not data: - return None if data["type"] not in ("phone_number", "email"): secure_data = getattr(credentials.secure_data, data["type"]) @@ -261,20 +260,21 @@ def de_json_decrypted( data["data"] = ResidentialAddress.de_json(data["data"], bot=bot) data["files"] = ( - PassportFile.de_list_decrypted(data.get("files"), bot, secure_data.files) or None + de_list_decrypted_wo(data.get("files"), PassportFile, bot, secure_data.files) + or None ) - data["front_side"] = PassportFile.de_json_decrypted( - data.get("front_side"), bot, secure_data.front_side + data["front_side"] = de_json_decrypted_wo( + data.get("front_side"), PassportFile, bot, secure_data.front_side ) - data["reverse_side"] = PassportFile.de_json_decrypted( - data.get("reverse_side"), bot, secure_data.reverse_side + data["reverse_side"] = de_json_decrypted_wo( + data.get("reverse_side"), PassportFile, bot, secure_data.reverse_side ) - data["selfie"] = PassportFile.de_json_decrypted( - data.get("selfie"), bot, secure_data.selfie + data["selfie"] = de_json_decrypted_wo( + data.get("selfie"), PassportFile, bot, secure_data.selfie ) data["translation"] = ( - PassportFile.de_list_decrypted( - data.get("translation"), bot, secure_data.translation + de_list_decrypted_wo( + data.get("translation"), PassportFile, bot, secure_data.translation ) or None ) diff --git a/telegram/_passport/passportdata.py b/telegram/_passport/passportdata.py index 8b4db028a05..254322e74bd 100644 --- a/telegram/_passport/passportdata.py +++ b/telegram/_passport/passportdata.py @@ -23,7 +23,7 @@ from telegram._passport.credentials import EncryptedCredentials from telegram._passport.encryptedpassportelement import EncryptedPassportElement from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -82,17 +82,12 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["PassportData"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PassportData": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["data"] = EncryptedPassportElement.de_list(data.get("data"), bot) - data["credentials"] = EncryptedCredentials.de_json(data.get("credentials"), bot) + data["data"] = de_list_wo(data.get("data"), EncryptedPassportElement, bot) + data["credentials"] = de_json_wo(data.get("credentials"), EncryptedCredentials, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_passport/passportfile.py b/telegram/_passport/passportfile.py index e023457f670..ac02a268e4f 100644 --- a/telegram/_passport/passportfile.py +++ b/telegram/_passport/passportfile.py @@ -118,8 +118,8 @@ def file_date(self) -> int: @classmethod def de_json_decrypted( - cls, data: Optional[JSONDict], bot: Optional["Bot"], credentials: "FileCredentials" - ) -> Optional["PassportFile"]: + cls, data: JSONDict, bot: Optional["Bot"], credentials: "FileCredentials" + ) -> "PassportFile": """Variant of :meth:`telegram.TelegramObject.de_json` that also takes into account passport credentials. @@ -141,9 +141,6 @@ def de_json_decrypted( """ data = cls._parse_data(data) - if not data: - return None - data["credentials"] = credentials return super().de_json(data=data, bot=bot) @@ -151,10 +148,10 @@ def de_json_decrypted( @classmethod def de_list_decrypted( cls, - data: Optional[list[JSONDict]], + data: list[JSONDict], bot: Optional["Bot"], credentials: list["FileCredentials"], - ) -> tuple[Optional["PassportFile"], ...]: + ) -> tuple["PassportFile", ...]: """Variant of :meth:`telegram.TelegramObject.de_list` that also takes into account passport credentials. @@ -179,16 +176,12 @@ def de_list_decrypted( tuple[:class:`telegram.PassportFile`]: """ - if not data: - return () - return tuple( obj for obj in ( cls.de_json_decrypted(passport_file, bot, credentials[i]) for i, passport_file in enumerate(data) ) - if obj is not None ) async def get_file( diff --git a/telegram/_payment/orderinfo.py b/telegram/_payment/orderinfo.py index 7d3ee84a37b..8adfd3abeb1 100644 --- a/telegram/_payment/orderinfo.py +++ b/telegram/_payment/orderinfo.py @@ -22,6 +22,7 @@ from telegram._payment.shippingaddress import ShippingAddress from telegram._telegramobject import TelegramObject +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -71,15 +72,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["OrderInfo"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "OrderInfo": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return cls() - - data["shipping_address"] = ShippingAddress.de_json(data.get("shipping_address"), bot) + data["shipping_address"] = de_json_wo(data.get("shipping_address"), ShippingAddress, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/precheckoutquery.py b/telegram/_payment/precheckoutquery.py index 60e1d6078a1..eba80506b68 100644 --- a/telegram/_payment/precheckoutquery.py +++ b/telegram/_payment/precheckoutquery.py @@ -23,6 +23,7 @@ from telegram._payment.orderinfo import OrderInfo from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.types import JSONDict, ODVInput @@ -110,17 +111,12 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["PreCheckoutQuery"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PreCheckoutQuery": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["from_user"] = User.de_json(data.pop("from", None), bot) - data["order_info"] = OrderInfo.de_json(data.get("order_info"), bot) + data["from_user"] = de_json_wo(data.pop("from", None), User, bot) + data["order_info"] = de_json_wo(data.get("order_info"), OrderInfo, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/shippingquery.py b/telegram/_payment/shippingquery.py index 24b4e0a662f..f31287a90a3 100644 --- a/telegram/_payment/shippingquery.py +++ b/telegram/_payment/shippingquery.py @@ -24,6 +24,7 @@ from telegram._payment.shippingaddress import ShippingAddress from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.types import JSONDict, ODVInput @@ -78,17 +79,12 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ShippingQuery"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ShippingQuery": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["from_user"] = User.de_json(data.pop("from", None), bot) - data["shipping_address"] = ShippingAddress.de_json(data.get("shipping_address"), bot) + data["from_user"] = de_json_wo(data.pop("from", None), User, bot) + data["shipping_address"] = de_json_wo(data.get("shipping_address"), ShippingAddress, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/stars/affiliateinfo.py b/telegram/_payment/stars/affiliateinfo.py index 795b243d2c8..59961316f7d 100644 --- a/telegram/_payment/stars/affiliateinfo.py +++ b/telegram/_payment/stars/affiliateinfo.py @@ -16,13 +16,13 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. -# pylint: disable=redefined-builtin """This module contains the classes for Telegram Stars affiliates.""" from typing import TYPE_CHECKING, Optional from telegram._chat import Chat from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -106,16 +106,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["AffiliateInfo"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "AffiliateInfo": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["affiliate_user"] = User.de_json(data.get("affiliate_user"), bot) - data["affiliate_chat"] = Chat.de_json(data.get("affiliate_chat"), bot) + data["affiliate_user"] = de_json_wo(data.get("affiliate_user"), User, bot) + data["affiliate_chat"] = de_json_wo(data.get("affiliate_chat"), Chat, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/stars/revenuewithdrawalstate.py b/telegram/_payment/stars/revenuewithdrawalstate.py index 52d7592f421..4c7eaae6918 100644 --- a/telegram/_payment/stars/revenuewithdrawalstate.py +++ b/telegram/_payment/stars/revenuewithdrawalstate.py @@ -68,9 +68,7 @@ def __init__(self, type: str, *, api_kwargs: Optional[JSONDict] = None) -> None: self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["RevenueWithdrawalState"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "RevenueWithdrawalState": """Converts JSON data to the appropriate :class:`RevenueWithdrawalState` object, i.e. takes care of selecting the correct subclass. @@ -84,9 +82,6 @@ def de_json( """ data = cls._parse_data(data) - if (cls is RevenueWithdrawalState and not data) or data is None: - return None - _class_mapping: dict[str, type[RevenueWithdrawalState]] = { cls.PENDING: RevenueWithdrawalStatePending, cls.SUCCEEDED: RevenueWithdrawalStateSucceeded, @@ -156,14 +151,11 @@ def __init__( @classmethod def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["RevenueWithdrawalStateSucceeded"]: + cls, data: JSONDict, bot: Optional["Bot"] = None + ) -> "RevenueWithdrawalStateSucceeded": """See :meth:`telegram.RevenueWithdrawalState.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date", None), tzinfo=loc_tzinfo) diff --git a/telegram/_payment/stars/startransactions.py b/telegram/_payment/stars/startransactions.py index 3d2c4309477..6b0a77d3c78 100644 --- a/telegram/_payment/stars/startransactions.py +++ b/telegram/_payment/stars/startransactions.py @@ -24,7 +24,7 @@ from typing import TYPE_CHECKING, Optional from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -112,21 +112,16 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["StarTransaction"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "StarTransaction": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date", None), tzinfo=loc_tzinfo) - data["source"] = TransactionPartner.de_json(data.get("source"), bot) - data["receiver"] = TransactionPartner.de_json(data.get("receiver"), bot) + data["source"] = de_json_wo(data.get("source"), TransactionPartner, bot) + data["receiver"] = de_json_wo(data.get("receiver"), TransactionPartner, bot) return super().de_json(data=data, bot=bot) @@ -159,14 +154,9 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["StarTransactions"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "StarTransactions": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if data is None: - return None - - data["transactions"] = StarTransaction.de_list(data.get("transactions"), bot) + data["transactions"] = de_list_wo(data.get("transactions"), StarTransaction, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/stars/transactionpartner.py b/telegram/_payment/stars/transactionpartner.py index 199a219c1a4..f68d6c291d3 100644 --- a/telegram/_payment/stars/transactionpartner.py +++ b/telegram/_payment/stars/transactionpartner.py @@ -28,7 +28,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.types import JSONDict from .affiliateinfo import AffiliateInfo @@ -87,9 +87,7 @@ def __init__(self, type: str, *, api_kwargs: Optional[JSONDict] = None) -> None: self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["TransactionPartner"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "TransactionPartner": """Converts JSON data to the appropriate :class:`TransactionPartner` object, i.e. takes care of selecting the correct subclass. @@ -103,9 +101,6 @@ def de_json( """ data = cls._parse_data(data) - if (cls is TransactionPartner and not data) or data is None: - return None - _class_mapping: dict[str, type[TransactionPartner]] = { cls.AFFILIATE_PROGRAM: TransactionPartnerAffiliateProgram, cls.FRAGMENT: TransactionPartnerFragment, @@ -166,15 +161,12 @@ def __init__( @classmethod def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["TransactionPartnerAffiliateProgram"]: + cls, data: JSONDict, bot: Optional["Bot"] = None + ) -> "TransactionPartnerAffiliateProgram": """See :meth:`telegram.TransactionPartner.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["sponsor_user"] = User.de_json(data.get("sponsor_user"), bot) + data["sponsor_user"] = de_json_wo(data.get("sponsor_user"), User, bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] @@ -209,17 +201,12 @@ def __init__( self.withdrawal_state: Optional[RevenueWithdrawalState] = withdrawal_state @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["TransactionPartnerFragment"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "TransactionPartnerFragment": """See :meth:`telegram.TransactionPartner.de_json`.""" data = cls._parse_data(data) - if data is None: - return None - - data["withdrawal_state"] = RevenueWithdrawalState.de_json( - data.get("withdrawal_state"), bot + data["withdrawal_state"] = de_json_wo( + data.get("withdrawal_state"), RevenueWithdrawalState, bot ) return super().de_json(data=data, bot=bot) # type: ignore[return-value] @@ -320,24 +307,19 @@ def __init__( ) @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["TransactionPartnerUser"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "TransactionPartnerUser": """See :meth:`telegram.TransactionPartner.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["user"] = User.de_json(data.get("user"), bot) - data["affiliate"] = AffiliateInfo.de_json(data.get("affiliate"), bot) - data["paid_media"] = PaidMedia.de_list(data.get("paid_media"), bot=bot) + data["user"] = de_json_wo(data.get("user"), User, bot) + data["affiliate"] = de_json_wo(data.get("affiliate"), AffiliateInfo, bot) + data["paid_media"] = de_list_wo(data.get("paid_media"), PaidMedia, bot) data["subscription_period"] = ( dtm.timedelta(seconds=sp) if (sp := data.get("subscription_period")) is not None else None ) - data["gift"] = Gift.de_json(data.get("gift"), bot) + data["gift"] = de_json_wo(data.get("gift"), Gift, bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] diff --git a/telegram/_payment/successfulpayment.py b/telegram/_payment/successfulpayment.py index 5a947a8f434..cc852f1a8c7 100644 --- a/telegram/_payment/successfulpayment.py +++ b/telegram/_payment/successfulpayment.py @@ -23,6 +23,7 @@ from telegram._payment.orderinfo import OrderInfo from telegram._telegramobject import TelegramObject +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -138,16 +139,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["SuccessfulPayment"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "SuccessfulPayment": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["order_info"] = OrderInfo.de_json(data.get("order_info"), bot) + data["order_info"] = de_json_wo(data.get("order_info"), OrderInfo, bot) # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) diff --git a/telegram/_poll.py b/telegram/_poll.py index 4fcbd8f8ca5..5e89cfb5394 100644 --- a/telegram/_poll.py +++ b/telegram/_poll.py @@ -27,7 +27,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.entities import parse_message_entities, parse_message_entity @@ -91,16 +91,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["InputPollOption"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "InputPollOption": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["text_entities"] = MessageEntity.de_list(data.get("text_entities"), bot) + data["text_entities"] = de_list_wo(data.get("text_entities"), MessageEntity, bot) return super().de_json(data=data, bot=bot) @@ -157,16 +152,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["PollOption"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PollOption": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["text_entities"] = MessageEntity.de_list(data.get("text_entities"), bot) + data["text_entities"] = de_list_wo(data.get("text_entities"), MessageEntity, bot) return super().de_json(data=data, bot=bot) @@ -306,17 +296,12 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["PollAnswer"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PollAnswer": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["user"] = User.de_json(data.get("user"), bot) - data["voter_chat"] = Chat.de_json(data.get("voter_chat"), bot) + data["user"] = de_json_wo(data.get("user"), User, bot) + data["voter_chat"] = de_json_wo(data.get("voter_chat"), Chat, bot) return super().de_json(data=data, bot=bot) @@ -474,20 +459,19 @@ def __init__( self._freeze() @classmethod - def de_json(cls, data: Optional[JSONDict], bot: Optional["Bot"] = None) -> Optional["Poll"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Poll": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) data["options"] = [PollOption.de_json(option, bot) for option in data["options"]] - data["explanation_entities"] = MessageEntity.de_list(data.get("explanation_entities"), bot) + data["explanation_entities"] = de_list_wo( + data.get("explanation_entities"), MessageEntity, bot + ) data["close_date"] = from_timestamp(data.get("close_date"), tzinfo=loc_tzinfo) - data["question_entities"] = MessageEntity.de_list(data.get("question_entities"), bot) + data["question_entities"] = de_list_wo(data.get("question_entities"), MessageEntity, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_proximityalerttriggered.py b/telegram/_proximityalerttriggered.py index 0880ca9a6f6..e39a473e961 100644 --- a/telegram/_proximityalerttriggered.py +++ b/telegram/_proximityalerttriggered.py @@ -21,6 +21,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -67,16 +68,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ProximityAlertTriggered"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ProximityAlertTriggered": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["traveler"] = User.de_json(data.get("traveler"), bot) - data["watcher"] = User.de_json(data.get("watcher"), bot) + data["traveler"] = de_json_wo(data.get("traveler"), User, bot) + data["watcher"] = de_json_wo(data.get("watcher"), User, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_reaction.py b/telegram/_reaction.py index ca0f37fb0cc..0e21847fedf 100644 --- a/telegram/_reaction.py +++ b/telegram/_reaction.py @@ -23,6 +23,7 @@ from telegram import constants from telegram._telegramobject import TelegramObject from telegram._utils import enum +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -77,18 +78,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ReactionType"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ReactionType": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if data is None: - return None - - if not data and cls is ReactionType: - return None - _class_mapping: dict[str, type[ReactionType]] = { cls.EMOJI: ReactionTypeEmoji, cls.CUSTOM_EMOJI: ReactionTypeCustomEmoji, @@ -230,15 +223,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ReactionCount"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ReactionCount": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["type"] = ReactionType.de_json(data.get("type"), bot) + data["type"] = de_json_wo(data.get("type"), ReactionType, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_reply.py b/telegram/_reply.py index afaa379ca38..9e72e97d50d 100644 --- a/telegram/_reply.py +++ b/telegram/_reply.py @@ -43,7 +43,7 @@ from telegram._poll import Poll from telegram._story import Story from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.types import JSONDict, ODVInput @@ -248,39 +248,34 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ExternalReplyInfo"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ExternalReplyInfo": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if data is None: - return None - - data["origin"] = MessageOrigin.de_json(data.get("origin"), bot) - data["chat"] = Chat.de_json(data.get("chat"), bot) - data["link_preview_options"] = LinkPreviewOptions.de_json( - data.get("link_preview_options"), bot + data["origin"] = de_json_wo(data.get("origin"), MessageOrigin, bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["link_preview_options"] = de_json_wo( + data.get("link_preview_options"), LinkPreviewOptions, bot ) - data["animation"] = Animation.de_json(data.get("animation"), bot) - data["audio"] = Audio.de_json(data.get("audio"), bot) - data["document"] = Document.de_json(data.get("document"), bot) - data["photo"] = tuple(PhotoSize.de_list(data.get("photo"), bot)) - data["sticker"] = Sticker.de_json(data.get("sticker"), bot) - data["story"] = Story.de_json(data.get("story"), bot) - data["video"] = Video.de_json(data.get("video"), bot) - data["video_note"] = VideoNote.de_json(data.get("video_note"), bot) - data["voice"] = Voice.de_json(data.get("voice"), bot) - data["contact"] = Contact.de_json(data.get("contact"), bot) - data["dice"] = Dice.de_json(data.get("dice"), bot) - data["game"] = Game.de_json(data.get("game"), bot) - data["giveaway"] = Giveaway.de_json(data.get("giveaway"), bot) - data["giveaway_winners"] = GiveawayWinners.de_json(data.get("giveaway_winners"), bot) - data["invoice"] = Invoice.de_json(data.get("invoice"), bot) - data["location"] = Location.de_json(data.get("location"), bot) - data["poll"] = Poll.de_json(data.get("poll"), bot) - data["venue"] = Venue.de_json(data.get("venue"), bot) - data["paid_media"] = PaidMediaInfo.de_json(data.get("paid_media"), bot) + data["animation"] = de_json_wo(data.get("animation"), Animation, bot) + data["audio"] = de_json_wo(data.get("audio"), Audio, bot) + data["document"] = de_json_wo(data.get("document"), Document, bot) + data["photo"] = tuple(de_list_wo(data.get("photo"), PhotoSize, bot)) + data["sticker"] = de_json_wo(data.get("sticker"), Sticker, bot) + data["story"] = de_json_wo(data.get("story"), Story, bot) + data["video"] = de_json_wo(data.get("video"), Video, bot) + data["video_note"] = de_json_wo(data.get("video_note"), VideoNote, bot) + data["voice"] = de_json_wo(data.get("voice"), Voice, bot) + data["contact"] = de_json_wo(data.get("contact"), Contact, bot) + data["dice"] = de_json_wo(data.get("dice"), Dice, bot) + data["game"] = de_json_wo(data.get("game"), Game, bot) + data["giveaway"] = de_json_wo(data.get("giveaway"), Giveaway, bot) + data["giveaway_winners"] = de_json_wo(data.get("giveaway_winners"), GiveawayWinners, bot) + data["invoice"] = de_json_wo(data.get("invoice"), Invoice, bot) + data["location"] = de_json_wo(data.get("location"), Location, bot) + data["poll"] = de_json_wo(data.get("poll"), Poll, bot) + data["venue"] = de_json_wo(data.get("venue"), Venue, bot) + data["paid_media"] = de_json_wo(data.get("paid_media"), PaidMediaInfo, bot) return super().de_json(data=data, bot=bot) @@ -350,16 +345,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["TextQuote"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "TextQuote": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if data is None: - return None - - data["entities"] = tuple(MessageEntity.de_list(data.get("entities"), bot)) + data["entities"] = tuple(de_list_wo(data.get("entities"), MessageEntity, bot)) return super().de_json(data=data, bot=bot) @@ -458,15 +448,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ReplyParameters"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ReplyParameters": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if data is None: - return None - - data["quote_entities"] = tuple(MessageEntity.de_list(data.get("quote_entities"), bot)) + data["quote_entities"] = tuple(de_list_wo(data.get("quote_entities"), MessageEntity, bot)) return super().de_json(data=data, bot=bot) diff --git a/telegram/_shared.py b/telegram/_shared.py index 60d8ef3b961..953fd640c76 100644 --- a/telegram/_shared.py +++ b/telegram/_shared.py @@ -22,7 +22,7 @@ from telegram._files.photosize import PhotoSize from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_list_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -84,16 +84,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["UsersShared"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "UsersShared": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["users"] = SharedUser.de_list(data.get("users"), bot) + data["users"] = de_list_wo(data.get("users"), SharedUser, bot) api_kwargs = {} # This is a deprecated field that TG still returns for backwards compatibility @@ -175,16 +170,11 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["ChatShared"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatShared": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["photo"] = PhotoSize.de_list(data.get("photo"), bot) + data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) return super().de_json(data=data, bot=bot) @@ -255,14 +245,9 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["SharedUser"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "SharedUser": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["photo"] = PhotoSize.de_list(data.get("photo"), bot) + data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_story.py b/telegram/_story.py index 40d17cdb16d..19f671d8791 100644 --- a/telegram/_story.py +++ b/telegram/_story.py @@ -71,12 +71,9 @@ def __init__( self._freeze() @classmethod - def de_json(cls, data: Optional[JSONDict], bot: Optional["Bot"] = None) -> Optional["Story"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Story": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - data["chat"] = Chat.de_json(data.get("chat", {}), bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_telegramobject.py b/telegram/_telegramobject.py index 2e4116b9675..d8858e56c77 100644 --- a/telegram/_telegramobject.py +++ b/telegram/_telegramobject.py @@ -377,23 +377,20 @@ def __deepcopy__(self: Tele_co, memodict: dict[int, object]) -> Tele_co: return result @staticmethod - def _parse_data(data: Optional[JSONDict]) -> Optional[JSONDict]: + def _parse_data(data: JSONDict) -> JSONDict: """Should be called by subclasses that override de_json to ensure that the input is not altered. Whoever calls de_json might still want to use the original input for something else. """ - return None if data is None else data.copy() + return data.copy() @classmethod def _de_json( cls: type[Tele_co], - data: Optional[JSONDict], + data: JSONDict, bot: Optional["Bot"], api_kwargs: Optional[JSONDict] = None, - ) -> Optional[Tele_co]: - if data is None: - return None - + ) -> Tele_co: # try-except is significantly faster in case we already have a correct argument set try: obj = cls(**data, api_kwargs=api_kwargs) @@ -417,9 +414,7 @@ def _de_json( return obj @classmethod - def de_json( - cls: type[Tele_co], data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional[Tele_co]: + def de_json(cls: type[Tele_co], data: JSONDict, bot: Optional["Bot"] = None) -> Tele_co: """Converts JSON data to a Telegram object. Args: @@ -438,7 +433,7 @@ def de_json( @classmethod def de_list( - cls: type[Tele_co], data: Optional[list[JSONDict]], bot: Optional["Bot"] = None + cls: type[Tele_co], data: list[JSONDict], bot: Optional["Bot"] = None ) -> tuple[Tele_co, ...]: """Converts a list of JSON objects to a tuple of Telegram objects. @@ -459,10 +454,7 @@ def de_list( A tuple of Telegram objects. """ - if not data: - return () - - return tuple(obj for obj in (cls.de_json(d, bot) for d in data) if obj is not None) + return tuple(obj for obj in (cls.de_json(d, bot) for d in data)) @contextmanager def _unfrozen(self: Tele_co) -> Iterator[Tele_co]: diff --git a/telegram/_update.py b/telegram/_update.py index abacce72c5f..3b0ebf81f3e 100644 --- a/telegram/_update.py +++ b/telegram/_update.py @@ -35,6 +35,7 @@ from telegram._payment.shippingquery import ShippingQuery from telegram._poll import Poll, PollAnswer from telegram._telegramobject import TelegramObject +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict from telegram._utils.warnings import warn @@ -757,47 +758,50 @@ def effective_message(self) -> Optional[Message]: return message @classmethod - def de_json(cls, data: Optional[JSONDict], bot: Optional["Bot"] = None) -> Optional["Update"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Update": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - - data["message"] = Message.de_json(data.get("message"), bot) - data["edited_message"] = Message.de_json(data.get("edited_message"), bot) - data["inline_query"] = InlineQuery.de_json(data.get("inline_query"), bot) - data["chosen_inline_result"] = ChosenInlineResult.de_json( - data.get("chosen_inline_result"), bot + data["message"] = de_json_wo(data.get("message"), Message, bot) + data["edited_message"] = de_json_wo(data.get("edited_message"), Message, bot) + data["inline_query"] = de_json_wo(data.get("inline_query"), InlineQuery, bot) + data["chosen_inline_result"] = de_json_wo( + data.get("chosen_inline_result"), ChosenInlineResult, bot + ) + data["callback_query"] = de_json_wo(data.get("callback_query"), CallbackQuery, bot) + data["shipping_query"] = de_json_wo(data.get("shipping_query"), ShippingQuery, bot) + data["pre_checkout_query"] = de_json_wo( + data.get("pre_checkout_query"), PreCheckoutQuery, bot + ) + data["channel_post"] = de_json_wo(data.get("channel_post"), Message, bot) + data["edited_channel_post"] = de_json_wo(data.get("edited_channel_post"), Message, bot) + data["poll"] = de_json_wo(data.get("poll"), Poll, bot) + data["poll_answer"] = de_json_wo(data.get("poll_answer"), PollAnswer, bot) + data["my_chat_member"] = de_json_wo(data.get("my_chat_member"), ChatMemberUpdated, bot) + data["chat_member"] = de_json_wo(data.get("chat_member"), ChatMemberUpdated, bot) + data["chat_join_request"] = de_json_wo(data.get("chat_join_request"), ChatJoinRequest, bot) + data["chat_boost"] = de_json_wo(data.get("chat_boost"), ChatBoostUpdated, bot) + data["removed_chat_boost"] = de_json_wo( + data.get("removed_chat_boost"), ChatBoostRemoved, bot + ) + data["message_reaction"] = de_json_wo( + data.get("message_reaction"), MessageReactionUpdated, bot ) - data["callback_query"] = CallbackQuery.de_json(data.get("callback_query"), bot) - data["shipping_query"] = ShippingQuery.de_json(data.get("shipping_query"), bot) - data["pre_checkout_query"] = PreCheckoutQuery.de_json(data.get("pre_checkout_query"), bot) - data["channel_post"] = Message.de_json(data.get("channel_post"), bot) - data["edited_channel_post"] = Message.de_json(data.get("edited_channel_post"), bot) - data["poll"] = Poll.de_json(data.get("poll"), bot) - data["poll_answer"] = PollAnswer.de_json(data.get("poll_answer"), bot) - data["my_chat_member"] = ChatMemberUpdated.de_json(data.get("my_chat_member"), bot) - data["chat_member"] = ChatMemberUpdated.de_json(data.get("chat_member"), bot) - data["chat_join_request"] = ChatJoinRequest.de_json(data.get("chat_join_request"), bot) - data["chat_boost"] = ChatBoostUpdated.de_json(data.get("chat_boost"), bot) - data["removed_chat_boost"] = ChatBoostRemoved.de_json(data.get("removed_chat_boost"), bot) - data["message_reaction"] = MessageReactionUpdated.de_json( - data.get("message_reaction"), bot + data["message_reaction_count"] = de_json_wo( + data.get("message_reaction_count"), MessageReactionCountUpdated, bot ) - data["message_reaction_count"] = MessageReactionCountUpdated.de_json( - data.get("message_reaction_count"), bot + data["business_connection"] = de_json_wo( + data.get("business_connection"), BusinessConnection, bot ) - data["business_connection"] = BusinessConnection.de_json( - data.get("business_connection"), bot + data["business_message"] = de_json_wo(data.get("business_message"), Message, bot) + data["edited_business_message"] = de_json_wo( + data.get("edited_business_message"), Message, bot ) - data["business_message"] = Message.de_json(data.get("business_message"), bot) - data["edited_business_message"] = Message.de_json(data.get("edited_business_message"), bot) - data["deleted_business_messages"] = BusinessMessagesDeleted.de_json( - data.get("deleted_business_messages"), bot + data["deleted_business_messages"] = de_json_wo( + data.get("deleted_business_messages"), BusinessMessagesDeleted, bot ) - data["purchased_paid_media"] = PaidMediaPurchased.de_json( - data.get("purchased_paid_media"), bot + data["purchased_paid_media"] = de_json_wo( + data.get("purchased_paid_media"), PaidMediaPurchased, bot ) return super().de_json(data=data, bot=bot) diff --git a/telegram/_userprofilephotos.py b/telegram/_userprofilephotos.py index c7355bb8723..3d78b05cc77 100644 --- a/telegram/_userprofilephotos.py +++ b/telegram/_userprofilephotos.py @@ -71,15 +71,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["UserProfilePhotos"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "UserProfilePhotos": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - data["photos"] = [PhotoSize.de_list(photo, bot) for photo in data["photos"]] return super().de_json(data=data, bot=bot) diff --git a/telegram/_utils/argumentparsing.py b/telegram/_utils/argumentparsing.py index 22485512ff4..97a129fc712 100644 --- a/telegram/_utils/argumentparsing.py +++ b/telegram/_utils/argumentparsing.py @@ -24,10 +24,14 @@ the changelog. """ from collections.abc import Sequence -from typing import Optional, TypeVar +from typing import TYPE_CHECKING, Optional, Protocol, TypeVar from telegram._linkpreviewoptions import LinkPreviewOptions -from telegram._utils.types import ODVInput +from telegram._telegramobject import TelegramObject +from telegram._utils.types import JSONDict, ODVInput + +if TYPE_CHECKING: + from telegram import Bot, FileCredentials T = TypeVar("T") @@ -60,3 +64,71 @@ def parse_lpo_and_dwpp( link_preview_options = LinkPreviewOptions(is_disabled=disable_web_page_preview) return link_preview_options + + +Tele_co = TypeVar("Tele_co", bound=TelegramObject, covariant=True) +TeleCrypto_co = TypeVar("TeleCrypto_co", bound="HasDecryptMethod", covariant=True) + + +class HasDecryptMethod(Protocol): + @classmethod + def de_json_decrypted( + cls: type[TeleCrypto_co], + data: JSONDict, + bot: Optional["Bot"], + credentials: list["FileCredentials"], + ) -> TeleCrypto_co: ... + + @classmethod + def de_list_decrypted( + cls: type[TeleCrypto_co], + data: list[JSONDict], + bot: Optional["Bot"], + credentials: list["FileCredentials"], + ) -> tuple[TeleCrypto_co, ...]: ... + + +def de_json_wo( + data: Optional[JSONDict], cls: type[Tele_co], bot: Optional["Bot"] +) -> Optional[Tele_co]: + """Wrapper around TO.de_json that returns None if data is None.""" + if data is None: + return None + + return cls.de_json(data, bot) + + +def de_json_decrypted_wo( + data: Optional[JSONDict], + cls: type[TeleCrypto_co], + bot: Optional["Bot"], + credentials: list["FileCredentials"], +) -> Optional[TeleCrypto_co]: + """Wrapper around TO.de_json_decrypted that returns None if data is None.""" + if data is None: + return None + + return cls.de_json_decrypted(data, bot, credentials) + + +def de_list_wo( + data: Optional[list[JSONDict]], cls: type[Tele_co], bot: Optional["Bot"] +) -> tuple[Tele_co, ...]: + """Wrapper around TO.de_list that returns an empty list if data is None.""" + if data is None: + return () + + return cls.de_list(data, bot) + + +def de_list_decrypted_wo( + data: Optional[list[JSONDict]], + cls: type[TeleCrypto_co], + bot: Optional["Bot"], + credentials: list["FileCredentials"], +) -> tuple[TeleCrypto_co, ...]: + """Wrapper around TO.de_list_decrypted that returns an empty list if data is None.""" + if data is None: + return () + + return cls.de_list_decrypted(data, bot, credentials) diff --git a/telegram/_videochat.py b/telegram/_videochat.py index 916d8f9ef9c..3b46d776442 100644 --- a/telegram/_videochat.py +++ b/telegram/_videochat.py @@ -126,14 +126,11 @@ def __init__( @classmethod def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["VideoChatParticipantsInvited"]: + cls, data: JSONDict, bot: Optional["Bot"] = None + ) -> "VideoChatParticipantsInvited": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - data["users"] = User.de_list(data.get("users", []), bot) return super().de_json(data=data, bot=bot) @@ -178,15 +175,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["VideoChatScheduled"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "VideoChatScheduled": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) diff --git a/telegram/_webhookinfo.py b/telegram/_webhookinfo.py index 95ae31e510f..b28a1d1acd9 100644 --- a/telegram/_webhookinfo.py +++ b/telegram/_webhookinfo.py @@ -166,15 +166,10 @@ def __init__( self._freeze() @classmethod - def de_json( - cls, data: Optional[JSONDict], bot: Optional["Bot"] = None - ) -> Optional["WebhookInfo"]: + def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "WebhookInfo": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - if not data: - return None - # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) From 04de3eff7a7b6d1581673f8ec6496d34bd8df5f8 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Sun, 29 Dec 2024 22:00:38 +0100 Subject: [PATCH 02/14] Get a Number of Tests passing --- telegram/_utils/argumentparsing.py | 2 ++ tests/_files/test_animation.py | 5 +++- tests/_files/test_audio.py | 5 +++- tests/_files/test_document.py | 5 +++- tests/_files/test_photo.py | 5 +++- tests/_files/test_sticker.py | 6 +++- tests/_files/test_video.py | 5 +++- tests/_files/test_videonote.py | 3 +- tests/_files/test_voice.py | 5 +++- tests/_games/test_gamehighscore.py | 2 -- tests/_inline/test_inlinekeyboardbutton.py | 3 -- .../test_inputinvoicemessagecontent.py | 1 - tests/_payment/stars/test_affiliateinfo.py | 3 -- .../stars/test_revenuewithdrawelstate.py | 9 ------ tests/_payment/stars/test_startransactions.py | 4 --- .../_payment/stars/test_transactionpartner.py | 17 ----------- tests/conftest.py | 12 +++++++- tests/test_bot.py | 29 +++++++++++++++++-- tests/test_botcommand.py | 2 -- tests/test_botcommandscope.py | 2 -- tests/test_chatbackground.py | 2 -- tests/test_chatboost.py | 2 -- tests/test_chatmember.py | 1 - tests/test_copytextbutton.py | 1 - tests/test_dice.py | 1 - tests/test_forum.py | 4 --- tests/test_gifts.py | 4 --- tests/test_giveaway.py | 8 ----- tests/test_inlinequeryresultsbutton.py | 2 -- tests/test_keyboardbutton.py | 3 -- tests/test_keyboardbuttonrequest.py | 3 -- tests/test_menubutton.py | 3 -- tests/test_messageorigin.py | 1 - tests/test_paidmedia.py | 7 ----- tests/test_poll.py | 3 +- tests/test_reaction.py | 4 --- tests/test_reply.py | 6 ---- tests/test_shared.py | 4 --- tests/test_story.py | 1 - tests/test_telegramobject.py | 2 +- tests/test_update.py | 5 ---- tests/test_videochat.py | 1 - tests/test_webhookinfo.py | 3 -- 43 files changed, 72 insertions(+), 124 deletions(-) diff --git a/telegram/_utils/argumentparsing.py b/telegram/_utils/argumentparsing.py index 97a129fc712..262aa8bb8aa 100644 --- a/telegram/_utils/argumentparsing.py +++ b/telegram/_utils/argumentparsing.py @@ -71,6 +71,8 @@ def parse_lpo_and_dwpp( class HasDecryptMethod(Protocol): + __slots__ = () + @classmethod def de_json_decrypted( cls: type[TeleCrypto_co], diff --git a/tests/_files/test_animation.py b/tests/_files/test_animation.py index 0f581259db9..3ae775e3cf5 100644 --- a/tests/_files/test_animation.py +++ b/tests/_files/test_animation.py @@ -138,7 +138,9 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): ) @pytest.mark.parametrize("local_mode", [True, False]) - async def test_send_animation_local_files(self, monkeypatch, offline_bot, chat_id, local_mode): + async def test_send_animation_local_files( + self, monkeypatch, offline_bot, chat_id, local_mode, dummy_message_dict + ): try: offline_bot._local_mode = local_mode # For just test that the correct paths are passed as we have no local Bot API set up @@ -156,6 +158,7 @@ async def make_assertion(_, data, *args, **kwargs): test_flag = isinstance(data.get("animation"), InputFile) and isinstance( data.get("thumbnail"), InputFile ) + return dummy_message_dict monkeypatch.setattr(offline_bot, "_post", make_assertion) await offline_bot.send_animation(chat_id, file, thumbnail=file) diff --git a/tests/_files/test_audio.py b/tests/_files/test_audio.py index 08e598cb267..39c1de11cd1 100644 --- a/tests/_files/test_audio.py +++ b/tests/_files/test_audio.py @@ -150,7 +150,9 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): assert await offline_bot.send_audio(chat_id, audio_file, filename="custom_filename") @pytest.mark.parametrize("local_mode", [True, False]) - async def test_send_audio_local_files(self, monkeypatch, offline_bot, chat_id, local_mode): + async def test_send_audio_local_files( + self, dummy_message_dict, monkeypatch, offline_bot, chat_id, local_mode + ): try: offline_bot._local_mode = local_mode # For just test that the correct paths are passed as we have no local Bot API set up @@ -166,6 +168,7 @@ async def make_assertion(_, data, *args, **kwargs): test_flag = isinstance(data.get("audio"), InputFile) and isinstance( data.get("thumbnail"), InputFile ) + return dummy_message_dict monkeypatch.setattr(offline_bot, "_post", make_assertion) await offline_bot.send_audio(chat_id, file, thumbnail=file) diff --git a/tests/_files/test_document.py b/tests/_files/test_document.py index e6037403408..521e3a753e8 100644 --- a/tests/_files/test_document.py +++ b/tests/_files/test_document.py @@ -169,7 +169,9 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): ) @pytest.mark.parametrize("local_mode", [True, False]) - async def test_send_document_local_files(self, monkeypatch, offline_bot, chat_id, local_mode): + async def test_send_document_local_files( + self, dummy_message_dict, monkeypatch, offline_bot, chat_id, local_mode + ): try: offline_bot._local_mode = local_mode # For just test that the correct paths are passed as we have no local Bot API set up @@ -187,6 +189,7 @@ async def make_assertion(_, data, *args, **kwargs): test_flag = isinstance(data.get("document"), InputFile) and isinstance( data.get("thumbnail"), InputFile ) + return dummy_message_dict monkeypatch.setattr(offline_bot, "_post", make_assertion) await offline_bot.send_document(chat_id, file, thumbnail=file) diff --git a/tests/_files/test_photo.py b/tests/_files/test_photo.py index bdf34f72b4a..e83afe579f4 100644 --- a/tests/_files/test_photo.py +++ b/tests/_files/test_photo.py @@ -144,7 +144,9 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): assert await offline_bot.send_photo(chat_id, photo_file, filename="custom_filename") @pytest.mark.parametrize("local_mode", [True, False]) - async def test_send_photo_local_files(self, monkeypatch, offline_bot, chat_id, local_mode): + async def test_send_photo_local_files( + self, dummy_message_dict, monkeypatch, offline_bot, chat_id, local_mode + ): try: offline_bot._local_mode = local_mode # For just test that the correct paths are passed as we have no local Bot API set up @@ -158,6 +160,7 @@ async def make_assertion(_, data, *args, **kwargs): test_flag = data.get("photo") == expected else: test_flag = isinstance(data.get("photo"), InputFile) + return dummy_message_dict monkeypatch.setattr(offline_bot, "_post", make_assertion) await offline_bot.send_photo(chat_id, file) diff --git a/tests/_files/test_sticker.py b/tests/_files/test_sticker.py index 07cf2e932c3..a7a532308dd 100644 --- a/tests/_files/test_sticker.py +++ b/tests/_files/test_sticker.py @@ -256,7 +256,9 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): assert await offline_bot.send_sticker(sticker=sticker, chat_id=chat_id) @pytest.mark.parametrize("local_mode", [True, False]) - async def test_send_sticker_local_files(self, monkeypatch, offline_bot, chat_id, local_mode): + async def test_send_sticker_local_files( + self, dummy_message_dict, monkeypatch, offline_bot, chat_id, local_mode + ): try: offline_bot._local_mode = local_mode # For just test that the correct paths are passed as we have no local Bot API set up @@ -270,6 +272,7 @@ async def make_assertion(_, data, *args, **kwargs): test_flag = data.get("sticker") == expected else: test_flag = isinstance(data.get("sticker"), InputFile) + return dummy_message_dict monkeypatch.setattr(offline_bot, "_post", make_assertion) await offline_bot.send_sticker(chat_id, file) @@ -581,6 +584,7 @@ async def make_assertion(_, data, *args, **kwargs): if local_mode else isinstance(data.get("sticker"), InputFile) ) + return File(file_id="file_id", file_unique_id="file_unique_id").to_dict() monkeypatch.setattr(offline_bot, "_post", make_assertion) await offline_bot.upload_sticker_file( diff --git a/tests/_files/test_video.py b/tests/_files/test_video.py index 66230389f7e..d13483ee6c2 100644 --- a/tests/_files/test_video.py +++ b/tests/_files/test_video.py @@ -157,7 +157,9 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): assert await offline_bot.send_video(chat_id, video_file, filename="custom_filename") @pytest.mark.parametrize("local_mode", [True, False]) - async def test_send_video_local_files(self, monkeypatch, offline_bot, chat_id, local_mode): + async def test_send_video_local_files( + self, dummy_message_dict, monkeypatch, offline_bot, chat_id, local_mode + ): try: offline_bot._local_mode = local_mode # For just test that the correct paths are passed as we have no local Bot API set up @@ -173,6 +175,7 @@ async def make_assertion(_, data, *args, **kwargs): test_flag = isinstance(data.get("video"), InputFile) and isinstance( data.get("thumbnail"), InputFile ) + return dummy_message_dict monkeypatch.setattr(offline_bot, "_post", make_assertion) await offline_bot.send_video(chat_id, file, thumbnail=file) diff --git a/tests/_files/test_videonote.py b/tests/_files/test_videonote.py index ce69fa8f850..9f2ef7a35ce 100644 --- a/tests/_files/test_videonote.py +++ b/tests/_files/test_videonote.py @@ -157,7 +157,7 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): @pytest.mark.parametrize("local_mode", [True, False]) async def test_send_video_note_local_files( - self, monkeypatch, offline_bot, chat_id, local_mode + self, monkeypatch, offline_bot, chat_id, local_mode, dummy_message_dict ): try: offline_bot._local_mode = local_mode @@ -176,6 +176,7 @@ async def make_assertion(_, data, *args, **kwargs): test_flag = isinstance(data.get("video_note"), InputFile) and isinstance( data.get("thumbnail"), InputFile ) + return dummy_message_dict monkeypatch.setattr(offline_bot, "_post", make_assertion) await offline_bot.send_video_note(chat_id, file, thumbnail=file) diff --git a/tests/_files/test_voice.py b/tests/_files/test_voice.py index e32bb195c8e..7516e0f9bdf 100644 --- a/tests/_files/test_voice.py +++ b/tests/_files/test_voice.py @@ -145,7 +145,9 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): assert await offline_bot.send_voice(chat_id, voice=voice) @pytest.mark.parametrize("local_mode", [True, False]) - async def test_send_voice_local_files(self, monkeypatch, offline_bot, chat_id, local_mode): + async def test_send_voice_local_files( + self, dummy_message_dict, monkeypatch, offline_bot, chat_id, local_mode + ): try: offline_bot._local_mode = local_mode # For just test that the correct paths are passed as we have no local Bot API set up @@ -159,6 +161,7 @@ async def make_assertion(_, data, *args, **kwargs): test_flag = data.get("voice") == expected else: test_flag = isinstance(data.get("voice"), InputFile) + return dummy_message_dict monkeypatch.setattr(offline_bot, "_post", make_assertion) await offline_bot.send_voice(chat_id, file) diff --git a/tests/_games/test_gamehighscore.py b/tests/_games/test_gamehighscore.py index c07488c80fc..488f1b3fe01 100644 --- a/tests/_games/test_gamehighscore.py +++ b/tests/_games/test_gamehighscore.py @@ -55,8 +55,6 @@ def test_de_json(self, offline_bot): assert highscore.user == self.user assert highscore.score == self.score - assert GameHighScore.de_json(None, offline_bot) is None - def test_to_dict(self, game_highscore): game_highscore_dict = game_highscore.to_dict() diff --git a/tests/_inline/test_inlinekeyboardbutton.py b/tests/_inline/test_inlinekeyboardbutton.py index a71e774898d..bb2e004ad86 100644 --- a/tests/_inline/test_inlinekeyboardbutton.py +++ b/tests/_inline/test_inlinekeyboardbutton.py @@ -159,9 +159,6 @@ def test_de_json(self, offline_bot): ) assert inline_keyboard_button.copy_text == self.copy_text - none = InlineKeyboardButton.de_json({}, offline_bot) - assert none is None - def test_equality(self): a = InlineKeyboardButton("text", callback_data="data") b = InlineKeyboardButton("text", callback_data="data") diff --git a/tests/_inline/test_inputinvoicemessagecontent.py b/tests/_inline/test_inputinvoicemessagecontent.py index 4e35e9f6f43..52fc8882ca5 100644 --- a/tests/_inline/test_inputinvoicemessagecontent.py +++ b/tests/_inline/test_inputinvoicemessagecontent.py @@ -204,7 +204,6 @@ def test_to_dict(self, input_invoice_message_content): ) def test_de_json(self, offline_bot): - assert InputInvoiceMessageContent.de_json({}, bot=offline_bot) is None json_dict = { "title": self.title, diff --git a/tests/_payment/stars/test_affiliateinfo.py b/tests/_payment/stars/test_affiliateinfo.py index 9a199b69491..33da23378c7 100644 --- a/tests/_payment/stars/test_affiliateinfo.py +++ b/tests/_payment/stars/test_affiliateinfo.py @@ -64,9 +64,6 @@ def test_de_json(self, offline_bot): assert ai.amount == self.amount assert ai.nanostar_amount == self.nanostar_amount - assert AffiliateInfo.de_json(None, offline_bot) is None - assert AffiliateInfo.de_json({}, offline_bot) is None - def test_to_dict(self, affiliate_info): ai_dict = affiliate_info.to_dict() diff --git a/tests/_payment/stars/test_revenuewithdrawelstate.py b/tests/_payment/stars/test_revenuewithdrawelstate.py index 5ff8fddc2fe..b4a0d0375b3 100644 --- a/tests/_payment/stars/test_revenuewithdrawelstate.py +++ b/tests/_payment/stars/test_revenuewithdrawelstate.py @@ -77,9 +77,6 @@ def test_de_json(self, offline_bot): assert rws.api_kwargs == {} assert rws.type == "unknown" - assert RevenueWithdrawalState.de_json(None, offline_bot) is None - assert RevenueWithdrawalState.de_json({}, offline_bot) is None - @pytest.mark.parametrize( ("state", "subclass"), [ @@ -129,8 +126,6 @@ def test_de_json(self, offline_bot): assert rws.api_kwargs == {} assert rws.type == "pending" - assert RevenueWithdrawalStatePending.de_json(None, offline_bot) is None - def test_to_dict(self, revenue_withdrawal_state_pending): json_dict = revenue_withdrawal_state_pending.to_dict() assert json_dict == {"type": "pending"} @@ -168,8 +163,6 @@ def test_de_json(self, offline_bot): assert rws.date == self.date assert rws.url == self.url - assert RevenueWithdrawalStateSucceeded.de_json(None, offline_bot) is None - def test_to_dict(self, revenue_withdrawal_state_succeeded): json_dict = revenue_withdrawal_state_succeeded.to_dict() assert json_dict["type"] == "succeeded" @@ -213,8 +206,6 @@ def test_de_json(self, offline_bot): assert rws.api_kwargs == {} assert rws.type == "failed" - assert RevenueWithdrawalStateFailed.de_json(None, offline_bot) is None - def test_to_dict(self, revenue_withdrawal_state_failed): json_dict = revenue_withdrawal_state_failed.to_dict() assert json_dict == {"type": "failed"} diff --git a/tests/_payment/stars/test_startransactions.py b/tests/_payment/stars/test_startransactions.py index 71d706b8636..0f91e9023df 100644 --- a/tests/_payment/stars/test_startransactions.py +++ b/tests/_payment/stars/test_startransactions.py @@ -89,7 +89,6 @@ def test_de_json(self, offline_bot): "receiver": self.receiver.to_dict(), } st = StarTransaction.de_json(json_dict, offline_bot) - st_none = StarTransaction.de_json(None, offline_bot) assert st.api_kwargs == {} assert st.id == self.id assert st.amount == self.amount @@ -97,7 +96,6 @@ def test_de_json(self, offline_bot): assert st.date == from_timestamp(self.date) assert st.source == self.source assert st.receiver == self.receiver - assert st_none is None def test_de_json_star_transaction_localization( self, tz_bot, offline_bot, raw_bot, star_transaction @@ -178,10 +176,8 @@ def test_de_json(self, offline_bot): "transactions": [t.to_dict() for t in self.transactions], } st = StarTransactions.de_json(json_dict, offline_bot) - st_none = StarTransactions.de_json(None, offline_bot) assert st.api_kwargs == {} assert st.transactions == tuple(self.transactions) - assert st_none is None def test_to_dict(self, star_transactions): expected_dict = { diff --git a/tests/_payment/stars/test_transactionpartner.py b/tests/_payment/stars/test_transactionpartner.py index 0982700cfdd..511ad87a05e 100644 --- a/tests/_payment/stars/test_transactionpartner.py +++ b/tests/_payment/stars/test_transactionpartner.py @@ -114,9 +114,6 @@ def test_de_json(self, offline_bot): assert transaction_partner.api_kwargs == {} assert transaction_partner.type == "unknown" - assert TransactionPartner.de_json(None, offline_bot) is None - assert TransactionPartner.de_json({}, offline_bot) is None - @pytest.mark.parametrize( ("tp_type", "subclass"), [ @@ -191,9 +188,6 @@ def test_de_json(self, offline_bot): assert tp.commission_per_mille == self.commission_per_mille assert tp.sponsor_user == self.sponsor_user - assert TransactionPartnerAffiliateProgram.de_json(None, offline_bot) is None - assert TransactionPartnerAffiliateProgram.de_json({}, offline_bot) is None - def test_to_dict(self, transaction_partner_affiliate_program): json_dict = transaction_partner_affiliate_program.to_dict() assert json_dict["type"] == self.type @@ -243,8 +237,6 @@ def test_de_json(self, offline_bot): assert tp.type == "fragment" assert tp.withdrawal_state == self.withdrawal_state - assert TransactionPartnerFragment.de_json(None, offline_bot) is None - def test_to_dict(self, transaction_partner_fragment): json_dict = transaction_partner_fragment.to_dict() assert json_dict["type"] == self.type @@ -303,9 +295,6 @@ def test_de_json(self, offline_bot): assert tp.paid_media_payload == self.paid_media_payload assert tp.subscription_period == self.subscription_period - assert TransactionPartnerUser.de_json(None, offline_bot) is None - assert TransactionPartnerUser.de_json({}, offline_bot) is None - def test_to_dict(self, transaction_partner_user): json_dict = transaction_partner_user.to_dict() assert json_dict["type"] == self.type @@ -355,8 +344,6 @@ def test_de_json(self, offline_bot): assert tp.api_kwargs == {} assert tp.type == "other" - assert TransactionPartnerOther.de_json(None, offline_bot) is None - def test_to_dict(self, transaction_partner_other): json_dict = transaction_partner_other.to_dict() assert json_dict == {"type": self.type} @@ -397,8 +384,6 @@ def test_de_json(self, offline_bot): assert tp.api_kwargs == {} assert tp.type == "telegram_ads" - assert TransactionPartnerTelegramAds.de_json(None, offline_bot) is None - def test_to_dict(self, transaction_partner_telegram_ads): json_dict = transaction_partner_telegram_ads.to_dict() assert json_dict == {"type": self.type} @@ -442,8 +427,6 @@ def test_de_json(self, offline_bot): assert tp.type == "telegram_api" assert tp.request_count == self.request_count - assert TransactionPartnerTelegramApi.de_json(None, offline_bot) is None - def test_to_dict(self, transaction_partner_telegram_api): json_dict = transaction_partner_telegram_api.to_dict() assert json_dict["type"] == self.type diff --git a/tests/conftest.py b/tests/conftest.py index 7147fa8f765..9f67e91db99 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -37,7 +37,7 @@ User, ) from telegram.ext import Defaults -from tests.auxil.build_messages import DATE +from tests.auxil.build_messages import DATE, make_message from tests.auxil.ci_bots import BOT_INFO_PROVIDER, JOB_INDEX from tests.auxil.constants import PRIVATE_KEY, TEST_TOPIC_ICON_COLOR, TEST_TOPIC_NAME from tests.auxil.envvars import GITHUB_ACTION, RUN_TEST_OFFICIAL, TEST_WITH_OPT_DEPS @@ -324,3 +324,13 @@ def timezone(tzinfo): @pytest.fixture def tmp_file(tmp_path) -> Path: return tmp_path / uuid4().hex + + +@pytest.fixture(scope="session") +def dummy_message(): + return make_message("dummy_message") + + +@pytest.fixture(scope="session") +def dummy_message_dict(dummy_message): + return dummy_message.to_dict() diff --git a/tests/test_bot.py b/tests/test_bot.py index 7977efec36c..e3ddf7e6ff5 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -43,6 +43,7 @@ Chat, ChatAdministratorRights, ChatFullInfo, + ChatInviteLink, ChatPermissions, Dice, InlineKeyboardButton, @@ -1432,7 +1433,9 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): ) @pytest.mark.parametrize("local_mode", [True, False]) - async def test_set_chat_photo_local_files(self, monkeypatch, offline_bot, chat_id, local_mode): + async def test_set_chat_photo_local_files( + self, dummy_message_dict, monkeypatch, offline_bot, chat_id, local_mode + ): try: offline_bot._local_mode = local_mode # For just test that the correct paths are passed as we have no local Bot API set up @@ -2228,14 +2231,31 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): api_kwargs={"chat_id": 2, "user_id": 32, "until_date": until_timestamp}, ) - async def test_business_connection_id_argument(self, offline_bot, monkeypatch): + async def test_business_connection_id_argument( + self, offline_bot, monkeypatch, dummy_message_dict + ): """We can't connect to a business acc, so we just test that the correct data is passed. We also can't test every single method easily, so we just test a few. Our linting will catch any unused args with the others.""" + return_values = asyncio.Queue() + await return_values.put(dummy_message_dict) + await return_values.put( + Poll( + id="42", + question="question", + options=[PollOption("option", 0)], + total_voter_count=5, + is_closed=True, + is_anonymous=True, + type="regular", + ).to_dict() + ) + await return_values.put(True) + await return_values.put(True) async def make_assertion(url, request_data: RequestData, *args, **kwargs): assert request_data.parameters.get("business_connection_id") == 42 - return {} + return await return_values.get() monkeypatch.setattr(offline_bot.request, "post", make_assertion) @@ -2348,6 +2368,9 @@ async def test_create_chat_subscription_invite_link( async def make_assertion(url, request_data: RequestData, *args, **kwargs): assert request_data.parameters.get("subscription_period") == 2592000 assert request_data.parameters.get("subscription_price") == 6 + return ChatInviteLink( + "https://t.me/joinchat/invite_link", User(1, "first", False), False, False, False + ).to_dict() monkeypatch.setattr(offline_bot.request, "post", make_assertion) diff --git a/tests/test_botcommand.py b/tests/test_botcommand.py index f38abb320ab..9c63471cd13 100644 --- a/tests/test_botcommand.py +++ b/tests/test_botcommand.py @@ -45,8 +45,6 @@ def test_de_json(self, offline_bot): assert bot_command.command == self.command assert bot_command.description == self.description - assert BotCommand.de_json(None, offline_bot) is None - def test_to_dict(self, bot_command): bot_command_dict = bot_command.to_dict() diff --git a/tests/test_botcommandscope.py b/tests/test_botcommandscope.py index a4bddfc8f69..46141eeeb9a 100644 --- a/tests/test_botcommandscope.py +++ b/tests/test_botcommandscope.py @@ -129,8 +129,6 @@ def test_de_json(self, offline_bot, scope_class_and_type, chat_id): cls = scope_class_and_type[0] type_ = scope_class_and_type[1] - assert cls.de_json({}, offline_bot) is None - json_dict = {"type": type_, "chat_id": chat_id, "user_id": 42} bot_command_scope = BotCommandScope.de_json(json_dict, offline_bot) assert set(bot_command_scope.api_kwargs.keys()) == {"chat_id", "user_id"} - set( diff --git a/tests/test_chatbackground.py b/tests/test_chatbackground.py index ccf90d41147..39a1b4d1f3f 100644 --- a/tests/test_chatbackground.py +++ b/tests/test_chatbackground.py @@ -170,7 +170,6 @@ def test_slot_behaviour(self, background_type): def test_de_json_required_args(self, offline_bot, background_type): cls = background_type.__class__ - assert cls.de_json({}, offline_bot) is None json_dict = make_json_dict(background_type) const_background_type = BackgroundType.de_json(json_dict, offline_bot) @@ -277,7 +276,6 @@ def test_slot_behaviour(self, background_fill): def test_de_json_required_args(self, offline_bot, background_fill): cls = background_fill.__class__ - assert cls.de_json({}, offline_bot) is None json_dict = make_json_dict(background_fill) const_background_fill = BackgroundFill.de_json(json_dict, offline_bot) diff --git a/tests/test_chatboost.py b/tests/test_chatboost.py index 1f1d71ad56b..d83769702f0 100644 --- a/tests/test_chatboost.py +++ b/tests/test_chatboost.py @@ -174,8 +174,6 @@ def test_slot_behaviour(self, chat_boost_source): def test_de_json_required_args(self, offline_bot, chat_boost_source): cls = chat_boost_source.__class__ - assert cls.de_json({}, offline_bot) is None - assert ChatBoost.de_json({}, offline_bot) is None json_dict = make_json_dict(chat_boost_source) const_boost_source = ChatBoostSource.de_json(json_dict, offline_bot) diff --git a/tests/test_chatmember.py b/tests/test_chatmember.py index a9f3ebabe73..9df27235e21 100644 --- a/tests/test_chatmember.py +++ b/tests/test_chatmember.py @@ -207,7 +207,6 @@ def test_slot_behaviour(self, chat_member_type): def test_de_json_required_args(self, offline_bot, chat_member_type): cls = chat_member_type.__class__ - assert cls.de_json({}, offline_bot) is None json_dict = make_json_dict(chat_member_type) const_chat_member = ChatMember.de_json(json_dict, offline_bot) diff --git a/tests/test_copytextbutton.py b/tests/test_copytextbutton.py index 7092456d490..8bdf879c1ce 100644 --- a/tests/test_copytextbutton.py +++ b/tests/test_copytextbutton.py @@ -46,7 +46,6 @@ def test_de_json(self, offline_bot): assert copy_text_button.api_kwargs == {} assert copy_text_button.text == self.text - assert CopyTextButton.de_json(None, offline_bot) is None def test_to_dict(self, copy_text_button): copy_text_button_dict = copy_text_button.to_dict() diff --git a/tests/test_dice.py b/tests/test_dice.py index de82d29aef0..95b000e7e57 100644 --- a/tests/test_dice.py +++ b/tests/test_dice.py @@ -46,7 +46,6 @@ def test_de_json(self, offline_bot, emoji): assert dice.value == self.value assert dice.emoji == emoji - assert Dice.de_json(None, offline_bot) is None def test_to_dict(self, dice): dice_dict = dice.to_dict() diff --git a/tests/test_forum.py b/tests/test_forum.py index 2237742a40a..ef9c9f38b9f 100644 --- a/tests/test_forum.py +++ b/tests/test_forum.py @@ -60,7 +60,6 @@ async def test_expected_values(self, emoji_id, forum_group_id, forum_topic_objec assert forum_topic_object.icon_custom_emoji_id == emoji_id def test_de_json(self, offline_bot, emoji_id, forum_group_id): - assert ForumTopic.de_json(None, bot=offline_bot) is None json_dict = { "message_thread_id": forum_group_id, @@ -307,7 +306,6 @@ def test_expected_values(self, topic_created): assert topic_created.name == TEST_TOPIC_NAME def test_de_json(self, offline_bot): - assert ForumTopicCreated.de_json(None, bot=offline_bot) is None json_dict = {"icon_color": TEST_TOPIC_ICON_COLOR, "name": TEST_TOPIC_NAME} action = ForumTopicCreated.de_json(json_dict, offline_bot) @@ -395,8 +393,6 @@ def test_expected_values(self, topic_edited, emoji_id): assert topic_edited.icon_custom_emoji_id == emoji_id def test_de_json(self, bot, emoji_id): - assert ForumTopicEdited.de_json(None, bot=bot) is None - json_dict = {"name": TEST_TOPIC_NAME, "icon_custom_emoji_id": emoji_id} action = ForumTopicEdited.de_json(json_dict, bot) assert action.api_kwargs == {} diff --git a/tests/test_gifts.py b/tests/test_gifts.py index e7e13c75cef..b7300e0914b 100644 --- a/tests/test_gifts.py +++ b/tests/test_gifts.py @@ -76,8 +76,6 @@ def test_de_json(self, offline_bot, gift): assert gift.total_count == self.total_count assert gift.remaining_count == self.remaining_count - assert Gift.de_json(None, offline_bot) is None - def test_to_dict(self, gift): gift_dict = gift.to_dict() @@ -237,8 +235,6 @@ def test_de_json(self, offline_bot, gifts): assert de_json_gift.total_count == original_gift.total_count assert de_json_gift.remaining_count == original_gift.remaining_count - assert Gifts.de_json(None, offline_bot) is None - def test_to_dict(self, gifts): gifts_dict = gifts.to_dict() diff --git a/tests/test_giveaway.py b/tests/test_giveaway.py index 3ef8bb7a1df..35228d5e5ef 100644 --- a/tests/test_giveaway.py +++ b/tests/test_giveaway.py @@ -94,8 +94,6 @@ def test_de_json(self, offline_bot): assert giveaway.premium_subscription_month_count == self.premium_subscription_month_count assert giveaway.prize_star_count == self.prize_star_count - assert Giveaway.de_json(None, offline_bot) is None - def test_de_json_localization(self, tz_bot, offline_bot, raw_bot): json_dict = { "chats": [chat.to_dict() for chat in self.chats], @@ -196,8 +194,6 @@ def test_de_json(self, bot): assert gac.api_kwargs == {} assert gac.prize_star_count == self.prize_star_count - assert Giveaway.de_json(None, bot) is None - def test_to_dict(self, giveaway_created): gac_dict = giveaway_created.to_dict() @@ -281,8 +277,6 @@ def test_de_json(self, offline_bot): assert giveaway_winners.prize_description == self.prize_description assert giveaway_winners.prize_star_count == self.prize_star_count - assert GiveawayWinners.de_json(None, offline_bot) is None - def test_de_json_localization(self, tz_bot, offline_bot, raw_bot): json_dict = { "chat": self.chat.to_dict(), @@ -411,8 +405,6 @@ def test_de_json(self, offline_bot): assert giveaway_completed.giveaway_message == self.giveaway_message assert giveaway_completed.is_star_giveaway == self.is_star_giveaway - assert GiveawayCompleted.de_json(None, offline_bot) is None - def test_to_dict(self, giveaway_completed): giveaway_completed_dict = giveaway_completed.to_dict() diff --git a/tests/test_inlinequeryresultsbutton.py b/tests/test_inlinequeryresultsbutton.py index 1ec59573a3b..521afab1343 100644 --- a/tests/test_inlinequeryresultsbutton.py +++ b/tests/test_inlinequeryresultsbutton.py @@ -52,8 +52,6 @@ def test_to_dict(self, inline_query_results_button): assert inline_query_results_button_dict["web_app"] == self.web_app.to_dict() def test_de_json(self, offline_bot): - assert InlineQueryResultsButton.de_json(None, offline_bot) is None - assert InlineQueryResultsButton.de_json({}, offline_bot) is None json_dict = { "text": self.text, diff --git a/tests/test_keyboardbutton.py b/tests/test_keyboardbutton.py index 91f5ccab71f..42fdfeee81d 100644 --- a/tests/test_keyboardbutton.py +++ b/tests/test_keyboardbutton.py @@ -108,9 +108,6 @@ def test_de_json(self, request_user): assert keyboard_button.request_chat == self.request_chat assert keyboard_button.request_users == self.request_users - none = KeyboardButton.de_json({}, None) - assert none is None - def test_equality(self): a = KeyboardButton("test", request_contact=True) b = KeyboardButton("test", request_contact=True) diff --git a/tests/test_keyboardbuttonrequest.py b/tests/test_keyboardbuttonrequest.py index 9d9a0295206..f0484ea2056 100644 --- a/tests/test_keyboardbuttonrequest.py +++ b/tests/test_keyboardbuttonrequest.py @@ -179,9 +179,6 @@ def test_de_json(self, offline_bot): assert request_chat.bot_administrator_rights == self.bot_administrator_rights assert request_chat.bot_is_member == self.bot_is_member - empty_chat = KeyboardButtonRequestChat.de_json({}, offline_bot) - assert empty_chat is None - def test_equality(self): a = KeyboardButtonRequestChat(self.request_id, True) b = KeyboardButtonRequestChat(self.request_id, True) diff --git a/tests/test_menubutton.py b/tests/test_menubutton.py index d9ae7c1ef12..e03405066b6 100644 --- a/tests/test_menubutton.py +++ b/tests/test_menubutton.py @@ -119,9 +119,6 @@ def test_de_json(self, offline_bot, scope_class_and_type): if "text" in cls.__slots__: assert menu_button.text == self.text - assert cls.de_json(None, offline_bot) is None - assert MenuButton.de_json({}, offline_bot) is None - def test_de_json_invalid_type(self, offline_bot): json_dict = {"type": "invalid", "text": self.text, "web_app": self.web_app.to_dict()} menu_button = MenuButton.de_json(json_dict, offline_bot) diff --git a/tests/test_messageorigin.py b/tests/test_messageorigin.py index be85d73b391..0480795293c 100644 --- a/tests/test_messageorigin.py +++ b/tests/test_messageorigin.py @@ -138,7 +138,6 @@ def test_slot_behaviour(self, message_origin_type): def test_de_json_required_args(self, offline_bot, message_origin_type): cls = message_origin_type.__class__ - assert cls.de_json({}, offline_bot) is None json_dict = make_json_dict(message_origin_type) const_message_origin = MessageOrigin.de_json(json_dict, offline_bot) diff --git a/tests/test_paidmedia.py b/tests/test_paidmedia.py index ee2ea9f9636..77e91efcff7 100644 --- a/tests/test_paidmedia.py +++ b/tests/test_paidmedia.py @@ -193,9 +193,6 @@ def test_de_json(self, offline_bot, pm_scope_class_and_type): if "photo" in cls.__slots__: assert pm.photo == self.photo - assert cls.de_json(None, offline_bot) is None - assert PaidMedia.de_json({}, offline_bot) is None - def test_de_json_invalid_type(self, offline_bot): json_dict = { "type": "invalid", @@ -308,10 +305,8 @@ def test_de_json(self, offline_bot): "paid_media": [t.to_dict() for t in self.paid_media], } pmi = PaidMediaInfo.de_json(json_dict, offline_bot) - pmi_none = PaidMediaInfo.de_json(None, offline_bot) assert pmi.paid_media == tuple(self.paid_media) assert pmi.star_count == self.star_count - assert pmi_none is None def test_to_dict(self, paid_media_info): assert paid_media_info.to_dict() == { @@ -353,11 +348,9 @@ def test_de_json(self, bot): "paid_media_payload": self.paid_media_payload, } pmp = PaidMediaPurchased.de_json(json_dict, bot) - pmp_none = PaidMediaPurchased.de_json(None, bot) assert pmp.from_user == self.from_user assert pmp.paid_media_payload == self.paid_media_payload assert pmp.api_kwargs == {} - assert pmp_none is None def test_to_dict(self, paid_media_purchased): assert paid_media_purchased.to_dict() == { diff --git a/tests/test_poll.py b/tests/test_poll.py index 4d5304fdca5..134f0429c51 100644 --- a/tests/test_poll.py +++ b/tests/test_poll.py @@ -54,7 +54,6 @@ def test_slot_behaviour(self, input_poll_option): ), "duplicate slot" def test_de_json(self): - assert InputPollOption.de_json({}, None) is None json_dict = { "text": self.text, @@ -144,7 +143,7 @@ def test_de_json_all(self): "text_entities": [e.to_dict() for e in self.text_entities], } poll_option = PollOption.de_json(json_dict, None) - assert PollOption.de_json(None, None) is None + assert poll_option.api_kwargs == {} assert poll_option.text == self.text diff --git a/tests/test_reaction.py b/tests/test_reaction.py index 79f3e2c40be..fad9d2bb969 100644 --- a/tests/test_reaction.py +++ b/tests/test_reaction.py @@ -117,8 +117,6 @@ def test_slot_behaviour(self, reaction_type): def test_de_json_required_args(self, offline_bot, reaction_type): cls = reaction_type.__class__ - assert cls.de_json(None, offline_bot) is None - assert ReactionType.de_json({}, offline_bot) is None json_dict = make_json_dict(reaction_type) const_reaction_type = ReactionType.de_json(json_dict, offline_bot) @@ -252,8 +250,6 @@ def test_de_json(self, offline_bot): assert reaction_count.type.emoji == self.type.emoji assert reaction_count.total_count == self.total_count - assert ReactionCount.de_json(None, offline_bot) is None - def test_to_dict(self, reaction_count): reaction_count_dict = reaction_count.to_dict() diff --git a/tests/test_reply.py b/tests/test_reply.py index a450a721d7d..2030f9a6cb0 100644 --- a/tests/test_reply.py +++ b/tests/test_reply.py @@ -93,8 +93,6 @@ def test_de_json(self, offline_bot): assert external_reply_info.giveaway == self.giveaway assert external_reply_info.paid_media == self.paid_media - assert ExternalReplyInfo.de_json(None, offline_bot) is None - def test_to_dict(self, external_reply_info): ext_reply_info_dict = external_reply_info.to_dict() @@ -167,8 +165,6 @@ def test_de_json(self, offline_bot): assert text_quote.entities == tuple(self.entities) assert text_quote.is_manual == self.is_manual - assert TextQuote.de_json(None, offline_bot) is None - def test_to_dict(self, text_quote): text_quote_dict = text_quote.to_dict() @@ -255,8 +251,6 @@ def test_de_json(self, offline_bot): assert reply_parameters.quote_entities == tuple(self.quote_entities) assert reply_parameters.quote_position == self.quote_position - assert ReplyParameters.de_json(None, offline_bot) is None - def test_to_dict(self, reply_parameters): reply_parameters_dict = reply_parameters.to_dict() diff --git a/tests/test_shared.py b/tests/test_shared.py index 9cc8d4bcaa8..aa565d66606 100644 --- a/tests/test_shared.py +++ b/tests/test_shared.py @@ -59,8 +59,6 @@ def test_de_json(self, offline_bot): assert users_shared.request_id == self.request_id assert users_shared.users == self.users - assert UsersShared.de_json({}, offline_bot) is None - def test_equality(self): a = UsersShared(self.request_id, users=self.users) b = UsersShared(self.request_id, users=self.users) @@ -209,8 +207,6 @@ def test_de_json_all(self, offline_bot): assert shared_user.username == self.username assert shared_user.photo == self.photo - assert SharedUser.de_json({}, offline_bot) is None - def test_equality(self, chat_shared): a = SharedUser( self.user_id, diff --git a/tests/test_story.py b/tests/test_story.py index 190c4ec133c..51df3a7fcbf 100644 --- a/tests/test_story.py +++ b/tests/test_story.py @@ -45,7 +45,6 @@ def test_de_json(self, offline_bot): assert story.chat == self.chat assert story.id == self.id assert isinstance(story, Story) - assert Story.de_json(None, offline_bot) is None def test_to_dict(self, story): story_dict = story.to_dict() diff --git a/tests/test_telegramobject.py b/tests/test_telegramobject.py index 73d1e62e52c..18fb9672b9e 100644 --- a/tests/test_telegramobject.py +++ b/tests/test_telegramobject.py @@ -103,7 +103,7 @@ def __init__(self, arg: int, **kwargs): self._id_attrs = (self.arg,) - assert SubClass.de_list([{"arg": 1}, None, {"arg": 2}, None], bot) == ( + assert SubClass.de_list([{"arg": 1}, {"arg": 2}], bot) == ( SubClass(1), SubClass(2), ) diff --git a/tests/test_update.py b/tests/test_update.py index 0e91efcc998..baeff8b7499 100644 --- a/tests/test_update.py +++ b/tests/test_update.py @@ -252,11 +252,6 @@ def test_de_json(self, offline_bot, paramdict): assert getattr(update, _type) == paramdict[_type] assert i == 1 - def test_update_de_json_empty(self, offline_bot): - update = Update.de_json(None, offline_bot) - - assert update is None - def test_to_dict(self, update): update_dict = update.to_dict() diff --git a/tests/test_videochat.py b/tests/test_videochat.py index e5de669c672..6e527181fe9 100644 --- a/tests/test_videochat.py +++ b/tests/test_videochat.py @@ -162,7 +162,6 @@ def test_expected_values(self): assert VideoChatScheduled(self.start_date).start_date == self.start_date def test_de_json(self, offline_bot): - assert VideoChatScheduled.de_json({}, bot=offline_bot) is None json_dict = {"start_date": to_timestamp(self.start_date)} video_chat_scheduled = VideoChatScheduled.de_json(json_dict, offline_bot) diff --git a/tests/test_webhookinfo.py b/tests/test_webhookinfo.py index 4b6ab2ebb6c..c010ad61970 100644 --- a/tests/test_webhookinfo.py +++ b/tests/test_webhookinfo.py @@ -99,9 +99,6 @@ def test_de_json(self, offline_bot): self.last_synchronization_error_date ) - none = WebhookInfo.de_json(None, offline_bot) - assert none is None - def test_de_json_localization(self, offline_bot, raw_bot, tz_bot): json_dict = { "url": self.url, From ae639fbe8721cfcdc7613f6a3c24c97a87990e26 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Mon, 30 Dec 2024 13:57:17 +0100 Subject: [PATCH 03/14] Get defaults handling tests to run --- .gitignore | 1 + telegram/_poll.py | 2 +- tests/auxil/bot_method_checks.py | 64 ++++++++------ tests/auxil/dummy_objects.py | 145 +++++++++++++++++++++++++++++++ tests/auxil/pytest_classes.py | 4 +- tests/test_bot.py | 11 +-- 6 files changed, 190 insertions(+), 37 deletions(-) create mode 100644 tests/auxil/dummy_objects.py diff --git a/.gitignore b/.gitignore index 470d2a2aac1..9e944f66958 100644 --- a/.gitignore +++ b/.gitignore @@ -67,6 +67,7 @@ docs/_build/ # PyBuilder target/ .idea/ +.run/ # Sublime Text 2 *.sublime* diff --git a/telegram/_poll.py b/telegram/_poll.py index 5e89cfb5394..5380bdbe9d8 100644 --- a/telegram/_poll.py +++ b/telegram/_poll.py @@ -466,7 +466,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Poll": # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["options"] = [PollOption.de_json(option, bot) for option in data["options"]] + data["options"] = PollOption.de_list(data["options"], bot) data["explanation_entities"] = de_list_wo( data.get("explanation_entities"), MessageEntity, bot ) diff --git a/tests/auxil/bot_method_checks.py b/tests/auxil/bot_method_checks.py index dff21b0b440..3566bc61679 100644 --- a/tests/auxil/bot_method_checks.py +++ b/tests/auxil/bot_method_checks.py @@ -22,7 +22,8 @@ import inspect import re from collections.abc import Collection, Iterable -from typing import Any, Callable, Optional +from types import GenericAlias +from typing import Any, Callable, ForwardRef, Optional, Union import pytest @@ -30,7 +31,6 @@ from telegram import ( Bot, ChatPermissions, - File, InlineQueryResultArticle, InlineQueryResultCachedPhoto, InputMediaPhoto, @@ -44,6 +44,7 @@ from telegram.constants import InputMediaType from telegram.ext import Defaults, ExtBot from telegram.request import RequestData +from tests.auxil.dummy_objects import get_dummy_object_json_dict from tests.auxil.envvars import TEST_WITH_OPT_DEPS if TEST_WITH_OPT_DEPS: @@ -261,10 +262,6 @@ async def make_assertion(**kw): f"{expected_args - received_kwargs}" ) - if bot_method_name == "get_file": - # This is here mainly for PassportFile.get_file, which calls .set_credentials on the - # return value - return File(file_id="result", file_unique_id="result") return True setattr(bot, bot_method_name, make_assertion) @@ -395,6 +392,34 @@ def make_assertion_for_link_preview_options( ) +def _check_forward_ref(obj: object) -> Union[str, object]: + if isinstance(obj, ForwardRef): + return obj.__forward_arg__ + return obj + + +def guess_return_type_name(method: Callable[[...], Any]) -> tuple[Union[str, object], bool]: + # Using typing.get_type_hints(method) would be the nicer as it also resolves ForwardRefs + # and string annotations. But it also wants to resolve the parameter annotations, which + # need additional namespaces and that's not worth the struggle for now … + return_annotation = _check_forward_ref(inspect.signature(method).return_annotation) + print(return_annotation, type(return_annotation)) + as_tuple = False + + if isinstance(return_annotation, GenericAlias): + if return_annotation.__origin__ is tuple: + as_tuple = True + else: + raise ValueError( + f"Return type of {method.__name__} is a GenericAlias. This can not be handled yet." + ) + + # For tuples and Unions, we simply take the first element + if hasattr(return_annotation, "__args__"): + return _check_forward_ref(return_annotation.__args__[0]), as_tuple + return return_annotation, as_tuple + + async def make_assertion( url, request_data: RequestData, @@ -539,15 +564,6 @@ def check_input_media(m: dict): if default_value_expected and until_date != 946702800: pytest.fail("Naive until_date should have been interpreted as America/New_York") - if method_name in ["get_file", "get_small_file", "get_big_file"]: - # This is here mainly for PassportFile.get_file, which calls .set_credentials on the - # return value - out = File(file_id="result", file_unique_id="result") - return out.to_dict() - # Otherwise return None by default, as TGObject.de_json/list(None) in [None, []] - # That way we can check what gets passed to Request.post without having to actually - # make a request - # Some methods expect specific output, so we allow to customize that if isinstance(return_value, TelegramObject): return return_value.to_dict() return return_value @@ -556,7 +572,6 @@ def check_input_media(m: dict): async def check_defaults_handling( method: Callable, bot: Bot, - return_value=None, no_default_kwargs: Collection[str] = frozenset(), ) -> bool: """ @@ -566,13 +581,12 @@ async def check_defaults_handling( method: The shortcut/bot_method bot: The bot. May be a telegram.Bot or a telegram.ext.ExtBot. In the former case, all default values will be converted to None. - return_value: Optional. The return value of Bot._post that the method expects. Defaults to - None. get_file is automatically handled. If this is a `TelegramObject`, Bot._post will - return the `to_dict` representation of it. no_default_kwargs: Optional. A collection of keyword arguments that should not have default values. Defaults to an empty frozenset. """ + guess_return_type_name(method) + raw_bot = not isinstance(bot, ExtBot) get_updates = method.__name__.lower().replace("_", "") == "getupdates" @@ -604,12 +618,10 @@ async def check_defaults_handling( ) defaults_custom_defaults = Defaults(**kwargs) - expected_return_values = [None, ()] if return_value is None else [return_value] - if method.__name__ in ["get_file", "get_small_file", "get_big_file"]: - expected_return_values = [File(file_id="result", file_unique_id="result")] - request = bot._request[0] if get_updates else bot.request orig_post = request.post + return_value = get_dummy_object_json_dict(*guess_return_type_name(method)) + try: if raw_bot: combinations = [(None, None)] @@ -633,7 +645,7 @@ async def check_defaults_handling( expected_defaults_value=expected_defaults_value, ) request.post = assertion_callback - assert await method(**kwargs) in expected_return_values + await method(**kwargs) # 2: test that we get the manually passed non-None value kwargs = build_kwargs( @@ -648,7 +660,7 @@ async def check_defaults_handling( expected_defaults_value=expected_defaults_value, ) request.post = assertion_callback - assert await method(**kwargs) in expected_return_values + await method(**kwargs) # 3: test that we get the manually passed None value kwargs = build_kwargs( @@ -663,7 +675,7 @@ async def check_defaults_handling( expected_defaults_value=expected_defaults_value, ) request.post = assertion_callback - assert await method(**kwargs) in expected_return_values + await method(**kwargs) except Exception as exc: raise exc finally: diff --git a/tests/auxil/dummy_objects.py b/tests/auxil/dummy_objects.py new file mode 100644 index 00000000000..23525ad7c5f --- /dev/null +++ b/tests/auxil/dummy_objects.py @@ -0,0 +1,145 @@ +import datetime as dtm +from collections.abc import Sequence +from typing import Union + +from telegram import ( + BotCommand, + BotDescription, + BotName, + BotShortDescription, + BusinessConnection, + ChatAdministratorRights, + ChatFullInfo, + ChatInviteLink, + ChatMember, + File, + ForumTopic, + GameHighScore, + Gifts, + MenuButton, + MessageId, + Poll, + PollOption, + PreparedInlineMessage, + SentWebAppMessage, + StarTransactions, + Sticker, + StickerSet, + TelegramObject, + Update, + User, + UserChatBoosts, + UserProfilePhotos, + WebhookInfo, +) +from tests.auxil.build_messages import make_message + +_DUMMY_USER = User( + id=123456, is_bot=False, first_name="Dummy", last_name="User", username="dummy_user" +) +_DUMMY_DATE = dtm.datetime(1970, 1, 1, 0, 0, 0, 0, tzinfo=dtm.timezone.utc) + +_PREPARED_DUMMY_OBJECTS: dict[str, object] = { + "bool": True, + "BotCommand": BotCommand(command="dummy_command", description="dummy_description"), + "BotDescription": BotDescription(description="dummy_description"), + "BotName": BotName(name="dummy_name"), + "BotShortDescription": BotShortDescription(short_description="dummy_short_description"), + "BusinessConnection": BusinessConnection( + user=_DUMMY_USER, + id="123", + user_chat_id=123456, + date=_DUMMY_DATE, + can_reply=True, + is_enabled=True, + ), + "ChatAdministratorRights": ChatAdministratorRights.all_rights(), + "ChatFullInfo": ChatFullInfo( + id=123456, + type="dummy_type", + accent_color_id=1, + max_reaction_count=1, + ), + "ChatInviteLink": ChatInviteLink( + "dummy_invite_link", + creator=_DUMMY_USER, + is_primary=True, + is_revoked=False, + creates_join_request=False, + ), + "ChatMember": ChatMember(user=_DUMMY_USER, status="dummy_status"), + "File": File(file_id="dummy_file_id", file_unique_id="dummy_file_unique_id"), + "ForumTopic": ForumTopic(message_thread_id=2, name="dummy_name", icon_color=1), + "Gifts": Gifts(gifts=[]), + "GameHighScore": GameHighScore(position=1, user=_DUMMY_USER, score=1), + "int": 123456, + "MenuButton": MenuButton(type="dummy_type"), + "Message": make_message("dummy_text"), + "MessageId": MessageId(123456), + "Poll": Poll( + id="dummy_id", + question="dummy_question", + options=[PollOption(text="dummy_text", voter_count=1)], + is_closed=False, + is_anonymous=False, + total_voter_count=1, + type="dummy_type", + allows_multiple_answers=False, + ), + "PreparedInlineMessage": PreparedInlineMessage(id="dummy_id", expiration_date=_DUMMY_DATE), + "SentWebAppMessage": SentWebAppMessage(inline_message_id="dummy_inline_message_id"), + "StarTransactions": StarTransactions(transactions=[]), + "Sticker": Sticker( + file_id="dummy_file_id", + file_unique_id="dummy_file_unique_id", + width=1, + height=1, + is_animated=False, + is_video=False, + type="dummy_type", + ), + "StickerSet": StickerSet( + name="dummy_name", title="dummy_title", stickers=[], sticker_type="dummy_type" + ), + "str": "dummy_string", + "Update": Update(update_id=123456), + "User": _DUMMY_USER, + "UserChatBoosts": UserChatBoosts(boosts=[]), + "UserProfilePhotos": UserProfilePhotos(total_count=1, photos=[[]]), + "WebhookInfo": WebhookInfo( + url="dummy_url", + has_custom_certificate=False, + pending_update_count=1, + ), +} + + +def get_dummy_object(obj_type: Union[type, str], as_tuple: bool = False) -> object: + obj_type_name = obj_type.__name__ if isinstance(obj_type, type) else obj_type + if (return_value := _PREPARED_DUMMY_OBJECTS.get(obj_type_name)) is None: + raise ValueError( + f"Dummy object of type '{obj_type_name}' not found. Please add it manually." + ) + + if as_tuple: + return (return_value,) + return return_value + + +_RETURN_TYPES = Union[bool, int, str, dict[str, object]] +_RETURN_TYPE = Union[_RETURN_TYPES, tuple[_RETURN_TYPES, ...]] + + +def _serialize_dummy_object(obj: object) -> _RETURN_TYPE: + if isinstance(obj, Sequence) and not isinstance(obj, str): + return tuple(_serialize_dummy_object(item) for item in obj) + if isinstance(obj, (str, int, bool)): + return obj + if isinstance(obj, TelegramObject): + return obj.to_dict() + + raise ValueError(f"Serialization of object of type '{type(obj)}' is not supported yet.") + + +def get_dummy_object_json_dict(obj_type: Union[type, str], as_tuple: bool = False) -> _RETURN_TYPE: + return _serialize_dummy_object(get_dummy_object(obj_type, as_tuple=as_tuple)) diff --git a/tests/auxil/pytest_classes.py b/tests/auxil/pytest_classes.py index f85e12ac23c..f44d51f31a3 100644 --- a/tests/auxil/pytest_classes.py +++ b/tests/auxil/pytest_classes.py @@ -66,7 +66,7 @@ def __init__(self, *args, **kwargs): self._unfreeze() # Here we override get_me for caching because we don't want to call the API repeatedly in tests - async def get_me(self, *args, **kwargs): + async def get_me(self, *args, **kwargs) -> User: return await _mocked_get_me(self) @@ -77,7 +77,7 @@ def __init__(self, *args, **kwargs): self._unfreeze() # Here we override get_me for caching because we don't want to call the API repeatedly in tests - async def get_me(self, *args, **kwargs): + async def get_me(self, *args, **kwargs) -> User: return await _mocked_get_me(self) diff --git a/tests/test_bot.py b/tests/test_bot.py index e3ddf7e6ff5..4124dd15a83 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -488,17 +488,11 @@ async def test_defaults_handling( Finally, there are some tests for Defaults.{parse_mode, quote, allow_sending_without_reply} at the appropriate places, as those are the only things we can actually check. """ - # Mocking get_me within check_defaults_handling messes with the cached values like - # Bot.{bot, username, id, …}` unless we return the expected User object. - return_value = ( - offline_bot.bot if bot_method_name.lower().replace("_", "") == "getme" else None - ) - # Check that ExtBot does the right thing bot_method = getattr(offline_bot, bot_method_name) raw_bot_method = getattr(raw_bot, bot_method_name) - assert await check_defaults_handling(bot_method, offline_bot, return_value=return_value) - assert await check_defaults_handling(raw_bot_method, raw_bot, return_value=return_value) + assert await check_defaults_handling(bot_method, offline_bot) + assert await check_defaults_handling(raw_bot_method, raw_bot) @pytest.mark.parametrize( ("name", "method"), inspect.getmembers(Bot, predicate=inspect.isfunction) @@ -2248,6 +2242,7 @@ async def test_business_connection_id_argument( is_closed=True, is_anonymous=True, type="regular", + allows_multiple_answers=False, ).to_dict() ) await return_values.put(True) From 3fe033d30aca40b0772702b2483a522c65240d12 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Mon, 30 Dec 2024 14:09:46 +0100 Subject: [PATCH 04/14] Use `de_list` instead of `de_list_wo` for required args --- telegram/_business.py | 6 ++---- telegram/_chatboost.py | 4 ++-- telegram/_files/sticker.py | 4 ++-- telegram/_games/game.py | 2 +- telegram/_gifts.py | 4 ++-- telegram/_giveaway.py | 6 +++--- telegram/_inline/inputinvoicemessagecontent.py | 4 ++-- telegram/_messagereactionupdated.py | 8 ++++---- telegram/_paidmedia.py | 6 +++--- telegram/_passport/passportdata.py | 4 ++-- telegram/_payment/stars/startransactions.py | 4 ++-- telegram/_reply.py | 6 +++--- telegram/_shared.py | 2 +- 13 files changed, 29 insertions(+), 31 deletions(-) diff --git a/telegram/_business.py b/telegram/_business.py index 24b800d13ea..2bb86b1264a 100644 --- a/telegram/_business.py +++ b/telegram/_business.py @@ -27,7 +27,7 @@ from telegram._files.sticker import Sticker from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -423,8 +423,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessOpenin """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["opening_hours"] = de_list_wo( - data.get("opening_hours"), BusinessOpeningHoursInterval, bot - ) + data["opening_hours"] = BusinessOpeningHoursInterval.de_list(data["opening_hours"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatboost.py b/telegram/_chatboost.py index f2140323be4..9c0e14ecd2c 100644 --- a/telegram/_chatboost.py +++ b/telegram/_chatboost.py @@ -26,7 +26,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -434,6 +434,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "UserChatBoosts """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["boosts"] = de_list_wo(data.get("boosts"), ChatBoost, bot) + data["boosts"] = ChatBoost.de_list(data["boosts"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_files/sticker.py b/telegram/_files/sticker.py index 1cd24c8f1e5..fbc6a81b048 100644 --- a/telegram/_files/sticker.py +++ b/telegram/_files/sticker.py @@ -26,7 +26,7 @@ from telegram._files.photosize import PhotoSize from telegram._telegramobject import TelegramObject from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -307,7 +307,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "StickerSet": """See :meth:`telegram.TelegramObject.de_json`.""" data["thumbnail"] = de_json_wo(data.get("thumbnail"), PhotoSize, bot) - data["stickers"] = de_list_wo(data.get("stickers"), Sticker, bot) + data["stickers"] = Sticker.de_list(data["stickers"], bot) api_kwargs = {} # These are deprecated fields that TG still returns for backwards compatibility diff --git a/telegram/_games/game.py b/telegram/_games/game.py index 2d544e2c5b3..814a8f814be 100644 --- a/telegram/_games/game.py +++ b/telegram/_games/game.py @@ -128,7 +128,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Game": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) + data["photo"] = PhotoSize.de_list(data["photo"], bot) data["text_entities"] = de_list_wo(data.get("text_entities"), MessageEntity, bot) data["animation"] = de_json_wo(data.get("animation"), Animation, bot) diff --git a/telegram/_gifts.py b/telegram/_gifts.py index 1b57ea97a1e..0bb847ee3fd 100644 --- a/telegram/_gifts.py +++ b/telegram/_gifts.py @@ -23,7 +23,7 @@ from telegram._files.sticker import Sticker from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -126,5 +126,5 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Gifts": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["gifts"] = de_list_wo(data.get("gifts"), Gift, bot) + data["gifts"] = Gifts.de_list(data["gifts"], bot) return cls(**data) diff --git a/telegram/_giveaway.py b/telegram/_giveaway.py index 0344b605cfc..95bc0ea03d6 100644 --- a/telegram/_giveaway.py +++ b/telegram/_giveaway.py @@ -24,7 +24,7 @@ from telegram._chat import Chat from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -144,7 +144,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Giveaway": # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chats"] = tuple(de_list_wo(data.get("chats"), Chat, bot)) + data["chats"] = Chat.de_list(data["chats"], bot) data["winners_selection_date"] = from_timestamp( data.get("winners_selection_date"), tzinfo=loc_tzinfo ) @@ -302,7 +302,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "GiveawayWinner loc_tzinfo = extract_tzinfo_from_defaults(bot) data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["winners"] = tuple(de_list_wo(data.get("winners"), User, bot)) + data["winners"] = User.de_list(data["winners"], bot) data["winners_selection_date"] = from_timestamp( data.get("winners_selection_date"), tzinfo=loc_tzinfo ) diff --git a/telegram/_inline/inputinvoicemessagecontent.py b/telegram/_inline/inputinvoicemessagecontent.py index cd10ee49ac3..eef1953796e 100644 --- a/telegram/_inline/inputinvoicemessagecontent.py +++ b/telegram/_inline/inputinvoicemessagecontent.py @@ -22,7 +22,7 @@ from telegram._inline.inputmessagecontent import InputMessageContent from telegram._payment.labeledprice import LabeledPrice -from telegram._utils.argumentparsing import de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -258,6 +258,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "InputInvoiceMe """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["prices"] = de_list_wo(data.get("prices"), LabeledPrice, bot) + data["prices"] = LabeledPrice.de_list(data["prices"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_messagereactionupdated.py b/telegram/_messagereactionupdated.py index 5eb5c42a809..18fa6a811e8 100644 --- a/telegram/_messagereactionupdated.py +++ b/telegram/_messagereactionupdated.py @@ -25,7 +25,7 @@ from telegram._reaction import ReactionCount, ReactionType from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -95,7 +95,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageReactio data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["reactions"] = de_list_wo(data.get("reactions"), ReactionCount, bot) + data["reactions"] = ReactionCount.de_list(data["reactions"], bot) return super().de_json(data=data, bot=bot) @@ -191,8 +191,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageReactio data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["old_reaction"] = de_list_wo(data.get("old_reaction"), ReactionType, bot) - data["new_reaction"] = de_list_wo(data.get("new_reaction"), ReactionType, bot) + data["old_reaction"] = ReactionType.de_list(data["old_reaction"], bot) + data["new_reaction"] = ReactionType.de_list(data["new_reaction"], bot) data["user"] = de_json_wo(data.get("user"), User, bot) data["actor_chat"] = de_json_wo(data.get("actor_chat"), Chat, bot) diff --git a/telegram/_paidmedia.py b/telegram/_paidmedia.py index 1337e6f1df0..9b57f037784 100644 --- a/telegram/_paidmedia.py +++ b/telegram/_paidmedia.py @@ -27,7 +27,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -180,7 +180,7 @@ def __init__( def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PaidMediaPhoto": data = cls._parse_data(data) - data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) + data["photo"] = PhotoSize.de_list(data["photo"], bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] @@ -265,7 +265,7 @@ def __init__( def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PaidMediaInfo": data = cls._parse_data(data) - data["paid_media"] = de_list_wo(data.get("paid_media"), PaidMedia, bot) + data["paid_media"] = PaidMedia.de_list(data["paid_media"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_passport/passportdata.py b/telegram/_passport/passportdata.py index 254322e74bd..11b8fc60a86 100644 --- a/telegram/_passport/passportdata.py +++ b/telegram/_passport/passportdata.py @@ -23,7 +23,7 @@ from telegram._passport.credentials import EncryptedCredentials from telegram._passport.encryptedpassportelement import EncryptedPassportElement from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -86,7 +86,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PassportData": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["data"] = de_list_wo(data.get("data"), EncryptedPassportElement, bot) + data["data"] = EncryptedPassportElement.de_list(data["data"], bot) data["credentials"] = de_json_wo(data.get("credentials"), EncryptedCredentials, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/stars/startransactions.py b/telegram/_payment/stars/startransactions.py index 6b0a77d3c78..1dad67f56ae 100644 --- a/telegram/_payment/stars/startransactions.py +++ b/telegram/_payment/stars/startransactions.py @@ -24,7 +24,7 @@ from typing import TYPE_CHECKING, Optional from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -158,5 +158,5 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "StarTransactio """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["transactions"] = de_list_wo(data.get("transactions"), StarTransaction, bot) + data["transactions"] = StarTransaction.de_list(data["transactions"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_reply.py b/telegram/_reply.py index 9e72e97d50d..35a675be11e 100644 --- a/telegram/_reply.py +++ b/telegram/_reply.py @@ -260,7 +260,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ExternalReplyI data["animation"] = de_json_wo(data.get("animation"), Animation, bot) data["audio"] = de_json_wo(data.get("audio"), Audio, bot) data["document"] = de_json_wo(data.get("document"), Document, bot) - data["photo"] = tuple(de_list_wo(data.get("photo"), PhotoSize, bot)) + data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) data["sticker"] = de_json_wo(data.get("sticker"), Sticker, bot) data["story"] = de_json_wo(data.get("story"), Story, bot) data["video"] = de_json_wo(data.get("video"), Video, bot) @@ -349,7 +349,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "TextQuote": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["entities"] = tuple(de_list_wo(data.get("entities"), MessageEntity, bot)) + data["entities"] = de_list_wo(data.get("entities"), MessageEntity, bot) return super().de_json(data=data, bot=bot) @@ -452,6 +452,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ReplyParameter """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["quote_entities"] = tuple(de_list_wo(data.get("quote_entities"), MessageEntity, bot)) + data["quote_entities"] = de_list_wo(data.get("quote_entities"), MessageEntity, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_shared.py b/telegram/_shared.py index 953fd640c76..90bc7d73825 100644 --- a/telegram/_shared.py +++ b/telegram/_shared.py @@ -88,7 +88,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "UsersShared": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["users"] = de_list_wo(data.get("users"), SharedUser, bot) + data["users"] = SharedUser.de_list(data["users"], bot) api_kwargs = {} # This is a deprecated field that TG still returns for backwards compatibility From c5f3bf7e828c568940cb346862fb58a2ab62a484 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Mon, 30 Dec 2024 14:43:55 +0100 Subject: [PATCH 05/14] Use `de_json` instead of `de_json_wo` for required args --- telegram/_business.py | 4 ++-- telegram/_chatbackground.py | 8 ++++---- telegram/_chatboost.py | 14 +++++++------- telegram/_chatinvitelink.py | 3 +-- telegram/_chatjoinrequest.py | 2 +- telegram/_chatlocation.py | 3 +-- telegram/_chatmember.py | 3 +-- telegram/_chatmemberupdated.py | 6 +++--- telegram/_files/venue.py | 3 +-- telegram/_games/gamehighscore.py | 3 +-- telegram/_gifts.py | 4 ++-- telegram/_giveaway.py | 2 +- telegram/_menubutton.py | 3 +-- telegram/_message.py | 2 +- telegram/_messageorigin.py | 7 +++---- telegram/_messagereactionupdated.py | 4 ++-- telegram/_paidmedia.py | 4 ++-- telegram/_passport/credentials.py | 2 +- telegram/_passport/passportdata.py | 4 ++-- telegram/_payment/shippingquery.py | 2 +- telegram/_payment/stars/transactionpartner.py | 2 +- telegram/_proximityalerttriggered.py | 5 ++--- telegram/_reaction.py | 3 +-- telegram/_reply.py | 2 +- 24 files changed, 43 insertions(+), 52 deletions(-) diff --git a/telegram/_business.py b/telegram/_business.py index 2bb86b1264a..903c5e0ffd8 100644 --- a/telegram/_business.py +++ b/telegram/_business.py @@ -114,7 +114,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessConnec loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["user"] = de_json_wo(data.get("user"), User, bot) + data["user"] = User.de_json(data["user"], bot) return super().de_json(data=data, bot=bot) @@ -176,7 +176,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessMessag """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["chat"] = Chat.de_json(data["chat"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatbackground.py b/telegram/_chatbackground.py index 4d9f110b483..6220cde7cd4 100644 --- a/telegram/_chatbackground.py +++ b/telegram/_chatbackground.py @@ -24,7 +24,7 @@ from telegram._files.document import Document from telegram._telegramobject import TelegramObject from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -280,10 +280,10 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BackgroundType return _class_mapping[data.pop("type")].de_json(data=data, bot=bot) if "fill" in data: - data["fill"] = de_json_wo(data.get("fill"), BackgroundFill, bot) + data["fill"] = BackgroundFill.de_json(data["fill"], bot) if "document" in data: - data["document"] = de_json_wo(data.get("document"), Document, bot) + data["document"] = Document.de_json(data["document"], bot) return super().de_json(data=data, bot=bot) @@ -527,6 +527,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBackground """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["type"] = de_json_wo(data.get("type"), BackgroundType, bot) + data["type"] = BackgroundType.de_json(data["type"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatboost.py b/telegram/_chatboost.py index 9c0e14ecd2c..20a1e927ae8 100644 --- a/telegram/_chatboost.py +++ b/telegram/_chatboost.py @@ -26,7 +26,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -124,7 +124,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoostSourc return _class_mapping[data.pop("source")].de_json(data=data, bot=bot) if "user" in data: - data["user"] = de_json_wo(data.get("user"), User, bot) + data["user"] = User.de_json(data["user"], bot) return super().de_json(data=data, bot=bot) @@ -289,7 +289,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoost": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["source"] = de_json_wo(data.get("source"), ChatBoostSource, bot) + data["source"] = ChatBoostSource.de_json(data["source"], bot) loc_tzinfo = extract_tzinfo_from_defaults(bot) data["add_date"] = from_timestamp(data["add_date"], tzinfo=loc_tzinfo) data["expiration_date"] = from_timestamp(data["expiration_date"], tzinfo=loc_tzinfo) @@ -336,8 +336,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoostUpdat """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["boost"] = de_json_wo(data.get("boost"), ChatBoost, bot) + data["chat"] = Chat.de_json(data["chat"], bot) + data["boost"] = ChatBoost.de_json(data["boost"], bot) return super().de_json(data=data, bot=bot) @@ -390,8 +390,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoostRemov """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["source"] = de_json_wo(data.get("source"), ChatBoostSource, bot) + data["chat"] = Chat.de_json(data["chat"], bot) + data["source"] = ChatBoostSource.de_json(data["source"], bot) loc_tzinfo = extract_tzinfo_from_defaults(bot) data["remove_date"] = from_timestamp(data["remove_date"], tzinfo=loc_tzinfo) diff --git a/telegram/_chatinvitelink.py b/telegram/_chatinvitelink.py index 9ccdf0aedcb..b4e554e14f5 100644 --- a/telegram/_chatinvitelink.py +++ b/telegram/_chatinvitelink.py @@ -22,7 +22,6 @@ from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -185,7 +184,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatInviteLink # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["creator"] = de_json_wo(data.get("creator"), User, bot) + data["creator"] = User.de_json(data["creator"], bot) data["expire_date"] = from_timestamp(data.get("expire_date", None), tzinfo=loc_tzinfo) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatjoinrequest.py b/telegram/_chatjoinrequest.py index 3590a7e0747..678e65cb6cf 100644 --- a/telegram/_chatjoinrequest.py +++ b/telegram/_chatjoinrequest.py @@ -137,7 +137,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatJoinReques # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["chat"] = Chat.de_json(data["chat"], bot) data["from_user"] = de_json_wo(data.pop("from", None), User, bot) data["date"] = from_timestamp(data.get("date", None), tzinfo=loc_tzinfo) data["invite_link"] = de_json_wo(data.get("invite_link"), ChatInviteLink, bot) diff --git a/telegram/_chatlocation.py b/telegram/_chatlocation.py index a02824f4648..acab097355e 100644 --- a/telegram/_chatlocation.py +++ b/telegram/_chatlocation.py @@ -23,7 +23,6 @@ from telegram import constants from telegram._files.location import Location from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -73,7 +72,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatLocation": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["location"] = de_json_wo(data.get("location"), Location, bot) + data["location"] = Location.de_json(data["location"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatmember.py b/telegram/_chatmember.py index af37a6d60d0..af105768178 100644 --- a/telegram/_chatmember.py +++ b/telegram/_chatmember.py @@ -24,7 +24,6 @@ from telegram import constants from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -122,7 +121,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatMember": if cls is ChatMember and data.get("status") in _class_mapping: return _class_mapping[data.pop("status")].de_json(data=data, bot=bot) - data["user"] = de_json_wo(data.get("user"), User, bot) + data["user"] = User.de_json(data["user"], bot) if "until_date" in data: # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) diff --git a/telegram/_chatmemberupdated.py b/telegram/_chatmemberupdated.py index 676aba316a8..4eefb9771bf 100644 --- a/telegram/_chatmemberupdated.py +++ b/telegram/_chatmemberupdated.py @@ -149,11 +149,11 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatMemberUpda # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["chat"] = Chat.de_json(data["chat"], bot) data["from_user"] = de_json_wo(data.pop("from", None), User, bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["old_chat_member"] = de_json_wo(data.get("old_chat_member"), ChatMember, bot) - data["new_chat_member"] = de_json_wo(data.get("new_chat_member"), ChatMember, bot) + data["old_chat_member"] = ChatMember.de_json(data["old_chat_member"], bot) + data["new_chat_member"] = ChatMember.de_json(data["new_chat_member"], bot) data["invite_link"] = de_json_wo(data.get("invite_link"), ChatInviteLink, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_files/venue.py b/telegram/_files/venue.py index 6d28a16914f..13abd3cd3a9 100644 --- a/telegram/_files/venue.py +++ b/telegram/_files/venue.py @@ -22,7 +22,6 @@ from telegram._files.location import Location from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -108,6 +107,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Venue": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["location"] = de_json_wo(data.get("location"), Location, bot) + data["location"] = Location.de_json(data["location"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_games/gamehighscore.py b/telegram/_games/gamehighscore.py index c2082d3f9dc..8054aa92f4f 100644 --- a/telegram/_games/gamehighscore.py +++ b/telegram/_games/gamehighscore.py @@ -22,7 +22,6 @@ from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -66,6 +65,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "GameHighScore" """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["user"] = de_json_wo(data.get("user"), User, bot) + data["user"] = User.de_json(data["user"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_gifts.py b/telegram/_gifts.py index 0bb847ee3fd..a716d69a884 100644 --- a/telegram/_gifts.py +++ b/telegram/_gifts.py @@ -23,7 +23,7 @@ from telegram._files.sticker import Sticker from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -86,7 +86,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Gift": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["sticker"] = de_json_wo(data.get("sticker"), Sticker, bot) + data["sticker"] = Sticker.de_json(data["sticker"], bot) return cls(**data) diff --git a/telegram/_giveaway.py b/telegram/_giveaway.py index 95bc0ea03d6..8c030492722 100644 --- a/telegram/_giveaway.py +++ b/telegram/_giveaway.py @@ -301,7 +301,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "GiveawayWinner # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["chat"] = Chat.de_json(data["chat"], bot) data["winners"] = User.de_list(data["winners"], bot) data["winners_selection_date"] = from_timestamp( data.get("winners_selection_date"), tzinfo=loc_tzinfo diff --git a/telegram/_menubutton.py b/telegram/_menubutton.py index af410d97cbc..431ea6c341c 100644 --- a/telegram/_menubutton.py +++ b/telegram/_menubutton.py @@ -22,7 +22,6 @@ from telegram import constants from telegram._telegramobject import TelegramObject from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict from telegram._webappinfo import WebAppInfo @@ -169,7 +168,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MenuButtonWebA """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["web_app"] = de_json_wo(data.get("web_app"), WebAppInfo, bot) + data["web_app"] = WebAppInfo.de_json(data["web_app"], bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] diff --git a/telegram/_message.py b/telegram/_message.py index 989cfb66867..d98f5f874c7 100644 --- a/telegram/_message.py +++ b/telegram/_message.py @@ -205,7 +205,7 @@ def _de_json( else: data["date"] = from_timestamp(data["date"], tzinfo=loc_tzinfo) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["chat"] = Chat.de_json(data["chat"], bot) return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs) diff --git a/telegram/_messageorigin.py b/telegram/_messageorigin.py index 91a5732d551..7de4b26ce3f 100644 --- a/telegram/_messageorigin.py +++ b/telegram/_messageorigin.py @@ -25,7 +25,6 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -114,13 +113,13 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageOrigin" data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) if "sender_user" in data: - data["sender_user"] = de_json_wo(data.get("sender_user"), User, bot) + data["sender_user"] = User.de_json(data["sender_user"], bot) if "sender_chat" in data: - data["sender_chat"] = de_json_wo(data.get("sender_chat"), Chat, bot) + data["sender_chat"] = Chat.de_json(data["sender_chat"], bot) if "chat" in data: - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["chat"] = Chat.de_json(data["chat"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_messagereactionupdated.py b/telegram/_messagereactionupdated.py index 18fa6a811e8..1b30b94197b 100644 --- a/telegram/_messagereactionupdated.py +++ b/telegram/_messagereactionupdated.py @@ -94,7 +94,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageReactio loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["chat"] = Chat.de_json(data["chat"], bot) data["reactions"] = ReactionCount.de_list(data["reactions"], bot) return super().de_json(data=data, bot=bot) @@ -190,7 +190,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageReactio loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["chat"] = Chat.de_json(data["chat"], bot) data["old_reaction"] = ReactionType.de_list(data["old_reaction"], bot) data["new_reaction"] = ReactionType.de_list(data["new_reaction"], bot) data["user"] = de_json_wo(data.get("user"), User, bot) diff --git a/telegram/_paidmedia.py b/telegram/_paidmedia.py index 9b57f037784..7ce99ef8b8f 100644 --- a/telegram/_paidmedia.py +++ b/telegram/_paidmedia.py @@ -27,7 +27,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -221,7 +221,7 @@ def __init__( def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PaidMediaVideo": data = cls._parse_data(data) - data["video"] = de_json_wo(data.get("video"), Video, bot) + data["video"] = Video.de_json(data["video"], bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] diff --git a/telegram/_passport/credentials.py b/telegram/_passport/credentials.py index 607b973538c..d6724b7e15f 100644 --- a/telegram/_passport/credentials.py +++ b/telegram/_passport/credentials.py @@ -238,7 +238,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Credentials": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["secure_data"] = de_json_wo(data.get("secure_data"), SecureData, bot) + data["secure_data"] = SecureData.de_json(data["secure_data"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_passport/passportdata.py b/telegram/_passport/passportdata.py index 11b8fc60a86..a236a2768e4 100644 --- a/telegram/_passport/passportdata.py +++ b/telegram/_passport/passportdata.py @@ -23,7 +23,7 @@ from telegram._passport.credentials import EncryptedCredentials from telegram._passport.encryptedpassportelement import EncryptedPassportElement from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -87,7 +87,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PassportData": data = cls._parse_data(data) data["data"] = EncryptedPassportElement.de_list(data["data"], bot) - data["credentials"] = de_json_wo(data.get("credentials"), EncryptedCredentials, bot) + data["credentials"] = EncryptedCredentials.de_json(data["credentials"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/shippingquery.py b/telegram/_payment/shippingquery.py index f31287a90a3..f176d5f483e 100644 --- a/telegram/_payment/shippingquery.py +++ b/telegram/_payment/shippingquery.py @@ -84,7 +84,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ShippingQuery" data = cls._parse_data(data) data["from_user"] = de_json_wo(data.pop("from", None), User, bot) - data["shipping_address"] = de_json_wo(data.get("shipping_address"), ShippingAddress, bot) + data["shipping_address"] = ShippingAddress.de_json(data["shipping_address"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/stars/transactionpartner.py b/telegram/_payment/stars/transactionpartner.py index f68d6c291d3..61b142b4a1b 100644 --- a/telegram/_payment/stars/transactionpartner.py +++ b/telegram/_payment/stars/transactionpartner.py @@ -311,7 +311,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "TransactionPar """See :meth:`telegram.TransactionPartner.de_json`.""" data = cls._parse_data(data) - data["user"] = de_json_wo(data.get("user"), User, bot) + data["user"] = User.de_json(data["user"], bot) data["affiliate"] = de_json_wo(data.get("affiliate"), AffiliateInfo, bot) data["paid_media"] = de_list_wo(data.get("paid_media"), PaidMedia, bot) data["subscription_period"] = ( diff --git a/telegram/_proximityalerttriggered.py b/telegram/_proximityalerttriggered.py index e39a473e961..0f26c1c21f1 100644 --- a/telegram/_proximityalerttriggered.py +++ b/telegram/_proximityalerttriggered.py @@ -21,7 +21,6 @@ from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -72,7 +71,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ProximityAlert """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["traveler"] = de_json_wo(data.get("traveler"), User, bot) - data["watcher"] = de_json_wo(data.get("watcher"), User, bot) + data["traveler"] = User.de_json(data["traveler"], bot) + data["watcher"] = User.de_json(data["watcher"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_reaction.py b/telegram/_reaction.py index 0e21847fedf..781f8595aa6 100644 --- a/telegram/_reaction.py +++ b/telegram/_reaction.py @@ -23,7 +23,6 @@ from telegram import constants from telegram._telegramobject import TelegramObject from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -227,6 +226,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ReactionCount" """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["type"] = de_json_wo(data.get("type"), ReactionType, bot) + data["type"] = ReactionType.de_json(data["type"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_reply.py b/telegram/_reply.py index 35a675be11e..8a556e7b7a1 100644 --- a/telegram/_reply.py +++ b/telegram/_reply.py @@ -252,7 +252,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ExternalReplyI """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["origin"] = de_json_wo(data.get("origin"), MessageOrigin, bot) + data["origin"] = MessageOrigin.de_json(data["origin"], bot) data["chat"] = de_json_wo(data.get("chat"), Chat, bot) data["link_preview_options"] = de_json_wo( data.get("link_preview_options"), LinkPreviewOptions, bot From 0a1b976ac18af125e5b36cb481ef34b272335074 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Mon, 30 Dec 2024 15:18:49 +0100 Subject: [PATCH 06/14] Fix failing tests --- telegram/_gifts.py | 2 +- tests/auxil/dummy_objects.py | 45 ++++++++++++++++++++++++++---------- tests/test_bot.py | 7 +++--- tests/test_chatboost.py | 3 ++- tests/test_message.py | 5 ++-- tests/test_update.py | 7 +++++- 6 files changed, 49 insertions(+), 20 deletions(-) diff --git a/telegram/_gifts.py b/telegram/_gifts.py index a716d69a884..b406a3a5d4d 100644 --- a/telegram/_gifts.py +++ b/telegram/_gifts.py @@ -126,5 +126,5 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Gifts": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["gifts"] = Gifts.de_list(data["gifts"], bot) + data["gifts"] = Gift.de_list(data["gifts"], bot) return cls(**data) diff --git a/tests/auxil/dummy_objects.py b/tests/auxil/dummy_objects.py index 23525ad7c5f..7e504f0db78 100644 --- a/tests/auxil/dummy_objects.py +++ b/tests/auxil/dummy_objects.py @@ -8,13 +8,17 @@ BotName, BotShortDescription, BusinessConnection, + Chat, ChatAdministratorRights, + ChatBoost, + ChatBoostSource, ChatFullInfo, ChatInviteLink, ChatMember, File, ForumTopic, GameHighScore, + Gift, Gifts, MenuButton, MessageId, @@ -22,6 +26,7 @@ PollOption, PreparedInlineMessage, SentWebAppMessage, + StarTransaction, StarTransactions, Sticker, StickerSet, @@ -38,6 +43,15 @@ id=123456, is_bot=False, first_name="Dummy", last_name="User", username="dummy_user" ) _DUMMY_DATE = dtm.datetime(1970, 1, 1, 0, 0, 0, 0, tzinfo=dtm.timezone.utc) +_DUMMY_STICKER = Sticker( + file_id="dummy_file_id", + file_unique_id="dummy_file_unique_id", + width=1, + height=1, + is_animated=False, + is_video=False, + type="dummy_type", +) _PREPARED_DUMMY_OBJECTS: dict[str, object] = { "bool": True, @@ -53,6 +67,7 @@ can_reply=True, is_enabled=True, ), + "Chat": Chat(id=123456, type="dummy_type"), "ChatAdministratorRights": ChatAdministratorRights.all_rights(), "ChatFullInfo": ChatFullInfo( id=123456, @@ -70,7 +85,7 @@ "ChatMember": ChatMember(user=_DUMMY_USER, status="dummy_status"), "File": File(file_id="dummy_file_id", file_unique_id="dummy_file_unique_id"), "ForumTopic": ForumTopic(message_thread_id=2, name="dummy_name", icon_color=1), - "Gifts": Gifts(gifts=[]), + "Gifts": Gifts(gifts=[Gift(id="dummy_id", sticker=_DUMMY_STICKER, star_count=1)]), "GameHighScore": GameHighScore(position=1, user=_DUMMY_USER, score=1), "int": 123456, "MenuButton": MenuButton(type="dummy_type"), @@ -88,23 +103,29 @@ ), "PreparedInlineMessage": PreparedInlineMessage(id="dummy_id", expiration_date=_DUMMY_DATE), "SentWebAppMessage": SentWebAppMessage(inline_message_id="dummy_inline_message_id"), - "StarTransactions": StarTransactions(transactions=[]), - "Sticker": Sticker( - file_id="dummy_file_id", - file_unique_id="dummy_file_unique_id", - width=1, - height=1, - is_animated=False, - is_video=False, - type="dummy_type", + "StarTransactions": StarTransactions( + transactions=[StarTransaction(id="dummy_id", amount=1, date=_DUMMY_DATE)] ), + "Sticker": _DUMMY_STICKER, "StickerSet": StickerSet( - name="dummy_name", title="dummy_title", stickers=[], sticker_type="dummy_type" + name="dummy_name", + title="dummy_title", + stickers=[_DUMMY_STICKER], + sticker_type="dummy_type", ), "str": "dummy_string", "Update": Update(update_id=123456), "User": _DUMMY_USER, - "UserChatBoosts": UserChatBoosts(boosts=[]), + "UserChatBoosts": UserChatBoosts( + boosts=[ + ChatBoost( + boost_id="dummy_id", + add_date=_DUMMY_DATE, + expiration_date=_DUMMY_DATE, + source=ChatBoostSource(source="dummy_source"), + ) + ] + ), "UserProfilePhotos": UserProfilePhotos(total_count=1, photos=[[]]), "WebhookInfo": WebhookInfo( url="dummy_url", diff --git a/tests/test_bot.py b/tests/test_bot.py index 4124dd15a83..92397e17eea 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -105,6 +105,7 @@ from tests.auxil.slots import mro_slots from .auxil.build_messages import make_message +from .auxil.dummy_objects import get_dummy_object @pytest.fixture @@ -1625,7 +1626,7 @@ async def test_arbitrary_callback_data_pinned_message_reply_to_message( message = Message( 1, dtm.datetime.utcnow(), - None, + get_dummy_object(Chat), reply_markup=offline_bot.callback_data_cache.process_keyboard(reply_markup), ) message._unfreeze() @@ -1639,7 +1640,7 @@ async def post(*args, **kwargs): message_type: Message( 1, dtm.datetime.utcnow(), - None, + get_dummy_object(Chat), pinned_message=message, reply_to_message=Message.de_json(message.to_dict(), offline_bot), ) @@ -1782,7 +1783,7 @@ async def test_arbitrary_callback_data_via_bot( message = Message( 1, dtm.datetime.utcnow(), - None, + get_dummy_object(Chat), reply_markup=reply_markup, via_bot=bot.bot if self_sender else User(1, "first", False), ) diff --git a/tests/test_chatboost.py b/tests/test_chatboost.py index d83769702f0..4f75a204d38 100644 --- a/tests/test_chatboost.py +++ b/tests/test_chatboost.py @@ -38,6 +38,7 @@ from telegram._utils.datetime import UTC, to_timestamp from telegram.constants import ChatBoostSources from telegram.request import RequestData +from tests.auxil.dummy_objects import get_dummy_object_json_dict from tests.auxil.slots import mro_slots @@ -532,7 +533,7 @@ async def make_assertion(url, request_data: RequestData, *args, **kwargs): user_id = data["user_id"] == "2" if not all((chat_id, user_id)): pytest.fail("I got wrong parameters in post") - return data + return get_dummy_object_json_dict(UserChatBoosts) monkeypatch.setattr(offline_bot.request, "post", make_assertion) diff --git a/tests/test_message.py b/tests/test_message.py index 8fc9a32f8ec..f997a6f485e 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -89,6 +89,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message +from tests.auxil.dummy_objects import get_dummy_object_json_dict from tests.auxil.pytest_classes import PytestExtBot, PytestMessage from tests.auxil.slots import mro_slots @@ -591,9 +592,9 @@ def test_all_possibilities_de_json_and_to_dict(self, offline_bot, message_params def test_de_json_localization(self, offline_bot, raw_bot, tz_bot): json_dict = { "message_id": 12, - "from_user": None, + "from_user": get_dummy_object_json_dict("User"), "date": int(dtm.datetime.now().timestamp()), - "chat": None, + "chat": get_dummy_object_json_dict("Chat"), "edit_date": int(dtm.datetime.now().timestamp()), } diff --git a/tests/test_update.py b/tests/test_update.py index baeff8b7499..7d0d5d3885b 100644 --- a/tests/test_update.py +++ b/tests/test_update.py @@ -47,6 +47,7 @@ PreCheckoutQuery, ReactionCount, ReactionTypeEmoji, + ShippingAddress, ShippingQuery, Update, User, @@ -158,7 +159,11 @@ {"edited_channel_post": channel_post}, {"inline_query": InlineQuery(1, User(1, "", False), "", "")}, {"chosen_inline_result": ChosenInlineResult("id", User(1, "", False), "")}, - {"shipping_query": ShippingQuery("id", User(1, "", False), "", None)}, + { + "shipping_query": ShippingQuery( + "id", User(1, "", False), "", ShippingAddress("", "", "", "", "", "") + ) + }, {"pre_checkout_query": PreCheckoutQuery("id", User(1, "", False), "", 0, "")}, {"poll": Poll("id", "?", [PollOption(".", 1)], False, False, False, Poll.REGULAR, True)}, { From 56cbe650afdc102aeb7d453b339ff903e752862d Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Mon, 30 Dec 2024 15:34:58 +0100 Subject: [PATCH 07/14] More failures & one Improvement in TO --- telegram/_files/sticker.py | 1 + telegram/_telegramobject.py | 2 +- tests/auxil/bot_method_checks.py | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telegram/_files/sticker.py b/telegram/_files/sticker.py index fbc6a81b048..9d412ef8ece 100644 --- a/telegram/_files/sticker.py +++ b/telegram/_files/sticker.py @@ -305,6 +305,7 @@ def __init__( @classmethod def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "StickerSet": """See :meth:`telegram.TelegramObject.de_json`.""" + data = cls._parse_data(data) data["thumbnail"] = de_json_wo(data.get("thumbnail"), PhotoSize, bot) data["stickers"] = Sticker.de_list(data["stickers"], bot) diff --git a/telegram/_telegramobject.py b/telegram/_telegramobject.py index d8858e56c77..c668e1df250 100644 --- a/telegram/_telegramobject.py +++ b/telegram/_telegramobject.py @@ -454,7 +454,7 @@ def de_list( A tuple of Telegram objects. """ - return tuple(obj for obj in (cls.de_json(d, bot) for d in data)) + return tuple(cls.de_json(d, bot) for d in data) @contextmanager def _unfrozen(self: Tele_co) -> Iterator[Tele_co]: diff --git a/tests/auxil/bot_method_checks.py b/tests/auxil/bot_method_checks.py index 3566bc61679..da6a42c4d90 100644 --- a/tests/auxil/bot_method_checks.py +++ b/tests/auxil/bot_method_checks.py @@ -403,7 +403,6 @@ def guess_return_type_name(method: Callable[[...], Any]) -> tuple[Union[str, obj # and string annotations. But it also wants to resolve the parameter annotations, which # need additional namespaces and that's not worth the struggle for now … return_annotation = _check_forward_ref(inspect.signature(method).return_annotation) - print(return_annotation, type(return_annotation)) as_tuple = False if isinstance(return_annotation, GenericAlias): From 7c00b03b609ed2f5b9fd2b6c630027bd711d6fd6 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Mon, 30 Dec 2024 15:50:56 +0100 Subject: [PATCH 08/14] remove type checking protocol from runtime --- telegram/_utils/argumentparsing.py | 40 ++++++++++++++++-------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/telegram/_utils/argumentparsing.py b/telegram/_utils/argumentparsing.py index 262aa8bb8aa..9f005c21e4a 100644 --- a/telegram/_utils/argumentparsing.py +++ b/telegram/_utils/argumentparsing.py @@ -31,6 +31,8 @@ from telegram._utils.types import JSONDict, ODVInput if TYPE_CHECKING: + from typing import type_check_only + from telegram import Bot, FileCredentials T = TypeVar("T") @@ -69,25 +71,27 @@ def parse_lpo_and_dwpp( Tele_co = TypeVar("Tele_co", bound=TelegramObject, covariant=True) TeleCrypto_co = TypeVar("TeleCrypto_co", bound="HasDecryptMethod", covariant=True) +if TYPE_CHECKING: -class HasDecryptMethod(Protocol): - __slots__ = () - - @classmethod - def de_json_decrypted( - cls: type[TeleCrypto_co], - data: JSONDict, - bot: Optional["Bot"], - credentials: list["FileCredentials"], - ) -> TeleCrypto_co: ... - - @classmethod - def de_list_decrypted( - cls: type[TeleCrypto_co], - data: list[JSONDict], - bot: Optional["Bot"], - credentials: list["FileCredentials"], - ) -> tuple[TeleCrypto_co, ...]: ... + @type_check_only + class HasDecryptMethod(Protocol): + __slots__ = () + + @classmethod + def de_json_decrypted( + cls: type[TeleCrypto_co], + data: JSONDict, + bot: Optional["Bot"], + credentials: list["FileCredentials"], + ) -> TeleCrypto_co: ... + + @classmethod + def de_list_decrypted( + cls: type[TeleCrypto_co], + data: list[JSONDict], + bot: Optional["Bot"], + credentials: list["FileCredentials"], + ) -> tuple[TeleCrypto_co, ...]: ... def de_json_wo( From cddf8c47e505a83efb9a6d4c40bf3dacf360d5f0 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Fri, 3 Jan 2025 13:14:27 +0100 Subject: [PATCH 09/14] Revert "Use `de_json` instead of `de_json_wo` for required args" This reverts commit c5f3bf7e --- telegram/_business.py | 4 ++-- telegram/_chatbackground.py | 8 ++++---- telegram/_chatboost.py | 14 +++++++------- telegram/_chatinvitelink.py | 3 ++- telegram/_chatjoinrequest.py | 2 +- telegram/_chatlocation.py | 3 ++- telegram/_chatmember.py | 3 ++- telegram/_chatmemberupdated.py | 6 +++--- telegram/_files/venue.py | 3 ++- telegram/_games/gamehighscore.py | 3 ++- telegram/_gifts.py | 6 +++--- telegram/_giveaway.py | 2 +- telegram/_menubutton.py | 3 ++- telegram/_message.py | 2 +- telegram/_messageorigin.py | 7 ++++--- telegram/_messagereactionupdated.py | 4 ++-- telegram/_paidmedia.py | 4 ++-- telegram/_passport/credentials.py | 2 +- telegram/_passport/passportdata.py | 4 ++-- telegram/_payment/shippingquery.py | 2 +- telegram/_payment/stars/transactionpartner.py | 2 +- telegram/_proximityalerttriggered.py | 5 +++-- telegram/_reaction.py | 3 ++- telegram/_reply.py | 2 +- 24 files changed, 53 insertions(+), 44 deletions(-) diff --git a/telegram/_business.py b/telegram/_business.py index 2f66131526b..01122645126 100644 --- a/telegram/_business.py +++ b/telegram/_business.py @@ -114,7 +114,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessConnec loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["user"] = User.de_json(data["user"], bot) + data["user"] = de_json_wo(data.get("user"), User, bot) return super().de_json(data=data, bot=bot) @@ -176,7 +176,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessMessag """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["chat"] = Chat.de_json(data["chat"], bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatbackground.py b/telegram/_chatbackground.py index 97ee05cc524..322fda017a4 100644 --- a/telegram/_chatbackground.py +++ b/telegram/_chatbackground.py @@ -24,7 +24,7 @@ from telegram._files.document import Document from telegram._telegramobject import TelegramObject from telegram._utils import enum -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -280,10 +280,10 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BackgroundType return _class_mapping[data.pop("type")].de_json(data=data, bot=bot) if "fill" in data: - data["fill"] = BackgroundFill.de_json(data["fill"], bot) + data["fill"] = de_json_wo(data.get("fill"), BackgroundFill, bot) if "document" in data: - data["document"] = Document.de_json(data["document"], bot) + data["document"] = de_json_wo(data.get("document"), Document, bot) return super().de_json(data=data, bot=bot) @@ -527,6 +527,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBackground """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["type"] = BackgroundType.de_json(data["type"], bot) + data["type"] = de_json_wo(data.get("type"), BackgroundType, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatboost.py b/telegram/_chatboost.py index e07e321a82a..afab3b818dd 100644 --- a/telegram/_chatboost.py +++ b/telegram/_chatboost.py @@ -26,7 +26,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -124,7 +124,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoostSourc return _class_mapping[data.pop("source")].de_json(data=data, bot=bot) if "user" in data: - data["user"] = User.de_json(data["user"], bot) + data["user"] = de_json_wo(data.get("user"), User, bot) return super().de_json(data=data, bot=bot) @@ -289,7 +289,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoost": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["source"] = ChatBoostSource.de_json(data["source"], bot) + data["source"] = de_json_wo(data.get("source"), ChatBoostSource, bot) loc_tzinfo = extract_tzinfo_from_defaults(bot) data["add_date"] = from_timestamp(data["add_date"], tzinfo=loc_tzinfo) data["expiration_date"] = from_timestamp(data["expiration_date"], tzinfo=loc_tzinfo) @@ -336,8 +336,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoostUpdat """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["chat"] = Chat.de_json(data["chat"], bot) - data["boost"] = ChatBoost.de_json(data["boost"], bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["boost"] = de_json_wo(data.get("boost"), ChatBoost, bot) return super().de_json(data=data, bot=bot) @@ -390,8 +390,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoostRemov """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["chat"] = Chat.de_json(data["chat"], bot) - data["source"] = ChatBoostSource.de_json(data["source"], bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["source"] = de_json_wo(data.get("source"), ChatBoostSource, bot) loc_tzinfo = extract_tzinfo_from_defaults(bot) data["remove_date"] = from_timestamp(data["remove_date"], tzinfo=loc_tzinfo) diff --git a/telegram/_chatinvitelink.py b/telegram/_chatinvitelink.py index 510bd5604b6..63e133b2e17 100644 --- a/telegram/_chatinvitelink.py +++ b/telegram/_chatinvitelink.py @@ -22,6 +22,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -184,7 +185,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatInviteLink # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["creator"] = User.de_json(data["creator"], bot) + data["creator"] = de_json_wo(data.get("creator"), User, bot) data["expire_date"] = from_timestamp(data.get("expire_date", None), tzinfo=loc_tzinfo) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatjoinrequest.py b/telegram/_chatjoinrequest.py index 15ff3513a43..323c27d2ff2 100644 --- a/telegram/_chatjoinrequest.py +++ b/telegram/_chatjoinrequest.py @@ -137,7 +137,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatJoinReques # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chat"] = Chat.de_json(data["chat"], bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) data["from_user"] = de_json_wo(data.pop("from", None), User, bot) data["date"] = from_timestamp(data.get("date", None), tzinfo=loc_tzinfo) data["invite_link"] = de_json_wo(data.get("invite_link"), ChatInviteLink, bot) diff --git a/telegram/_chatlocation.py b/telegram/_chatlocation.py index 0993b62bfa2..3520cc9b977 100644 --- a/telegram/_chatlocation.py +++ b/telegram/_chatlocation.py @@ -23,6 +23,7 @@ from telegram import constants from telegram._files.location import Location from telegram._telegramobject import TelegramObject +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -72,7 +73,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatLocation": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["location"] = Location.de_json(data["location"], bot) + data["location"] = de_json_wo(data.get("location"), Location, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatmember.py b/telegram/_chatmember.py index f7d1593e26e..1ca67e95b9b 100644 --- a/telegram/_chatmember.py +++ b/telegram/_chatmember.py @@ -24,6 +24,7 @@ from telegram import constants from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -121,7 +122,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatMember": if cls is ChatMember and data.get("status") in _class_mapping: return _class_mapping[data.pop("status")].de_json(data=data, bot=bot) - data["user"] = User.de_json(data["user"], bot) + data["user"] = de_json_wo(data.get("user"), User, bot) if "until_date" in data: # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) diff --git a/telegram/_chatmemberupdated.py b/telegram/_chatmemberupdated.py index 97d3194bdff..b16b34e5227 100644 --- a/telegram/_chatmemberupdated.py +++ b/telegram/_chatmemberupdated.py @@ -149,11 +149,11 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatMemberUpda # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chat"] = Chat.de_json(data["chat"], bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) data["from_user"] = de_json_wo(data.pop("from", None), User, bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["old_chat_member"] = ChatMember.de_json(data["old_chat_member"], bot) - data["new_chat_member"] = ChatMember.de_json(data["new_chat_member"], bot) + data["old_chat_member"] = de_json_wo(data.get("old_chat_member"), ChatMember, bot) + data["new_chat_member"] = de_json_wo(data.get("new_chat_member"), ChatMember, bot) data["invite_link"] = de_json_wo(data.get("invite_link"), ChatInviteLink, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_files/venue.py b/telegram/_files/venue.py index 4ddfe8c1073..20a4bef7f8d 100644 --- a/telegram/_files/venue.py +++ b/telegram/_files/venue.py @@ -22,6 +22,7 @@ from telegram._files.location import Location from telegram._telegramobject import TelegramObject +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -107,6 +108,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Venue": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["location"] = Location.de_json(data["location"], bot) + data["location"] = de_json_wo(data.get("location"), Location, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_games/gamehighscore.py b/telegram/_games/gamehighscore.py index 3c57a287aea..b497fadcabd 100644 --- a/telegram/_games/gamehighscore.py +++ b/telegram/_games/gamehighscore.py @@ -22,6 +22,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -65,6 +66,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "GameHighScore" """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["user"] = User.de_json(data["user"], bot) + data["user"] = de_json_wo(data.get("user"), User, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_gifts.py b/telegram/_gifts.py index adcbc9ac71c..2d8d991b904 100644 --- a/telegram/_gifts.py +++ b/telegram/_gifts.py @@ -23,7 +23,7 @@ from telegram._files.sticker import Sticker from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -103,7 +103,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Gift": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["sticker"] = Sticker.de_json(data["sticker"], bot) + data["sticker"] = de_json_wo(data.get("sticker"), Sticker, bot) return super().de_json(data=data, bot=bot) @@ -143,5 +143,5 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Gifts": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["gifts"] = Gift.de_list(data["gifts"], bot) + data["gifts"] = Gifts.de_list(data["gifts"], bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_giveaway.py b/telegram/_giveaway.py index a11ef4d7949..fa34a991cd3 100644 --- a/telegram/_giveaway.py +++ b/telegram/_giveaway.py @@ -301,7 +301,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "GiveawayWinner # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chat"] = Chat.de_json(data["chat"], bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) data["winners"] = User.de_list(data["winners"], bot) data["winners_selection_date"] = from_timestamp( data.get("winners_selection_date"), tzinfo=loc_tzinfo diff --git a/telegram/_menubutton.py b/telegram/_menubutton.py index 188f09bdca2..20fffc01cd1 100644 --- a/telegram/_menubutton.py +++ b/telegram/_menubutton.py @@ -22,6 +22,7 @@ from telegram import constants from telegram._telegramobject import TelegramObject from telegram._utils import enum +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict from telegram._webappinfo import WebAppInfo @@ -168,7 +169,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MenuButtonWebA """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["web_app"] = WebAppInfo.de_json(data["web_app"], bot) + data["web_app"] = de_json_wo(data.get("web_app"), WebAppInfo, bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] diff --git a/telegram/_message.py b/telegram/_message.py index d92149d3e30..01bbd860227 100644 --- a/telegram/_message.py +++ b/telegram/_message.py @@ -205,7 +205,7 @@ def _de_json( else: data["date"] = from_timestamp(data["date"], tzinfo=loc_tzinfo) - data["chat"] = Chat.de_json(data["chat"], bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs) diff --git a/telegram/_messageorigin.py b/telegram/_messageorigin.py index 42944586d32..d3577d1d4bb 100644 --- a/telegram/_messageorigin.py +++ b/telegram/_messageorigin.py @@ -25,6 +25,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -113,13 +114,13 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageOrigin" data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) if "sender_user" in data: - data["sender_user"] = User.de_json(data["sender_user"], bot) + data["sender_user"] = de_json_wo(data.get("sender_user"), User, bot) if "sender_chat" in data: - data["sender_chat"] = Chat.de_json(data["sender_chat"], bot) + data["sender_chat"] = de_json_wo(data.get("sender_chat"), Chat, bot) if "chat" in data: - data["chat"] = Chat.de_json(data["chat"], bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_messagereactionupdated.py b/telegram/_messagereactionupdated.py index 83158eba51f..e41d1aeb1d0 100644 --- a/telegram/_messagereactionupdated.py +++ b/telegram/_messagereactionupdated.py @@ -94,7 +94,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageReactio loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["chat"] = Chat.de_json(data["chat"], bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) data["reactions"] = ReactionCount.de_list(data["reactions"], bot) return super().de_json(data=data, bot=bot) @@ -190,7 +190,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageReactio loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["chat"] = Chat.de_json(data["chat"], bot) + data["chat"] = de_json_wo(data.get("chat"), Chat, bot) data["old_reaction"] = ReactionType.de_list(data["old_reaction"], bot) data["new_reaction"] = ReactionType.de_list(data["new_reaction"], bot) data["user"] = de_json_wo(data.get("user"), User, bot) diff --git a/telegram/_paidmedia.py b/telegram/_paidmedia.py index 16aec261a0c..48f4cb6a0ae 100644 --- a/telegram/_paidmedia.py +++ b/telegram/_paidmedia.py @@ -27,7 +27,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -221,7 +221,7 @@ def __init__( def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PaidMediaVideo": data = cls._parse_data(data) - data["video"] = Video.de_json(data["video"], bot) + data["video"] = de_json_wo(data.get("video"), Video, bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] diff --git a/telegram/_passport/credentials.py b/telegram/_passport/credentials.py index 618fa3179d7..a32ee788563 100644 --- a/telegram/_passport/credentials.py +++ b/telegram/_passport/credentials.py @@ -238,7 +238,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Credentials": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["secure_data"] = SecureData.de_json(data["secure_data"], bot) + data["secure_data"] = de_json_wo(data.get("secure_data"), SecureData, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_passport/passportdata.py b/telegram/_passport/passportdata.py index 2f95158742a..ec3ad9a7098 100644 --- a/telegram/_passport/passportdata.py +++ b/telegram/_passport/passportdata.py @@ -23,7 +23,7 @@ from telegram._passport.credentials import EncryptedCredentials from telegram._passport.encryptedpassportelement import EncryptedPassportElement from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -87,7 +87,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PassportData": data = cls._parse_data(data) data["data"] = EncryptedPassportElement.de_list(data["data"], bot) - data["credentials"] = EncryptedCredentials.de_json(data["credentials"], bot) + data["credentials"] = de_json_wo(data.get("credentials"), EncryptedCredentials, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/shippingquery.py b/telegram/_payment/shippingquery.py index 4bfe8237527..81b85eb1b34 100644 --- a/telegram/_payment/shippingquery.py +++ b/telegram/_payment/shippingquery.py @@ -84,7 +84,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ShippingQuery" data = cls._parse_data(data) data["from_user"] = de_json_wo(data.pop("from", None), User, bot) - data["shipping_address"] = ShippingAddress.de_json(data["shipping_address"], bot) + data["shipping_address"] = de_json_wo(data.get("shipping_address"), ShippingAddress, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/stars/transactionpartner.py b/telegram/_payment/stars/transactionpartner.py index 7b2aaf03d93..2266208c453 100644 --- a/telegram/_payment/stars/transactionpartner.py +++ b/telegram/_payment/stars/transactionpartner.py @@ -311,7 +311,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "TransactionPar """See :meth:`telegram.TransactionPartner.de_json`.""" data = cls._parse_data(data) - data["user"] = User.de_json(data["user"], bot) + data["user"] = de_json_wo(data.get("user"), User, bot) data["affiliate"] = de_json_wo(data.get("affiliate"), AffiliateInfo, bot) data["paid_media"] = de_list_wo(data.get("paid_media"), PaidMedia, bot) data["subscription_period"] = ( diff --git a/telegram/_proximityalerttriggered.py b/telegram/_proximityalerttriggered.py index 77b88d6b07a..39d0b238a18 100644 --- a/telegram/_proximityalerttriggered.py +++ b/telegram/_proximityalerttriggered.py @@ -21,6 +21,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -71,7 +72,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ProximityAlert """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["traveler"] = User.de_json(data["traveler"], bot) - data["watcher"] = User.de_json(data["watcher"], bot) + data["traveler"] = de_json_wo(data.get("traveler"), User, bot) + data["watcher"] = de_json_wo(data.get("watcher"), User, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_reaction.py b/telegram/_reaction.py index aa490d811ba..af443691bd8 100644 --- a/telegram/_reaction.py +++ b/telegram/_reaction.py @@ -23,6 +23,7 @@ from telegram import constants from telegram._telegramobject import TelegramObject from telegram._utils import enum +from telegram._utils.argumentparsing import de_json_wo from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -226,6 +227,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ReactionCount" """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["type"] = ReactionType.de_json(data["type"], bot) + data["type"] = de_json_wo(data.get("type"), ReactionType, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_reply.py b/telegram/_reply.py index a300bae9c25..bf0b71c3a11 100644 --- a/telegram/_reply.py +++ b/telegram/_reply.py @@ -252,7 +252,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ExternalReplyI """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["origin"] = MessageOrigin.de_json(data["origin"], bot) + data["origin"] = de_json_wo(data.get("origin"), MessageOrigin, bot) data["chat"] = de_json_wo(data.get("chat"), Chat, bot) data["link_preview_options"] = de_json_wo( data.get("link_preview_options"), LinkPreviewOptions, bot From 4a5a93d4ca0ce39464761e719fe855e33a5cd4c0 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Fri, 3 Jan 2025 13:16:04 +0100 Subject: [PATCH 10/14] Revert "Use `de_list` instead of `de_list_wo` for required args" This reverts commit 3fe033d3 --- telegram/_business.py | 6 ++++-- telegram/_chatboost.py | 4 ++-- telegram/_files/sticker.py | 4 ++-- telegram/_games/game.py | 2 +- telegram/_gifts.py | 4 ++-- telegram/_giveaway.py | 6 +++--- telegram/_inline/inputinvoicemessagecontent.py | 4 ++-- telegram/_messagereactionupdated.py | 8 ++++---- telegram/_paidmedia.py | 6 +++--- telegram/_passport/passportdata.py | 4 ++-- telegram/_payment/stars/startransactions.py | 4 ++-- telegram/_reply.py | 6 +++--- telegram/_shared.py | 2 +- 13 files changed, 31 insertions(+), 29 deletions(-) diff --git a/telegram/_business.py b/telegram/_business.py index 01122645126..1bbb9dcd1ac 100644 --- a/telegram/_business.py +++ b/telegram/_business.py @@ -27,7 +27,7 @@ from telegram._files.sticker import Sticker from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -423,6 +423,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessOpenin """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["opening_hours"] = BusinessOpeningHoursInterval.de_list(data["opening_hours"], bot) + data["opening_hours"] = de_list_wo( + data.get("opening_hours"), BusinessOpeningHoursInterval, bot + ) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatboost.py b/telegram/_chatboost.py index afab3b818dd..352e59cd219 100644 --- a/telegram/_chatboost.py +++ b/telegram/_chatboost.py @@ -26,7 +26,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -434,6 +434,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "UserChatBoosts """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["boosts"] = ChatBoost.de_list(data["boosts"], bot) + data["boosts"] = de_list_wo(data.get("boosts"), ChatBoost, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_files/sticker.py b/telegram/_files/sticker.py index f1c94a2af36..2eb2a093c75 100644 --- a/telegram/_files/sticker.py +++ b/telegram/_files/sticker.py @@ -26,7 +26,7 @@ from telegram._files.photosize import PhotoSize from telegram._telegramobject import TelegramObject from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -308,7 +308,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "StickerSet": data = cls._parse_data(data) data["thumbnail"] = de_json_wo(data.get("thumbnail"), PhotoSize, bot) - data["stickers"] = Sticker.de_list(data["stickers"], bot) + data["stickers"] = de_list_wo(data.get("stickers"), Sticker, bot) api_kwargs = {} # These are deprecated fields that TG still returns for backwards compatibility diff --git a/telegram/_games/game.py b/telegram/_games/game.py index 37e99195132..9fca4d70392 100644 --- a/telegram/_games/game.py +++ b/telegram/_games/game.py @@ -128,7 +128,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Game": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["photo"] = PhotoSize.de_list(data["photo"], bot) + data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) data["text_entities"] = de_list_wo(data.get("text_entities"), MessageEntity, bot) data["animation"] = de_json_wo(data.get("animation"), Animation, bot) diff --git a/telegram/_gifts.py b/telegram/_gifts.py index 2d8d991b904..8fc2e0153c0 100644 --- a/telegram/_gifts.py +++ b/telegram/_gifts.py @@ -23,7 +23,7 @@ from telegram._files.sticker import Sticker from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -143,5 +143,5 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Gifts": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["gifts"] = Gifts.de_list(data["gifts"], bot) + data["gifts"] = de_list_wo(data.get("gifts"), Gift, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_giveaway.py b/telegram/_giveaway.py index fa34a991cd3..51ce026d81e 100644 --- a/telegram/_giveaway.py +++ b/telegram/_giveaway.py @@ -24,7 +24,7 @@ from telegram._chat import Chat from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -144,7 +144,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Giveaway": # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chats"] = Chat.de_list(data["chats"], bot) + data["chats"] = tuple(de_list_wo(data.get("chats"), Chat, bot)) data["winners_selection_date"] = from_timestamp( data.get("winners_selection_date"), tzinfo=loc_tzinfo ) @@ -302,7 +302,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "GiveawayWinner loc_tzinfo = extract_tzinfo_from_defaults(bot) data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["winners"] = User.de_list(data["winners"], bot) + data["winners"] = tuple(de_list_wo(data.get("winners"), User, bot)) data["winners_selection_date"] = from_timestamp( data.get("winners_selection_date"), tzinfo=loc_tzinfo ) diff --git a/telegram/_inline/inputinvoicemessagecontent.py b/telegram/_inline/inputinvoicemessagecontent.py index 7d53c79fe38..577a28f4f20 100644 --- a/telegram/_inline/inputinvoicemessagecontent.py +++ b/telegram/_inline/inputinvoicemessagecontent.py @@ -22,7 +22,7 @@ from telegram._inline.inputmessagecontent import InputMessageContent from telegram._payment.labeledprice import LabeledPrice -from telegram._utils.argumentparsing import parse_sequence_arg +from telegram._utils.argumentparsing import de_list_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -258,6 +258,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "InputInvoiceMe """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["prices"] = LabeledPrice.de_list(data["prices"], bot) + data["prices"] = de_list_wo(data.get("prices"), LabeledPrice, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_messagereactionupdated.py b/telegram/_messagereactionupdated.py index e41d1aeb1d0..664728d415a 100644 --- a/telegram/_messagereactionupdated.py +++ b/telegram/_messagereactionupdated.py @@ -25,7 +25,7 @@ from telegram._reaction import ReactionCount, ReactionType from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -95,7 +95,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageReactio data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["reactions"] = ReactionCount.de_list(data["reactions"], bot) + data["reactions"] = de_list_wo(data.get("reactions"), ReactionCount, bot) return super().de_json(data=data, bot=bot) @@ -191,8 +191,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageReactio data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["old_reaction"] = ReactionType.de_list(data["old_reaction"], bot) - data["new_reaction"] = ReactionType.de_list(data["new_reaction"], bot) + data["old_reaction"] = de_list_wo(data.get("old_reaction"), ReactionType, bot) + data["new_reaction"] = de_list_wo(data.get("new_reaction"), ReactionType, bot) data["user"] = de_json_wo(data.get("user"), User, bot) data["actor_chat"] = de_json_wo(data.get("actor_chat"), Chat, bot) diff --git a/telegram/_paidmedia.py b/telegram/_paidmedia.py index 48f4cb6a0ae..415f7f93b70 100644 --- a/telegram/_paidmedia.py +++ b/telegram/_paidmedia.py @@ -27,7 +27,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -180,7 +180,7 @@ def __init__( def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PaidMediaPhoto": data = cls._parse_data(data) - data["photo"] = PhotoSize.de_list(data["photo"], bot) + data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] @@ -265,7 +265,7 @@ def __init__( def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PaidMediaInfo": data = cls._parse_data(data) - data["paid_media"] = PaidMedia.de_list(data["paid_media"], bot) + data["paid_media"] = de_list_wo(data.get("paid_media"), PaidMedia, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_passport/passportdata.py b/telegram/_passport/passportdata.py index ec3ad9a7098..55f243c7ec9 100644 --- a/telegram/_passport/passportdata.py +++ b/telegram/_passport/passportdata.py @@ -23,7 +23,7 @@ from telegram._passport.credentials import EncryptedCredentials from telegram._passport.encryptedpassportelement import EncryptedPassportElement from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -86,7 +86,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PassportData": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["data"] = EncryptedPassportElement.de_list(data["data"], bot) + data["data"] = de_list_wo(data.get("data"), EncryptedPassportElement, bot) data["credentials"] = de_json_wo(data.get("credentials"), EncryptedCredentials, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/stars/startransactions.py b/telegram/_payment/stars/startransactions.py index afa186c2506..f0ecb865e72 100644 --- a/telegram/_payment/stars/startransactions.py +++ b/telegram/_payment/stars/startransactions.py @@ -24,7 +24,7 @@ from typing import TYPE_CHECKING, Optional from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -158,5 +158,5 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "StarTransactio """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["transactions"] = StarTransaction.de_list(data["transactions"], bot) + data["transactions"] = de_list_wo(data.get("transactions"), StarTransaction, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_reply.py b/telegram/_reply.py index bf0b71c3a11..c2432ce9412 100644 --- a/telegram/_reply.py +++ b/telegram/_reply.py @@ -260,7 +260,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ExternalReplyI data["animation"] = de_json_wo(data.get("animation"), Animation, bot) data["audio"] = de_json_wo(data.get("audio"), Audio, bot) data["document"] = de_json_wo(data.get("document"), Document, bot) - data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) + data["photo"] = tuple(de_list_wo(data.get("photo"), PhotoSize, bot)) data["sticker"] = de_json_wo(data.get("sticker"), Sticker, bot) data["story"] = de_json_wo(data.get("story"), Story, bot) data["video"] = de_json_wo(data.get("video"), Video, bot) @@ -349,7 +349,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "TextQuote": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["entities"] = de_list_wo(data.get("entities"), MessageEntity, bot) + data["entities"] = tuple(de_list_wo(data.get("entities"), MessageEntity, bot)) return super().de_json(data=data, bot=bot) @@ -452,6 +452,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ReplyParameter """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["quote_entities"] = de_list_wo(data.get("quote_entities"), MessageEntity, bot) + data["quote_entities"] = tuple(de_list_wo(data.get("quote_entities"), MessageEntity, bot)) return super().de_json(data=data, bot=bot) diff --git a/telegram/_shared.py b/telegram/_shared.py index c320c9c3d52..6971f9cd939 100644 --- a/telegram/_shared.py +++ b/telegram/_shared.py @@ -88,7 +88,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "UsersShared": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["users"] = SharedUser.de_list(data["users"], bot) + data["users"] = de_list_wo(data.get("users"), SharedUser, bot) api_kwargs = {} # This is a deprecated field that TG still returns for backwards compatibility From 4c9ea4170a305d0e60c78c02d4b6a85a5397cc83 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Fri, 3 Jan 2025 13:23:39 +0100 Subject: [PATCH 11/14] Use data.get in remaining places --- telegram/_chatboost.py | 6 +++--- telegram/_chatmember.py | 2 +- telegram/_message.py | 2 +- telegram/_poll.py | 2 +- telegram/_videochat.py | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/telegram/_chatboost.py b/telegram/_chatboost.py index 352e59cd219..86623b9a349 100644 --- a/telegram/_chatboost.py +++ b/telegram/_chatboost.py @@ -291,8 +291,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoost": data["source"] = de_json_wo(data.get("source"), ChatBoostSource, bot) loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["add_date"] = from_timestamp(data["add_date"], tzinfo=loc_tzinfo) - data["expiration_date"] = from_timestamp(data["expiration_date"], tzinfo=loc_tzinfo) + data["add_date"] = from_timestamp(data.get("add_date"), tzinfo=loc_tzinfo) + data["expiration_date"] = from_timestamp(data.get("expiration_date"), tzinfo=loc_tzinfo) return super().de_json(data=data, bot=bot) @@ -393,7 +393,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoostRemov data["chat"] = de_json_wo(data.get("chat"), Chat, bot) data["source"] = de_json_wo(data.get("source"), ChatBoostSource, bot) loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["remove_date"] = from_timestamp(data["remove_date"], tzinfo=loc_tzinfo) + data["remove_date"] = from_timestamp(data.get("remove_date"), tzinfo=loc_tzinfo) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatmember.py b/telegram/_chatmember.py index 1ca67e95b9b..47472a081dc 100644 --- a/telegram/_chatmember.py +++ b/telegram/_chatmember.py @@ -127,7 +127,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatMember": # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["until_date"] = from_timestamp(data["until_date"], tzinfo=loc_tzinfo) + data["until_date"] = from_timestamp(data.get("until_date"), tzinfo=loc_tzinfo) # This is a deprecated field that TG still returns for backwards compatibility # Let's filter it out to speed up the de-json process diff --git a/telegram/_message.py b/telegram/_message.py index 01bbd860227..0f53febf6b4 100644 --- a/telegram/_message.py +++ b/telegram/_message.py @@ -203,7 +203,7 @@ def _de_json( if data["date"] == 0: data["date"] = ZERO_DATE else: - data["date"] = from_timestamp(data["date"], tzinfo=loc_tzinfo) + data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) data["chat"] = de_json_wo(data.get("chat"), Chat, bot) return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs) diff --git a/telegram/_poll.py b/telegram/_poll.py index 33f9043ae32..c5f1dd85949 100644 --- a/telegram/_poll.py +++ b/telegram/_poll.py @@ -466,7 +466,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Poll": # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["options"] = PollOption.de_list(data["options"], bot) + data["options"] = de_list_wo(data.get("options"), PollOption, bot) data["explanation_entities"] = de_list_wo( data.get("explanation_entities"), MessageEntity, bot ) diff --git a/telegram/_videochat.py b/telegram/_videochat.py index 0fbc3f2e42d..7c1ec00aabb 100644 --- a/telegram/_videochat.py +++ b/telegram/_videochat.py @@ -182,6 +182,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "VideoChatSched # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["start_date"] = from_timestamp(data["start_date"], tzinfo=loc_tzinfo) + data["start_date"] = from_timestamp(data.get("start_date"), tzinfo=loc_tzinfo) return super().de_json(data=data, bot=bot) From e991b935e42922738acd4340afd43f95eef36837 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Fri, 3 Jan 2025 13:31:03 +0100 Subject: [PATCH 12/14] Rename functions according to review --- telegram/_business.py | 12 +- telegram/_callbackquery.py | 6 +- telegram/_chatbackground.py | 8 +- telegram/_chatboost.py | 16 +-- telegram/_chatfullinfo.py | 22 +-- telegram/_chatinvitelink.py | 4 +- telegram/_chatjoinrequest.py | 8 +- telegram/_chatlocation.py | 4 +- telegram/_chatmember.py | 4 +- telegram/_chatmemberupdated.py | 12 +- telegram/_choseninlineresult.py | 6 +- telegram/_files/_basethumbedmedium.py | 4 +- telegram/_files/sticker.py | 12 +- telegram/_files/venue.py | 4 +- telegram/_games/game.py | 8 +- telegram/_games/gamehighscore.py | 4 +- telegram/_gifts.py | 6 +- telegram/_giveaway.py | 10 +- telegram/_inline/inlinekeyboardbutton.py | 12 +- telegram/_inline/inlinequery.py | 6 +- telegram/_inline/inlinequeryresultsbutton.py | 4 +- .../_inline/inputinvoicemessagecontent.py | 4 +- telegram/_keyboardbutton.py | 14 +- telegram/_keyboardbuttonrequest.py | 6 +- telegram/_menubutton.py | 4 +- telegram/_message.py | 136 ++++++++++-------- telegram/_messageentity.py | 4 +- telegram/_messageorigin.py | 8 +- telegram/_messagereactionupdated.py | 16 +-- telegram/_paidmedia.py | 8 +- telegram/_passport/credentials.py | 40 +++--- .../_passport/encryptedpassportelement.py | 28 ++-- telegram/_passport/passportdata.py | 6 +- telegram/_payment/orderinfo.py | 6 +- telegram/_payment/precheckoutquery.py | 6 +- telegram/_payment/shippingquery.py | 8 +- telegram/_payment/stars/affiliateinfo.py | 6 +- telegram/_payment/stars/startransactions.py | 8 +- telegram/_payment/stars/transactionpartner.py | 14 +- telegram/_payment/successfulpayment.py | 4 +- telegram/_poll.py | 18 +-- telegram/_proximityalerttriggered.py | 6 +- telegram/_reaction.py | 4 +- telegram/_reply.py | 54 +++---- telegram/_shared.py | 8 +- telegram/_update.py | 54 +++---- telegram/_utils/argumentparsing.py | 8 +- 47 files changed, 343 insertions(+), 307 deletions(-) diff --git a/telegram/_business.py b/telegram/_business.py index 1bbb9dcd1ac..95607c24344 100644 --- a/telegram/_business.py +++ b/telegram/_business.py @@ -27,7 +27,7 @@ from telegram._files.sticker import Sticker from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -114,7 +114,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessConnec loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["user"] = de_json_wo(data.get("user"), User, bot) + data["user"] = de_json_optional(data.get("user"), User, bot) return super().de_json(data=data, bot=bot) @@ -176,7 +176,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessMessag """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["chat"] = de_json_optional(data.get("chat"), Chat, bot) return super().de_json(data=data, bot=bot) @@ -230,7 +230,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessIntro" """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["sticker"] = de_json_wo(data.get("sticker"), Sticker, bot) + data["sticker"] = de_json_optional(data.get("sticker"), Sticker, bot) return super().de_json(data=data, bot=bot) @@ -279,7 +279,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessLocati """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["location"] = de_json_wo(data.get("location"), Location, bot) + data["location"] = de_json_optional(data.get("location"), Location, bot) return super().de_json(data=data, bot=bot) @@ -423,7 +423,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BusinessOpenin """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["opening_hours"] = de_list_wo( + data["opening_hours"] = de_list_optional( data.get("opening_hours"), BusinessOpeningHoursInterval, bot ) diff --git a/telegram/_callbackquery.py b/telegram/_callbackquery.py index e9d924a0a55..83efbfaa675 100644 --- a/telegram/_callbackquery.py +++ b/telegram/_callbackquery.py @@ -26,7 +26,7 @@ from telegram._message import MaybeInaccessibleMessage, Message from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.types import JSONDict, ODVInput, ReplyMarkup @@ -154,8 +154,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "CallbackQuery" """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["from_user"] = de_json_wo(data.pop("from", None), User, bot) - data["message"] = de_json_wo(data.get("message"), Message, bot) + data["from_user"] = de_json_optional(data.pop("from", None), User, bot) + data["message"] = de_json_optional(data.get("message"), Message, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatbackground.py b/telegram/_chatbackground.py index 322fda017a4..37fc0c81ca6 100644 --- a/telegram/_chatbackground.py +++ b/telegram/_chatbackground.py @@ -24,7 +24,7 @@ from telegram._files.document import Document from telegram._telegramobject import TelegramObject from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -280,10 +280,10 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "BackgroundType return _class_mapping[data.pop("type")].de_json(data=data, bot=bot) if "fill" in data: - data["fill"] = de_json_wo(data.get("fill"), BackgroundFill, bot) + data["fill"] = de_json_optional(data.get("fill"), BackgroundFill, bot) if "document" in data: - data["document"] = de_json_wo(data.get("document"), Document, bot) + data["document"] = de_json_optional(data.get("document"), Document, bot) return super().de_json(data=data, bot=bot) @@ -527,6 +527,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBackground """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["type"] = de_json_wo(data.get("type"), BackgroundType, bot) + data["type"] = de_json_optional(data.get("type"), BackgroundType, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatboost.py b/telegram/_chatboost.py index 86623b9a349..678b713afc3 100644 --- a/telegram/_chatboost.py +++ b/telegram/_chatboost.py @@ -26,7 +26,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -124,7 +124,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoostSourc return _class_mapping[data.pop("source")].de_json(data=data, bot=bot) if "user" in data: - data["user"] = de_json_wo(data.get("user"), User, bot) + data["user"] = de_json_optional(data.get("user"), User, bot) return super().de_json(data=data, bot=bot) @@ -289,7 +289,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoost": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["source"] = de_json_wo(data.get("source"), ChatBoostSource, bot) + data["source"] = de_json_optional(data.get("source"), ChatBoostSource, bot) loc_tzinfo = extract_tzinfo_from_defaults(bot) data["add_date"] = from_timestamp(data.get("add_date"), tzinfo=loc_tzinfo) data["expiration_date"] = from_timestamp(data.get("expiration_date"), tzinfo=loc_tzinfo) @@ -336,8 +336,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoostUpdat """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["boost"] = de_json_wo(data.get("boost"), ChatBoost, bot) + data["chat"] = de_json_optional(data.get("chat"), Chat, bot) + data["boost"] = de_json_optional(data.get("boost"), ChatBoost, bot) return super().de_json(data=data, bot=bot) @@ -390,8 +390,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatBoostRemov """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["source"] = de_json_wo(data.get("source"), ChatBoostSource, bot) + data["chat"] = de_json_optional(data.get("chat"), Chat, bot) + data["source"] = de_json_optional(data.get("source"), ChatBoostSource, bot) loc_tzinfo = extract_tzinfo_from_defaults(bot) data["remove_date"] = from_timestamp(data.get("remove_date"), tzinfo=loc_tzinfo) @@ -434,6 +434,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "UserChatBoosts """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["boosts"] = de_list_wo(data.get("boosts"), ChatBoost, bot) + data["boosts"] = de_list_optional(data.get("boosts"), ChatBoost, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatfullinfo.py b/telegram/_chatfullinfo.py index 017b176987f..c763efca78e 100644 --- a/telegram/_chatfullinfo.py +++ b/telegram/_chatfullinfo.py @@ -28,7 +28,7 @@ from telegram._chatpermissions import ChatPermissions from telegram._files.chatphoto import ChatPhoto from telegram._reaction import ReactionType -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -523,7 +523,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatFullInfo": data.get("emoji_status_expiration_date"), tzinfo=loc_tzinfo ) - data["photo"] = de_json_wo(data.get("photo"), ChatPhoto, bot) + data["photo"] = de_json_optional(data.get("photo"), ChatPhoto, bot) from telegram import ( # pylint: disable=import-outside-toplevel BusinessIntro, @@ -532,19 +532,19 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatFullInfo": Message, ) - data["pinned_message"] = de_json_wo(data.get("pinned_message"), Message, bot) - data["permissions"] = de_json_wo(data.get("permissions"), ChatPermissions, bot) - data["location"] = de_json_wo(data.get("location"), ChatLocation, bot) - data["available_reactions"] = de_list_wo( + data["pinned_message"] = de_json_optional(data.get("pinned_message"), Message, bot) + data["permissions"] = de_json_optional(data.get("permissions"), ChatPermissions, bot) + data["location"] = de_json_optional(data.get("location"), ChatLocation, bot) + data["available_reactions"] = de_list_optional( data.get("available_reactions"), ReactionType, bot ) - data["birthdate"] = de_json_wo(data.get("birthdate"), Birthdate, bot) - data["personal_chat"] = de_json_wo(data.get("personal_chat"), Chat, bot) - data["business_intro"] = de_json_wo(data.get("business_intro"), BusinessIntro, bot) - data["business_location"] = de_json_wo( + data["birthdate"] = de_json_optional(data.get("birthdate"), Birthdate, bot) + data["personal_chat"] = de_json_optional(data.get("personal_chat"), Chat, bot) + data["business_intro"] = de_json_optional(data.get("business_intro"), BusinessIntro, bot) + data["business_location"] = de_json_optional( data.get("business_location"), BusinessLocation, bot ) - data["business_opening_hours"] = de_json_wo( + data["business_opening_hours"] = de_json_optional( data.get("business_opening_hours"), BusinessOpeningHours, bot ) diff --git a/telegram/_chatinvitelink.py b/telegram/_chatinvitelink.py index 63e133b2e17..289ee48bdba 100644 --- a/telegram/_chatinvitelink.py +++ b/telegram/_chatinvitelink.py @@ -22,7 +22,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -185,7 +185,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatInviteLink # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["creator"] = de_json_wo(data.get("creator"), User, bot) + data["creator"] = de_json_optional(data.get("creator"), User, bot) data["expire_date"] = from_timestamp(data.get("expire_date", None), tzinfo=loc_tzinfo) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatjoinrequest.py b/telegram/_chatjoinrequest.py index 323c27d2ff2..048b6a80b5d 100644 --- a/telegram/_chatjoinrequest.py +++ b/telegram/_chatjoinrequest.py @@ -24,7 +24,7 @@ from telegram._chatinvitelink import ChatInviteLink from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.types import JSONDict, ODVInput @@ -137,10 +137,10 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatJoinReques # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["from_user"] = de_json_wo(data.pop("from", None), User, bot) + data["chat"] = de_json_optional(data.get("chat"), Chat, bot) + data["from_user"] = de_json_optional(data.pop("from", None), User, bot) data["date"] = from_timestamp(data.get("date", None), tzinfo=loc_tzinfo) - data["invite_link"] = de_json_wo(data.get("invite_link"), ChatInviteLink, bot) + data["invite_link"] = de_json_optional(data.get("invite_link"), ChatInviteLink, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatlocation.py b/telegram/_chatlocation.py index 3520cc9b977..4514b2566db 100644 --- a/telegram/_chatlocation.py +++ b/telegram/_chatlocation.py @@ -23,7 +23,7 @@ from telegram import constants from telegram._files.location import Location from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -73,7 +73,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatLocation": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["location"] = de_json_wo(data.get("location"), Location, bot) + data["location"] = de_json_optional(data.get("location"), Location, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_chatmember.py b/telegram/_chatmember.py index 47472a081dc..d9f256aa2c1 100644 --- a/telegram/_chatmember.py +++ b/telegram/_chatmember.py @@ -24,7 +24,7 @@ from telegram import constants from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -122,7 +122,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatMember": if cls is ChatMember and data.get("status") in _class_mapping: return _class_mapping[data.pop("status")].de_json(data=data, bot=bot) - data["user"] = de_json_wo(data.get("user"), User, bot) + data["user"] = de_json_optional(data.get("user"), User, bot) if "until_date" in data: # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) diff --git a/telegram/_chatmemberupdated.py b/telegram/_chatmemberupdated.py index b16b34e5227..5aeab80a1fa 100644 --- a/telegram/_chatmemberupdated.py +++ b/telegram/_chatmemberupdated.py @@ -25,7 +25,7 @@ from telegram._chatmember import ChatMember from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -149,12 +149,12 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatMemberUpda # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["from_user"] = de_json_wo(data.pop("from", None), User, bot) + data["chat"] = de_json_optional(data.get("chat"), Chat, bot) + data["from_user"] = de_json_optional(data.pop("from", None), User, bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["old_chat_member"] = de_json_wo(data.get("old_chat_member"), ChatMember, bot) - data["new_chat_member"] = de_json_wo(data.get("new_chat_member"), ChatMember, bot) - data["invite_link"] = de_json_wo(data.get("invite_link"), ChatInviteLink, bot) + data["old_chat_member"] = de_json_optional(data.get("old_chat_member"), ChatMember, bot) + data["new_chat_member"] = de_json_optional(data.get("new_chat_member"), ChatMember, bot) + data["invite_link"] = de_json_optional(data.get("invite_link"), ChatInviteLink, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_choseninlineresult.py b/telegram/_choseninlineresult.py index 133f38d69ce..e3754039230 100644 --- a/telegram/_choseninlineresult.py +++ b/telegram/_choseninlineresult.py @@ -24,7 +24,7 @@ from telegram._files.location import Location from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -98,8 +98,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChosenInlineRe data = cls._parse_data(data) # Required - data["from_user"] = de_json_wo(data.pop("from", None), User, bot) + data["from_user"] = de_json_optional(data.pop("from", None), User, bot) # Optionals - data["location"] = de_json_wo(data.get("location"), Location, bot) + data["location"] = de_json_optional(data.get("location"), Location, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_files/_basethumbedmedium.py b/telegram/_files/_basethumbedmedium.py index d02b9f1a082..2008475c2f2 100644 --- a/telegram/_files/_basethumbedmedium.py +++ b/telegram/_files/_basethumbedmedium.py @@ -21,7 +21,7 @@ from telegram._files._basemedium import _BaseMedium from telegram._files.photosize import PhotoSize -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -90,7 +90,7 @@ def de_json( # In case this wasn't already done by the subclass if not isinstance(data.get("thumbnail"), PhotoSize): - data["thumbnail"] = de_json_wo(data.get("thumbnail"), PhotoSize, bot) + data["thumbnail"] = de_json_optional(data.get("thumbnail"), PhotoSize, bot) api_kwargs = {} # This is a deprecated field that TG still returns for backwards compatibility diff --git a/telegram/_files/sticker.py b/telegram/_files/sticker.py index 2eb2a093c75..0bf63d4b073 100644 --- a/telegram/_files/sticker.py +++ b/telegram/_files/sticker.py @@ -26,7 +26,7 @@ from telegram._files.photosize import PhotoSize from telegram._telegramobject import TelegramObject from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -198,9 +198,9 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Sticker": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["thumbnail"] = de_json_wo(data.get("thumbnail"), PhotoSize, bot) - data["mask_position"] = de_json_wo(data.get("mask_position"), MaskPosition, bot) - data["premium_animation"] = de_json_wo(data.get("premium_animation"), File, bot) + data["thumbnail"] = de_json_optional(data.get("thumbnail"), PhotoSize, bot) + data["mask_position"] = de_json_optional(data.get("mask_position"), MaskPosition, bot) + data["premium_animation"] = de_json_optional(data.get("premium_animation"), File, bot) api_kwargs = {} # This is a deprecated field that TG still returns for backwards compatibility @@ -307,8 +307,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "StickerSet": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["thumbnail"] = de_json_wo(data.get("thumbnail"), PhotoSize, bot) - data["stickers"] = de_list_wo(data.get("stickers"), Sticker, bot) + data["thumbnail"] = de_json_optional(data.get("thumbnail"), PhotoSize, bot) + data["stickers"] = de_list_optional(data.get("stickers"), Sticker, bot) api_kwargs = {} # These are deprecated fields that TG still returns for backwards compatibility diff --git a/telegram/_files/venue.py b/telegram/_files/venue.py index 20a4bef7f8d..fd9cbdf69f0 100644 --- a/telegram/_files/venue.py +++ b/telegram/_files/venue.py @@ -22,7 +22,7 @@ from telegram._files.location import Location from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -108,6 +108,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Venue": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["location"] = de_json_wo(data.get("location"), Location, bot) + data["location"] = de_json_optional(data.get("location"), Location, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_games/game.py b/telegram/_games/game.py index 9fca4d70392..bd8cf19caea 100644 --- a/telegram/_games/game.py +++ b/telegram/_games/game.py @@ -24,7 +24,7 @@ from telegram._files.photosize import PhotoSize from telegram._messageentity import MessageEntity from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.strings import TextEncoding from telegram._utils.types import JSONDict @@ -128,9 +128,9 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Game": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) - data["text_entities"] = de_list_wo(data.get("text_entities"), MessageEntity, bot) - data["animation"] = de_json_wo(data.get("animation"), Animation, bot) + data["photo"] = de_list_optional(data.get("photo"), PhotoSize, bot) + data["text_entities"] = de_list_optional(data.get("text_entities"), MessageEntity, bot) + data["animation"] = de_json_optional(data.get("animation"), Animation, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_games/gamehighscore.py b/telegram/_games/gamehighscore.py index b497fadcabd..2866b59fb99 100644 --- a/telegram/_games/gamehighscore.py +++ b/telegram/_games/gamehighscore.py @@ -22,7 +22,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -66,6 +66,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "GameHighScore" """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["user"] = de_json_wo(data.get("user"), User, bot) + data["user"] = de_json_optional(data.get("user"), User, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_gifts.py b/telegram/_gifts.py index 8fc2e0153c0..d068923c6df 100644 --- a/telegram/_gifts.py +++ b/telegram/_gifts.py @@ -23,7 +23,7 @@ from telegram._files.sticker import Sticker from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -103,7 +103,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Gift": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["sticker"] = de_json_wo(data.get("sticker"), Sticker, bot) + data["sticker"] = de_json_optional(data.get("sticker"), Sticker, bot) return super().de_json(data=data, bot=bot) @@ -143,5 +143,5 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Gifts": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["gifts"] = de_list_wo(data.get("gifts"), Gift, bot) + data["gifts"] = de_list_optional(data.get("gifts"), Gift, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_giveaway.py b/telegram/_giveaway.py index 51ce026d81e..5ebd78bb661 100644 --- a/telegram/_giveaway.py +++ b/telegram/_giveaway.py @@ -24,7 +24,7 @@ from telegram._chat import Chat from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -144,7 +144,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Giveaway": # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chats"] = tuple(de_list_wo(data.get("chats"), Chat, bot)) + data["chats"] = tuple(de_list_optional(data.get("chats"), Chat, bot)) data["winners_selection_date"] = from_timestamp( data.get("winners_selection_date"), tzinfo=loc_tzinfo ) @@ -301,8 +301,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "GiveawayWinner # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["winners"] = tuple(de_list_wo(data.get("winners"), User, bot)) + data["chat"] = de_json_optional(data.get("chat"), Chat, bot) + data["winners"] = tuple(de_list_optional(data.get("winners"), User, bot)) data["winners_selection_date"] = from_timestamp( data.get("winners_selection_date"), tzinfo=loc_tzinfo ) @@ -373,6 +373,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "GiveawayComple # Unfortunately, this needs to be here due to cyclic imports from telegram._message import Message # pylint: disable=import-outside-toplevel - data["giveaway_message"] = de_json_wo(data.get("giveaway_message"), Message, bot) + data["giveaway_message"] = de_json_optional(data.get("giveaway_message"), Message, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_inline/inlinekeyboardbutton.py b/telegram/_inline/inlinekeyboardbutton.py index f05ab1cf3bc..07d0eed3b2d 100644 --- a/telegram/_inline/inlinekeyboardbutton.py +++ b/telegram/_inline/inlinekeyboardbutton.py @@ -26,7 +26,7 @@ from telegram._loginurl import LoginUrl from telegram._switchinlinequerychosenchat import SwitchInlineQueryChosenChat from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict from telegram._webappinfo import WebAppInfo @@ -301,13 +301,13 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "InlineKeyboard """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["login_url"] = de_json_wo(data.get("login_url"), LoginUrl, bot) - data["web_app"] = de_json_wo(data.get("web_app"), WebAppInfo, bot) - data["callback_game"] = de_json_wo(data.get("callback_game"), CallbackGame, bot) - data["switch_inline_query_chosen_chat"] = de_json_wo( + data["login_url"] = de_json_optional(data.get("login_url"), LoginUrl, bot) + data["web_app"] = de_json_optional(data.get("web_app"), WebAppInfo, bot) + data["callback_game"] = de_json_optional(data.get("callback_game"), CallbackGame, bot) + data["switch_inline_query_chosen_chat"] = de_json_optional( data.get("switch_inline_query_chosen_chat"), SwitchInlineQueryChosenChat, bot ) - data["copy_text"] = de_json_wo(data.get("copy_text"), CopyTextButton, bot) + data["copy_text"] = de_json_optional(data.get("copy_text"), CopyTextButton, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_inline/inlinequery.py b/telegram/_inline/inlinequery.py index 588fa883597..4cf7f5a7366 100644 --- a/telegram/_inline/inlinequery.py +++ b/telegram/_inline/inlinequery.py @@ -27,7 +27,7 @@ from telegram._inline.inlinequeryresultsbutton import InlineQueryResultsButton from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.types import JSONDict, ODVInput @@ -131,8 +131,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "InlineQuery": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["from_user"] = de_json_wo(data.pop("from", None), User, bot) - data["location"] = de_json_wo(data.get("location"), Location, bot) + data["from_user"] = de_json_optional(data.pop("from", None), User, bot) + data["location"] = de_json_optional(data.get("location"), Location, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_inline/inlinequeryresultsbutton.py b/telegram/_inline/inlinequeryresultsbutton.py index b665d016f21..513a366df9f 100644 --- a/telegram/_inline/inlinequeryresultsbutton.py +++ b/telegram/_inline/inlinequeryresultsbutton.py @@ -22,7 +22,7 @@ from telegram import constants from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict from telegram._webappinfo import WebAppInfo @@ -101,7 +101,7 @@ def __init__( def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "InlineQueryResultsButton": """See :meth:`telegram.TelegramObject.de_json`.""" - data["web_app"] = de_json_wo(data.get("web_app"), WebAppInfo, bot) + data["web_app"] = de_json_optional(data.get("web_app"), WebAppInfo, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_inline/inputinvoicemessagecontent.py b/telegram/_inline/inputinvoicemessagecontent.py index 577a28f4f20..11f248513ee 100644 --- a/telegram/_inline/inputinvoicemessagecontent.py +++ b/telegram/_inline/inputinvoicemessagecontent.py @@ -22,7 +22,7 @@ from telegram._inline.inputmessagecontent import InputMessageContent from telegram._payment.labeledprice import LabeledPrice -from telegram._utils.argumentparsing import de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_list_optional, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -258,6 +258,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "InputInvoiceMe """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["prices"] = de_list_wo(data.get("prices"), LabeledPrice, bot) + data["prices"] = de_list_optional(data.get("prices"), LabeledPrice, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_keyboardbutton.py b/telegram/_keyboardbutton.py index 2382f174a12..8fd29846946 100644 --- a/telegram/_keyboardbutton.py +++ b/telegram/_keyboardbutton.py @@ -23,7 +23,7 @@ from telegram._keyboardbuttonpolltype import KeyboardButtonPollType from telegram._keyboardbuttonrequest import KeyboardButtonRequestChat, KeyboardButtonRequestUsers from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict from telegram._webappinfo import WebAppInfo @@ -173,12 +173,16 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "KeyboardButton """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["request_poll"] = de_json_wo(data.get("request_poll"), KeyboardButtonPollType, bot) - data["request_users"] = de_json_wo( + data["request_poll"] = de_json_optional( + data.get("request_poll"), KeyboardButtonPollType, bot + ) + data["request_users"] = de_json_optional( data.get("request_users"), KeyboardButtonRequestUsers, bot ) - data["request_chat"] = de_json_wo(data.get("request_chat"), KeyboardButtonRequestChat, bot) - data["web_app"] = de_json_wo(data.get("web_app"), WebAppInfo, bot) + data["request_chat"] = de_json_optional( + data.get("request_chat"), KeyboardButtonRequestChat, bot + ) + data["web_app"] = de_json_optional(data.get("web_app"), WebAppInfo, bot) api_kwargs = {} # This is a deprecated field that TG still returns for backwards compatibility diff --git a/telegram/_keyboardbuttonrequest.py b/telegram/_keyboardbuttonrequest.py index a733eb87cf7..620e6e16911 100644 --- a/telegram/_keyboardbuttonrequest.py +++ b/telegram/_keyboardbuttonrequest.py @@ -22,7 +22,7 @@ from telegram._chatadministratorrights import ChatAdministratorRights from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -262,10 +262,10 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "KeyboardButton """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["user_administrator_rights"] = de_json_wo( + data["user_administrator_rights"] = de_json_optional( data.get("user_administrator_rights"), ChatAdministratorRights, bot ) - data["bot_administrator_rights"] = de_json_wo( + data["bot_administrator_rights"] = de_json_optional( data.get("bot_administrator_rights"), ChatAdministratorRights, bot ) diff --git a/telegram/_menubutton.py b/telegram/_menubutton.py index 20fffc01cd1..fb59a561d25 100644 --- a/telegram/_menubutton.py +++ b/telegram/_menubutton.py @@ -22,7 +22,7 @@ from telegram import constants from telegram._telegramobject import TelegramObject from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict from telegram._webappinfo import WebAppInfo @@ -169,7 +169,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MenuButtonWebA """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["web_app"] = de_json_wo(data.get("web_app"), WebAppInfo, bot) + data["web_app"] = de_json_optional(data.get("web_app"), WebAppInfo, bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] diff --git a/telegram/_message.py b/telegram/_message.py index 0f53febf6b4..f089851e969 100644 --- a/telegram/_message.py +++ b/telegram/_message.py @@ -65,7 +65,7 @@ from telegram._story import Story from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.defaultvalue import DEFAULT_NONE, DefaultValue from telegram._utils.entities import parse_message_entities, parse_message_entity @@ -205,7 +205,7 @@ def _de_json( else: data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["chat"] = de_json_optional(data.get("chat"), Chat, bot) return super()._de_json(data=data, bot=bot, api_kwargs=api_kwargs) @@ -1255,85 +1255,93 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Message": # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["from_user"] = de_json_wo(data.pop("from", None), User, bot) - data["sender_chat"] = de_json_wo(data.get("sender_chat"), Chat, bot) - data["entities"] = de_list_wo(data.get("entities"), MessageEntity, bot) - data["caption_entities"] = de_list_wo(data.get("caption_entities"), MessageEntity, bot) - data["reply_to_message"] = de_json_wo(data.get("reply_to_message"), Message, bot) + data["from_user"] = de_json_optional(data.pop("from", None), User, bot) + data["sender_chat"] = de_json_optional(data.get("sender_chat"), Chat, bot) + data["entities"] = de_list_optional(data.get("entities"), MessageEntity, bot) + data["caption_entities"] = de_list_optional( + data.get("caption_entities"), MessageEntity, bot + ) + data["reply_to_message"] = de_json_optional(data.get("reply_to_message"), Message, bot) data["edit_date"] = from_timestamp(data.get("edit_date"), tzinfo=loc_tzinfo) - data["audio"] = de_json_wo(data.get("audio"), Audio, bot) - data["document"] = de_json_wo(data.get("document"), Document, bot) - data["animation"] = de_json_wo(data.get("animation"), Animation, bot) - data["game"] = de_json_wo(data.get("game"), Game, bot) - data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) - data["sticker"] = de_json_wo(data.get("sticker"), Sticker, bot) - data["story"] = de_json_wo(data.get("story"), Story, bot) - data["video"] = de_json_wo(data.get("video"), Video, bot) - data["voice"] = de_json_wo(data.get("voice"), Voice, bot) - data["video_note"] = de_json_wo(data.get("video_note"), VideoNote, bot) - data["contact"] = de_json_wo(data.get("contact"), Contact, bot) - data["location"] = de_json_wo(data.get("location"), Location, bot) - data["venue"] = de_json_wo(data.get("venue"), Venue, bot) - data["new_chat_members"] = de_list_wo(data.get("new_chat_members"), User, bot) - data["left_chat_member"] = de_json_wo(data.get("left_chat_member"), User, bot) - data["new_chat_photo"] = de_list_wo(data.get("new_chat_photo"), PhotoSize, bot) - data["message_auto_delete_timer_changed"] = de_json_wo( + data["audio"] = de_json_optional(data.get("audio"), Audio, bot) + data["document"] = de_json_optional(data.get("document"), Document, bot) + data["animation"] = de_json_optional(data.get("animation"), Animation, bot) + data["game"] = de_json_optional(data.get("game"), Game, bot) + data["photo"] = de_list_optional(data.get("photo"), PhotoSize, bot) + data["sticker"] = de_json_optional(data.get("sticker"), Sticker, bot) + data["story"] = de_json_optional(data.get("story"), Story, bot) + data["video"] = de_json_optional(data.get("video"), Video, bot) + data["voice"] = de_json_optional(data.get("voice"), Voice, bot) + data["video_note"] = de_json_optional(data.get("video_note"), VideoNote, bot) + data["contact"] = de_json_optional(data.get("contact"), Contact, bot) + data["location"] = de_json_optional(data.get("location"), Location, bot) + data["venue"] = de_json_optional(data.get("venue"), Venue, bot) + data["new_chat_members"] = de_list_optional(data.get("new_chat_members"), User, bot) + data["left_chat_member"] = de_json_optional(data.get("left_chat_member"), User, bot) + data["new_chat_photo"] = de_list_optional(data.get("new_chat_photo"), PhotoSize, bot) + data["message_auto_delete_timer_changed"] = de_json_optional( data.get("message_auto_delete_timer_changed"), MessageAutoDeleteTimerChanged, bot ) - data["pinned_message"] = de_json_wo( + data["pinned_message"] = de_json_optional( data.get("pinned_message"), MaybeInaccessibleMessage, bot ) - data["invoice"] = de_json_wo(data.get("invoice"), Invoice, bot) - data["successful_payment"] = de_json_wo( + data["invoice"] = de_json_optional(data.get("invoice"), Invoice, bot) + data["successful_payment"] = de_json_optional( data.get("successful_payment"), SuccessfulPayment, bot ) - data["passport_data"] = de_json_wo(data.get("passport_data"), PassportData, bot) - data["poll"] = de_json_wo(data.get("poll"), Poll, bot) - data["dice"] = de_json_wo(data.get("dice"), Dice, bot) - data["via_bot"] = de_json_wo(data.get("via_bot"), User, bot) - data["proximity_alert_triggered"] = de_json_wo( + data["passport_data"] = de_json_optional(data.get("passport_data"), PassportData, bot) + data["poll"] = de_json_optional(data.get("poll"), Poll, bot) + data["dice"] = de_json_optional(data.get("dice"), Dice, bot) + data["via_bot"] = de_json_optional(data.get("via_bot"), User, bot) + data["proximity_alert_triggered"] = de_json_optional( data.get("proximity_alert_triggered"), ProximityAlertTriggered, bot ) - data["reply_markup"] = de_json_wo(data.get("reply_markup"), InlineKeyboardMarkup, bot) - data["video_chat_scheduled"] = de_json_wo( + data["reply_markup"] = de_json_optional( + data.get("reply_markup"), InlineKeyboardMarkup, bot + ) + data["video_chat_scheduled"] = de_json_optional( data.get("video_chat_scheduled"), VideoChatScheduled, bot ) - data["video_chat_started"] = de_json_wo( + data["video_chat_started"] = de_json_optional( data.get("video_chat_started"), VideoChatStarted, bot ) - data["video_chat_ended"] = de_json_wo(data.get("video_chat_ended"), VideoChatEnded, bot) - data["video_chat_participants_invited"] = de_json_wo( + data["video_chat_ended"] = de_json_optional( + data.get("video_chat_ended"), VideoChatEnded, bot + ) + data["video_chat_participants_invited"] = de_json_optional( data.get("video_chat_participants_invited"), VideoChatParticipantsInvited, bot ) - data["web_app_data"] = de_json_wo(data.get("web_app_data"), WebAppData, bot) - data["forum_topic_closed"] = de_json_wo( + data["web_app_data"] = de_json_optional(data.get("web_app_data"), WebAppData, bot) + data["forum_topic_closed"] = de_json_optional( data.get("forum_topic_closed"), ForumTopicClosed, bot ) - data["forum_topic_created"] = de_json_wo( + data["forum_topic_created"] = de_json_optional( data.get("forum_topic_created"), ForumTopicCreated, bot ) - data["forum_topic_reopened"] = de_json_wo( + data["forum_topic_reopened"] = de_json_optional( data.get("forum_topic_reopened"), ForumTopicReopened, bot ) - data["forum_topic_edited"] = de_json_wo( + data["forum_topic_edited"] = de_json_optional( data.get("forum_topic_edited"), ForumTopicEdited, bot ) - data["general_forum_topic_hidden"] = de_json_wo( + data["general_forum_topic_hidden"] = de_json_optional( data.get("general_forum_topic_hidden"), GeneralForumTopicHidden, bot ) - data["general_forum_topic_unhidden"] = de_json_wo( + data["general_forum_topic_unhidden"] = de_json_optional( data.get("general_forum_topic_unhidden"), GeneralForumTopicUnhidden, bot ) - data["write_access_allowed"] = de_json_wo( + data["write_access_allowed"] = de_json_optional( data.get("write_access_allowed"), WriteAccessAllowed, bot ) - data["users_shared"] = de_json_wo(data.get("users_shared"), UsersShared, bot) - data["chat_shared"] = de_json_wo(data.get("chat_shared"), ChatShared, bot) - data["chat_background_set"] = de_json_wo( + data["users_shared"] = de_json_optional(data.get("users_shared"), UsersShared, bot) + data["chat_shared"] = de_json_optional(data.get("chat_shared"), ChatShared, bot) + data["chat_background_set"] = de_json_optional( data.get("chat_background_set"), ChatBackground, bot ) - data["paid_media"] = de_json_wo(data.get("paid_media"), PaidMediaInfo, bot) - data["refunded_payment"] = de_json_wo(data.get("refunded_payment"), RefundedPayment, bot) + data["paid_media"] = de_json_optional(data.get("paid_media"), PaidMediaInfo, bot) + data["refunded_payment"] = de_json_optional( + data.get("refunded_payment"), RefundedPayment, bot + ) # Unfortunately, this needs to be here due to cyclic imports from telegram._giveaway import ( # pylint: disable=import-outside-toplevel @@ -1350,21 +1358,27 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Message": TextQuote, ) - data["giveaway"] = de_json_wo(data.get("giveaway"), Giveaway, bot) - data["giveaway_completed"] = de_json_wo( + data["giveaway"] = de_json_optional(data.get("giveaway"), Giveaway, bot) + data["giveaway_completed"] = de_json_optional( data.get("giveaway_completed"), GiveawayCompleted, bot ) - data["giveaway_created"] = de_json_wo(data.get("giveaway_created"), GiveawayCreated, bot) - data["giveaway_winners"] = de_json_wo(data.get("giveaway_winners"), GiveawayWinners, bot) - data["link_preview_options"] = de_json_wo( + data["giveaway_created"] = de_json_optional( + data.get("giveaway_created"), GiveawayCreated, bot + ) + data["giveaway_winners"] = de_json_optional( + data.get("giveaway_winners"), GiveawayWinners, bot + ) + data["link_preview_options"] = de_json_optional( data.get("link_preview_options"), LinkPreviewOptions, bot ) - data["external_reply"] = de_json_wo(data.get("external_reply"), ExternalReplyInfo, bot) - data["quote"] = de_json_wo(data.get("quote"), TextQuote, bot) - data["forward_origin"] = de_json_wo(data.get("forward_origin"), MessageOrigin, bot) - data["reply_to_story"] = de_json_wo(data.get("reply_to_story"), Story, bot) - data["boost_added"] = de_json_wo(data.get("boost_added"), ChatBoostAdded, bot) - data["sender_business_bot"] = de_json_wo(data.get("sender_business_bot"), User, bot) + data["external_reply"] = de_json_optional( + data.get("external_reply"), ExternalReplyInfo, bot + ) + data["quote"] = de_json_optional(data.get("quote"), TextQuote, bot) + data["forward_origin"] = de_json_optional(data.get("forward_origin"), MessageOrigin, bot) + data["reply_to_story"] = de_json_optional(data.get("reply_to_story"), Story, bot) + data["boost_added"] = de_json_optional(data.get("boost_added"), ChatBoostAdded, bot) + data["sender_business_bot"] = de_json_optional(data.get("sender_business_bot"), User, bot) api_kwargs = {} # This is a deprecated field that TG still returns for backwards compatibility diff --git a/telegram/_messageentity.py b/telegram/_messageentity.py index 04824a4a66f..10c90093f6d 100644 --- a/telegram/_messageentity.py +++ b/telegram/_messageentity.py @@ -27,7 +27,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.strings import TextEncoding from telegram._utils.types import JSONDict @@ -142,7 +142,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageEntity" """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["user"] = de_json_wo(data.get("user"), User, bot) + data["user"] = de_json_optional(data.get("user"), User, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_messageorigin.py b/telegram/_messageorigin.py index d3577d1d4bb..9838d6bea7c 100644 --- a/telegram/_messageorigin.py +++ b/telegram/_messageorigin.py @@ -25,7 +25,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -114,13 +114,13 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageOrigin" data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) if "sender_user" in data: - data["sender_user"] = de_json_wo(data.get("sender_user"), User, bot) + data["sender_user"] = de_json_optional(data.get("sender_user"), User, bot) if "sender_chat" in data: - data["sender_chat"] = de_json_wo(data.get("sender_chat"), Chat, bot) + data["sender_chat"] = de_json_optional(data.get("sender_chat"), Chat, bot) if "chat" in data: - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) + data["chat"] = de_json_optional(data.get("chat"), Chat, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_messagereactionupdated.py b/telegram/_messagereactionupdated.py index 664728d415a..b1b33851454 100644 --- a/telegram/_messagereactionupdated.py +++ b/telegram/_messagereactionupdated.py @@ -25,7 +25,7 @@ from telegram._reaction import ReactionCount, ReactionType from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -94,8 +94,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageReactio loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["reactions"] = de_list_wo(data.get("reactions"), ReactionCount, bot) + data["chat"] = de_json_optional(data.get("chat"), Chat, bot) + data["reactions"] = de_list_optional(data.get("reactions"), ReactionCount, bot) return super().de_json(data=data, bot=bot) @@ -190,10 +190,10 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "MessageReactio loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date"), tzinfo=loc_tzinfo) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["old_reaction"] = de_list_wo(data.get("old_reaction"), ReactionType, bot) - data["new_reaction"] = de_list_wo(data.get("new_reaction"), ReactionType, bot) - data["user"] = de_json_wo(data.get("user"), User, bot) - data["actor_chat"] = de_json_wo(data.get("actor_chat"), Chat, bot) + data["chat"] = de_json_optional(data.get("chat"), Chat, bot) + data["old_reaction"] = de_list_optional(data.get("old_reaction"), ReactionType, bot) + data["new_reaction"] = de_list_optional(data.get("new_reaction"), ReactionType, bot) + data["user"] = de_json_optional(data.get("user"), User, bot) + data["actor_chat"] = de_json_optional(data.get("actor_chat"), Chat, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_paidmedia.py b/telegram/_paidmedia.py index 415f7f93b70..972c46fa333 100644 --- a/telegram/_paidmedia.py +++ b/telegram/_paidmedia.py @@ -27,7 +27,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -180,7 +180,7 @@ def __init__( def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PaidMediaPhoto": data = cls._parse_data(data) - data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) + data["photo"] = de_list_optional(data.get("photo"), PhotoSize, bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] @@ -221,7 +221,7 @@ def __init__( def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PaidMediaVideo": data = cls._parse_data(data) - data["video"] = de_json_wo(data.get("video"), Video, bot) + data["video"] = de_json_optional(data.get("video"), Video, bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] @@ -265,7 +265,7 @@ def __init__( def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PaidMediaInfo": data = cls._parse_data(data) - data["paid_media"] = de_list_wo(data.get("paid_media"), PaidMedia, bot) + data["paid_media"] = de_list_optional(data.get("paid_media"), PaidMedia, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_passport/credentials.py b/telegram/_passport/credentials.py index a32ee788563..11bd2d92d43 100644 --- a/telegram/_passport/credentials.py +++ b/telegram/_passport/credentials.py @@ -39,7 +39,7 @@ CRYPTO_INSTALLED = False from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.strings import TextEncoding from telegram._utils.types import JSONDict from telegram.error import PassportDecryptionError @@ -238,7 +238,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Credentials": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["secure_data"] = de_json_wo(data.get("secure_data"), SecureData, bot) + data["secure_data"] = de_json_optional(data.get("secure_data"), SecureData, bot) return super().de_json(data=data, bot=bot) @@ -345,21 +345,23 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "SecureData": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["temporary_registration"] = de_json_wo( + data["temporary_registration"] = de_json_optional( data.get("temporary_registration"), SecureValue, bot ) - data["passport_registration"] = de_json_wo( + data["passport_registration"] = de_json_optional( data.get("passport_registration"), SecureValue, bot ) - data["rental_agreement"] = de_json_wo(data.get("rental_agreement"), SecureValue, bot) - data["bank_statement"] = de_json_wo(data.get("bank_statement"), SecureValue, bot) - data["utility_bill"] = de_json_wo(data.get("utility_bill"), SecureValue, bot) - data["address"] = de_json_wo(data.get("address"), SecureValue, bot) - data["identity_card"] = de_json_wo(data.get("identity_card"), SecureValue, bot) - data["driver_license"] = de_json_wo(data.get("driver_license"), SecureValue, bot) - data["internal_passport"] = de_json_wo(data.get("internal_passport"), SecureValue, bot) - data["passport"] = de_json_wo(data.get("passport"), SecureValue, bot) - data["personal_details"] = de_json_wo(data.get("personal_details"), SecureValue, bot) + data["rental_agreement"] = de_json_optional(data.get("rental_agreement"), SecureValue, bot) + data["bank_statement"] = de_json_optional(data.get("bank_statement"), SecureValue, bot) + data["utility_bill"] = de_json_optional(data.get("utility_bill"), SecureValue, bot) + data["address"] = de_json_optional(data.get("address"), SecureValue, bot) + data["identity_card"] = de_json_optional(data.get("identity_card"), SecureValue, bot) + data["driver_license"] = de_json_optional(data.get("driver_license"), SecureValue, bot) + data["internal_passport"] = de_json_optional( + data.get("internal_passport"), SecureValue, bot + ) + data["passport"] = de_json_optional(data.get("passport"), SecureValue, bot) + data["personal_details"] = de_json_optional(data.get("personal_details"), SecureValue, bot) return super().de_json(data=data, bot=bot) @@ -448,12 +450,12 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "SecureValue": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["data"] = de_json_wo(data.get("data"), DataCredentials, bot) - data["front_side"] = de_json_wo(data.get("front_side"), FileCredentials, bot) - data["reverse_side"] = de_json_wo(data.get("reverse_side"), FileCredentials, bot) - data["selfie"] = de_json_wo(data.get("selfie"), FileCredentials, bot) - data["files"] = de_list_wo(data.get("files"), FileCredentials, bot) - data["translation"] = de_list_wo(data.get("translation"), FileCredentials, bot) + data["data"] = de_json_optional(data.get("data"), DataCredentials, bot) + data["front_side"] = de_json_optional(data.get("front_side"), FileCredentials, bot) + data["reverse_side"] = de_json_optional(data.get("reverse_side"), FileCredentials, bot) + data["selfie"] = de_json_optional(data.get("selfie"), FileCredentials, bot) + data["files"] = de_list_optional(data.get("files"), FileCredentials, bot) + data["translation"] = de_list_optional(data.get("translation"), FileCredentials, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_passport/encryptedpassportelement.py b/telegram/_passport/encryptedpassportelement.py index 06bd7d5fe6f..ae7e6517ac9 100644 --- a/telegram/_passport/encryptedpassportelement.py +++ b/telegram/_passport/encryptedpassportelement.py @@ -26,10 +26,10 @@ from telegram._passport.passportfile import PassportFile from telegram._telegramobject import TelegramObject from telegram._utils.argumentparsing import ( - de_json_decrypted_wo, - de_json_wo, - de_list_decrypted_wo, - de_list_wo, + de_json_decrypted_optional, + de_json_optional, + de_list_decrypted_optional, + de_list_optional, parse_sequence_arg, ) from telegram._utils.types import JSONDict @@ -204,11 +204,11 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "EncryptedPassp """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["files"] = de_list_wo(data.get("files"), PassportFile, bot) or None - data["front_side"] = de_json_wo(data.get("front_side"), PassportFile, bot) - data["reverse_side"] = de_json_wo(data.get("reverse_side"), PassportFile, bot) - data["selfie"] = de_json_wo(data.get("selfie"), PassportFile, bot) - data["translation"] = de_list_wo(data.get("translation"), PassportFile, bot) or None + data["files"] = de_list_optional(data.get("files"), PassportFile, bot) or None + data["front_side"] = de_json_optional(data.get("front_side"), PassportFile, bot) + data["reverse_side"] = de_json_optional(data.get("reverse_side"), PassportFile, bot) + data["selfie"] = de_json_optional(data.get("selfie"), PassportFile, bot) + data["translation"] = de_list_optional(data.get("translation"), PassportFile, bot) or None return super().de_json(data=data, bot=bot) @@ -260,20 +260,20 @@ def de_json_decrypted( data["data"] = ResidentialAddress.de_json(data["data"], bot=bot) data["files"] = ( - de_list_decrypted_wo(data.get("files"), PassportFile, bot, secure_data.files) + de_list_decrypted_optional(data.get("files"), PassportFile, bot, secure_data.files) or None ) - data["front_side"] = de_json_decrypted_wo( + data["front_side"] = de_json_decrypted_optional( data.get("front_side"), PassportFile, bot, secure_data.front_side ) - data["reverse_side"] = de_json_decrypted_wo( + data["reverse_side"] = de_json_decrypted_optional( data.get("reverse_side"), PassportFile, bot, secure_data.reverse_side ) - data["selfie"] = de_json_decrypted_wo( + data["selfie"] = de_json_decrypted_optional( data.get("selfie"), PassportFile, bot, secure_data.selfie ) data["translation"] = ( - de_list_decrypted_wo( + de_list_decrypted_optional( data.get("translation"), PassportFile, bot, secure_data.translation ) or None diff --git a/telegram/_passport/passportdata.py b/telegram/_passport/passportdata.py index 55f243c7ec9..fff227a04b6 100644 --- a/telegram/_passport/passportdata.py +++ b/telegram/_passport/passportdata.py @@ -23,7 +23,7 @@ from telegram._passport.credentials import EncryptedCredentials from telegram._passport.encryptedpassportelement import EncryptedPassportElement from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -86,8 +86,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PassportData": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["data"] = de_list_wo(data.get("data"), EncryptedPassportElement, bot) - data["credentials"] = de_json_wo(data.get("credentials"), EncryptedCredentials, bot) + data["data"] = de_list_optional(data.get("data"), EncryptedPassportElement, bot) + data["credentials"] = de_json_optional(data.get("credentials"), EncryptedCredentials, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/orderinfo.py b/telegram/_payment/orderinfo.py index 4b2e3e398c1..ac963cacd87 100644 --- a/telegram/_payment/orderinfo.py +++ b/telegram/_payment/orderinfo.py @@ -22,7 +22,7 @@ from telegram._payment.shippingaddress import ShippingAddress from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -76,6 +76,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "OrderInfo": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["shipping_address"] = de_json_wo(data.get("shipping_address"), ShippingAddress, bot) + data["shipping_address"] = de_json_optional( + data.get("shipping_address"), ShippingAddress, bot + ) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/precheckoutquery.py b/telegram/_payment/precheckoutquery.py index 3cc2a351f17..b3d2c0241e0 100644 --- a/telegram/_payment/precheckoutquery.py +++ b/telegram/_payment/precheckoutquery.py @@ -23,7 +23,7 @@ from telegram._payment.orderinfo import OrderInfo from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.types import JSONDict, ODVInput @@ -115,8 +115,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PreCheckoutQue """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["from_user"] = de_json_wo(data.pop("from", None), User, bot) - data["order_info"] = de_json_wo(data.get("order_info"), OrderInfo, bot) + data["from_user"] = de_json_optional(data.pop("from", None), User, bot) + data["order_info"] = de_json_optional(data.get("order_info"), OrderInfo, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/shippingquery.py b/telegram/_payment/shippingquery.py index 81b85eb1b34..a31f7633de3 100644 --- a/telegram/_payment/shippingquery.py +++ b/telegram/_payment/shippingquery.py @@ -24,7 +24,7 @@ from telegram._payment.shippingaddress import ShippingAddress from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.types import JSONDict, ODVInput @@ -83,8 +83,10 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ShippingQuery" """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["from_user"] = de_json_wo(data.pop("from", None), User, bot) - data["shipping_address"] = de_json_wo(data.get("shipping_address"), ShippingAddress, bot) + data["from_user"] = de_json_optional(data.pop("from", None), User, bot) + data["shipping_address"] = de_json_optional( + data.get("shipping_address"), ShippingAddress, bot + ) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/stars/affiliateinfo.py b/telegram/_payment/stars/affiliateinfo.py index f0f7df531c2..80349290b44 100644 --- a/telegram/_payment/stars/affiliateinfo.py +++ b/telegram/_payment/stars/affiliateinfo.py @@ -22,7 +22,7 @@ from telegram._chat import Chat from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -110,7 +110,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "AffiliateInfo" """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["affiliate_user"] = de_json_wo(data.get("affiliate_user"), User, bot) - data["affiliate_chat"] = de_json_wo(data.get("affiliate_chat"), Chat, bot) + data["affiliate_user"] = de_json_optional(data.get("affiliate_user"), User, bot) + data["affiliate_chat"] = de_json_optional(data.get("affiliate_chat"), Chat, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/stars/startransactions.py b/telegram/_payment/stars/startransactions.py index f0ecb865e72..6578cdd5a48 100644 --- a/telegram/_payment/stars/startransactions.py +++ b/telegram/_payment/stars/startransactions.py @@ -24,7 +24,7 @@ from typing import TYPE_CHECKING, Optional from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -120,8 +120,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "StarTransactio loc_tzinfo = extract_tzinfo_from_defaults(bot) data["date"] = from_timestamp(data.get("date", None), tzinfo=loc_tzinfo) - data["source"] = de_json_wo(data.get("source"), TransactionPartner, bot) - data["receiver"] = de_json_wo(data.get("receiver"), TransactionPartner, bot) + data["source"] = de_json_optional(data.get("source"), TransactionPartner, bot) + data["receiver"] = de_json_optional(data.get("receiver"), TransactionPartner, bot) return super().de_json(data=data, bot=bot) @@ -158,5 +158,5 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "StarTransactio """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["transactions"] = de_list_wo(data.get("transactions"), StarTransaction, bot) + data["transactions"] = de_list_optional(data.get("transactions"), StarTransaction, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_payment/stars/transactionpartner.py b/telegram/_payment/stars/transactionpartner.py index 2266208c453..860fccff17d 100644 --- a/telegram/_payment/stars/transactionpartner.py +++ b/telegram/_payment/stars/transactionpartner.py @@ -28,7 +28,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.types import JSONDict from .affiliateinfo import AffiliateInfo @@ -166,7 +166,7 @@ def de_json( """See :meth:`telegram.TransactionPartner.de_json`.""" data = cls._parse_data(data) - data["sponsor_user"] = de_json_wo(data.get("sponsor_user"), User, bot) + data["sponsor_user"] = de_json_optional(data.get("sponsor_user"), User, bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] @@ -205,7 +205,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "TransactionPar """See :meth:`telegram.TransactionPartner.de_json`.""" data = cls._parse_data(data) - data["withdrawal_state"] = de_json_wo( + data["withdrawal_state"] = de_json_optional( data.get("withdrawal_state"), RevenueWithdrawalState, bot ) @@ -311,15 +311,15 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "TransactionPar """See :meth:`telegram.TransactionPartner.de_json`.""" data = cls._parse_data(data) - data["user"] = de_json_wo(data.get("user"), User, bot) - data["affiliate"] = de_json_wo(data.get("affiliate"), AffiliateInfo, bot) - data["paid_media"] = de_list_wo(data.get("paid_media"), PaidMedia, bot) + data["user"] = de_json_optional(data.get("user"), User, bot) + data["affiliate"] = de_json_optional(data.get("affiliate"), AffiliateInfo, bot) + data["paid_media"] = de_list_optional(data.get("paid_media"), PaidMedia, bot) data["subscription_period"] = ( dtm.timedelta(seconds=sp) if (sp := data.get("subscription_period")) is not None else None ) - data["gift"] = de_json_wo(data.get("gift"), Gift, bot) + data["gift"] = de_json_optional(data.get("gift"), Gift, bot) return super().de_json(data=data, bot=bot) # type: ignore[return-value] diff --git a/telegram/_payment/successfulpayment.py b/telegram/_payment/successfulpayment.py index f4498488373..e7e72a24e3b 100644 --- a/telegram/_payment/successfulpayment.py +++ b/telegram/_payment/successfulpayment.py @@ -23,7 +23,7 @@ from telegram._payment.orderinfo import OrderInfo from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.types import JSONDict @@ -143,7 +143,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "SuccessfulPaym """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["order_info"] = de_json_wo(data.get("order_info"), OrderInfo, bot) + data["order_info"] = de_json_optional(data.get("order_info"), OrderInfo, bot) # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) diff --git a/telegram/_poll.py b/telegram/_poll.py index c5f1dd85949..8ecdc4105f9 100644 --- a/telegram/_poll.py +++ b/telegram/_poll.py @@ -27,7 +27,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.datetime import extract_tzinfo_from_defaults, from_timestamp from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.entities import parse_message_entities, parse_message_entity @@ -95,7 +95,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "InputPollOptio """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["text_entities"] = de_list_wo(data.get("text_entities"), MessageEntity, bot) + data["text_entities"] = de_list_optional(data.get("text_entities"), MessageEntity, bot) return super().de_json(data=data, bot=bot) @@ -156,7 +156,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PollOption": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["text_entities"] = de_list_wo(data.get("text_entities"), MessageEntity, bot) + data["text_entities"] = de_list_optional(data.get("text_entities"), MessageEntity, bot) return super().de_json(data=data, bot=bot) @@ -300,8 +300,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "PollAnswer": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["user"] = de_json_wo(data.get("user"), User, bot) - data["voter_chat"] = de_json_wo(data.get("voter_chat"), Chat, bot) + data["user"] = de_json_optional(data.get("user"), User, bot) + data["voter_chat"] = de_json_optional(data.get("voter_chat"), Chat, bot) return super().de_json(data=data, bot=bot) @@ -466,12 +466,14 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Poll": # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["options"] = de_list_wo(data.get("options"), PollOption, bot) - data["explanation_entities"] = de_list_wo( + data["options"] = de_list_optional(data.get("options"), PollOption, bot) + data["explanation_entities"] = de_list_optional( data.get("explanation_entities"), MessageEntity, bot ) data["close_date"] = from_timestamp(data.get("close_date"), tzinfo=loc_tzinfo) - data["question_entities"] = de_list_wo(data.get("question_entities"), MessageEntity, bot) + data["question_entities"] = de_list_optional( + data.get("question_entities"), MessageEntity, bot + ) return super().de_json(data=data, bot=bot) diff --git a/telegram/_proximityalerttriggered.py b/telegram/_proximityalerttriggered.py index 39d0b238a18..c9e00ef1bf0 100644 --- a/telegram/_proximityalerttriggered.py +++ b/telegram/_proximityalerttriggered.py @@ -21,7 +21,7 @@ from telegram._telegramobject import TelegramObject from telegram._user import User -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -72,7 +72,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ProximityAlert """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["traveler"] = de_json_wo(data.get("traveler"), User, bot) - data["watcher"] = de_json_wo(data.get("watcher"), User, bot) + data["traveler"] = de_json_optional(data.get("traveler"), User, bot) + data["watcher"] = de_json_optional(data.get("watcher"), User, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_reaction.py b/telegram/_reaction.py index af443691bd8..6e1e3fb79af 100644 --- a/telegram/_reaction.py +++ b/telegram/_reaction.py @@ -23,7 +23,7 @@ from telegram import constants from telegram._telegramobject import TelegramObject from telegram._utils import enum -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -227,6 +227,6 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ReactionCount" """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["type"] = de_json_wo(data.get("type"), ReactionType, bot) + data["type"] = de_json_optional(data.get("type"), ReactionType, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_reply.py b/telegram/_reply.py index c2432ce9412..a5192135c6d 100644 --- a/telegram/_reply.py +++ b/telegram/_reply.py @@ -43,7 +43,7 @@ from telegram._poll import Poll from telegram._story import Story from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo, de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_json_optional, de_list_optional, parse_sequence_arg from telegram._utils.defaultvalue import DEFAULT_NONE from telegram._utils.types import JSONDict, ODVInput @@ -252,30 +252,32 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ExternalReplyI """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["origin"] = de_json_wo(data.get("origin"), MessageOrigin, bot) - data["chat"] = de_json_wo(data.get("chat"), Chat, bot) - data["link_preview_options"] = de_json_wo( + data["origin"] = de_json_optional(data.get("origin"), MessageOrigin, bot) + data["chat"] = de_json_optional(data.get("chat"), Chat, bot) + data["link_preview_options"] = de_json_optional( data.get("link_preview_options"), LinkPreviewOptions, bot ) - data["animation"] = de_json_wo(data.get("animation"), Animation, bot) - data["audio"] = de_json_wo(data.get("audio"), Audio, bot) - data["document"] = de_json_wo(data.get("document"), Document, bot) - data["photo"] = tuple(de_list_wo(data.get("photo"), PhotoSize, bot)) - data["sticker"] = de_json_wo(data.get("sticker"), Sticker, bot) - data["story"] = de_json_wo(data.get("story"), Story, bot) - data["video"] = de_json_wo(data.get("video"), Video, bot) - data["video_note"] = de_json_wo(data.get("video_note"), VideoNote, bot) - data["voice"] = de_json_wo(data.get("voice"), Voice, bot) - data["contact"] = de_json_wo(data.get("contact"), Contact, bot) - data["dice"] = de_json_wo(data.get("dice"), Dice, bot) - data["game"] = de_json_wo(data.get("game"), Game, bot) - data["giveaway"] = de_json_wo(data.get("giveaway"), Giveaway, bot) - data["giveaway_winners"] = de_json_wo(data.get("giveaway_winners"), GiveawayWinners, bot) - data["invoice"] = de_json_wo(data.get("invoice"), Invoice, bot) - data["location"] = de_json_wo(data.get("location"), Location, bot) - data["poll"] = de_json_wo(data.get("poll"), Poll, bot) - data["venue"] = de_json_wo(data.get("venue"), Venue, bot) - data["paid_media"] = de_json_wo(data.get("paid_media"), PaidMediaInfo, bot) + data["animation"] = de_json_optional(data.get("animation"), Animation, bot) + data["audio"] = de_json_optional(data.get("audio"), Audio, bot) + data["document"] = de_json_optional(data.get("document"), Document, bot) + data["photo"] = tuple(de_list_optional(data.get("photo"), PhotoSize, bot)) + data["sticker"] = de_json_optional(data.get("sticker"), Sticker, bot) + data["story"] = de_json_optional(data.get("story"), Story, bot) + data["video"] = de_json_optional(data.get("video"), Video, bot) + data["video_note"] = de_json_optional(data.get("video_note"), VideoNote, bot) + data["voice"] = de_json_optional(data.get("voice"), Voice, bot) + data["contact"] = de_json_optional(data.get("contact"), Contact, bot) + data["dice"] = de_json_optional(data.get("dice"), Dice, bot) + data["game"] = de_json_optional(data.get("game"), Game, bot) + data["giveaway"] = de_json_optional(data.get("giveaway"), Giveaway, bot) + data["giveaway_winners"] = de_json_optional( + data.get("giveaway_winners"), GiveawayWinners, bot + ) + data["invoice"] = de_json_optional(data.get("invoice"), Invoice, bot) + data["location"] = de_json_optional(data.get("location"), Location, bot) + data["poll"] = de_json_optional(data.get("poll"), Poll, bot) + data["venue"] = de_json_optional(data.get("venue"), Venue, bot) + data["paid_media"] = de_json_optional(data.get("paid_media"), PaidMediaInfo, bot) return super().de_json(data=data, bot=bot) @@ -349,7 +351,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "TextQuote": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["entities"] = tuple(de_list_wo(data.get("entities"), MessageEntity, bot)) + data["entities"] = tuple(de_list_optional(data.get("entities"), MessageEntity, bot)) return super().de_json(data=data, bot=bot) @@ -452,6 +454,8 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ReplyParameter """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["quote_entities"] = tuple(de_list_wo(data.get("quote_entities"), MessageEntity, bot)) + data["quote_entities"] = tuple( + de_list_optional(data.get("quote_entities"), MessageEntity, bot) + ) return super().de_json(data=data, bot=bot) diff --git a/telegram/_shared.py b/telegram/_shared.py index 6971f9cd939..9c0d3684ec2 100644 --- a/telegram/_shared.py +++ b/telegram/_shared.py @@ -22,7 +22,7 @@ from telegram._files.photosize import PhotoSize from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_list_wo, parse_sequence_arg +from telegram._utils.argumentparsing import de_list_optional, parse_sequence_arg from telegram._utils.types import JSONDict if TYPE_CHECKING: @@ -88,7 +88,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "UsersShared": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["users"] = de_list_wo(data.get("users"), SharedUser, bot) + data["users"] = de_list_optional(data.get("users"), SharedUser, bot) api_kwargs = {} # This is a deprecated field that TG still returns for backwards compatibility @@ -174,7 +174,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ChatShared": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) + data["photo"] = de_list_optional(data.get("photo"), PhotoSize, bot) return super().de_json(data=data, bot=bot) @@ -249,5 +249,5 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "SharedUser": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["photo"] = de_list_wo(data.get("photo"), PhotoSize, bot) + data["photo"] = de_list_optional(data.get("photo"), PhotoSize, bot) return super().de_json(data=data, bot=bot) diff --git a/telegram/_update.py b/telegram/_update.py index a43c7234d0c..d1627ff81d3 100644 --- a/telegram/_update.py +++ b/telegram/_update.py @@ -35,7 +35,7 @@ from telegram._payment.shippingquery import ShippingQuery from telegram._poll import Poll, PollAnswer from telegram._telegramobject import TelegramObject -from telegram._utils.argumentparsing import de_json_wo +from telegram._utils.argumentparsing import de_json_optional from telegram._utils.types import JSONDict from telegram._utils.warnings import warn @@ -762,45 +762,51 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Update": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["message"] = de_json_wo(data.get("message"), Message, bot) - data["edited_message"] = de_json_wo(data.get("edited_message"), Message, bot) - data["inline_query"] = de_json_wo(data.get("inline_query"), InlineQuery, bot) - data["chosen_inline_result"] = de_json_wo( + data["message"] = de_json_optional(data.get("message"), Message, bot) + data["edited_message"] = de_json_optional(data.get("edited_message"), Message, bot) + data["inline_query"] = de_json_optional(data.get("inline_query"), InlineQuery, bot) + data["chosen_inline_result"] = de_json_optional( data.get("chosen_inline_result"), ChosenInlineResult, bot ) - data["callback_query"] = de_json_wo(data.get("callback_query"), CallbackQuery, bot) - data["shipping_query"] = de_json_wo(data.get("shipping_query"), ShippingQuery, bot) - data["pre_checkout_query"] = de_json_wo( + data["callback_query"] = de_json_optional(data.get("callback_query"), CallbackQuery, bot) + data["shipping_query"] = de_json_optional(data.get("shipping_query"), ShippingQuery, bot) + data["pre_checkout_query"] = de_json_optional( data.get("pre_checkout_query"), PreCheckoutQuery, bot ) - data["channel_post"] = de_json_wo(data.get("channel_post"), Message, bot) - data["edited_channel_post"] = de_json_wo(data.get("edited_channel_post"), Message, bot) - data["poll"] = de_json_wo(data.get("poll"), Poll, bot) - data["poll_answer"] = de_json_wo(data.get("poll_answer"), PollAnswer, bot) - data["my_chat_member"] = de_json_wo(data.get("my_chat_member"), ChatMemberUpdated, bot) - data["chat_member"] = de_json_wo(data.get("chat_member"), ChatMemberUpdated, bot) - data["chat_join_request"] = de_json_wo(data.get("chat_join_request"), ChatJoinRequest, bot) - data["chat_boost"] = de_json_wo(data.get("chat_boost"), ChatBoostUpdated, bot) - data["removed_chat_boost"] = de_json_wo( + data["channel_post"] = de_json_optional(data.get("channel_post"), Message, bot) + data["edited_channel_post"] = de_json_optional( + data.get("edited_channel_post"), Message, bot + ) + data["poll"] = de_json_optional(data.get("poll"), Poll, bot) + data["poll_answer"] = de_json_optional(data.get("poll_answer"), PollAnswer, bot) + data["my_chat_member"] = de_json_optional( + data.get("my_chat_member"), ChatMemberUpdated, bot + ) + data["chat_member"] = de_json_optional(data.get("chat_member"), ChatMemberUpdated, bot) + data["chat_join_request"] = de_json_optional( + data.get("chat_join_request"), ChatJoinRequest, bot + ) + data["chat_boost"] = de_json_optional(data.get("chat_boost"), ChatBoostUpdated, bot) + data["removed_chat_boost"] = de_json_optional( data.get("removed_chat_boost"), ChatBoostRemoved, bot ) - data["message_reaction"] = de_json_wo( + data["message_reaction"] = de_json_optional( data.get("message_reaction"), MessageReactionUpdated, bot ) - data["message_reaction_count"] = de_json_wo( + data["message_reaction_count"] = de_json_optional( data.get("message_reaction_count"), MessageReactionCountUpdated, bot ) - data["business_connection"] = de_json_wo( + data["business_connection"] = de_json_optional( data.get("business_connection"), BusinessConnection, bot ) - data["business_message"] = de_json_wo(data.get("business_message"), Message, bot) - data["edited_business_message"] = de_json_wo( + data["business_message"] = de_json_optional(data.get("business_message"), Message, bot) + data["edited_business_message"] = de_json_optional( data.get("edited_business_message"), Message, bot ) - data["deleted_business_messages"] = de_json_wo( + data["deleted_business_messages"] = de_json_optional( data.get("deleted_business_messages"), BusinessMessagesDeleted, bot ) - data["purchased_paid_media"] = de_json_wo( + data["purchased_paid_media"] = de_json_optional( data.get("purchased_paid_media"), PaidMediaPurchased, bot ) diff --git a/telegram/_utils/argumentparsing.py b/telegram/_utils/argumentparsing.py index 38b9e453a04..84ca1bc6a2f 100644 --- a/telegram/_utils/argumentparsing.py +++ b/telegram/_utils/argumentparsing.py @@ -94,7 +94,7 @@ def de_list_decrypted( ) -> tuple[TeleCrypto_co, ...]: ... -def de_json_wo( +def de_json_optional( data: Optional[JSONDict], cls: type[Tele_co], bot: Optional["Bot"] ) -> Optional[Tele_co]: """Wrapper around TO.de_json that returns None if data is None.""" @@ -104,7 +104,7 @@ def de_json_wo( return cls.de_json(data, bot) -def de_json_decrypted_wo( +def de_json_decrypted_optional( data: Optional[JSONDict], cls: type[TeleCrypto_co], bot: Optional["Bot"], @@ -117,7 +117,7 @@ def de_json_decrypted_wo( return cls.de_json_decrypted(data, bot, credentials) -def de_list_wo( +def de_list_optional( data: Optional[list[JSONDict]], cls: type[Tele_co], bot: Optional["Bot"] ) -> tuple[Tele_co, ...]: """Wrapper around TO.de_list that returns an empty list if data is None.""" @@ -127,7 +127,7 @@ def de_list_wo( return cls.de_list(data, bot) -def de_list_decrypted_wo( +def de_list_decrypted_optional( data: Optional[list[JSONDict]], cls: type[TeleCrypto_co], bot: Optional["Bot"], From 54b9988fff8e480a18b907d693d77f265330b041 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Fri, 3 Jan 2025 13:41:41 +0100 Subject: [PATCH 13/14] Remove debug code --- tests/auxil/bot_method_checks.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/auxil/bot_method_checks.py b/tests/auxil/bot_method_checks.py index be5bf207f05..8e3179ea944 100644 --- a/tests/auxil/bot_method_checks.py +++ b/tests/auxil/bot_method_checks.py @@ -592,8 +592,6 @@ async def check_defaults_handling( values. Defaults to an empty frozenset. """ - guess_return_type_name(method) - raw_bot = not isinstance(bot, ExtBot) get_updates = method.__name__.lower().replace("_", "") == "getupdates" From 05f52fa698bad482f1f8270f4007dac67c35ca36 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Tue, 14 Jan 2025 17:04:51 +0100 Subject: [PATCH 14/14] Review --- telegram/_giveaway.py | 4 ++-- telegram/_reply.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/telegram/_giveaway.py b/telegram/_giveaway.py index 5ebd78bb661..d7d086e6548 100644 --- a/telegram/_giveaway.py +++ b/telegram/_giveaway.py @@ -144,7 +144,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "Giveaway": # Get the local timezone from the bot if it has defaults loc_tzinfo = extract_tzinfo_from_defaults(bot) - data["chats"] = tuple(de_list_optional(data.get("chats"), Chat, bot)) + data["chats"] = de_list_optional(data.get("chats"), Chat, bot) data["winners_selection_date"] = from_timestamp( data.get("winners_selection_date"), tzinfo=loc_tzinfo ) @@ -302,7 +302,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "GiveawayWinner loc_tzinfo = extract_tzinfo_from_defaults(bot) data["chat"] = de_json_optional(data.get("chat"), Chat, bot) - data["winners"] = tuple(de_list_optional(data.get("winners"), User, bot)) + data["winners"] = de_list_optional(data.get("winners"), User, bot) data["winners_selection_date"] = from_timestamp( data.get("winners_selection_date"), tzinfo=loc_tzinfo ) diff --git a/telegram/_reply.py b/telegram/_reply.py index a5192135c6d..ca6b23b0507 100644 --- a/telegram/_reply.py +++ b/telegram/_reply.py @@ -260,7 +260,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "ExternalReplyI data["animation"] = de_json_optional(data.get("animation"), Animation, bot) data["audio"] = de_json_optional(data.get("audio"), Audio, bot) data["document"] = de_json_optional(data.get("document"), Document, bot) - data["photo"] = tuple(de_list_optional(data.get("photo"), PhotoSize, bot)) + data["photo"] = de_list_optional(data.get("photo"), PhotoSize, bot) data["sticker"] = de_json_optional(data.get("sticker"), Sticker, bot) data["story"] = de_json_optional(data.get("story"), Story, bot) data["video"] = de_json_optional(data.get("video"), Video, bot) @@ -351,7 +351,7 @@ def de_json(cls, data: JSONDict, bot: Optional["Bot"] = None) -> "TextQuote": """See :meth:`telegram.TelegramObject.de_json`.""" data = cls._parse_data(data) - data["entities"] = tuple(de_list_optional(data.get("entities"), MessageEntity, bot)) + data["entities"] = de_list_optional(data.get("entities"), MessageEntity, bot) return super().de_json(data=data, bot=bot)