Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions changes/unreleased/5186.VngJMeztfXKDXAhcqTxJjK.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
other = "Centralize `de_json` into `TelegramObject`"
[[pull_requests]]
uid = "5186"
author_uids = ["harshil21"]
closes_threads = []
14 changes: 1 addition & 13 deletions src/telegram/_botaccesssettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,12 @@
"""This module contains an object that represents a Telegram Bot Access Settings."""

from collections.abc import Sequence
from typing import TYPE_CHECKING

from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils.argumentparsing import de_list_optional, parse_sequence_arg
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.types import JSONDict

if TYPE_CHECKING:
from telegram import Bot


class BotAccessSettings(TelegramObject):
"""
Expand Down Expand Up @@ -67,11 +63,3 @@ def __init__(

self._id_attrs = (self.is_access_restricted, self.added_users)
self._freeze()

@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "BotAccessSettings":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)
data["added_users"] = de_list_optional(data.get("added_users"), User, bot)

return super().de_json(data=data, bot=bot)
51 changes: 14 additions & 37 deletions src/telegram/_botcommandscope.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,13 @@
# pylint: disable=redefined-builtin
"""This module contains objects representing Telegram bot command scopes."""

from typing import TYPE_CHECKING, Final
from typing import ClassVar, Final

from telegram import constants
from telegram._telegramobject import TelegramObject
from telegram._utils import enum
from telegram._utils.types import JSONDict

if TYPE_CHECKING:
from telegram import Bot


class BotCommandScope(TelegramObject):
"""Base class for objects that represent the scope to which bot commands are applied.
Expand Down Expand Up @@ -62,6 +59,19 @@ class BotCommandScope(TelegramObject):

__slots__ = ("type",)

__DE_JSON_DISPATCH__: ClassVar[tuple[str, dict[str, str]] | None] = (
"type",
{
"default": "BotCommandScopeDefault",
"all_private_chats": "BotCommandScopeAllPrivateChats",
"all_group_chats": "BotCommandScopeAllGroupChats",
"all_chat_administrators": "BotCommandScopeAllChatAdministrators",
"chat": "BotCommandScopeChat",
"chat_administrators": "BotCommandScopeChatAdministrators",
"chat_member": "BotCommandScopeChatMember",
},
)

DEFAULT: Final[str] = constants.BotCommandScopeType.DEFAULT
""":const:`telegram.constants.BotCommandScopeType.DEFAULT`"""
ALL_PRIVATE_CHATS: Final[str] = constants.BotCommandScopeType.ALL_PRIVATE_CHATS
Expand All @@ -84,39 +94,6 @@ def __init__(self, type: str, *, api_kwargs: JSONDict | None = None):

self._freeze()

@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "BotCommandScope":
"""Converts JSON data to the appropriate :class:`BotCommandScope` object, i.e. takes
care of selecting the correct subclass.

Args:
data (dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot`, optional): The bot associated with this object. Defaults to
:obj:`None`, in which case shortcut methods will not be available.

.. versionchanged:: 21.4
:paramref:`bot` is now optional and defaults to :obj:`None`

Returns:
The Telegram object.

"""
data = cls._parse_data(data)

_class_mapping: dict[str, type[BotCommandScope]] = {
cls.DEFAULT: BotCommandScopeDefault,
cls.ALL_PRIVATE_CHATS: BotCommandScopeAllPrivateChats,
cls.ALL_GROUP_CHATS: BotCommandScopeAllGroupChats,
cls.ALL_CHAT_ADMINISTRATORS: BotCommandScopeAllChatAdministrators,
cls.CHAT: BotCommandScopeChat,
cls.CHAT_ADMINISTRATORS: BotCommandScopeChatAdministrators,
cls.CHAT_MEMBER: BotCommandScopeChatMember,
}

if cls is BotCommandScope and data.get("type") in _class_mapping:
return _class_mapping[data.pop("type")].de_json(data=data, bot=bot)
return super().de_json(data=data, bot=bot)


class BotCommandScopeDefault(BotCommandScope):
"""Represents the default scope of bot commands. Default commands are used if no commands with
Expand Down
61 changes: 2 additions & 59 deletions src/telegram/_business.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,19 @@
from zoneinfo import ZoneInfo

from telegram._chat import Chat
from telegram._files.location import Location
from telegram._files.sticker import Sticker
from telegram._telegramobject import TelegramObject
from telegram._user import User
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,
get_zone_info,
)
from telegram._utils.types import JSONDict

if TYPE_CHECKING:
from telegram import Bot
from telegram._files.location import Location
from telegram._user import User


class BusinessBotRights(TelegramObject):
Expand Down Expand Up @@ -266,20 +261,6 @@ def __init__(

self._freeze()

@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "BusinessConnection":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)

# 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"] = de_json_optional(data.get("user"), User, bot)
data["rights"] = de_json_optional(data.get("rights"), BusinessBotRights, bot)

return super().de_json(data=data, bot=bot)


class BusinessMessagesDeleted(TelegramObject):
"""
Expand Down Expand Up @@ -333,15 +314,6 @@ def __init__(

self._freeze()

@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "BusinessMessagesDeleted":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)

data["chat"] = de_json_optional(data.get("chat"), Chat, bot)

return super().de_json(data=data, bot=bot)


class BusinessIntro(TelegramObject):
"""
Expand Down Expand Up @@ -387,15 +359,6 @@ def __init__(

self._freeze()

@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "BusinessIntro":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)

data["sticker"] = de_json_optional(data.get("sticker"), Sticker, bot)

return super().de_json(data=data, bot=bot)


class BusinessLocation(TelegramObject):
"""
Expand Down Expand Up @@ -436,15 +399,6 @@ def __init__(

self._freeze()

@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "BusinessLocation":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)

data["location"] = de_json_optional(data.get("location"), Location, bot)

return super().de_json(data=data, bot=bot)


class BusinessOpeningHoursInterval(TelegramObject):
"""
Expand Down Expand Up @@ -678,14 +632,3 @@ def is_open(self, datetime: dtm.datetime) -> bool:
return True

return False

@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "BusinessOpeningHours":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)

data["opening_hours"] = de_list_optional(
data.get("opening_hours"), BusinessOpeningHoursInterval, bot
)

return super().de_json(data=data, bot=bot)
12 changes: 0 additions & 12 deletions src/telegram/_callbackquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,11 @@
from telegram._message import MaybeInaccessibleMessage, Message
from telegram._telegramobject import TelegramObject
from telegram._user import User
from telegram._utils.argumentparsing import de_json_optional
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.types import JSONDict, ODVInput, TimePeriod

if TYPE_CHECKING:
from telegram import (
Bot,
GameHighScore,
InlineKeyboardMarkup,
InputMedia,
Expand Down Expand Up @@ -153,16 +151,6 @@ def __init__(

self._freeze()

@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "CallbackQuery":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)

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)

async def answer(
self,
text: str | None = None,
Expand Down
74 changes: 21 additions & 53 deletions src/telegram/_chatbackground.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,15 @@
"""This module contains objects related to chat backgrounds."""

from collections.abc import Sequence
from typing import TYPE_CHECKING, Final
from typing import ClassVar, Final

from telegram import constants
from telegram._files.document import Document
from telegram._telegramobject import TelegramObject
from telegram._utils import enum
from telegram._utils.argumentparsing import de_json_optional, parse_sequence_arg
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.types import JSONDict

if TYPE_CHECKING:
from telegram import Bot


class BackgroundFill(TelegramObject):
"""Base class for Telegram BackgroundFill Objects. It can be one of:
Expand All @@ -57,6 +54,15 @@ class BackgroundFill(TelegramObject):

__slots__ = ("type",)

__DE_JSON_DISPATCH__: ClassVar[tuple[str, dict[str, str]] | None] = (
"type",
{
"solid": "BackgroundFillSolid",
"gradient": "BackgroundFillGradient",
"freeform_gradient": "BackgroundFillFreeformGradient",
},
)

SOLID: Final[constants.BackgroundFillType] = constants.BackgroundFillType.SOLID
""":const:`telegram.constants.BackgroundFillType.SOLID`"""
GRADIENT: Final[constants.BackgroundFillType] = constants.BackgroundFillType.GRADIENT
Expand All @@ -79,22 +85,6 @@ def __init__(
self._id_attrs = (self.type,)
self._freeze()

@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "BackgroundFill":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)

_class_mapping: dict[str, type[BackgroundFill]] = {
cls.SOLID: BackgroundFillSolid,
cls.GRADIENT: BackgroundFillGradient,
cls.FREEFORM_GRADIENT: BackgroundFillFreeformGradient,
}

if cls is BackgroundFill and data.get("type") in _class_mapping:
return _class_mapping[data.pop("type")].de_json(data=data, bot=bot)

return super().de_json(data=data, bot=bot)


class BackgroundFillSolid(BackgroundFill):
"""
Expand Down Expand Up @@ -243,6 +233,16 @@ class BackgroundType(TelegramObject):

__slots__ = ("type",)

__DE_JSON_DISPATCH__: ClassVar[tuple[str, dict[str, str]] | None] = (
"type",
{
"fill": "BackgroundTypeFill",
"wallpaper": "BackgroundTypeWallpaper",
"pattern": "BackgroundTypePattern",
"chat_theme": "BackgroundTypeChatTheme",
},
)

FILL: Final[constants.BackgroundTypeType] = constants.BackgroundTypeType.FILL
""":const:`telegram.constants.BackgroundTypeType.FILL`"""
WALLPAPER: Final[constants.BackgroundTypeType] = constants.BackgroundTypeType.WALLPAPER
Expand All @@ -265,29 +265,6 @@ def __init__(
self._id_attrs = (self.type,)
self._freeze()

@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "BackgroundType":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)

_class_mapping: dict[str, type[BackgroundType]] = {
cls.FILL: BackgroundTypeFill,
cls.WALLPAPER: BackgroundTypeWallpaper,
cls.PATTERN: BackgroundTypePattern,
cls.CHAT_THEME: BackgroundTypeChatTheme,
}

if cls is BackgroundType and data.get("type") in _class_mapping:
return _class_mapping[data.pop("type")].de_json(data=data, bot=bot)

if "fill" in data:
data["fill"] = de_json_optional(data.get("fill"), BackgroundFill, bot)

if "document" in data:
data["document"] = de_json_optional(data.get("document"), Document, bot)

return super().de_json(data=data, bot=bot)


class BackgroundTypeFill(BackgroundType):
"""
Expand Down Expand Up @@ -522,12 +499,3 @@ def __init__(

self._id_attrs = (self.type,)
self._freeze()

@classmethod
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "ChatBackground":
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)

data["type"] = de_json_optional(data.get("type"), BackgroundType, bot)

return super().de_json(data=data, bot=bot)
Loading
Loading