8000 Bot API 7.11: Add `CopyTextButton` and Integrate into `InlineKeyboardButton` by Bibo-Joshi · Pull Request #4547 · python-telegram-bot/python-telegram-bot · GitHub
[go: up one dir, main page]

Skip to content

Bot API 7.11: Add CopyTextButton and Integrate into InlineKeyboardButton #4547

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 3, 2024
Merged
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
1 change: 1 addition & 0 deletions docs/source/telegram.at-tree.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Available Types
telegram.chat
telegram.chatadministratorrights
telegram.chatbackground
telegram.copytextbutton
telegram.backgroundtype
telegram.backgroundtypefill
telegram.backgroundtypewallpaper
Expand Down
6 changes: 6 additions & 0 deletions docs/source/telegram.copytextbutton.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CopyTextButton
==============

.. autoclass:: telegram.CopyTextButton
:members:
:show-inheritance:
2 changes: 2 additions & 0 deletions telegram/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"ChatShared",
"ChosenInlineResult",
"Contact",
"CopyTextButton",
"Credentials",
"DataCredentials",
"Dice",
Expand Down Expand Up @@ -330,6 +331,7 @@
from ._chatmemberupdated import ChatMemberUpdated
from ._chatpermissions import ChatPermissions
from ._choseninlineresult import ChosenInlineResult
from ._copytextbutton import CopyTextButton
from ._dice import Dice
from ._files.animation import Animation
from ._files.audio import Audio
Expand Down
55 changes: 55 additions & 0 deletions telegram/_copytextbutton.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2024
# 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/].
"""This module contains an object that represents a Telegram CopyTextButton."""
from typing import Optional

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


class CopyTextButton(TelegramObject):
"""
This object represents an inline keyboard button that copies specified text to the clipboard.

Objects of this class are comparable in terms of equality. Two objects of this class are
considered equal, if their :attr:`text` is equal.

.. versionadded:: NEXT.VERSION

Args:
text (:obj:`str`): The text to be copied to the clipboard;
:tg-const:`telegram.constants.InlineKeyboardButtonLimit.MIN_COPY_TEXT`-
:tg-const:`telegram.constants.InlineKeyboardButtonLimit.MAX_COPY_TEXT` characters

Attributes:
text (:obj:`str`): The text to be copied to the clipboard;
:tg-const:`telegram.constants.InlineKeyboardButtonLimit.MIN_COPY_TEXT`-
:tg-const:`telegram.constants.InlineKeyboardButtonLimit.MAX_COPY_TEXT` characters

"""

__slots__ = ("text",)

def __init__(self, text: str, *, api_kwargs: Optional[JSONDict] = None):
super().__init__(api_kwargs=api_kwargs)
self.text: str = text

self._id_attrs = (self.text,)

self._freeze()
13 changes: 13 additions & 0 deletions telegram/_inline/inlinekeyboardbutton.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from typing import TYPE_CHECKING, Final, Optional, Union

from telegram import constants
from telegram._copytextbutton import CopyTextButton
from telegram._games.callbackgame import CallbackGame
from telegram._loginurl import LoginUrl
from telegram._switchinlinequerychosenchat import SwitchInlineQueryChosenChat
Expand Down Expand Up @@ -123,6 +124,10 @@ class InlineKeyboardButton(TelegramObject):
This offers a quick way for the user to open your bot in inline mode in the same chat
- good for selecting something from multiple options. Not supported in channels and for
messages sent on behalf of a Telegram Business account.
copy_text (:class:`telegram.CopyTextButton`, optional): Description of the button that
copies the specified text to the clipboard.

.. versionadded:: NEXT.VERSION
callback_game (:class:`telegram.CallbackGame`, optional): Description of the game that will
be launched when the user presses the button

Expand Down Expand Up @@ -192,6 +197,10 @@ class InlineKeyboardButton(TelegramObject):
This offers a quick way for the user to open your bot in inline mode in the same chat
- good for selecting something from multiple options. Not supported in channels and for
messages sent on behalf of a Telegram Business account.
copy_text (:class:`telegram.CopyTextButton`): Optional. Description of the button that
copies the specified text to the clipboard.

.. versionadded:: NEXT.VERSION
callback_game (:class:`telegram.CallbackGame`): Optional. Description of the game that will
be launched when the user presses the button.

Expand Down Expand Up @@ -224,6 +233,7 @@ class InlineKeyboardButton(TelegramObject):
__slots__ = (
"callback_data",
"callback_game",
"copy_text",
"login_url",
"pay",
"switch_inline_query",
Expand All @@ -246,6 +256,7 @@ def __init__(
login_url: Optional[LoginUrl] = None,
web_app: Optional[WebAppInfo] = None,
switch_inline_query_chosen_chat: Optional[SwitchInlineQueryChosenChat] = None,
copy_text: Optional[CopyTextButton] = None,
*,
api_kwargs: Optional[JSONDict] = None,
):
Expand All @@ -265,6 +276,7 @@ def __init__(
self.switch_inline_query_chosen_chat: Optional[SwitchInlineQueryChosenChat] = (
switch_inline_query_chosen_chat
)
self.copy_text: Optional[CopyTextButton] = copy_text
self._id_attrs = ()
self._set_id_attrs()

Expand Down Expand Up @@ -299,6 +311,7 @@ def de_json(
data["switch_inline_query_chosen_chat"] = SwitchInlineQueryChosenChat.de_json(
data.get("switch_inline_query_chosen_chat"), bot
)
data["copy_text"] = CopyTextButton.de_json(data.get("copy_text"), bot)

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

Expand Down
12 changes: 10 additions & 2 deletions telegram/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -1261,15 +1261,23 @@ class InlineKeyboardButtonLimit(IntEnum):
__slots__ = ()

MIN_CALLBACK_DATA = 1
""":obj:`int`: Minimum value allowed for
""":obj:`int`: Minimum length allowed for
:paramref:`~telegram.InlineKeyboardButton.callback_data` parameter of
:class:`telegram.InlineKeyboardButton`
"""
MAX_CALLBACK_DATA = 64
""":obj:`int`: Maximum value allowed for
""":obj:`int`: Maximum length allowed for
:paramref:`~telegram.InlineKeyboardButton.callback_data` parameter of
:class:`telegram.InlineKeyboardButton`
"""
MIN_COPY_TEXT = 1
""":obj:`int`: Minimum length allowed for
:paramref:`~telegram.CopyTextButton.text` parameter of :class:`telegram.CopyTextButton`
"""
MAX_COPY_TEXT = 256
""":obj:`int`: Maximum length allowed for
:paramref:`~telegram.CopyTextButton.text` parameter of :class:`telegram.CopyTextButton`
"""


class InlineKeyboardMarkupLimit(IntEnum):
Expand Down
9 changes: 9 additions & 0 deletions tests/_inline/test_inlinekeyboardbutton.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from telegram import (
CallbackGame,
CopyTextButton,
InlineKeyboardButton,
LoginUrl,
SwitchInlineQueryChosenChat,
Expand All @@ -46,6 +47,7 @@ def inline_keyboard_button():
switch_inline_query_chosen_chat=(
InlineKeyboardButtonTestBase.switch_inline_query_chosen_chat
),
copy_text=InlineKeyboardButtonTestBase.copy_text,
)


Expand All @@ -60,6 +62,7 @@ class InlineKeyboardButtonTestBase:
login_url = LoginUrl("http://google.com")
web_app = WebAppInfo(url="https://example.com")
switch_inline_query_chosen_chat = SwitchInlineQueryChosenChat("a_bot", True, False, True, True)
copy_text = CopyTextButton("python-telegram-bot")


class TestInlineKeyboardButtonWithoutRequest(InlineKeyboardButtonTestBase):
Expand All @@ -86,6 +89,7 @@ def test_expected_values(self, inline_keyboard_button):
inline_keyboard_button.switch_inline_query_chosen_chat
== self.switch_inline_query_chosen_chat
)
assert inline_keyboard_button.copy_text == self.copy_text

def test_to_dict(self, inline_keyboard_button):
inline_keyboard_button_dict = inline_keyboard_button.to_dict()
Expand Down Expand Up @@ -115,6 +119,9 @@ def test_to_dict(self, inline_keyboard_button):
inline_keyboard_button_dict["switch_inline_query_chosen_chat"]
== inline_keyboard_button.switch_inline_query_chosen_chat.to_dict()
)
assert (
inline_keyboard_button_dict["copy_text"] == inline_keyboard_button.copy_text.to_dict()
)

def test_de_json(self, offline_bot):
json_dict = {
Expand All @@ -128,6 +135,7 @@ def test_de_json(self, offline_bot):
"login_url": self.login_url.to_dict(),
"pay": self.pay,
"switch_inline_query_chosen_chat": self.switch_inline_query_chosen_chat.to_dict(),
"copy_text": self.copy_text.to_dict(),
}

inline_keyboard_button = InlineKeyboardButton.de_json(json_dict, None)
Expand All @@ -149,6 +157,7 @@ def test_de_json(self, offline_bot):
inline_keyboard_button.switch_inline_query_chosen_chat
== self.switch_inline_query_chosen_chat
)
assert inline_keyboard_button.copy_text == self.copy_text

none = InlineKeyboardButton.de_json({}, offline_bot)
assert none is None
Expand Down
70 changes: 70 additions & 0 deletions tests/test_copytextbutton.py
B2F9
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2024
# 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 pytest

from telegram import BotCommand, CopyTextButton
from tests.auxil.slots import mro_slots


@pytest.fixture(scope="module")
def copy_text_button():
return CopyTextButton(text=CopyTextButtonTestBase.text)


class CopyTextButtonTestBase:
text = "This is some text"


class TestCopyTextButtonWithoutRequest(CopyTextButtonTestBase):
def test_slot_behaviour(self, copy_text_button):
for attr in copy_text_button.__slots__:
assert getattr(copy_text_button, attr, "err") != "err", f"got extra slot '{attr}'"
assert len(mro_slots(copy_text_button)) == len(
set(mro_slots(copy_text_button))
), "duplicate slot"

def test_de_json(self, offline_bot):
json_dict = {"text": self.text}
copy_text_button = CopyTextButton.de_json(json_dict, 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()

assert isinstance(copy_text_button_dict, dict)
assert copy_text_button_dict["text"] == copy_text_button.text

def test_equality(self):
a = CopyTextButton(self.text)
b = CopyTextButton(self.text)
c = CopyTextButton("text")
d = BotCommand("start", "description")

assert a == b
assert hash(a) == hash(b)

assert a != c
assert hash(a) != hash(c)

assert a != d
assert hash(a) != hash(d)
Loading
0