Skip to content

Commit

Permalink
Add Missing Conversions of type to Corresponding Enum from `telegra…
Browse files Browse the repository at this point in the history
…m.constants` (#4067)
  • Loading branch information
Bibo-Joshi committed Jan 17, 2024
1 parent f452c13 commit b73dc57
Show file tree
Hide file tree
Showing 13 changed files with 166 additions and 8 deletions.
3 changes: 2 additions & 1 deletion telegram/_botcommandscope.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

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

if TYPE_CHECKING:
Expand Down Expand Up @@ -77,7 +78,7 @@ class BotCommandScope(TelegramObject):

def __init__(self, type: str, *, api_kwargs: Optional[JSONDict] = None):
super().__init__(api_kwargs=api_kwargs)
self.type: str = type
self.type: str = enum.get_member(constants.BotCommandScopeType, type, type)
self._id_attrs = (self.type,)

self._freeze()
Expand Down
4 changes: 3 additions & 1 deletion telegram/_files/inputmedia.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"""Base class for Telegram InputMedia Objects."""
from typing import Optional, Sequence, Tuple, Union

from telegram import constants
from telegram._files.animation import Animation
from telegram._files.audio import Audio
from telegram._files.document import Document
Expand All @@ -27,6 +28,7 @@
from telegram._files.video import Video
from telegram._messageentity import MessageEntity
from telegram._telegramobject import TelegramObject
from telegram._utils import enum
from telegram._utils.argumentparsing import parse_sequence_arg
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram._utils.files import parse_file_input
Expand Down Expand Up @@ -94,7 +96,7 @@ def __init__(
api_kwargs: Optional[JSONDict] = None,
):
super().__init__(api_kwargs=api_kwargs)
self.type: str = media_type
self.type: str = enum.get_member(constants.InputMediaType, media_type, media_type)
self.media: Union[str, InputFile, Animation, Audio, Document, PhotoSize, Video] = media
self.caption: Optional[str] = caption
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
Expand Down
3 changes: 2 additions & 1 deletion telegram/_files/sticker.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from telegram._files.file import File
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.types import JSONDict

Expand Down Expand Up @@ -175,7 +176,7 @@ def __init__(
self.height: int = height
self.is_animated: bool = is_animated
self.is_video: bool = is_video
self.type: str = type
self.type: str = enum.get_member(constants.StickerType, type, type)
# Optional
self.emoji: Optional[str] = emoji
self.set_name: Optional[str] = set_name
Expand Down
3 changes: 2 additions & 1 deletion telegram/_inline/inlinequeryresult.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

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


Expand Down Expand Up @@ -59,7 +60,7 @@ def __init__(self, type: str, id: str, *, api_kwargs: Optional[JSONDict] = None)
super().__init__(api_kwargs=api_kwargs)

# Required
self.type: str = type
self.type: str = enum.get_member(constants.InlineQueryResultType, type, type)
self.id: str = str(id)

self._id_attrs = (self.id,)
Expand Down
4 changes: 3 additions & 1 deletion telegram/_keyboardbuttonpolltype.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
from typing import Optional

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


class KeyboardButtonPollType(TelegramObject):
Expand Down Expand Up @@ -54,7 +56,7 @@ def __init__(
api_kwargs: Optional[JSONDict] = None, # skipcq: PYL-W0622
):
super().__init__(api_kwargs=api_kwargs)
self.type: Optional[str] = type
self.type: Optional[str] = enum.get_member(PollType, type, type)

self._id_attrs = (self.type,)

Expand Down
3 changes: 2 additions & 1 deletion telegram/_menubutton.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

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

Expand Down Expand Up @@ -61,7 +62,7 @@ def __init__(
api_kwargs: Optional[JSONDict] = None,
): # pylint: disable=redefined-builtin
super().__init__(api_kwargs=api_kwargs)
self.type: str = type
self.type: str = enum.get_member(constants.MenuButtonType, type, type)

self._id_attrs = (self.type,)

Expand Down
23 changes: 22 additions & 1 deletion tests/_files/test_inputmedia.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

from telegram import (
InputFile,
InputMedia,
InputMediaAnimation,
InputMediaAudio,
InputMediaDocument,
Expand All @@ -33,7 +34,7 @@
Message,
MessageEntity,
)
from telegram.constants import ParseMode
from telegram.constants import InputMediaType, ParseMode

# noinspection PyUnresolvedReferences
from telegram.error import BadRequest
Expand Down Expand Up @@ -203,6 +204,26 @@ def test_with_local_files(self):
assert input_media_video.media == data_file("telegram.mp4").as_uri()
assert input_media_video.thumbnail == data_file("telegram.jpg").as_uri()

def test_type_enum_conversion(self):
# Since we have a lot of different test classes for all the input media types, we test this
# conversion only here. It is independent of the specific class
assert (
type(
InputMedia(
media_type="animation",
media="media",
).type
)
is InputMediaType
)
assert (
InputMedia(
media_type="unknown",
media="media",
).type
== "unknown"
)


class TestInputMediaPhotoBase:
type_ = "photo"
Expand Down
30 changes: 29 additions & 1 deletion tests/_files/test_sticker.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
Sticker,
StickerSet,
)
from telegram.constants import StickerFormat
from telegram.constants import StickerFormat, StickerType
from telegram.error import BadRequest, TelegramError
from telegram.request import RequestData
from tests.auxil.bot_method_checks import (
Expand Down Expand Up @@ -196,6 +196,34 @@ def test_de_json(self, bot, sticker):
assert json_sticker.custom_emoji_id == self.custom_emoji_id
assert json_sticker.needs_repainting == self.needs_repainting

def test_type_enum_conversion(self):
assert (
type(
Sticker(
file_id=self.sticker_file_id,
file_unique_id=self.sticker_file_unique_id,
width=self.width,
height=self.height,
is_animated=self.is_animated,
is_video=self.is_video,
type="regular",
).type
)
is StickerType
)
assert (
Sticker(
file_id=self.sticker_file_id,
file_unique_id=self.sticker_file_unique_id,
width=self.width,
height=self.height,
is_animated=self.is_animated,
is_video=self.is_video,
type="unknown",
).type
== "unknown"
)

def test_equality(self, sticker):
a = Sticker(
sticker.file_id,
Expand Down
22 changes: 22 additions & 0 deletions tests/_inline/test_inlinequeryresultarticle.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
from telegram import (
InlineKeyboardButton,
InlineKeyboardMarkup,
InlineQueryResult,
InlineQueryResultArticle,
InlineQueryResultAudio,
InputTextMessageContent,
)
from telegram.constants import InlineQueryResultType
from tests.auxil.slots import mro_slots


Expand Down Expand Up @@ -116,6 +118,26 @@ def test_to_dict(self, inline_query_result_article):
== inline_query_result_article.thumbnail_width
)

def test_type_enum_conversion(self):
# Since we have a lot of different test files for all the result types, we test this
# conversion only here. It is independent of the specific class
assert (
type(
InlineQueryResult(
id="id",
type="article",
).type
)
is InlineQueryResultType
)
assert (
InlineQueryResult(
id="id",
type="unknown",
).type
== "unknown"
)

def test_equality(self):
a = InlineQueryResultArticle(self.id_, self.title, self.input_message_content)
b = InlineQueryResultArticle(self.id_, self.title, self.input_message_content)
Expand Down
5 changes: 5 additions & 0 deletions tests/test_botcommandscope.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
BotCommandScopeDefault,
Dice,
)
from telegram.constants import BotCommandScopeType
from tests.auxil.slots import mro_slots


Expand Down Expand Up @@ -167,6 +168,10 @@ def test_to_dict(self, bot_command_scope):
if hasattr(bot_command_scope, "user_id"):
assert bot_command_scope["user_id"] == bot_command_scope.user_id

def test_type_enum_conversion(self):
assert type(BotCommandScope("default").type) is BotCommandScopeType
assert BotCommandScope("unknown").type == "unknown"

def test_equality(self, bot_command_scope, bot):
a = BotCommandScope("base_type")
b = BotCommandScope("base_type")
Expand Down
52 changes: 52 additions & 0 deletions tests/test_enum_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2023
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser Public License for more details.
#
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
import re
from pathlib import Path

telegram_root = Path(__file__).parent.parent / "telegram"
telegram_ext_root = telegram_root / "ext"
exclude_dirs = {
# We touch passport stuff only if strictly necessary.
telegram_root
/ "_passport",
}


def test_types_are_converted_to_enum():
"""We want to convert all attributes of name "type" to an enum from telegram.constants.
Since we don't necessarily document this as type hint, we simply check this with a regex.
"""
pattern = re.compile(r"self\.type: [^=]+ = ([^\n]+)\n", re.MULTILINE)

for path in telegram_root.rglob("*.py"):
if telegram_ext_root in path.parents or any(
exclude_dir in path.parents for exclude_dir in exclude_dirs
):
# We don't check tg.ext.
continue

text = path.read_text(encoding="utf-8")
for match in re.finditer(pattern, text):
assert match.group(1).startswith("enum.get_member") or match.group(1).startswith(
"get_member"
), (
f"`{match.group(1)}` in `{path}` does not seem to convert the type to an enum. "
f"Please fix this and also make sure to add a separate test to the classes test "
f"file."
)
17 changes: 17 additions & 0 deletions tests/test_keyboardbuttonpolltype.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import pytest

from telegram import KeyboardButtonPollType, Poll
from telegram.constants import PollType
from tests.auxil.slots import mro_slots


Expand All @@ -43,6 +44,22 @@ def test_to_dict(self, keyboard_button_poll_type):
assert isinstance(keyboard_button_poll_type_dict, dict)
assert keyboard_button_poll_type_dict["type"] == self.type

def test_type_enum_conversion(self):
assert (
type(
KeyboardButtonPollType(
type="quiz",
).type
)
is PollType
)
assert (
KeyboardButtonPollType(
type="unknown",
).type
== "unknown"
)

def test_equality(self):
a = KeyboardButtonPollType(Poll.QUIZ)
b = KeyboardButtonPollType(Poll.QUIZ)
Expand Down
5 changes: 5 additions & 0 deletions tests/test_menubutton.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
MenuButtonWebApp,
WebAppInfo,
)
from telegram.constants import MenuButtonType
from tests.auxil.slots import mro_slots


Expand Down Expand Up @@ -145,6 +146,10 @@ def test_to_dict(self, menu_button):
if hasattr(menu_button, "text"):
assert menu_button_dict["text"] == menu_button.text

def test_type_enum_conversion(self):
assert type(MenuButton("commands").type) is MenuButtonType
assert MenuButton("unknown").type == "unknown"

def test_equality(self, menu_button, bot):
a = MenuButton("base_type")
b = MenuButton("base_type")
Expand Down

0 comments on commit b73dc57

Please sign in to comment.