Drop Support for Python 3.8 (#4398)

Co-authored-by: poolitzer <github@poolitzer.eu>
Co-authored-by: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com>
This commit is contained in:
Pablo Martínez 2024-10-24 20:48:49 +02:00 committed by GitHub
parent 847b97f86e
commit 5ab82a9c2b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
133 changed files with 894 additions and 950 deletions

View file

@ -20,7 +20,7 @@ jobs:
runs-on: ${{matrix.os}}
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
os: [ubuntu-latest, windows-latest, macos-latest]
fail-fast: False
steps:

View file

@ -72,7 +72,7 @@ repos:
hooks:
- id: pyupgrade
args:
- --py38-plus
- --py39-plus
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:

View file

@ -70,7 +70,7 @@ Introduction
This library provides a pure Python, asynchronous interface for the
`Telegram Bot API <https://core.telegram.org/bots/api>`_.
It's compatible with Python versions **3.8+**.
It's compatible with Python versions **3.9+**.
In addition to the pure API implementation, this library features several convenience methods and shortcuts as well as a number of high-level classes to
make the development of bots easy and straightforward. These classes are contained in the

View file

@ -20,7 +20,8 @@ import inspect
import re
import typing
from collections import defaultdict
from typing import Any, Iterator, Union
from collections.abc import Iterator
from typing import Any, Union
import telegram
import telegram.ext

View file

@ -16,7 +16,6 @@
# 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 inspect
from typing import List
keyword_args = [
"Keyword Arguments:",
@ -85,7 +84,7 @@ get_updates_read_timeout_addition = [
]
def find_insert_pos_for_kwargs(lines: List[str]) -> int:
def find_insert_pos_for_kwargs(lines: list[str]) -> int:
"""Finds the correct position to insert the keyword arguments and returns the index."""
for idx, value in reversed(list(enumerate(lines))): # reversed since :returns: is at the end
if value.startswith("Returns"):

View file

@ -21,7 +21,6 @@ https://github.com/sphinx-doc/sphinx/issues/1556 is closed
"""
import subprocess
from pathlib import Path
from typing import Dict, Tuple
from sphinx.util import logging
@ -32,7 +31,7 @@ sphinx_logger = logging.getLogger(__name__)
# must be a module-level variable so that it can be written to by the `autodoc-process-docstring`
# event handler in `sphinx_hooks.py`
LINE_NUMBERS: Dict[str, Tuple[Path, int, int]] = {}
LINE_NUMBERS: dict[str, tuple[Path, int, int]] = {}
def _git_branch() -> str:

View file

@ -12,7 +12,7 @@ To use arbitrary callback data, you must install PTB via
`pip install "python-telegram-bot[callback-data]"`
"""
import logging
from typing import List, Tuple, cast
from typing import cast
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import (
@ -36,7 +36,7 @@ logger = logging.getLogger(__name__)
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
"""Sends a message with 5 inline buttons attached."""
number_list: List[int] = []
number_list: list[int] = []
await update.message.reply_text("Please choose:", reply_markup=build_keyboard(number_list))
@ -55,7 +55,7 @@ async def clear(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.effective_message.reply_text("All clear!")
def build_keyboard(current_list: List[int]) -> InlineKeyboardMarkup:
def build_keyboard(current_list: list[int]) -> InlineKeyboardMarkup:
"""Helper function to build the next inline keyboard."""
return InlineKeyboardMarkup.from_column(
[InlineKeyboardButton(str(i), callback_data=(i, current_list)) for i in range(1, 6)]
@ -69,7 +69,7 @@ async def list_button(update: Update, context: ContextTypes.DEFAULT_TYPE) -> Non
# Get the data from the callback_data.
# If you're using a type checker like MyPy, you'll have to use typing.cast
# to make the checker get the expected type of the callback_data
number, number_list = cast(Tuple[int, List[int]], query.data)
number, number_list = cast(tuple[int, list[int]], query.data)
# append the number to the list
number_list.append(number)

View file

@ -12,7 +12,7 @@ bot.
"""
import logging
from typing import Optional, Tuple
from typing import Optional
from telegram import Chat, ChatMember, ChatMemberUpdated, Update
from telegram.constants import ParseMode
@ -37,7 +37,7 @@ logging.getLogger("httpx").setLevel(logging.WARNING)
logger = logging.getLogger(__name__)
def extract_status_change(chat_member_update: ChatMemberUpdated) -> Optional[Tuple[bool, bool]]:
def extract_status_change(chat_member_update: ChatMemberUpdated) -> Optional[tuple[bool, bool]]:
"""Takes a ChatMemberUpdated instance and extracts whether the 'old_chat_member' was a member
of the chat and whether the 'new_chat_member' is a member of the chat. Returns None, if
the status didn't change.

View file

@ -12,7 +12,7 @@ bot.
import logging
from collections import defaultdict
from typing import DefaultDict, Optional, Set
from typing import Optional
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.constants import ParseMode
@ -40,7 +40,7 @@ class ChatData:
"""Custom class for chat_data. Here we store data per message."""
def __init__(self) -> None:
self.clicks_per_message: DefaultDict[int, int] = defaultdict(int)
self.clicks_per_message: defaultdict[int, int] = defaultdict(int)
# The [ExtBot, dict, ChatData, dict] is for type checkers like mypy
@ -57,7 +57,7 @@ class CustomContext(CallbackContext[ExtBot, dict, ChatData, dict]):
self._message_id: Optional[int] = None
@property
def bot_user_ids(self) -> Set[int]:
def bot_user_ids(self) -> set[int]:
"""Custom shortcut to access a value stored in the bot_data dict"""
return self.bot_data.setdefault("user_ids", set())

View file

@ -15,7 +15,6 @@ bot.
"""
import logging
from typing import Dict
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
from telegram.ext import (
@ -46,7 +45,7 @@ reply_keyboard = [
markup = ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)
def facts_to_str(user_data: Dict[str, str]) -> str:
def facts_to_str(user_data: dict[str, str]) -> str:
"""Helper function for formatting the gathered user info."""
facts = [f"{key} - {value}" for key, value in user_data.items()]
return "\n".join(facts).join(["\n", "\n"])

View file

@ -15,7 +15,7 @@ bot.
"""
import logging
from typing import Any, Dict, Tuple
from typing import Any
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import (
@ -66,7 +66,7 @@ END = ConversationHandler.END
# Helper
def _name_switcher(level: str) -> Tuple[str, str]:
def _name_switcher(level: str) -> tuple[str, str]:
if level == PARENTS:
return "Father", "Mother"
return "Brother", "Sister"
@ -122,7 +122,7 @@ async def adding_self(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str
async def show_data(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str:
"""Pretty print gathered data."""
def pretty_print(data: Dict[str, Any], level: str) -> str:
def pretty_print(data: dict[str, Any], level: str) -> str:
people = data.get(level)
if not people:
return "\nNo information yet."

View file

@ -15,7 +15,6 @@ bot.
"""
import logging
from typing import Dict
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
from telegram.ext import (
@ -47,7 +46,7 @@ reply_keyboard = [
markup = ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True)
def facts_to_str(user_data: Dict[str, str]) -> str:
def facts_to_str(user_data: dict[str, str]) -> str:
"""Helper function for formatting the gathered user info."""
facts = [f"{key} - {value}" for key, value in user_data.items()]
return "\n".join(facts).join(["\n", "\n"])

View file

@ -8,7 +8,7 @@ dynamic = ["version"]
name = "python-telegram-bot"
description = "We have made you a wrapper you can't refuse"
readme = "README.rst"
requires-python = ">=3.8"
requires-python = ">=3.9"
license = "LGPL-3.0-only"
license-files = { paths = ["LICENSE", "LICENSE.dual", "LICENSE.lesser"] }
authors = [
@ -31,7 +31,6 @@ classifiers = [
"Topic :: Internet",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
@ -192,7 +191,7 @@ disallow_untyped_defs = true
disallow_incomplete_defs = true
disallow_untyped_decorators = true
show_error_codes = true
python_version = "3.8"
python_version = "3.9"
# For some files, it's easier to just disable strict-optional all together instead of
# cluttering the code with `# type: ignore`s or stuff like

View file

@ -23,21 +23,15 @@ import asyncio
import contextlib
import copy
import pickle
from collections.abc import Sequence
from datetime import datetime
from types import TracebackType
from typing import (
TYPE_CHECKING,
Any,
AsyncContextManager,
Callable,
Dict,
List,
NoReturn,
Optional,
Sequence,
Set,
Tuple,
Type,
TypeVar,
Union,
cast,
@ -130,7 +124,7 @@ if TYPE_CHECKING:
BT = TypeVar("BT", bound="Bot")
class Bot(TelegramObject, AsyncContextManager["Bot"]):
class Bot(TelegramObject, contextlib.AbstractAsyncContextManager["Bot"]):
"""This object represents a Telegram Bot.
Instances of this class can be used as asyncio context managers, where
@ -263,7 +257,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
self._private_key: Optional[bytes] = None
self._initialized: bool = False
self._request: Tuple[BaseRequest, BaseRequest] = (
self._request: tuple[BaseRequest, BaseRequest] = (
HTTPXRequest() if get_updates_request is None else get_updates_request,
HTTPXRequest() if request is None else request,
)
@ -332,7 +326,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
async def __aexit__(
self,
exc_type: Optional[Type[BaseException]],
exc_type: Optional[type[BaseException]],
exc_val: Optional[BaseException],
exc_tb: Optional[TracebackType],
) -> None:
@ -352,7 +346,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
"""
raise pickle.PicklingError("Bot objects cannot be pickled!")
def __deepcopy__(self, memodict: Dict[int, object]) -> NoReturn:
def __deepcopy__(self, memodict: dict[int, object]) -> NoReturn:
"""Customizes how :func:`copy.deepcopy` processes objects of this type. Bots can not
be deepcopied and this method will always raise an exception.
@ -528,7 +522,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
def _warn(
cls,
message: Union[str, PTBUserWarning],
category: Type[Warning] = PTBUserWarning,
category: type[Warning] = PTBUserWarning,
stacklevel: int = 0,
) -> None:
"""Convenience method to issue a warning. This method is here mostly to make it easier
@ -539,7 +533,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
def _parse_file_input(
self,
file_input: Union[FileInput, "TelegramObject"],
tg_type: Optional[Type["TelegramObject"]] = None,
tg_type: Optional[type["TelegramObject"]] = None,
filename: Optional[str] = None,
attach: bool = False,
) -> Union[str, "InputFile", Any]:
@ -551,7 +545,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
local_mode=self._local_mode,
)
def _insert_defaults(self, data: Dict[str, object]) -> None:
def _insert_defaults(self, data: dict[str, object]) -> None:
"""This method is here to make ext.Defaults work. Because we need to be able to tell
e.g. `send_message(chat_id, text)` from `send_message(chat_id, text, parse_mode=None)`, the
default values for `parse_mode` etc are not `None` but `DEFAULT_NONE`. While this *could*
@ -605,7 +599,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Any:
# We know that the return type is Union[bool, JSONDict, List[JSONDict]], but it's hard
# We know that the return type is Union[bool, JSONDict, list[JSONDict]], but it's hard
# to tell mypy which methods expects which of these return values and `Any` saves us a
# lot of `type: ignore` comments
if data is None:
@ -638,7 +632,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
) -> Union[bool, JSONDict, List[JSONDict]]:
) -> Union[bool, JSONDict, list[JSONDict]]:
# This also converts datetimes into timestamps.
# We don't do this earlier so that _insert_defaults (see above) has a chance to convert
# to the default timezone in case this is called by ExtBot
@ -798,7 +792,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
self,
endpoint: str,
api_kwargs: Optional[JSONDict] = None,
return_type: Optional[Type[TelegramObject]] = None,
return_type: Optional[type[TelegramObject]] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@ -1226,7 +1220,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[MessageId, ...]:
) -> tuple[MessageId, ...]:
"""
Use this method to forward messages of any kind. If some of the specified messages can't be
found or forwarded, they are skipped. Service messages and messages with protected content
@ -1248,7 +1242,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
message_thread_id (:obj:`int`, optional): |message_thread_id_arg|
Returns:
Tuple[:class:`telegram.Message`]: On success, a tuple of ``MessageId`` of sent messages
tuple[:class:`telegram.Message`]: On success, a tuple of ``MessageId`` of sent messages
is returned.
Raises:
@ -2499,7 +2493,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
caption: Optional[str] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
) -> Tuple[Message, ...]:
) -> tuple[Message, ...]:
"""Use this method to send a group of photos, videos, documents or audios as an album.
Documents and audio files can be only grouped in an album with messages of the same type.
@ -2581,7 +2575,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
.. versionadded:: 20.0
Returns:
Tuple[:class:`telegram.Message`]: An array of the sent Messages.
tuple[:class:`telegram.Message`]: An array of the sent Messages.
Raises:
:class:`telegram.error.TelegramError`
@ -3403,7 +3397,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
],
next_offset: Optional[str] = None,
current_offset: Optional[str] = None,
) -> Tuple[Sequence["InlineQueryResult"], Optional[str]]:
) -> tuple[Sequence["InlineQueryResult"], Optional[str]]:
"""
Builds the effective results from the results input.
We make this a stand-alone method so tg.ext.ExtBot can wrap it.
@ -3526,7 +3520,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
Args:
inline_query_id (:obj:`str`): Unique identifier for the answered query.
results (List[:class:`telegram.InlineQueryResult`] | Callable): A list of results for
results (list[:class:`telegram.InlineQueryResult`] | Callable): A list of results for
the inline query. In case :paramref:`current_offset` is passed,
:paramref:`results` may also be
a callable that accepts the current page index starting from 0. It must return
@ -4280,7 +4274,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[Update, ...]:
) -> tuple[Update, ...]:
"""Use this method to receive incoming updates using long polling.
Note:
@ -4325,7 +4319,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|sequenceargs|
Returns:
Tuple[:class:`telegram.Update`]
tuple[:class:`telegram.Update`]
Raises:
:class:`telegram.error.TelegramError`
@ -4362,7 +4356,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
# waiting for the server to return and there's no way of knowing the connection had been
# dropped in real time.
result = cast(
List[JSONDict],
list[JSONDict],
await self._post(
"getUpdates",
data,
@ -4626,7 +4620,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[ChatMember, ...]:
) -> tuple[ChatMember, ...]:
"""
Use this method to get a list of administrators in a chat.
@ -4637,7 +4631,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
chat_id (:obj:`int` | :obj:`str`): |chat_id_channel|
Returns:
Tuple[:class:`telegram.ChatMember`]: On success, returns a tuple of ``ChatMember``
tuple[:class:`telegram.ChatMember`]: On success, returns a tuple of ``ChatMember``
objects that contains information about all chat administrators except
other bots. If the chat is a group or a supergroup and no administrators were
appointed, only the creator will be returned.
@ -4901,7 +4895,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[GameHighScore, ...]:
) -> tuple[GameHighScore, ...]:
"""
Use this method to get data for high score tables. Will return the score of the specified
user and several of their neighbors in a game.
@ -4924,7 +4918,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
:paramref:`message_id` are not specified. Identifier of the inline message.
Returns:
Tuple[:class:`telegram.GameHighScore`]
tuple[:class:`telegram.GameHighScore`]
Raises:
:class:`telegram.error.TelegramError`
@ -6304,7 +6298,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[Sticker, ...]:
) -> tuple[Sticker, ...]:
"""
Use this method to get information about emoji stickers by their identifiers.
@ -6320,7 +6314,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|sequenceargs|
Returns:
Tuple[:class:`telegram.Sticker`]
tuple[:class:`telegram.Sticker`]
Raises:
:class:`telegram.error.TelegramError`
@ -7427,7 +7421,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[BotCommand, ...]:
) -> tuple[BotCommand, ...]:
"""
Use this method to get the current list of the bot's commands for the given scope and user
language.
@ -7449,7 +7443,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
.. versionadded:: 13.7
Returns:
Tuple[:class:`telegram.BotCommand`]: On success, the commands set for the bot. An empty
tuple[:class:`telegram.BotCommand`]: On success, the commands set for the bot. An empty
tuple is returned if commands are not set.
Raises:
@ -7472,7 +7466,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
async def set_my_commands(
self,
commands: Sequence[Union[BotCommand, Tuple[str, str]]],
commands: Sequence[Union[BotCommand, tuple[str, str]]],
scope: Optional[BotCommandScope] = None,
language_code: Optional[str] = None,
*,
@ -7791,7 +7785,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
"""
Use this method to copy messages of any kind. If some of the specified messages can't be
found or copied, they are skipped. Service messages, paid media messages, giveaway
@ -7819,7 +7813,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
their captions.
Returns:
Tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
of the sent messages is returned.
Raises:
@ -8072,14 +8066,14 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[Sticker, ...]:
) -> tuple[Sticker, ...]:
"""Use this method to get custom emoji stickers, which can be used as a forum topic
icon by any user. Requires no parameters.
.. versionadded:: 20.0
Returns:
Tuple[:class:`telegram.Sticker`]
tuple[:class:`telegram.Sticker`]
Raises:
:class:`telegram.error.TelegramError`
@ -8968,7 +8962,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
Raises:
:class:`telegram.error.TelegramError`
"""
allowed_reactions: Set[str] = set(ReactionEmoji)
allowed_reactions: set[str] = set(ReactionEmoji)
parsed_reaction = (
[
(

View file

@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
# pylint: disable=redefined-builtin
"""This module contains objects representing Telegram bot command scopes."""
from typing import TYPE_CHECKING, Dict, Final, Optional, Type, Union
from typing import TYPE_CHECKING, Final, Optional, Union
from telegram import constants
from telegram._telegramobject import TelegramObject
@ -91,7 +91,7 @@ class BotCommandScope(TelegramObject):
care of selecting the correct subclass.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
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.
@ -107,7 +107,7 @@ class BotCommandScope(TelegramObject):
if not data:
return None
_class_mapping: Dict[str, Type[BotCommandScope]] = {
_class_mapping: dict[str, type[BotCommandScope]] = {
cls.DEFAULT: BotCommandScopeDefault,
cls.ALL_PRIVATE_CHATS: BotCommandScopeAllPrivateChats,
cls.ALL_GROUP_CHATS: BotCommandScopeAllGroupChats,

View file

@ -19,8 +19,9 @@
# along with this program. If not, see [http://www.gnu.org/licenses/]
"""This module contains the Telegram Business related classes."""
from collections.abc import Sequence
from datetime import datetime
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from typing import TYPE_CHECKING, Optional
from telegram._chat import Chat
from telegram._files.location import Location
@ -145,7 +146,7 @@ class BusinessMessagesDeleted(TelegramObject):
business_connection_id (:obj:`str`): Unique identifier of the business connection.
chat (:class:`telegram.Chat`): Information about a chat in the business account. The bot
may not have access to the chat or the corresponding user.
message_ids (Tuple[:obj:`int`]): A list of identifiers of the deleted messages in the
message_ids (tuple[:obj:`int`]): A list of identifiers of the deleted messages in the
chat of the business account.
"""
@ -166,7 +167,7 @@ class BusinessMessagesDeleted(TelegramObject):
super().__init__(api_kwargs=api_kwargs)
self.business_connection_id: str = business_connection_id
self.chat: Chat = chat
self.message_ids: Tuple[int, ...] = parse_sequence_arg(message_ids)
self.message_ids: tuple[int, ...] = parse_sequence_arg(message_ids)
self._id_attrs = (
self.business_connection_id,
@ -359,37 +360,37 @@ class BusinessOpeningHoursInterval(TelegramObject):
self.opening_minute: int = opening_minute
self.closing_minute: int = closing_minute
self._opening_time: Optional[Tuple[int, int, int]] = None
self._closing_time: Optional[Tuple[int, int, int]] = None
self._opening_time: Optional[tuple[int, int, int]] = None
self._closing_time: Optional[tuple[int, int, int]] = None
self._id_attrs = (self.opening_minute, self.closing_minute)
self._freeze()
def _parse_minute(self, minute: int) -> Tuple[int, int, int]:
def _parse_minute(self, minute: int) -> tuple[int, int, int]:
return (minute // 1440, minute % 1440 // 60, minute % 1440 % 60)
@property
def opening_time(self) -> Tuple[int, int, int]:
def opening_time(self) -> tuple[int, int, int]:
"""Convenience attribute. A :obj:`tuple` parsed from :attr:`opening_minute`. It contains
the `weekday`, `hour` and `minute` in the same ranges as :attr:`datetime.datetime.weekday`,
:attr:`datetime.datetime.hour` and :attr:`datetime.datetime.minute`
Returns:
Tuple[:obj:`int`, :obj:`int`, :obj:`int`]:
tuple[:obj:`int`, :obj:`int`, :obj:`int`]:
"""
if self._opening_time is None:
self._opening_time = self._parse_minute(self.opening_minute)
return self._opening_time
@property
def closing_time(self) -> Tuple[int, int, int]:
def closing_time(self) -> tuple[int, int, int]:
"""Convenience attribute. A :obj:`tuple` parsed from :attr:`closing_minute`. It contains
the `weekday`, `hour` and `minute` in the same ranges as :attr:`datetime.datetime.weekday`,
:attr:`datetime.datetime.hour` and :attr:`datetime.datetime.minute`
Returns:
Tuple[:obj:`int`, :obj:`int`, :obj:`int`]:
tuple[:obj:`int`, :obj:`int`, :obj:`int`]:
"""
if self._closing_time is None:
self._closing_time = self._parse_minute(self.closing_minute)

View file

@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
# pylint: disable=redefined-builtin
"""This module contains an object that represents a Telegram CallbackQuery"""
from typing import TYPE_CHECKING, Final, Optional, Sequence, Tuple, Union
from collections.abc import Sequence
from typing import TYPE_CHECKING, Final, Optional, Union
from telegram import constants
from telegram._files.location import Location
@ -676,7 +677,7 @@ class CallbackQuery(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["GameHighScore", ...]:
) -> tuple["GameHighScore", ...]:
"""Shortcut for either::
await update.callback_query.message.get_game_high_score(*args, **kwargs)
@ -695,7 +696,7 @@ class CallbackQuery(TelegramObject):
Raises :exc:`TypeError` if :attr:`message` is not accessible.
Returns:
Tuple[:class:`telegram.GameHighScore`]
tuple[:class:`telegram.GameHighScore`]
Raises:
:exc:`TypeError` if :attr:`message` is not accessible.

View file

@ -18,9 +18,10 @@
# 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 Chat."""
from collections.abc import Sequence
from datetime import datetime
from html import escape
from typing import TYPE_CHECKING, Final, Optional, Sequence, Tuple, Union
from typing import TYPE_CHECKING, Final, Optional, Union
from telegram import constants
from telegram._chatpermissions import ChatPermissions
@ -296,7 +297,7 @@ class _ChatBase(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["ChatMember", ...]:
) -> tuple["ChatMember", ...]:
"""Shortcut for::
await bot.get_chat_administrators(update.effective_chat.id, *args, **kwargs)
@ -305,7 +306,7 @@ class _ChatBase(TelegramObject):
:meth:`telegram.Bot.get_chat_administrators`.
Returns:
Tuple[:class:`telegram.ChatMember`]: A tuple of administrators in a chat. An Array of
tuple[:class:`telegram.ChatMember`]: A tuple of administrators in a chat. An Array of
:class:`telegram.ChatMember` objects that contains information about all
chat administrators except other bots. If the chat is a group or a supergroup
and no administrators were appointed, only the creator will be returned.
@ -1140,7 +1141,7 @@ class _ChatBase(TelegramObject):
caption: Optional[str] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
) -> Tuple["Message", ...]:
) -> tuple["Message", ...]:
"""Shortcut for::
await bot.send_media_group(update.effective_chat.id, *args, **kwargs)
@ -1148,7 +1149,7 @@ class _ChatBase(TelegramObject):
For the documentation of the arguments, please see :meth:`telegram.Bot.send_media_group`.
Returns:
Tuple[:class:`telegram.Message`]: On success, a tuple of :class:`~telegram.Message`
tuple[:class:`telegram.Message`]: On success, a tuple of :class:`~telegram.Message`
instances that were sent is returned.
"""
@ -2268,7 +2269,7 @@ class _ChatBase(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
"""Shortcut for::
await bot.copy_messages(chat_id=update.effective_chat.id, *args, **kwargs)
@ -2280,7 +2281,7 @@ class _ChatBase(TelegramObject):
.. versionadded:: 20.8
Returns:
Tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
of the sent messages is returned.
"""
@ -2313,7 +2314,7 @@ class _ChatBase(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
"""Shortcut for::
await bot.copy_messages(from_chat_id=update.effective_chat.id, *args, **kwargs)
@ -2325,7 +2326,7 @@ class _ChatBase(TelegramObject):
.. versionadded:: 20.8
Returns:
Tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
of the sent messages is returned.
"""
@ -2442,7 +2443,7 @@ class _ChatBase(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
"""Shortcut for::
await bot.forward_messages(chat_id=update.effective_chat.id, *args, **kwargs)
@ -2454,7 +2455,7 @@ class _ChatBase(TelegramObject):
.. versionadded:: 20.8
Returns:
Tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
of sent messages is returned.
"""
@ -2485,7 +2486,7 @@ class _ChatBase(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
"""Shortcut for::
await bot.forward_messages(from_chat_id=update.effective_chat.id, *args, **kwargs)
@ -2497,7 +2498,7 @@ class _ChatBase(TelegramObject):
.. versionadded:: 20.8
Returns:
Tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
of sent messages is returned.
"""

View file

@ -17,7 +17,8 @@
# 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 objects related to chat backgrounds."""
from typing import TYPE_CHECKING, Dict, Final, Optional, Sequence, Tuple, Type
from collections.abc import Sequence
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._files.document import Document
@ -87,7 +88,7 @@ class BackgroundFill(TelegramObject):
if not data:
return None
_class_mapping: Dict[str, Type[BackgroundFill]] = {
_class_mapping: dict[str, type[BackgroundFill]] = {
cls.SOLID: BackgroundFillSolid,
cls.GRADIENT: BackgroundFillGradient,
cls.FREEFORM_GRADIENT: BackgroundFillFreeformGradient,
@ -212,7 +213,7 @@ class BackgroundFillFreeformGradient(BackgroundFill):
super().__init__(type=self.FREEFORM_GRADIENT, api_kwargs=api_kwargs)
with self._unfrozen():
self.colors: Tuple[int, ...] = parse_sequence_arg(colors)
self.colors: tuple[int, ...] = parse_sequence_arg(colors)
self._id_attrs = (self.colors,)
@ -278,7 +279,7 @@ class BackgroundType(TelegramObject):
if not data:
return None
_class_mapping: Dict[str, Type[BackgroundType]] = {
_class_mapping: dict[str, type[BackgroundType]] = {
cls.FILL: BackgroundTypeFill,
cls.WALLPAPER: BackgroundTypeWallpaper,
cls.PATTERN: BackgroundTypePattern,

View file

@ -18,8 +18,9 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram ChatBoosts."""
from collections.abc import Sequence
from datetime import datetime
from typing import TYPE_CHECKING, Dict, Final, Optional, Sequence, Tuple, Type
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._chat import Chat
@ -119,7 +120,7 @@ class ChatBoostSource(TelegramObject):
if not data:
return None
_class_mapping: Dict[str, Type[ChatBoostSource]] = {
_class_mapping: dict[str, type[ChatBoostSource]] = {
cls.PREMIUM: ChatBoostSourcePremium,
cls.GIFT_CODE: ChatBoostSourceGiftCode,
cls.GIVEAWAY: ChatBoostSourceGiveaway,
@ -431,7 +432,7 @@ class UserChatBoosts(TelegramObject):
user.
Attributes:
boosts (Tuple[:class:`telegram.ChatBoost`]): List of boosts added to the chat by the user.
boosts (tuple[:class:`telegram.ChatBoost`]): List of boosts added to the chat by the user.
"""
__slots__ = ("boosts",)
@ -444,7 +445,7 @@ class UserChatBoosts(TelegramObject):
):
super().__init__(api_kwargs=api_kwargs)
self.boosts: Tuple[ChatBoost, ...] = parse_sequence_arg(boosts)
self.boosts: tuple[ChatBoost, ...] = parse_sequence_arg(boosts)
self._id_attrs = (self.boosts,)
self._freeze()

View file

@ -18,8 +18,9 @@
# 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 ChatFullInfo."""
from collections.abc import Sequence
from datetime import datetime
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from typing import TYPE_CHECKING, Optional
from telegram._birthdate import Birthdate
from telegram._chat import Chat, _ChatBase
@ -224,7 +225,7 @@ class ChatFullInfo(_ChatBase):
.. versionadded:: 20.0
photo (:class:`telegram.ChatPhoto`): Optional. Chat photo.
active_usernames (Tuple[:obj:`str`]): Optional. If set, the list of all `active chat
active_usernames (tuple[:obj:`str`]): Optional. If set, the list of all `active chat
usernames <https://telegram.org/blog/topics-in-groups-collectible-usernames\
#collectible-usernames>`_; for private chats, supergroups and channels.
@ -252,7 +253,7 @@ class ChatFullInfo(_ChatBase):
of the user.
.. versionadded:: 21.1
available_reactions (Tuple[:class:`telegram.ReactionType`]): Optional. List of available
available_reactions (tuple[:class:`telegram.ReactionType`]): Optional. List of available
reactions allowed in the chat. If omitted, then all of
:const:`telegram.constants.ReactionEmoji` are allowed.
@ -483,14 +484,14 @@ class ChatFullInfo(_ChatBase):
self.has_restricted_voice_and_video_messages: Optional[bool] = (
has_restricted_voice_and_video_messages
)
self.active_usernames: Tuple[str, ...] = parse_sequence_arg(active_usernames)
self.active_usernames: tuple[str, ...] = parse_sequence_arg(active_usernames)
self.emoji_status_custom_emoji_id: Optional[str] = emoji_status_custom_emoji_id
self.emoji_status_expiration_date: Optional[datetime] = emoji_status_expiration_date
self.has_aggressive_anti_spam_enabled: Optional[bool] = (
has_aggressive_anti_spam_enabled
)
self.has_hidden_members: Optional[bool] = has_hidden_members
self.available_reactions: Optional[Tuple[ReactionType, ...]] = parse_sequence_arg(
self.available_reactions: Optional[tuple[ReactionType, ...]] = parse_sequence_arg(
available_reactions
)
self.accent_color_id: Optional[int] = accent_color_id

View file

@ -19,7 +19,7 @@
"""This module contains an object that represents a Telegram ChatMember."""
import datetime
from typing import TYPE_CHECKING, Dict, Final, Optional, Type
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._telegramobject import TelegramObject
@ -114,7 +114,7 @@ class ChatMember(TelegramObject):
if not data:
return None
_class_mapping: Dict[str, Type[ChatMember]] = {
_class_mapping: dict[str, type[ChatMember]] = {
cls.OWNER: ChatMemberOwner,
cls.ADMINISTRATOR: ChatMemberAdministrator,
cls.MEMBER: ChatMemberMember,

View file

@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram ChatMemberUpdated."""
import datetime
from typing import TYPE_CHECKING, Dict, Optional, Tuple, Union
from typing import TYPE_CHECKING, Optional, Union
from telegram._chat import Chat
from telegram._chatinvitelink import ChatInviteLink
@ -162,7 +162,7 @@ class ChatMemberUpdated(TelegramObject):
return super().de_json(data=data, bot=bot)
def _get_attribute_difference(self, attribute: str) -> Tuple[object, object]:
def _get_attribute_difference(self, attribute: str) -> tuple[object, object]:
try:
old = self.old_chat_member[attribute]
except KeyError:
@ -177,9 +177,9 @@ class ChatMemberUpdated(TelegramObject):
def difference(
self,
) -> Dict[
) -> dict[
str,
Tuple[
tuple[
Union[str, bool, datetime.datetime, User], Union[str, bool, datetime.datetime, User]
],
]:
@ -198,7 +198,7 @@ class ChatMemberUpdated(TelegramObject):
.. versionadded:: 13.5
Returns:
Dict[:obj:`str`, Tuple[:class:`object`, :class:`object`]]: A dictionary mapping
dict[:obj:`str`, tuple[:class:`object`, :class:`object`]]: A dictionary mapping
attribute names to tuples of the form ``(old_value, new_value)``
"""
# we first get the names of the attributes that have changed

View file

@ -17,7 +17,7 @@
# 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 Dice."""
from typing import Final, List, Optional
from typing import Final, Optional
from telegram import constants
from telegram._telegramobject import TelegramObject
@ -114,8 +114,8 @@ class Dice(TelegramObject):
.. versionadded:: 13.4
"""
ALL_EMOJI: Final[List[str]] = list(constants.DiceEmoji)
"""List[:obj:`str`]: A list of all available dice emoji."""
ALL_EMOJI: Final[list[str]] = list(constants.DiceEmoji)
"""list[:obj:`str`]: A list of all available dice emoji."""
MIN_VALUE: Final[int] = constants.DiceLimit.MIN_VALUE
""":const:`telegram.constants.DiceLimit.MIN_VALUE`

View file

@ -17,7 +17,7 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""Common base class for media objects with thumbnails"""
from typing import TYPE_CHECKING, Optional, Type, TypeVar
from typing import TYPE_CHECKING, Optional, TypeVar
from telegram._files._basemedium import _BaseMedium
from telegram._files.photosize import PhotoSize
@ -82,7 +82,7 @@ class _BaseThumbedMedium(_BaseMedium):
@classmethod
def de_json(
cls: Type[ThumbedMT_co], data: Optional[JSONDict], bot: Optional["Bot"] = None
cls: type[ThumbedMT_co], data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional[ThumbedMT_co]:
"""See :meth:`telegram.TelegramObject.de_json`."""
data = cls._parse_data(data)

View file

@ -130,7 +130,7 @@ class InputFile:
Content may now be a file handle.
Returns:
Tuple[:obj:`str`, :obj:`bytes` | :class:`IO`, :obj:`str`]:
tuple[:obj:`str`, :obj:`bytes` | :class:`IO`, :obj:`str`]:
"""
return self.filename, self.input_file_content, self.mimetype

View file

@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""Base class for Telegram InputMedia Objects."""
from typing import Final, Optional, Sequence, Tuple, Union
from collections.abc import Sequence
from typing import Final, Optional, Union
from telegram import constants
from telegram._files.animation import Animation
@ -74,7 +75,7 @@ class InputMedia(TelegramObject):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -99,7 +100,7 @@ class InputMedia(TelegramObject):
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)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.parse_mode: ODVInput[str] = parse_mode
self._freeze()
@ -321,7 +322,7 @@ class InputMediaAnimation(InputMedia):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. The parse mode to use for text formatting.
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -436,7 +437,7 @@ class InputMediaPhoto(InputMedia):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -546,7 +547,7 @@ class InputMediaVideo(InputMedia):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -676,7 +677,7 @@ class InputMediaAudio(InputMedia):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -779,7 +780,7 @@ class InputMediaDocument(InputMedia):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0

View file

@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram InputSticker."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple, Union
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional, Union
from telegram._files.sticker import MaskPosition
from telegram._telegramobject import TelegramObject
@ -67,13 +68,13 @@ class InputSticker(TelegramObject):
Attributes:
sticker (:obj:`str` | :class:`telegram.InputFile`): The added sticker.
emoji_list (Tuple[:obj:`str`]): Tuple of
emoji_list (tuple[:obj:`str`]): Tuple of
:tg-const:`telegram.constants.StickerLimit.MIN_STICKER_EMOJI` -
:tg-const:`telegram.constants.StickerLimit.MAX_STICKER_EMOJI` emoji associated with the
sticker.
mask_position (:class:`telegram.MaskPosition`): Optional. Position where the mask should be
placed on faces. For ":tg-const:`telegram.constants.StickerType.MASK`" stickers only.
keywords (Tuple[:obj:`str`]): Optional. Tuple of
keywords (tuple[:obj:`str`]): Optional. Tuple of
0-:tg-const:`telegram.constants.StickerLimit.MAX_SEARCH_KEYWORDS` search keywords
for the sticker with the total length of up to
:tg-const:`telegram.constants.StickerLimit.MAX_KEYWORD_LENGTH` characters. For
@ -110,9 +111,9 @@ class InputSticker(TelegramObject):
local_mode=True,
attach=True,
)
self.emoji_list: Tuple[str, ...] = parse_sequence_arg(emoji_list)
self.emoji_list: tuple[str, ...] = parse_sequence_arg(emoji_list)
self.format: str = format
self.mask_position: Optional[MaskPosition] = mask_position
self.keywords: Tuple[str, ...] = parse_sequence_arg(keywords)
self.keywords: tuple[str, ...] = parse_sequence_arg(keywords)
self._freeze()

View file

@ -17,7 +17,8 @@
# 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 objects that represent stickers."""
from typing import TYPE_CHECKING, Final, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._files._basethumbedmedium import _BaseThumbedMedium
@ -259,7 +260,7 @@ class StickerSet(TelegramObject):
Attributes:
name (:obj:`str`): Sticker set name.
title (:obj:`str`): Sticker set title.
stickers (Tuple[:class:`telegram.Sticker`]): List of all set stickers.
stickers (tuple[:class:`telegram.Sticker`]): List of all set stickers.
.. versionchanged:: 20.0
|tupleclassattrs|
@ -296,7 +297,7 @@ class StickerSet(TelegramObject):
super().__init__(api_kwargs=api_kwargs)
self.name: str = name
self.title: str = title
self.stickers: Tuple[Sticker, ...] = parse_sequence_arg(stickers)
self.stickers: tuple[Sticker, ...] = parse_sequence_arg(stickers)
self.sticker_type: str = sticker_type
# Optional
self.thumbnail: Optional[PhotoSize] = thumbnail

View file

@ -17,7 +17,8 @@
# 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 Game."""
from typing import TYPE_CHECKING, Dict, List, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._files.animation import Animation
from telegram._files.photosize import PhotoSize
@ -65,7 +66,7 @@ class Game(TelegramObject):
Attributes:
title (:obj:`str`): Title of the game.
description (:obj:`str`): Description of the game.
photo (Tuple[:class:`telegram.PhotoSize`]): Photo that will be displayed in the game
photo (tuple[:class:`telegram.PhotoSize`]): Photo that will be displayed in the game
message in chats.
.. versionchanged:: 20.0
@ -76,7 +77,7 @@ class Game(TelegramObject):
when the bot calls :meth:`telegram.Bot.set_game_score`, or manually edited
using :meth:`telegram.Bot.edit_message_text`.
0-:tg-const:`telegram.constants.MessageLimit.MAX_TEXT_LENGTH` characters.
text_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. Special entities that
text_entities (tuple[:class:`telegram.MessageEntity`]): Optional. Special entities that
appear in text, such as usernames, URLs, bot commands, etc.
This tuple is empty if the message does not contain text entities.
@ -112,10 +113,10 @@ class Game(TelegramObject):
# Required
self.title: str = title
self.description: str = description
self.photo: Tuple[PhotoSize, ...] = parse_sequence_arg(photo)
self.photo: tuple[PhotoSize, ...] = parse_sequence_arg(photo)
# Optionals
self.text: Optional[str] = text
self.text_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(text_entities)
self.text_entities: tuple[MessageEntity, ...] = parse_sequence_arg(text_entities)
self.animation: Optional[Animation] = animation
self._id_attrs = (self.title, self.description, self.photo)
@ -163,7 +164,7 @@ class Game(TelegramObject):
return entity_text.decode(TextEncoding.UTF_16_LE)
def parse_text_entities(self, types: Optional[List[str]] = None) -> Dict[MessageEntity, str]:
def parse_text_entities(self, types: Optional[list[str]] = None) -> dict[MessageEntity, str]:
"""
Returns a :obj:`dict` that maps :class:`telegram.MessageEntity` to :obj:`str`.
It contains entities from this message filtered by their
@ -176,13 +177,13 @@ class Game(TelegramObject):
See :attr:`parse_text_entity` for more info.
Args:
types (List[:obj:`str`], optional): List of :class:`telegram.MessageEntity` types as
types (list[:obj:`str`], optional): List of :class:`telegram.MessageEntity` types as
strings. If the :attr:`~telegram.MessageEntity.type` attribute of an entity is
contained in this list, it will be returned. Defaults to
:attr:`telegram.MessageEntity.ALL_TYPES`.
Returns:
Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
"""

View file

@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an objects that are related to Telegram giveaways."""
import datetime
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._chat import Chat
from telegram._telegramobject import TelegramObject
@ -41,7 +42,7 @@ class Giveaway(TelegramObject):
.. versionadded:: 20.8
Args:
chats (Tuple[:class:`telegram.Chat`]): The list of chats which the user must join to
chats (tuple[:class:`telegram.Chat`]): The list of chats which the user must join to
participate in the giveaway.
winners_selection_date (:class:`datetime.datetime`): The date when the giveaway winner will
be selected. |datetime_localization|
@ -76,7 +77,7 @@ class Giveaway(TelegramObject):
has_public_winners (:obj:`True`): Optional. :obj:`True`, if the list of giveaway winners
will be visible to everyone
prize_description (:obj:`str`): Optional. Description of additional giveaway prize
country_codes (Tuple[:obj:`str`]): Optional. A tuple of two-letter ISO 3166-1 alpha-2
country_codes (tuple[:obj:`str`]): Optional. A tuple of two-letter ISO 3166-1 alpha-2
country codes indicating the countries from which eligible users for the giveaway must
come. If empty, then all users can participate in the giveaway. Users with a phone
number that was bought on Fragment can always participate in giveaways.
@ -117,13 +118,13 @@ class Giveaway(TelegramObject):
):
super().__init__(api_kwargs=api_kwargs)
self.chats: Tuple[Chat, ...] = tuple(chats)
self.chats: tuple[Chat, ...] = tuple(chats)
self.winners_selection_date: datetime.datetime = winners_selection_date
self.winner_count: int = winner_count
self.only_new_members: Optional[bool] = only_new_members
self.has_public_winners: Optional[bool] = has_public_winners
self.prize_description: Optional[str] = prize_description
self.country_codes: Tuple[str, ...] = parse_sequence_arg(country_codes)
self.country_codes: tuple[str, ...] = parse_sequence_arg(country_codes)
self.premium_subscription_month_count: Optional[int] = premium_subscription_month_count
self.prize_star_count: Optional[int] = prize_star_count
@ -222,7 +223,7 @@ class GiveawayWinners(TelegramObject):
winners_selection_date (:class:`datetime.datetime`): Point in time when winners of the
giveaway were selected. |datetime_localization|
winner_count (:obj:`int`): Total number of winners in the giveaway
winners (Tuple[:class:`telegram.User`]): tuple of up to
winners (tuple[:class:`telegram.User`]): tuple of up to
:tg-const:`telegram.constants.GiveawayLimit.MAX_WINNERS` winners of the giveaway
additional_chat_count (:obj:`int`): Optional. The number of other chats the user had to
join in order to be eligible for the giveaway
@ -278,7 +279,7 @@ class GiveawayWinners(TelegramObject):
self.giveaway_message_id: int = giveaway_message_id
self.winners_selection_date: datetime.datetime = winners_selection_date
self.winner_count: int = winner_count
self.winners: Tuple[User, ...] = tuple(winners)
self.winners: tuple[User, ...] = tuple(winners)
self.additional_chat_count: Optional[int] = additional_chat_count
self.premium_subscription_month_count: Optional[int] = premium_subscription_month_count
self.unclaimed_prize_count: Optional[int] = unclaimed_prize_count

View file

@ -17,7 +17,8 @@
# 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 InlineKeyboardMarkup."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardbutton import InlineKeyboardButton
from telegram._telegramobject import TelegramObject
@ -57,7 +58,7 @@ class InlineKeyboardMarkup(TelegramObject):
|sequenceclassargs|
Attributes:
inline_keyboard (Tuple[Tuple[:class:`telegram.InlineKeyboardButton`]]): Tuple of
inline_keyboard (tuple[tuple[:class:`telegram.InlineKeyboardButton`]]): Tuple of
button rows, each represented by a tuple of :class:`~telegram.InlineKeyboardButton`
objects.
@ -81,7 +82,7 @@ class InlineKeyboardMarkup(TelegramObject):
"InlineKeyboardButtons"
)
# Required
self.inline_keyboard: Tuple[Tuple[InlineKeyboardButton, ...], ...] = tuple(
self.inline_keyboard: tuple[tuple[InlineKeyboardButton, ...], ...] = tuple(
tuple(row) for row in inline_keyboard
)

View file

@ -19,7 +19,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram InlineQuery."""
from typing import TYPE_CHECKING, Callable, Final, Optional, Sequence, Union
from collections.abc import Sequence
from typing import TYPE_CHECKING, Callable, Final, Optional, Union
from telegram import constants
from telegram._files.location import Location

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InlineQueryResultAudio."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@ -73,7 +74,7 @@ class InlineQueryResultAudio(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -124,6 +125,6 @@ class InlineQueryResultAudio(InlineQueryResult):
self.audio_duration: Optional[int] = audio_duration
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InlineQueryResultCachedAudio."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@ -68,7 +69,7 @@ class InlineQueryResultCachedAudio(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -110,6 +111,6 @@ class InlineQueryResultCachedAudio(InlineQueryResult):
# Optionals
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InlineQueryResultCachedDocument."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@ -72,7 +73,7 @@ class InlineQueryResultCachedDocument(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -120,6 +121,6 @@ class InlineQueryResultCachedDocument(InlineQueryResult):
self.description: Optional[str] = description
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InlineQueryResultCachedGif."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@ -74,7 +75,7 @@ class InlineQueryResultCachedGif(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -124,7 +125,7 @@ class InlineQueryResultCachedGif(InlineQueryResult):
self.title: Optional[str] = title
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.show_caption_above_media: Optional[bool] = show_caption_above_media

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InlineQueryResultMpeg4Gif."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@ -74,7 +75,7 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -124,7 +125,7 @@ class InlineQueryResultCachedMpeg4Gif(InlineQueryResult):
self.title: Optional[str] = title
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.show_caption_above_media: Optional[bool] = show_caption_above_media

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InlineQueryResultPhoto"""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@ -76,7 +77,7 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -129,7 +130,7 @@ class InlineQueryResultCachedPhoto(InlineQueryResult):
self.description: Optional[str] = description
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.show_caption_above_media: Optional[bool] = show_caption_above_media

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InlineQueryResultCachedVideo."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@ -72,7 +73,7 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -125,7 +126,7 @@ class InlineQueryResultCachedVideo(InlineQueryResult):
self.description: Optional[str] = description
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.show_caption_above_media: Optional[bool] = show_caption_above_media

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InlineQueryResultCachedVoice."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@ -70,7 +71,7 @@ class InlineQueryResultCachedVoice(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |caption_entities|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |caption_entities|
.. versionchanged:: 20.0
@ -115,6 +116,6 @@ class InlineQueryResultCachedVoice(InlineQueryResult):
# Optionals
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InlineQueryResultDocument"""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@ -86,7 +87,7 @@ class InlineQueryResultDocument(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -155,7 +156,7 @@ class InlineQueryResultDocument(InlineQueryResult):
# Optionals
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.description: Optional[str] = description
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InlineQueryResultGif."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@ -102,7 +103,7 @@ class InlineQueryResultGif(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -166,7 +167,7 @@ class InlineQueryResultGif(InlineQueryResult):
self.title: Optional[str] = title
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.thumbnail_mime_type: Optional[str] = thumbnail_mime_type

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InlineQueryResultMpeg4Gif."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@ -104,7 +105,7 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters
after entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |caption_entities|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |caption_entities|
.. versionchanged:: 20.0
@ -168,7 +169,7 @@ class InlineQueryResultMpeg4Gif(InlineQueryResult):
self.title: Optional[str] = title
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.thumbnail_mime_type: Optional[str] = thumbnail_mime_type

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InlineQueryResultPhoto."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@ -92,7 +93,7 @@ class InlineQueryResultPhoto(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after
entities parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -154,7 +155,7 @@ class InlineQueryResultPhoto(InlineQueryResult):
self.description: Optional[str] = description
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content
self.show_caption_above_media: Optional[bool] = show_caption_above_media

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InlineQueryResultVideo."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@ -99,7 +100,7 @@ class InlineQueryResultVideo(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional.
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional.
|captionentitiesattr|
.. versionchanged:: 20.0
@ -171,7 +172,7 @@ class InlineQueryResultVideo(InlineQueryResult):
# Optional
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.video_width: Optional[int] = video_width
self.video_height: Optional[int] = video_height
self.video_duration: Optional[int] = video_duration

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InlineQueryResultVoice."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inlinekeyboardmarkup import InlineKeyboardMarkup
from telegram._inline.inlinequeryresult import InlineQueryResult
@ -72,7 +73,7 @@ class InlineQueryResultVoice(InlineQueryResult):
0-:tg-const:`telegram.constants.MessageLimit.CAPTION_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -121,6 +122,6 @@ class InlineQueryResultVoice(InlineQueryResult):
self.voice_duration: Optional[int] = voice_duration
self.caption: Optional[str] = caption
self.parse_mode: ODVInput[str] = parse_mode
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.reply_markup: Optional[InlineKeyboardMarkup] = reply_markup
self.input_message_content: Optional[InputMessageContent] = input_message_content

View file

@ -17,7 +17,8 @@
# 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 a class that represents a Telegram InputInvoiceMessageContent."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inputmessagecontent import InputMessageContent
from telegram._payment.labeledprice import LabeledPrice
@ -122,7 +123,7 @@ class InputInvoiceMessageContent(InputMessageContent):
currency (:obj:`str`): Three-letter ISO 4217 currency code, see more on
`currencies <https://core.telegram.org/bots/payments#supported-currencies>`_.
Pass ``XTR`` for payments in |tg_stars|.
prices (Tuple[:class:`telegram.LabeledPrice`]): Price breakdown, a list of
prices (tuple[:class:`telegram.LabeledPrice`]): Price breakdown, a list of
components (e.g. product price, tax, discount, delivery cost, delivery tax, bonus,
etc.). Must contain exactly one item for payments in |tg_stars|.
@ -135,7 +136,7 @@ class InputInvoiceMessageContent(InputMessageContent):
`currencies.json <https://core.telegram.org/bots/payments/currencies.json>`_, it
shows the number of digits past the decimal point for each currency (2 for the majority
of currencies). Defaults to ``0``. Not supported for payments in |tg_stars|.
suggested_tip_amounts (Tuple[:obj:`int`]): Optional. An array of suggested
suggested_tip_amounts (tuple[:obj:`int`]): Optional. An array of suggested
amounts of tip in the *smallest units* of the currency (integer, **not** float/double).
At most 4 suggested tip amounts can be specified. The suggested tip amounts must be
positive, passed in a strictly increased order and must not exceed
@ -226,10 +227,10 @@ class InputInvoiceMessageContent(InputMessageContent):
self.payload: str = payload
self.provider_token: Optional[str] = provider_token
self.currency: str = currency
self.prices: Tuple[LabeledPrice, ...] = parse_sequence_arg(prices)
self.prices: tuple[LabeledPrice, ...] = parse_sequence_arg(prices)
# Optionals
self.max_tip_amount: Optional[int] = max_tip_amount
self.suggested_tip_amounts: Tuple[int, ...] = parse_sequence_arg(suggested_tip_amounts)
self.suggested_tip_amounts: tuple[int, ...] = parse_sequence_arg(suggested_tip_amounts)
self.provider_data: Optional[str] = provider_data
self.photo_url: Optional[str] = photo_url
self.photo_size: Optional[int] = photo_size

View file

@ -17,7 +17,8 @@
# 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 the classes that represent Telegram InputTextMessageContent."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._inline.inputmessagecontent import InputMessageContent
from telegram._messageentity import MessageEntity
@ -75,7 +76,7 @@ class InputTextMessageContent(InputMessageContent):
:tg-const:`telegram.constants.MessageLimit.MAX_TEXT_LENGTH` characters after entities
parsing.
parse_mode (:obj:`str`): Optional. |parse_mode|
entities (Tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
entities (tuple[:class:`telegram.MessageEntity`]): Optional. |captionentitiesattr|
.. versionchanged:: 20.0
@ -107,7 +108,7 @@ class InputTextMessageContent(InputMessageContent):
self.message_text: str = message_text
# Optionals
self.parse_mode: ODVInput[str] = parse_mode
self.entities: Tuple[MessageEntity, ...] = parse_sequence_arg(entities)
self.entities: tuple[MessageEntity, ...] = parse_sequence_arg(entities)
self.link_preview_options: ODVInput[LinkPreviewOptions] = parse_lpo_and_dwpp(
disable_web_page_preview, link_preview_options
)

View file

@ -17,7 +17,7 @@
# 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 objects related to Telegram menu buttons."""
from typing import TYPE_CHECKING, Dict, Final, Optional, Type
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._telegramobject import TelegramObject
@ -76,7 +76,7 @@ class MenuButton(TelegramObject):
care of selecting the correct subclass.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
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.
@ -95,7 +95,7 @@ class MenuButton(TelegramObject):
if not data and cls is MenuButton:
return None
_class_mapping: Dict[str, Type[MenuButton]] = {
_class_mapping: dict[str, type[MenuButton]] = {
cls.COMMANDS: MenuButtonCommands,
cls.WEB_APP: MenuButtonWebApp,
cls.DEFAULT: MenuButtonDefault,

View file

@ -21,8 +21,9 @@
import datetime
import re
from collections.abc import Sequence
from html import escape
from typing import TYPE_CHECKING, Dict, List, Optional, Sequence, Tuple, TypedDict, Union
from typing import TYPE_CHECKING, Optional, TypedDict, Union
from telegram._chat import Chat
from telegram._chatbackground import ChatBackground
@ -629,7 +630,7 @@ class Message(MaybeInaccessibleMessage):
message belongs to.
text (:obj:`str`): Optional. For text messages, the actual UTF-8 text of the message,
0-:tg-const:`telegram.constants.MessageLimit.MAX_TEXT_LENGTH` characters.
entities (Tuple[:class:`telegram.MessageEntity`]): Optional. For text messages, special
entities (tuple[:class:`telegram.MessageEntity`]): Optional. For text messages, special
entities like usernames, URLs, bot commands, etc. that appear in the text. See
:attr:`parse_entity` and :attr:`parse_entities` methods for how to use properly.
This list is empty if the message does not contain entities.
@ -648,7 +649,7 @@ class Message(MaybeInaccessibleMessage):
..versionadded:: 21.3
caption_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. For messages with a
caption_entities (tuple[:class:`telegram.MessageEntity`]): Optional. For messages with a
Caption. Special entities like usernames, URLs, bot commands, etc. that appear in the
caption. See :attr:`Message.parse_caption_entity` and :attr:`parse_caption_entities`
methods for how to use properly. This list is empty if the message does not contain
@ -675,7 +676,7 @@ class Message(MaybeInaccessibleMessage):
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
game (:class:`telegram.Game`): Optional. Message is a game, information about the game.
:ref:`More about games >> <games-tree>`.
photo (Tuple[:class:`telegram.PhotoSize`]): Optional. Message is a photo, available
photo (tuple[:class:`telegram.PhotoSize`]): Optional. Message is a photo, available
sizes of the photo. This list is empty if the message does not contain a photo.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
@ -703,7 +704,7 @@ class Message(MaybeInaccessibleMessage):
about the video message.
.. seealso:: :wiki:`Working with Files and Media <Working-with-Files-and-Media>`
new_chat_members (Tuple[:class:`telegram.User`]): Optional. New members that were added
new_chat_members (tuple[:class:`telegram.User`]): Optional. New members that were added
to the group or supergroup and information about them (the bot itself may be one of
these members). This list is empty if the message does not contain new chat members.
@ -722,7 +723,7 @@ class Message(MaybeInaccessibleMessage):
left_chat_member (:class:`telegram.User`): Optional. A member was removed from the group,
information about them (this member may be the bot itself).
new_chat_title (:obj:`str`): Optional. A chat title was changed to this value.
new_chat_photo (Tuple[:class:`telegram.PhotoSize`]): A chat photo was changed to
new_chat_photo (tuple[:class:`telegram.PhotoSize`]): A chat photo was changed to
this value. This list is empty if the message does not contain a new chat photo.
.. versionchanged:: 20.0
@ -1118,12 +1119,12 @@ class Message(MaybeInaccessibleMessage):
self.edit_date: Optional[datetime.datetime] = edit_date
self.has_protected_content: Optional[bool] = has_protected_content
self.text: Optional[str] = text
self.entities: Tuple[MessageEntity, ...] = parse_sequence_arg(entities)
self.caption_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.entities: tuple[MessageEntity, ...] = parse_sequence_arg(entities)
self.caption_entities: tuple[MessageEntity, ...] = parse_sequence_arg(caption_entities)
self.audio: Optional[Audio] = audio
self.game: Optional[Game] = game
self.document: Optional[Document] = document
self.photo: Tuple[PhotoSize, ...] = parse_sequence_arg(photo)
self.photo: tuple[PhotoSize, ...] = parse_sequence_arg(photo)
self.sticker: Optional[Sticker] = sticker
self.video: Optional[Video] = video
self.voice: Optional[Voice] = voice
@ -1132,10 +1133,10 @@ class Message(MaybeInaccessibleMessage):
self.contact: Optional[Contact] = contact
self.location: Optional[Location] = location
self.venue: Optional[Venue] = venue
self.new_chat_members: Tuple[User, ...] = parse_sequence_arg(new_chat_members)
self.new_chat_members: tuple[User, ...] = parse_sequence_arg(new_chat_members)
self.left_chat_member: Optional[User] = left_chat_member
self.new_chat_title: Optional[str] = new_chat_title
self.new_chat_photo: Tuple[PhotoSize, ...] = parse_sequence_arg(new_chat_photo)
self.new_chat_photo: tuple[PhotoSize, ...] = parse_sequence_arg(new_chat_photo)
self.delete_chat_photo: Optional[bool] = bool(delete_chat_photo)
self.group_chat_created: Optional[bool] = bool(group_chat_created)
self.supergroup_chat_created: Optional[bool] = bool(supergroup_chat_created)
@ -1406,7 +1407,7 @@ class Message(MaybeInaccessibleMessage):
* :class:`telegram.Invoice`
* :class:`telegram.Location`
* :class:`telegram.PassportData`
* List[:class:`telegram.PhotoSize`]
* list[:class:`telegram.PhotoSize`]
* :class:`telegram.PaidMediaInfo`
* :class:`telegram.Poll`
* :class:`telegram.Sticker`
@ -1478,7 +1479,7 @@ class Message(MaybeInaccessibleMessage):
def compute_quote_position_and_entities(
self, quote: str, index: Optional[int] = None
) -> Tuple[int, Optional[Tuple[MessageEntity, ...]]]:
) -> tuple[int, Optional[tuple[MessageEntity, ...]]]:
"""
Use this function to compute position and entities of a quote in the message text or
caption. Useful for filling the parameters
@ -1504,7 +1505,7 @@ class Message(MaybeInaccessibleMessage):
message. If not specified, the first occurrence is used.
Returns:
Tuple[:obj:`int`, :obj:`None` | Tuple[:class:`~telegram.MessageEntity`, ...]]: On
tuple[:obj:`int`, :obj:`None` | tuple[:class:`~telegram.MessageEntity`, ...]]: On
success, a tuple containing information about quote position and entities is returned.
Raises:
@ -1647,7 +1648,7 @@ class Message(MaybeInaccessibleMessage):
quote: Optional[bool],
reply_to_message_id: Optional[int],
reply_parameters: Optional["ReplyParameters"],
) -> Tuple[Union[str, int], ReplyParameters]:
) -> tuple[Union[str, int], ReplyParameters]:
if quote and do_quote:
raise ValueError("The arguments `quote` and `do_quote` are mutually exclusive")
@ -2048,7 +2049,7 @@ class Message(MaybeInaccessibleMessage):
caption: Optional[str] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
) -> Tuple["Message", ...]:
) -> tuple["Message", ...]:
"""Shortcut for::
await bot.send_media_group(
@ -2075,7 +2076,7 @@ class Message(MaybeInaccessibleMessage):
.. versionadded:: 20.8
Returns:
Tuple[:class:`telegram.Message`]: An array of the sent Messages.
tuple[:class:`telegram.Message`]: An array of the sent Messages.
Raises:
:class:`telegram.error.TelegramError`
@ -3989,7 +3990,7 @@ class Message(MaybeInaccessibleMessage):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["GameHighScore", ...]:
) -> tuple["GameHighScore", ...]:
"""Shortcut for::
await bot.get_game_high_scores(
@ -4005,7 +4006,7 @@ class Message(MaybeInaccessibleMessage):
behaviour is undocumented and might be changed by Telegram.
Returns:
Tuple[:class:`telegram.GameHighScore`]
tuple[:class:`telegram.GameHighScore`]
"""
return await self.get_bot().get_game_high_scores(
chat_id=self.chat_id,
@ -4431,7 +4432,7 @@ class Message(MaybeInaccessibleMessage):
return parse_message_entity(self.caption, entity)
def parse_entities(self, types: Optional[List[str]] = None) -> Dict[MessageEntity, str]:
def parse_entities(self, types: Optional[list[str]] = None) -> dict[MessageEntity, str]:
"""
Returns a :obj:`dict` that maps :class:`telegram.MessageEntity` to :obj:`str`.
It contains entities from this message filtered by their
@ -4444,21 +4445,21 @@ class Message(MaybeInaccessibleMessage):
See :attr:`parse_entity` for more info.
Args:
types (List[:obj:`str`], optional): List of :class:`telegram.MessageEntity` types as
types (list[:obj:`str`], optional): List of :class:`telegram.MessageEntity` types as
strings. If the ``type`` attribute of an entity is contained in this list, it will
be returned. Defaults to a list of all types. All types can be found as constants
in :class:`telegram.MessageEntity`.
Returns:
Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
"""
return parse_message_entities(self.text, self.entities, types=types)
def parse_caption_entities(
self, types: Optional[List[str]] = None
) -> Dict[MessageEntity, str]:
self, types: Optional[list[str]] = None
) -> dict[MessageEntity, str]:
"""
Returns a :obj:`dict` that maps :class:`telegram.MessageEntity` to :obj:`str`.
It contains entities from this message's caption filtered by their
@ -4471,13 +4472,13 @@ class Message(MaybeInaccessibleMessage):
codepoints. See :attr:`parse_entity` for more info.
Args:
types (List[:obj:`str`], optional): List of :class:`telegram.MessageEntity` types as
types (list[:obj:`str`], optional): List of :class:`telegram.MessageEntity` types as
strings. If the ``type`` attribute of an entity is contained in this list, it will
be returned. Defaults to a list of all types. All types can be found as constants
in :class:`telegram.MessageEntity`.
Returns:
Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
"""
@ -4487,7 +4488,7 @@ class Message(MaybeInaccessibleMessage):
def _parse_html(
cls,
message_text: Optional[str],
entities: Dict[MessageEntity, str],
entities: dict[MessageEntity, str],
urled: bool = False,
offset: int = 0,
) -> Optional[str]:
@ -4676,7 +4677,7 @@ class Message(MaybeInaccessibleMessage):
def _parse_markdown(
cls,
message_text: Optional[str],
entities: Dict[MessageEntity, str],
entities: dict[MessageEntity, str],
urled: bool = False,
version: MarkdownVersion = 1,
offset: int = 0,

View file

@ -20,7 +20,8 @@
import copy
import itertools
from typing import TYPE_CHECKING, Dict, Final, List, Optional, Sequence, Tuple, Union
from collections.abc import Sequence
from typing import TYPE_CHECKING, Final, Optional, Union
from telegram import constants
from telegram._telegramobject import TelegramObject
@ -200,7 +201,7 @@ class MessageEntity(TelegramObject):
accumulated_length = 0
# calculate the length of each slice text[:position] in utf-16 accordingly,
# store the position translations
position_translation: Dict[int, int] = {}
position_translation: dict[int, int] = {}
for i, position in enumerate(positions):
last_position = positions[i - 1] if i > 0 else 0
text_slice = text[last_position:position]
@ -286,8 +287,8 @@ class MessageEntity(TelegramObject):
@classmethod
def concatenate(
cls,
*args: Union[Tuple[str, _SEM], Tuple[str, _SEM, bool]],
) -> Tuple[str, _SEM]:
*args: Union[tuple[str, _SEM], tuple[str, _SEM, bool]],
) -> tuple[str, _SEM]:
"""Utility functionality for concatenating two text along with their formatting entities.
Tip:
@ -332,8 +333,8 @@ class MessageEntity(TelegramObject):
.. versionadded:: 21.5
Args:
*args (Tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`]] | \
Tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`], :obj:`bool`]):
*args (tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`]] | \
tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`], :obj:`bool`]):
Arbitrary number of tuples containing the text and its entities to concatenate.
If the last element of the tuple is a :obj:`bool`, it is used to determine whether
to adjust the entities to UTF-16 via
@ -341,11 +342,11 @@ class MessageEntity(TelegramObject):
default.
Returns:
Tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`]]: The concatenated text
tuple[:obj:`str`, Sequence[:class:`telegram.MessageEntity`]]: The concatenated text
and its entities
"""
output_text = ""
output_entities: List[MessageEntity] = []
output_entities: list[MessageEntity] = []
for arg in args:
text, entities = arg[0], arg[1]
@ -357,8 +358,8 @@ class MessageEntity(TelegramObject):
return output_text, output_entities
ALL_TYPES: Final[List[str]] = list(constants.MessageEntityType)
"""List[:obj:`str`]: A list of all available message entity types."""
ALL_TYPES: Final[list[str]] = list(constants.MessageEntityType)
"""list[:obj:`str`]: A list of all available message entity types."""
BLOCKQUOTE: Final[str] = constants.MessageEntityType.BLOCKQUOTE
""":const:`telegram.constants.MessageEntityType.BLOCKQUOTE`

View file

@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the classes that represent Telegram MessageOigin."""
import datetime
from typing import TYPE_CHECKING, Dict, Final, Optional, Type
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._chat import Chat
@ -105,7 +105,7 @@ class MessageOrigin(TelegramObject):
if not data:
return None
_class_mapping: Dict[str, Type[MessageOrigin]] = {
_class_mapping: dict[str, type[MessageOrigin]] = {
cls.USER: MessageOriginUser,
cls.HIDDEN_USER: MessageOriginHiddenUser,
cls.CHAT: MessageOriginChat,

View file

@ -17,8 +17,9 @@
# 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 MessageReaction Update."""
from collections.abc import Sequence
from datetime import datetime
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from typing import TYPE_CHECKING, Optional
from telegram._chat import Chat
from telegram._reaction import ReactionCount, ReactionType
@ -54,7 +55,7 @@ class MessageReactionCountUpdated(TelegramObject):
message_id (:obj:`int`): Unique message identifier inside the chat.
date (:class:`datetime.datetime`): Date of the change in Unix time
|datetime_localization|
reactions (Tuple[:class:`telegram.ReactionCount`]): List of reactions that are present on
reactions (tuple[:class:`telegram.ReactionCount`]): List of reactions that are present on
the message
"""
@ -79,7 +80,7 @@ class MessageReactionCountUpdated(TelegramObject):
self.chat: Chat = chat
self.message_id: int = message_id
self.date: datetime = date
self.reactions: Tuple[ReactionCount, ...] = parse_sequence_arg(reactions)
self.reactions: tuple[ReactionCount, ...] = parse_sequence_arg(reactions)
self._id_attrs = (self.chat, self.message_id, self.date, self.reactions)
self._freeze()
@ -132,9 +133,9 @@ class MessageReactionUpdated(TelegramObject):
message_id (:obj:`int`): Unique message identifier inside the chat.
date (:class:`datetime.datetime`): Date of the change in Unix time.
|datetime_localization|
old_reaction (Tuple[:class:`telegram.ReactionType`]): Previous list of reaction types
old_reaction (tuple[:class:`telegram.ReactionType`]): Previous list of reaction types
that were set by the user.
new_reaction (Tuple[:class:`telegram.ReactionType`]): New list of reaction types that
new_reaction (tuple[:class:`telegram.ReactionType`]): New list of reaction types that
were set by the user.
user (:class:`telegram.User`): Optional. The user that changed the reaction, if the user
isn't anonymous.
@ -169,8 +170,8 @@ class MessageReactionUpdated(TelegramObject):
self.chat: Chat = chat
self.message_id: int = message_id
self.date: datetime = date
self.old_reaction: Tuple[ReactionType, ...] = parse_sequence_arg(old_reaction)
self.new_reaction: Tuple[ReactionType, ...] = parse_sequence_arg(new_reaction)
self.old_reaction: tuple[ReactionType, ...] = parse_sequence_arg(old_reaction)
self.new_reaction: tuple[ReactionType, ...] = parse_sequence_arg(new_reaction)
# Optional
self.user: Optional[User] = user

View file

@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains objects that represent paid media in Telegram."""
from typing import TYPE_CHECKING, Dict, Final, Optional, Sequence, Tuple, Type
from collections.abc import Sequence
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._files.photosize import PhotoSize
@ -81,7 +82,7 @@ class PaidMedia(TelegramObject):
care of selecting the correct subclass.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
data (dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot`, optional): The bot associated with this object.
Returns:
@ -96,7 +97,7 @@ class PaidMedia(TelegramObject):
if not data and cls is PaidMedia:
return None
_class_mapping: Dict[str, Type[PaidMedia]] = {
_class_mapping: dict[str, type[PaidMedia]] = {
cls.PREVIEW: PaidMediaPreview,
cls.PHOTO: PaidMediaPhoto,
cls.VIDEO: PaidMediaVideo,
@ -165,7 +166,7 @@ class PaidMediaPhoto(PaidMedia):
Attributes:
type (:obj:`str`): Type of the paid media, always :tg-const:`telegram.PaidMedia.PHOTO`.
photo (Tuple[:class:`telegram.PhotoSize`]): The photo.
photo (tuple[:class:`telegram.PhotoSize`]): The photo.
"""
__slots__ = ("photo",)
@ -179,7 +180,7 @@ class PaidMediaPhoto(PaidMedia):
super().__init__(type=PaidMedia.PHOTO, api_kwargs=api_kwargs)
with self._unfrozen():
self.photo: Tuple[PhotoSize, ...] = parse_sequence_arg(photo)
self.photo: tuple[PhotoSize, ...] = parse_sequence_arg(photo)
self._id_attrs = (self.type, self.photo)
@ -259,7 +260,7 @@ class PaidMediaInfo(TelegramObject):
Attributes:
star_count (:obj:`int`): The number of Telegram Stars that must be paid to buy access to
the media.
paid_media (Tuple[:class:`telegram.PaidMedia`]): Information about the paid media.
paid_media (tuple[:class:`telegram.PaidMedia`]): Information about the paid media.
"""
__slots__ = ("paid_media", "star_count")
@ -273,7 +274,7 @@ class PaidMediaInfo(TelegramObject):
) -> None:
super().__init__(api_kwargs=api_kwargs)
self.star_count: int = star_count
self.paid_media: Tuple[PaidMedia, ...] = parse_sequence_arg(paid_media)
self.paid_media: tuple[PaidMedia, ...] = parse_sequence_arg(paid_media)
self._id_attrs = (self.star_count, self.paid_media)
self._freeze()

View file

@ -19,7 +19,8 @@
# pylint: disable=missing-module-docstring, redefined-builtin
import json
from base64 import b64decode
from typing import TYPE_CHECKING, Optional, Sequence, Tuple, no_type_check
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional, no_type_check
try:
from cryptography.hazmat.backends import default_backend
@ -390,11 +391,11 @@ class SecureValue(TelegramObject):
selfie (:class:`telegram.FileCredentials`, optional): Credentials for encrypted selfie
of the user with a document. Can be available for "passport", "driver_license",
"identity_card" and "internal_passport".
translation (List[:class:`telegram.FileCredentials`], optional): Credentials for an
translation (list[:class:`telegram.FileCredentials`], optional): Credentials for an
encrypted translation of the document. Available for "passport", "driver_license",
"identity_card", "internal_passport", "utility_bill", "bank_statement",
"rental_agreement", "passport_registration" and "temporary_registration".
files (List[:class:`telegram.FileCredentials`], optional): Credentials for encrypted
files (list[:class:`telegram.FileCredentials`], optional): Credentials for encrypted
files. Available for "utility_bill", "bank_statement", "rental_agreement",
"passport_registration" and "temporary_registration" types.
@ -410,7 +411,7 @@ class SecureValue(TelegramObject):
selfie (:class:`telegram.FileCredentials`): Optional. Credentials for encrypted selfie
of the user with a document. Can be available for "passport", "driver_license",
"identity_card" and "internal_passport".
translation (Tuple[:class:`telegram.FileCredentials`]): Optional. Credentials for an
translation (tuple[:class:`telegram.FileCredentials`]): Optional. Credentials for an
encrypted translation of the document. Available for "passport", "driver_license",
"identity_card", "internal_passport", "utility_bill", "bank_statement",
"rental_agreement", "passport_registration" and "temporary_registration".
@ -418,7 +419,7 @@ class SecureValue(TelegramObject):
.. versionchanged:: 20.0
|tupleclassattrs|
files (Tuple[:class:`telegram.FileCredentials`]): Optional. Credentials for encrypted
files (tuple[:class:`telegram.FileCredentials`]): Optional. Credentials for encrypted
files. Available for "utility_bill", "bank_statement", "rental_agreement",
"passport_registration" and "temporary_registration" types.
@ -447,8 +448,8 @@ class SecureValue(TelegramObject):
self.front_side: Optional[FileCredentials] = front_side
self.reverse_side: Optional[FileCredentials] = reverse_side
self.selfie: Optional[FileCredentials] = selfie
self.files: Tuple[FileCredentials, ...] = parse_sequence_arg(files)
self.translation: Tuple[FileCredentials, ...] = parse_sequence_arg(translation)
self.files: tuple[FileCredentials, ...] = parse_sequence_arg(files)
self.translation: tuple[FileCredentials, ...] = parse_sequence_arg(translation)
self._freeze()

View file

@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram EncryptedPassportElement."""
from base64 import b64decode
from typing import TYPE_CHECKING, Optional, Sequence, Tuple, Union
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional, Union
from telegram._passport.credentials import decrypt_json
from telegram._passport.data import IdDocumentData, PersonalDetails, ResidentialAddress
@ -100,7 +101,7 @@ class EncryptedPassportElement(TelegramObject):
"phone_number" type.
email (:obj:`str`): Optional. User's verified email address; available only for "email"
type.
files (Tuple[:class:`telegram.PassportFile`]): Optional. Array of encrypted/decrypted
files (tuple[:class:`telegram.PassportFile`]): Optional. Array of encrypted/decrypted
files with documents provided by the user; available only for "utility_bill",
"bank_statement", "rental_agreement", "passport_registration" and
"temporary_registration" types.
@ -119,7 +120,7 @@ class EncryptedPassportElement(TelegramObject):
selfie (:class:`telegram.PassportFile`): Optional. Encrypted/decrypted file with the
selfie of the user holding a document, provided by the user; available if requested for
"passport", "driver_license", "identity_card" and "internal_passport".
translation (Tuple[:class:`telegram.PassportFile`]): Optional. Array of
translation (tuple[:class:`telegram.PassportFile`]): Optional. Array of
encrypted/decrypted files with translated versions of documents provided by the user;
available if requested for "passport", "driver_license", "identity_card",
"internal_passport", "utility_bill", "bank_statement", "rental_agreement",
@ -172,11 +173,11 @@ class EncryptedPassportElement(TelegramObject):
self.data: Optional[Union[PersonalDetails, IdDocumentData, ResidentialAddress]] = data
self.phone_number: Optional[str] = phone_number
self.email: Optional[str] = email
self.files: Tuple[PassportFile, ...] = parse_sequence_arg(files)
self.files: tuple[PassportFile, ...] = parse_sequence_arg(files)
self.front_side: Optional[PassportFile] = front_side
self.reverse_side: Optional[PassportFile] = reverse_side
self.selfie: Optional[PassportFile] = selfie
self.translation: Tuple[PassportFile, ...] = parse_sequence_arg(translation)
self.translation: tuple[PassportFile, ...] = parse_sequence_arg(translation)
self.hash: str = hash
self._id_attrs = (
@ -218,7 +219,7 @@ class EncryptedPassportElement(TelegramObject):
passport credentials.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
data (dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot` | :obj:`None`): The bot associated with these object.
May be :obj:`None`, in which case shortcut methods will not be available.

View file

@ -17,7 +17,8 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""Contains information about Telegram Passport data shared with the bot by the user."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._passport.credentials import EncryptedCredentials
from telegram._passport.encryptedpassportelement import EncryptedPassportElement
@ -49,7 +50,7 @@ class PassportData(TelegramObject):
credentials (:class:`telegram.EncryptedCredentials`)): Encrypted credentials.
Attributes:
data (Tuple[:class:`telegram.EncryptedPassportElement`]): Array with encrypted
data (tuple[:class:`telegram.EncryptedPassportElement`]): Array with encrypted
information about documents and other Telegram Passport elements that was shared with
the bot.
@ -72,10 +73,10 @@ class PassportData(TelegramObject):
):
super().__init__(api_kwargs=api_kwargs)
self.data: Tuple[EncryptedPassportElement, ...] = parse_sequence_arg(data)
self.data: tuple[EncryptedPassportElement, ...] = parse_sequence_arg(data)
self.credentials: EncryptedCredentials = credentials
self._decrypted_data: Optional[Tuple[EncryptedPassportElement]] = None
self._decrypted_data: Optional[tuple[EncryptedPassportElement]] = None
self._id_attrs = tuple([x.type for x in data] + [credentials.hash])
self._freeze()
@ -96,9 +97,9 @@ class PassportData(TelegramObject):
return super().de_json(data=data, bot=bot)
@property
def decrypted_data(self) -> Tuple[EncryptedPassportElement, ...]:
def decrypted_data(self) -> tuple[EncryptedPassportElement, ...]:
"""
Tuple[:class:`telegram.EncryptedPassportElement`]: Lazily decrypt and return information
tuple[:class:`telegram.EncryptedPassportElement`]: Lazily decrypt and return information
about documents and other Telegram Passport elements which were shared with the bot.
.. versionchanged:: 20.0

View file

@ -19,7 +19,7 @@
# pylint: disable=redefined-builtin
"""This module contains the classes that represent Telegram PassportElementError."""
from typing import List, Optional
from typing import Optional
from telegram._telegramobject import TelegramObject
from telegram._utils.types import JSONDict
@ -168,7 +168,7 @@ class PassportElementErrorFiles(PassportElementError):
type (:obj:`str`): The section of the user's Telegram Passport which has the issue, one of
``"utility_bill"``, ``"bank_statement"``, ``"rental_agreement"``,
``"passport_registration"``, ``"temporary_registration"``.
file_hashes (List[:obj:`str`]): List of base64-encoded file hashes.
file_hashes (list[:obj:`str`]): List of base64-encoded file hashes.
message (:obj:`str`): Error message.
Attributes:
@ -184,7 +184,7 @@ class PassportElementErrorFiles(PassportElementError):
def __init__(
self,
type: str,
file_hashes: List[str],
file_hashes: list[str],
message: str,
*,
api_kwargs: Optional[JSONDict] = None,
@ -192,7 +192,7 @@ class PassportElementErrorFiles(PassportElementError):
# Required
super().__init__("files", type, message, api_kwargs=api_kwargs)
with self._unfrozen():
self._file_hashes: List[str] = file_hashes
self._file_hashes: list[str] = file_hashes
self._id_attrs = (self.source, self.type, self.message, *tuple(file_hashes))
@ -203,7 +203,7 @@ class PassportElementErrorFiles(PassportElementError):
return data
@property
def file_hashes(self) -> List[str]:
def file_hashes(self) -> list[str]:
"""List of base64-encoded file hashes.
.. deprecated:: 20.6
@ -386,7 +386,7 @@ class PassportElementErrorTranslationFiles(PassportElementError):
one of ``"passport"``, ``"driver_license"``, ``"identity_card"``,
``"internal_passport"``, ``"utility_bill"``, ``"bank_statement"``,
``"rental_agreement"``, ``"passport_registration"``, ``"temporary_registration"``.
file_hashes (List[:obj:`str`]): List of base64-encoded file hashes.
file_hashes (list[:obj:`str`]): List of base64-encoded file hashes.
message (:obj:`str`): Error message.
Attributes:
@ -403,7 +403,7 @@ class PassportElementErrorTranslationFiles(PassportElementError):
def __init__(
self,
type: str,
file_hashes: List[str],
file_hashes: list[str],
message: str,
*,
api_kwargs: Optional[JSONDict] = None,
@ -411,7 +411,7 @@ class PassportElementErrorTranslationFiles(PassportElementError):
# Required
super().__init__("translation_files", type, message, api_kwargs=api_kwargs)
with self._unfrozen():
self._file_hashes: List[str] = file_hashes
self._file_hashes: list[str] = file_hashes
self._id_attrs = (self.source, self.type, self.message, *tuple(file_hashes))
@ -422,7 +422,7 @@ class PassportElementErrorTranslationFiles(PassportElementError):
return data
@property
def file_hashes(self) -> List[str]:
def file_hashes(self) -> list[str]:
"""List of base64-encoded file hashes.
.. deprecated:: 20.6

View file

@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Encrypted PassportFile."""
from typing import TYPE_CHECKING, List, Optional, Tuple
from typing import TYPE_CHECKING, Optional
from telegram._telegramobject import TelegramObject
from telegram._utils.defaultvalue import DEFAULT_NONE
@ -124,7 +124,7 @@ class PassportFile(TelegramObject):
passport credentials.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
data (dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot` | :obj:`None`): The bot associated with these object.
May be :obj:`None`, in which case shortcut methods will not be available.
@ -151,10 +151,10 @@ class PassportFile(TelegramObject):
@classmethod
def de_list_decrypted(
cls,
data: Optional[List[JSONDict]],
data: Optional[list[JSONDict]],
bot: Optional["Bot"],
credentials: List["FileCredentials"],
) -> Tuple[Optional["PassportFile"], ...]:
credentials: list["FileCredentials"],
) -> tuple[Optional["PassportFile"], ...]:
"""Variant of :meth:`telegram.TelegramObject.de_list` that also takes into account
passport credentials.
@ -164,7 +164,7 @@ class PassportFile(TelegramObject):
* Filters out any :obj:`None` values
Args:
data (List[Dict[:obj:`str`, ...]]): The JSON data.
data (list[dict[:obj:`str`, ...]]): The JSON data.
bot (:class:`telegram.Bot` | :obj:`None`): The bot associated with these object.
May be :obj:`None`, in which case shortcut methods will not be available.
@ -176,7 +176,7 @@ class PassportFile(TelegramObject):
credentials (:class:`telegram.FileCredentials`): The credentials
Returns:
Tuple[:class:`telegram.PassportFile`]:
tuple[:class:`telegram.PassportFile`]:
"""
if not data:

View file

@ -17,7 +17,8 @@
# 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 ShippingOption."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._telegramobject import TelegramObject
from telegram._utils.argumentparsing import parse_sequence_arg
@ -47,7 +48,7 @@ class ShippingOption(TelegramObject):
Attributes:
id (:obj:`str`): Shipping option identifier.
title (:obj:`str`): Option title.
prices (Tuple[:class:`telegram.LabeledPrice`]): List of price portions.
prices (tuple[:class:`telegram.LabeledPrice`]): List of price portions.
.. versionchanged:: 20.0
|tupleclassattrs|
@ -68,7 +69,7 @@ class ShippingOption(TelegramObject):
self.id: str = id
self.title: str = title
self.prices: Tuple[LabeledPrice, ...] = parse_sequence_arg(prices)
self.prices: tuple[LabeledPrice, ...] = parse_sequence_arg(prices)
self._id_attrs = (self.id,)

View file

@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram ShippingQuery."""
from typing import TYPE_CHECKING, Optional, Sequence
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._payment.shippingaddress import ShippingAddress
from telegram._telegramobject import TelegramObject

View file

@ -19,8 +19,9 @@
# pylint: disable=redefined-builtin
"""This module contains the classes for Telegram Stars transactions."""
from collections.abc import Sequence
from datetime import datetime
from typing import TYPE_CHECKING, Dict, Final, Optional, Sequence, Tuple, Type
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._paidmedia import PaidMedia
@ -79,7 +80,7 @@ class RevenueWithdrawalState(TelegramObject):
care of selecting the correct subclass.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
data (dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot`): The bot associated with this object.
Returns:
@ -91,7 +92,7 @@ class RevenueWithdrawalState(TelegramObject):
if not data:
return None
_class_mapping: Dict[str, Type[RevenueWithdrawalState]] = {
_class_mapping: dict[str, type[RevenueWithdrawalState]] = {
cls.PENDING: RevenueWithdrawalStatePending,
cls.SUCCEEDED: RevenueWithdrawalStateSucceeded,
cls.FAILED: RevenueWithdrawalStateFailed,
@ -239,7 +240,7 @@ class TransactionPartner(TelegramObject):
care of selecting the correct subclass.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
data (dict[:obj:`str`, ...]): The JSON data.
bot (:class:`telegram.Bot`): The bot associated with this object.
Returns:
@ -254,7 +255,7 @@ class TransactionPartner(TelegramObject):
if not data and cls is TransactionPartner:
return None
_class_mapping: Dict[str, Type[TransactionPartner]] = {
_class_mapping: dict[str, type[TransactionPartner]] = {
cls.FRAGMENT: TransactionPartnerFragment,
cls.USER: TransactionPartnerUser,
cls.OTHER: TransactionPartnerOther,
@ -337,7 +338,7 @@ class TransactionPartnerUser(TransactionPartner):
always :tg-const:`telegram.TransactionPartner.USER`.
user (:class:`telegram.User`): Information about the user.
invoice_payload (:obj:`str`): Optional. Bot-specified invoice payload.
paid_media (Tuple[:class:`telegram.PaidMedia`]): Optional. Information about the paid
paid_media (tuple[:class:`telegram.PaidMedia`]): Optional. Information about the paid
media bought by the user.
.. versionadded:: 21.5
@ -363,7 +364,7 @@ class TransactionPartnerUser(TransactionPartner):
with self._unfrozen():
self.user: User = user
self.invoice_payload: Optional[str] = invoice_payload
self.paid_media: Optional[Tuple[PaidMedia, ...]] = parse_sequence_arg(paid_media)
self.paid_media: Optional[tuple[PaidMedia, ...]] = parse_sequence_arg(paid_media)
self.paid_media_payload: Optional[str] = paid_media_payload
self._id_attrs = (
self.type,
@ -516,7 +517,7 @@ class StarTransactions(TelegramObject):
transactions (Sequence[:class:`telegram.StarTransaction`]): The list of transactions.
Attributes:
transactions (Tuple[:class:`telegram.StarTransaction`]): The list of transactions.
transactions (tuple[:class:`telegram.StarTransaction`]): The list of transactions.
"""
__slots__ = ("transactions",)
@ -525,7 +526,7 @@ class StarTransactions(TelegramObject):
self, transactions: Sequence[StarTransaction], *, api_kwargs: Optional[JSONDict] = None
):
super().__init__(api_kwargs=api_kwargs)
self.transactions: Tuple[StarTransaction, ...] = parse_sequence_arg(transactions)
self.transactions: tuple[StarTransaction, ...] = parse_sequence_arg(transactions)
self._id_attrs = (self.transactions,)
self._freeze()

View file

@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram Poll."""
import datetime
from typing import TYPE_CHECKING, Dict, Final, List, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Final, Optional
from telegram import constants
from telegram._chat import Chat
@ -83,7 +84,7 @@ class InputPollOption(TelegramObject):
super().__init__(api_kwargs=api_kwargs)
self.text: str = text
self.text_parse_mode: ODVInput[str] = text_parse_mode
self.text_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(text_entities)
self.text_entities: tuple[MessageEntity, ...] = parse_sequence_arg(text_entities)
self._id_attrs = (self.text,)
@ -127,7 +128,7 @@ class PollOption(TelegramObject):
:tg-const:`telegram.PollOption.MIN_LENGTH`-:tg-const:`telegram.PollOption.MAX_LENGTH`
characters.
voter_count (:obj:`int`): Number of users that voted for this option.
text_entities (Tuple[:class:`telegram.MessageEntity`]): Special entities
text_entities (tuple[:class:`telegram.MessageEntity`]): Special entities
that appear in the option text. Currently, only custom emoji entities are allowed in
poll option texts.
This list is empty if the question does not contain entities.
@ -149,7 +150,7 @@ class PollOption(TelegramObject):
super().__init__(api_kwargs=api_kwargs)
self.text: str = text
self.voter_count: int = voter_count
self.text_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(text_entities)
self.text_entities: tuple[MessageEntity, ...] = parse_sequence_arg(text_entities)
self._id_attrs = (self.text, self.voter_count)
@ -189,7 +190,7 @@ class PollOption(TelegramObject):
"""
return parse_message_entity(self.text, entity)
def parse_entities(self, types: Optional[List[str]] = None) -> Dict[MessageEntity, str]:
def parse_entities(self, types: Optional[list[str]] = None) -> dict[MessageEntity, str]:
"""
Returns a :obj:`dict` that maps :class:`telegram.MessageEntity` to :obj:`str`.
It contains entities from this polls question filtered by their ``type`` attribute as
@ -203,12 +204,12 @@ class PollOption(TelegramObject):
.. versionadded:: 21.2
Args:
types (List[:obj:`str`], optional): List of ``MessageEntity`` types as strings. If the
types (list[:obj:`str`], optional): List of ``MessageEntity`` types as strings. If the
``type`` attribute of an entity is contained in this list, it will be returned.
Defaults to :attr:`telegram.MessageEntity.ALL_TYPES`.
Returns:
Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
"""
return parse_message_entities(self.text, self.text_entities, types)
@ -260,7 +261,7 @@ class PollAnswer(TelegramObject):
Attributes:
poll_id (:obj:`str`): Unique poll identifier.
option_ids (Tuple[:obj:`int`]): Identifiers of answer options, chosen by the user. May
option_ids (tuple[:obj:`int`]): Identifiers of answer options, chosen by the user. May
be empty if the user retracted their vote.
.. versionchanged:: 20.0
@ -292,7 +293,7 @@ class PollAnswer(TelegramObject):
super().__init__(api_kwargs=api_kwargs)
self.poll_id: str = poll_id
self.voter_chat: Optional[Chat] = voter_chat
self.option_ids: Tuple[int, ...] = parse_sequence_arg(option_ids)
self.option_ids: tuple[int, ...] = parse_sequence_arg(option_ids)
self.user: Optional[User] = user
self._id_attrs = (
@ -374,7 +375,7 @@ class Poll(TelegramObject):
id (:obj:`str`): Unique poll identifier.
question (:obj:`str`): Poll question, :tg-const:`telegram.Poll.MIN_QUESTION_LENGTH`-
:tg-const:`telegram.Poll.MAX_QUESTION_LENGTH` characters.
options (Tuple[:class:`~telegram.PollOption`]): List of poll options.
options (tuple[:class:`~telegram.PollOption`]): List of poll options.
.. versionchanged:: 20.0
|tupleclassattrs|
@ -389,7 +390,7 @@ class Poll(TelegramObject):
explanation (:obj:`str`): Optional. Text that is shown when a user chooses an incorrect
answer or taps on the lamp icon in a quiz-style poll,
0-:tg-const:`telegram.Poll.MAX_EXPLANATION_LENGTH` characters.
explanation_entities (Tuple[:class:`telegram.MessageEntity`]): Special entities
explanation_entities (tuple[:class:`telegram.MessageEntity`]): Special entities
like usernames, URLs, bot commands, etc. that appear in the :attr:`explanation`.
This list is empty if the message does not contain explanation entities.
@ -405,7 +406,7 @@ class Poll(TelegramObject):
.. versionchanged:: 20.3
|datetime_localization|
question_entities (Tuple[:class:`telegram.MessageEntity`]): Special entities
question_entities (tuple[:class:`telegram.MessageEntity`]): Special entities
that appear in the :attr:`question`. Currently, only custom emoji entities are allowed
in poll questions.
This list is empty if the question does not contain entities.
@ -453,7 +454,7 @@ class Poll(TelegramObject):
super().__init__(api_kwargs=api_kwargs)
self.id: str = id
self.question: str = question
self.options: Tuple[PollOption, ...] = parse_sequence_arg(options)
self.options: tuple[PollOption, ...] = parse_sequence_arg(options)
self.total_voter_count: int = total_voter_count
self.is_closed: bool = is_closed
self.is_anonymous: bool = is_anonymous
@ -461,12 +462,12 @@ class Poll(TelegramObject):
self.allows_multiple_answers: bool = allows_multiple_answers
self.correct_option_id: Optional[int] = correct_option_id
self.explanation: Optional[str] = explanation
self.explanation_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(
self.explanation_entities: tuple[MessageEntity, ...] = parse_sequence_arg(
explanation_entities
)
self.open_period: Optional[int] = open_period
self.close_date: Optional[datetime.datetime] = close_date
self.question_entities: Tuple[MessageEntity, ...] = parse_sequence_arg(question_entities)
self.question_entities: tuple[MessageEntity, ...] = parse_sequence_arg(question_entities)
self._id_attrs = (self.id,)
@ -516,8 +517,8 @@ class Poll(TelegramObject):
return parse_message_entity(self.explanation, entity)
def parse_explanation_entities(
self, types: Optional[List[str]] = None
) -> Dict[MessageEntity, str]:
self, types: Optional[list[str]] = None
) -> dict[MessageEntity, str]:
"""
Returns a :obj:`dict` that maps :class:`telegram.MessageEntity` to :obj:`str`.
It contains entities from this polls explanation filtered by their ``type`` attribute as
@ -529,12 +530,12 @@ class Poll(TelegramObject):
UTF-16 codepoints. See :attr:`parse_explanation_entity` for more info.
Args:
types (List[:obj:`str`], optional): List of ``MessageEntity`` types as strings. If the
types (list[:obj:`str`], optional): List of ``MessageEntity`` types as strings. If the
``type`` attribute of an entity is contained in this list, it will be returned.
Defaults to :attr:`telegram.MessageEntity.ALL_TYPES`.
Returns:
Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
Raises:
@ -567,8 +568,8 @@ class Poll(TelegramObject):
return parse_message_entity(self.question, entity)
def parse_question_entities(
self, types: Optional[List[str]] = None
) -> Dict[MessageEntity, str]:
self, types: Optional[list[str]] = None
) -> dict[MessageEntity, str]:
"""
Returns a :obj:`dict` that maps :class:`telegram.MessageEntity` to :obj:`str`.
It contains entities from this polls question filtered by their ``type`` attribute as
@ -582,12 +583,12 @@ class Poll(TelegramObject):
UTF-16 codepoints. See :attr:`parse_question_entity` for more info.
Args:
types (List[:obj:`str`], optional): List of ``MessageEntity`` types as strings. If the
types (list[:obj:`str`], optional): List of ``MessageEntity`` types as strings. If the
``type`` attribute of an entity is contained in this list, it will be returned.
Defaults to :attr:`telegram.MessageEntity.ALL_TYPES`.
Returns:
Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
"""

View file

@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains objects that represents a Telegram ReactionType."""
from typing import TYPE_CHECKING, Dict, Final, Literal, Optional, Type, Union
from typing import TYPE_CHECKING, Final, Literal, Optional, Union
from telegram import constants
from telegram._telegramobject import TelegramObject
@ -89,7 +89,7 @@ class ReactionType(TelegramObject):
if not data and cls is ReactionType:
return None
_class_mapping: Dict[str, Type[ReactionType]] = {
_class_mapping: dict[str, type[ReactionType]] = {
cls.EMOJI: ReactionTypeEmoji,
cls.CUSTOM_EMOJI: ReactionTypeCustomEmoji,
cls.PAID: ReactionTypePaid,

View file

@ -17,7 +17,8 @@
# 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 modules contains objects that represents Telegram Replies"""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple, Union
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional, Union
from telegram._chat import Chat
from telegram._dice import Dice
@ -124,7 +125,7 @@ class ExternalReplyInfo(TelegramObject):
file.
document (:class:`telegram.Document`): Optional. Message is a general file, information
about the file.
photo (Tuple[:class:`telegram.PhotoSize`]): Optional. Message is a photo, available sizes
photo (tuple[:class:`telegram.PhotoSize`]): Optional. Message is a photo, available sizes
of the photo.
sticker (:class:`telegram.Sticker`): Optional. Message is a sticker, information about the
sticker.
@ -224,7 +225,7 @@ class ExternalReplyInfo(TelegramObject):
self.animation: Optional[Animation] = animation
self.audio: Optional[Audio] = audio
self.document: Optional[Document] = document
self.photo: Optional[Tuple[PhotoSize, ...]] = parse_sequence_arg(photo)
self.photo: Optional[tuple[PhotoSize, ...]] = parse_sequence_arg(photo)
self.sticker: Optional[Sticker] = sticker
self.story: Optional[Story] = story
self.video: Optional[Video] = video
@ -311,7 +312,7 @@ class TextQuote(TelegramObject):
message.
position (:obj:`int`): Approximate quote position in the original message in UTF-16 code
units as specified by the sender.
entities (Tuple[:class:`telegram.MessageEntity`]): Optional. Special entities that appear
entities (tuple[:class:`telegram.MessageEntity`]): Optional. Special entities that appear
in the quote. Currently, only bold, italic, underline, strikethrough, spoiler, and
custom_emoji entities are kept in quotes.
is_manual (:obj:`bool`): Optional. :obj:`True`, if the quote was chosen manually by the
@ -338,7 +339,7 @@ class TextQuote(TelegramObject):
self.text: str = text
self.position: int = position
self.entities: Optional[Tuple[MessageEntity, ...]] = parse_sequence_arg(entities)
self.entities: Optional[tuple[MessageEntity, ...]] = parse_sequence_arg(entities)
self.is_manual: Optional[bool] = is_manual
self._id_attrs = (
@ -411,7 +412,7 @@ class ReplyParameters(TelegramObject):
quote_parse_mode (:obj:`str`): Optional. Mode for parsing entities in the quote. See
:wiki:`formatting options <Code-snippets#message-formatting-bold-italic-code->` for
more details.
quote_entities (Tuple[:class:`telegram.MessageEntity`]): Optional. A JSON-serialized list
quote_entities (tuple[:class:`telegram.MessageEntity`]): Optional. A JSON-serialized list
of special entities that appear in the quote. It can be specified instead of
:paramref:`quote_parse_mode`.
quote_position (:obj:`int`): Optional. Position of the quote in the original message in
@ -447,7 +448,7 @@ class ReplyParameters(TelegramObject):
self.allow_sending_without_reply: ODVInput[bool] = allow_sending_without_reply
self.quote: Optional[str] = quote
self.quote_parse_mode: ODVInput[str] = quote_parse_mode
self.quote_entities: Optional[Tuple[MessageEntity, ...]] = parse_sequence_arg(
self.quote_entities: Optional[tuple[MessageEntity, ...]] = parse_sequence_arg(
quote_entities
)
self.quote_position: Optional[int] = quote_position

View file

@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram ReplyKeyboardMarkup."""
from typing import Final, Optional, Sequence, Tuple, Union
from collections.abc import Sequence
from typing import Final, Optional, Union
from telegram import constants
from telegram._keyboardbutton import KeyboardButton
@ -85,7 +86,7 @@ class ReplyKeyboardMarkup(TelegramObject):
.. versionadded:: 20.0
Attributes:
keyboard (Tuple[Tuple[:class:`telegram.KeyboardButton`]]): Array of button rows,
keyboard (tuple[tuple[:class:`telegram.KeyboardButton`]]): Array of button rows,
each represented by an Array of :class:`telegram.KeyboardButton` objects.
resize_keyboard (:obj:`bool`): Optional. Requests clients to resize the keyboard vertically
for optimal fit (e.g., make the keyboard smaller if there are just two rows of
@ -148,7 +149,7 @@ class ReplyKeyboardMarkup(TelegramObject):
)
# Required
self.keyboard: Tuple[Tuple[KeyboardButton, ...], ...] = tuple(
self.keyboard: tuple[tuple[KeyboardButton, ...], ...] = tuple(
tuple(KeyboardButton(button) if isinstance(button, str) else button for button in row)
for row in keyboard
)

View file

@ -17,7 +17,8 @@
# 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 two objects used for request chats/users service messages."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._files.photosize import PhotoSize
from telegram._telegramobject import TelegramObject
@ -59,7 +60,7 @@ class UsersShared(TelegramObject):
Attributes:
request_id (:obj:`int`): Identifier of the request.
users (Tuple[:class:`telegram.SharedUser`]): Information about users shared with the
users (tuple[:class:`telegram.SharedUser`]): Information about users shared with the
bot.
.. versionadded:: 21.1
@ -76,7 +77,7 @@ class UsersShared(TelegramObject):
):
super().__init__(api_kwargs=api_kwargs)
self.request_id: int = request_id
self.users: Tuple[SharedUser, ...] = parse_sequence_arg(users)
self.users: tuple[SharedUser, ...] = parse_sequence_arg(users)
self._id_attrs = (self.request_id, self.users)
@ -144,7 +145,7 @@ class ChatShared(TelegramObject):
the bot and available.
.. versionadded:: 21.1
photo (Tuple[:class:`telegram.PhotoSize`]): Optional. Available sizes of the chat photo,
photo (tuple[:class:`telegram.PhotoSize`]): Optional. Available sizes of the chat photo,
if the photo was requested by the bot
.. versionadded:: 21.1
@ -167,7 +168,7 @@ class ChatShared(TelegramObject):
self.chat_id: int = chat_id
self.title: Optional[str] = title
self.username: Optional[str] = username
self.photo: Optional[Tuple[PhotoSize, ...]] = parse_sequence_arg(photo)
self.photo: Optional[tuple[PhotoSize, ...]] = parse_sequence_arg(photo)
self._id_attrs = (self.request_id, self.chat_id)
@ -226,7 +227,7 @@ class SharedUser(TelegramObject):
bot.
username (:obj:`str`): Optional. Username of the user, if the username was requested by the
bot.
photo (Tuple[:class:`telegram.PhotoSize`]): Available sizes of the chat photo, if
photo (tuple[:class:`telegram.PhotoSize`]): Available sizes of the chat photo, if
the photo was requested by the bot. This list is empty if the photo was not requsted.
"""
@ -247,7 +248,7 @@ class SharedUser(TelegramObject):
self.first_name: Optional[str] = first_name
self.last_name: Optional[str] = last_name
self.username: Optional[str] = username
self.photo: Optional[Tuple[PhotoSize, ...]] = parse_sequence_arg(photo)
self.photo: Optional[tuple[PhotoSize, ...]] = parse_sequence_arg(photo)
self._id_attrs = (self.user_id,)

View file

@ -21,27 +21,12 @@ import contextlib
import datetime
import inspect
import json
from collections.abc import Sized
from collections.abc import Iterator, Mapping, Sized
from contextlib import contextmanager
from copy import deepcopy
from itertools import chain
from types import MappingProxyType
from typing import (
TYPE_CHECKING,
Any,
ClassVar,
Dict,
Iterator,
List,
Mapping,
Optional,
Set,
Tuple,
Type,
TypeVar,
Union,
cast,
)
from typing import TYPE_CHECKING, Any, ClassVar, Optional, TypeVar, Union, cast
from telegram._utils.datetime import to_timestamp
from telegram._utils.defaultvalue import DefaultValue
@ -80,7 +65,7 @@ class TelegramObject:
:obj:`list` are now of type :obj:`tuple`.
Arguments:
api_kwargs (Dict[:obj:`str`, any], optional): |toapikwargsarg|
api_kwargs (dict[:obj:`str`, any], optional): |toapikwargsarg|
.. versionadded:: 20.0
@ -95,11 +80,11 @@ class TelegramObject:
# Used to cache the names of the parameters of the __init__ method of the class
# Must be a private attribute to avoid name clashes between subclasses
__INIT_PARAMS: ClassVar[Set[str]] = set()
__INIT_PARAMS: ClassVar[set[str]] = set()
# Used to check if __INIT_PARAMS has been set for the current class. Unfortunately, we can't
# just check if `__INIT_PARAMS is None`, since subclasses use the parent class' __INIT_PARAMS
# unless it's overridden
__INIT_PARAMS_CHECK: Optional[Type["TelegramObject"]] = None
__INIT_PARAMS_CHECK: Optional[type["TelegramObject"]] = None
def __init__(self, *, api_kwargs: Optional[JSONDict] = None) -> None:
# Setting _frozen to `False` here means that classes without arguments still need to
@ -107,7 +92,7 @@ class TelegramObject:
# `with self._unfrozen()` in the `__init__` of subclasses and we have fewer empty
# classes than classes with arguments.
self._frozen: bool = False
self._id_attrs: Tuple[object, ...] = ()
self._id_attrs: tuple[object, ...] = ()
self._bot: Optional[Bot] = None
# We don't do anything with api_kwargs here - see docstring of _apply_api_kwargs
self.api_kwargs: Mapping[str, Any] = MappingProxyType(api_kwargs or {})
@ -263,7 +248,7 @@ class TelegramObject:
f"`{item}`."
) from exc
def __getstate__(self) -> Dict[str, Union[str, object]]:
def __getstate__(self) -> dict[str, Union[str, object]]:
"""
Overrides :meth:`object.__getstate__` to customize the pickling process of objects of this
type.
@ -271,7 +256,7 @@ class TelegramObject:
:meth:`set_bot` (if any), as it can't be pickled.
Returns:
state (Dict[:obj:`str`, :obj:`object`]): The state of the object.
state (dict[:obj:`str`, :obj:`object`]): The state of the object.
"""
out = self._get_attrs(
include_private=True, recursive=False, remove_bot=True, convert_default_vault=False
@ -281,7 +266,7 @@ class TelegramObject:
out["api_kwargs"] = dict(self.api_kwargs)
return out
def __setstate__(self, state: Dict[str, object]) -> None:
def __setstate__(self, state: dict[str, object]) -> None:
"""
Overrides :meth:`object.__setstate__` to customize the unpickling process of objects of
this type. Modifies the object in-place.
@ -305,7 +290,7 @@ class TelegramObject:
self._bot = None
# get api_kwargs first because we may need to add entries to it (see try-except below)
api_kwargs = cast(Dict[str, object], state.pop("api_kwargs", {}))
api_kwargs = cast(dict[str, object], state.pop("api_kwargs", {}))
# get _frozen before the loop to avoid setting it to True in the loop
frozen = state.pop("_frozen", False)
@ -341,7 +326,7 @@ class TelegramObject:
if frozen:
self._freeze()
def __deepcopy__(self: Tele_co, memodict: Dict[int, object]) -> Tele_co:
def __deepcopy__(self: Tele_co, memodict: dict[int, object]) -> Tele_co:
"""
Customizes how :func:`copy.deepcopy` processes objects of this type.
The only difference to the default implementation is that the :class:`telegram.Bot`
@ -401,7 +386,7 @@ class TelegramObject:
@classmethod
def _de_json(
cls: Type[Tele_co],
cls: type[Tele_co],
data: Optional[JSONDict],
bot: Optional["Bot"],
api_kwargs: Optional[JSONDict] = None,
@ -433,12 +418,12 @@ class TelegramObject:
@classmethod
def de_json(
cls: Type[Tele_co], data: Optional[JSONDict], bot: Optional["Bot"] = None
cls: type[Tele_co], data: Optional[JSONDict], bot: Optional["Bot"] = None
) -> Optional[Tele_co]:
"""Converts JSON data to a Telegram object.
Args:
data (Dict[:obj:`str`, ...]): The JSON data.
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.
@ -453,8 +438,8 @@ class TelegramObject:
@classmethod
def de_list(
cls: Type[Tele_co], data: Optional[List[JSONDict]], bot: Optional["Bot"] = None
) -> Tuple[Tele_co, ...]:
cls: type[Tele_co], data: Optional[list[JSONDict]], bot: Optional["Bot"] = None
) -> tuple[Tele_co, ...]:
"""Converts a list of JSON objects to a tuple of Telegram objects.
.. versionchanged:: 20.0
@ -463,7 +448,7 @@ class TelegramObject:
* Filters out any :obj:`None` values.
Args:
data (List[Dict[:obj:`str`, ...]]): The JSON data.
data (list[dict[:obj:`str`, ...]]): The JSON data.
bot (:class:`telegram.Bot`, optional): The bot associated with these object. Defaults
to :obj:`None`, in which case shortcut methods will not be available.
@ -552,7 +537,7 @@ class TelegramObject:
recursive: bool = False,
remove_bot: bool = False,
convert_default_vault: bool = True,
) -> Dict[str, Union[str, object]]:
) -> dict[str, Union[str, object]]:
"""This method is used for obtaining the attributes of the object.
Args:
@ -625,7 +610,7 @@ class TelegramObject:
# Now we should convert TGObjects to dicts inside objects such as sequences, and convert
# datetimes to timestamps. This mostly eliminates the need for subclasses to override
# `to_dict`
pop_keys: Set[str] = set()
pop_keys: set[str] = set()
for key, value in out.items():
if isinstance(value, (tuple, list)):
if not value:
@ -637,7 +622,7 @@ class TelegramObject:
for item in value:
if hasattr(item, "to_dict"):
val.append(item.to_dict(recursive=recursive))
# This branch is useful for e.g. Tuple[Tuple[PhotoSize|KeyboardButton]]
# This branch is useful for e.g. tuple[tuple[PhotoSize|KeyboardButton]]
elif isinstance(item, (tuple, list)):
val.append(
[

View file

@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains an object that represents a Telegram Update."""
from typing import TYPE_CHECKING, Final, List, Optional, Union
from typing import TYPE_CHECKING, Final, Optional, Union
from telegram import constants
from telegram._business import BusinessConnection, BusinessMessagesDeleted
@ -402,8 +402,8 @@ class Update(TelegramObject):
.. versionadded:: 21.6
"""
ALL_TYPES: Final[List[str]] = list(constants.UpdateType)
"""List[:obj:`str`]: A list of all available update types.
ALL_TYPES: Final[list[str]] = list(constants.UpdateType)
"""list[:obj:`str`]: A list of all available update types.
.. versionadded:: 13.5"""

View file

@ -18,8 +18,9 @@
# 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 User."""
from collections.abc import Sequence
from datetime import datetime
from typing import TYPE_CHECKING, Optional, Sequence, Tuple, Union
from typing import TYPE_CHECKING, Optional, Union
from telegram._inline.inlinekeyboardbutton import InlineKeyboardButton
from telegram._menubutton import MenuButton
@ -621,7 +622,7 @@ class User(TelegramObject):
caption: Optional[str] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
) -> Tuple["Message", ...]:
) -> tuple["Message", ...]:
"""Shortcut for::
await bot.send_media_group(update.effective_user.id, *args, **kwargs)
@ -632,7 +633,7 @@ class User(TelegramObject):
|user_chat_id_note|
Returns:
Tuple[:class:`telegram.Message`:] On success, a tuple of :class:`~telegram.Message`
tuple[:class:`telegram.Message`:] On success, a tuple of :class:`~telegram.Message`
instances that were sent is returned.
"""
@ -1739,7 +1740,7 @@ class User(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
"""Shortcut for::
await bot.copy_messages(chat_id=update.effective_user.id, *argss, **kwargs)
@ -1751,7 +1752,7 @@ class User(TelegramObject):
.. versionadded:: 20.8
Returns:
Tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
of the sent messages is returned.
"""
@ -1784,7 +1785,7 @@ class User(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
"""Shortcut for::
await bot.copy_messages(from_chat_id=update.effective_user.id, *argss, **kwargs)
@ -1796,7 +1797,7 @@ class User(TelegramObject):
.. versionadded:: 20.8
Returns:
Tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
of the sent messages is returned.
"""
@ -1913,7 +1914,7 @@ class User(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
"""Shortcut for::
await bot.forward_messages(chat_id=update.effective_user.id, *argss, **kwargs)
@ -1925,7 +1926,7 @@ class User(TelegramObject):
.. versionadded:: 20.8
Returns:
Tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
of sent messages is returned.
"""
@ -1956,7 +1957,7 @@ class User(TelegramObject):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
"""Shortcut for::
await bot.forward_messages(from_chat_id=update.effective_user.id, *argss, **kwargs)
@ -1968,7 +1969,7 @@ class User(TelegramObject):
.. versionadded:: 20.8
Returns:
Tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
tuple[:class:`telegram.MessageId`]: On success, a tuple of :class:`~telegram.MessageId`
of sent messages is returned.
"""

View file

@ -17,7 +17,8 @@
# 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 UserProfilePhotos."""
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._files.photosize import PhotoSize
from telegram._telegramobject import TelegramObject
@ -43,7 +44,7 @@ class UserProfilePhotos(TelegramObject):
Attributes:
total_count (:obj:`int`): Total number of profile pictures.
photos (Tuple[Tuple[:class:`telegram.PhotoSize`]]): Requested profile pictures (in up to 4
photos (tuple[tuple[:class:`telegram.PhotoSize`]]): Requested profile pictures (in up to 4
sizes each).
.. versionchanged:: 20.0
@ -63,7 +64,7 @@ class UserProfilePhotos(TelegramObject):
super().__init__(api_kwargs=api_kwargs)
# Required
self.total_count: int = total_count
self.photos: Tuple[Tuple[PhotoSize, ...], ...] = tuple(tuple(sizes) for sizes in photos)
self.photos: tuple[tuple[PhotoSize, ...], ...] = tuple(tuple(sizes) for sizes in photos)
self._id_attrs = (self.total_count, self.photos)

View file

@ -23,7 +23,8 @@ Warning:
user. Changes to this module are not considered breaking changes and may not be documented in
the changelog.
"""
from typing import Optional, Sequence, Tuple, TypeVar
from collections.abc import Sequence
from typing import Optional, TypeVar
from telegram._linkpreviewoptions import LinkPreviewOptions
from telegram._utils.types import ODVInput
@ -31,7 +32,7 @@ from telegram._utils.types import ODVInput
T = TypeVar("T")
def parse_sequence_arg(arg: Optional[Sequence[T]]) -> Tuple[T, ...]:
def parse_sequence_arg(arg: Optional[Sequence[T]]) -> tuple[T, ...]:
"""Parses an optional sequence into a tuple
Args:

View file

@ -23,7 +23,8 @@ Warning:
user. Changes to this module are not considered breaking changes and may not be documented in
the changelog.
"""
from typing import Dict, Optional, Sequence
from collections.abc import Sequence
from typing import Optional
from telegram._messageentity import MessageEntity
from telegram._utils.strings import TextEncoding
@ -47,7 +48,7 @@ def parse_message_entity(text: str, entity: MessageEntity) -> str:
def parse_message_entities(
text: str, entities: Sequence[MessageEntity], types: Optional[Sequence[str]] = None
) -> Dict[MessageEntity, str]:
) -> dict[MessageEntity, str]:
"""
Returns a :obj:`dict` that maps :class:`telegram.MessageEntity` to :obj:`str`.
It contains entities filtered by their ``type`` attribute as
@ -55,13 +56,13 @@ def parse_message_entities(
Args:
text (:obj:`str`): The text to extract the entity from.
entities (List[:class:`telegram.MessageEntity`]): The entities to extract the text from.
types (List[:obj:`str`], optional): List of ``MessageEntity`` types as strings. If the
entities (list[:class:`telegram.MessageEntity`]): The entities to extract the text from.
types (list[:obj:`str`], optional): List of ``MessageEntity`` types as strings. If the
``type`` attribute of an entity is contained in this list, it will be returned.
Defaults to :attr:`telegram.MessageEntity.ALL_TYPES`.
Returns:
Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
the text that belongs to them, calculated based on UTF-16 codepoints.
"""
if types is None:

View file

@ -25,14 +25,14 @@ Warning:
"""
import enum as _enum
import sys
from typing import Type, TypeVar, Union
from typing import TypeVar, Union
_A = TypeVar("_A")
_B = TypeVar("_B")
_Enum = TypeVar("_Enum", bound=_enum.Enum)
def get_member(enum_cls: Type[_Enum], value: _A, default: _B) -> Union[_Enum, _A, _B]:
def get_member(enum_cls: type[_Enum], value: _A, default: _B) -> Union[_Enum, _A, _B]:
"""Tries to call ``enum_cls(value)`` to convert the value into an enumeration member.
If that fails, the ``default`` is returned.
"""

View file

@ -29,7 +29,7 @@ Warning:
"""
from pathlib import Path
from typing import IO, TYPE_CHECKING, Any, Optional, Tuple, Type, TypeVar, Union, cast, overload
from typing import IO, TYPE_CHECKING, Any, Optional, TypeVar, Union, cast, overload
from telegram._utils.types import FileInput, FilePathInput
@ -40,16 +40,16 @@ _T = TypeVar("_T", bound=Union[bytes, "InputFile", str, Path, None])
@overload
def load_file(obj: IO[bytes]) -> Tuple[Optional[str], bytes]: ...
def load_file(obj: IO[bytes]) -> tuple[Optional[str], bytes]: ...
@overload
def load_file(obj: _T) -> Tuple[None, _T]: ...
def load_file(obj: _T) -> tuple[None, _T]: ...
def load_file(
obj: Optional[FileInput],
) -> Tuple[Optional[str], Union[bytes, "InputFile", str, Path, None]]:
) -> tuple[Optional[str], Union[bytes, "InputFile", str, Path, None]]:
"""If the input is a file handle, read the data and name and return it. Otherwise, return
the input unchanged.
"""
@ -95,7 +95,7 @@ def is_local_file(obj: Optional[FilePathInput]) -> bool:
def parse_file_input( # pylint: disable=too-many-return-statements
file_input: Union[FileInput, "TelegramObject"],
tg_type: Optional[Type["TelegramObject"]] = None,
tg_type: Optional[type["TelegramObject"]] = None,
filename: Optional[str] = None,
attach: bool = False,
local_mode: bool = False,

View file

@ -23,19 +23,9 @@ Warning:
user. Changes to this module are not considered breaking changes and may not be documented in
the changelog.
"""
from collections.abc import Collection
from pathlib import Path
from typing import (
IO,
TYPE_CHECKING,
Any,
Collection,
Dict,
Literal,
Optional,
Tuple,
TypeVar,
Union,
)
from typing import IO, TYPE_CHECKING, Any, Literal, Optional, TypeVar, Union
if TYPE_CHECKING:
from telegram import (
@ -57,7 +47,7 @@ FileInput = Union[FilePathInput, FileLike, bytes, str]
"""Valid input for passing files to Telegram. Either a file id as string, a file like object,
a local file path as string, :class:`pathlib.Path` or the file contents as :obj:`bytes`."""
JSONDict = Dict[str, Any]
JSONDict = dict[str, Any]
"""Dictionary containing response from Telegram or data to send to the API."""
DVValueType = TypeVar("DVValueType") # pylint: disable=invalid-name
@ -82,9 +72,9 @@ ReplyMarkup = Union[
.. versionadded:: 20.0
"""
FieldTuple = Tuple[str, Union[bytes, IO[bytes]], str]
FieldTuple = tuple[str, Union[bytes, IO[bytes]], str]
"""Alias for return type of `InputFile.field_tuple`."""
UploadFileDict = Dict[str, FieldTuple]
UploadFileDict = dict[str, FieldTuple]
"""Dictionary containing file data to be uploaded to the API."""
HTTPVersion = Literal["1.1", "2.0", "2"]
@ -97,7 +87,7 @@ CorrectOptionID = Literal[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
MarkdownVersion = Literal[1, 2]
SocketOpt = Union[
Tuple[int, int, int],
Tuple[int, int, Union[bytes, bytearray]],
Tuple[int, int, None, int],
tuple[int, int, int],
tuple[int, int, Union[bytes, bytearray]],
tuple[int, int, None, int],
]

View file

@ -26,14 +26,14 @@ Warning:
the changelog.
"""
import warnings
from typing import Type, Union
from typing import Union
from telegram.warnings import PTBUserWarning
def warn(
message: Union[str, PTBUserWarning],
category: Type[Warning] = PTBUserWarning,
category: type[Warning] = PTBUserWarning,
stacklevel: int = 0,
) -> None:
"""
@ -48,7 +48,7 @@ def warn(
.. versionchanged:: 21.2
Now also accepts a :obj:`PTBUserWarning` instance.
category (:obj:`Type[Warning]`, optional): Specify the Warning class to pass to
category (:obj:`type[Warning]`, optional): Specify the Warning class to pass to
``warnings.warn()``. Defaults to :class:`telegram.warnings.PTBUserWarning`.
stacklevel (:obj:`int`, optional): Specify the stacklevel to pass to ``warnings.warn()``.
Pass the same value as you'd pass directly to ``warnings.warn()``. Defaults to ``0``.

View file

@ -23,7 +23,7 @@ inside warnings.py.
.. versionadded:: 20.2
"""
from typing import Any, Callable, Type, Union
from typing import Any, Callable, Union
from telegram._utils.warnings import warn
from telegram.warnings import PTBDeprecationWarning, PTBUserWarning
@ -56,7 +56,7 @@ def warn_about_deprecated_arg_return_new_arg(
bot_api_version: str,
ptb_version: str,
stacklevel: int = 2,
warn_callback: Callable[[Union[str, PTBUserWarning], Type[Warning], int], None] = warn,
warn_callback: Callable[[Union[str, PTBUserWarning], type[Warning], int], None] = warn,
) -> Any:
"""A helper function for the transition in API when argument is renamed.

View file

@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains objects related to Telegram video chats."""
import datetime as dtm
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from collections.abc import Sequence
from typing import TYPE_CHECKING, Optional
from telegram._telegramobject import TelegramObject
from telegram._user import User
@ -102,7 +103,7 @@ class VideoChatParticipantsInvited(TelegramObject):
|sequenceclassargs|
Attributes:
users (Tuple[:class:`telegram.User`]): New members that were invited to the video chat.
users (tuple[:class:`telegram.User`]): New members that were invited to the video chat.
.. versionchanged:: 20.0
|tupleclassattrs|
@ -118,7 +119,7 @@ class VideoChatParticipantsInvited(TelegramObject):
api_kwargs: Optional[JSONDict] = None,
) -> None:
super().__init__(api_kwargs=api_kwargs)
self.users: Tuple[User, ...] = parse_sequence_arg(users)
self.users: tuple[User, ...] = parse_sequence_arg(users)
self._id_attrs = (self.users,)
self._freeze()

View file

@ -17,8 +17,9 @@
# 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 WebhookInfo."""
from collections.abc import Sequence
from datetime import datetime
from typing import TYPE_CHECKING, Optional, Sequence, Tuple
from typing import TYPE_CHECKING, Optional
from telegram._telegramobject import TelegramObject
from telegram._utils.argumentparsing import parse_sequence_arg
@ -89,7 +90,7 @@ class WebhookInfo(TelegramObject):
most recent error that happened when trying to deliver an update via webhook.
max_connections (:obj:`int`): Optional. Maximum allowed number of simultaneous HTTPS
connections to the webhook for update delivery.
allowed_updates (Tuple[:obj:`str`]): Optional. A list of update types the bot is
allowed_updates (tuple[:obj:`str`]): Optional. A list of update types the bot is
subscribed to. Defaults to all update types, except
:attr:`telegram.Update.chat_member`.
@ -144,7 +145,7 @@ class WebhookInfo(TelegramObject):
self.last_error_date: Optional[datetime] = last_error_date
self.last_error_message: Optional[str] = last_error_message
self.max_connections: Optional[int] = max_connections
self.allowed_updates: Tuple[str, ...] = parse_sequence_arg(allowed_updates)
self.allowed_updates: tuple[str, ...] = parse_sequence_arg(allowed_updates)
self.last_synchronization_error_date: Optional[datetime] = last_synchronization_error_date
self._id_attrs = (

View file

@ -108,7 +108,7 @@ __all__ = [
import datetime
import sys
from enum import Enum
from typing import Final, List, NamedTuple, Optional, Tuple
from typing import Final, NamedTuple, Optional
from telegram._utils.datetime import UTC
from telegram._utils.enum import IntEnum, StringEnum
@ -141,8 +141,8 @@ class _AccentColor(NamedTuple):
identifier: int
name: Optional[str] = None
light_colors: Tuple[int, ...] = ()
dark_colors: Tuple[int, ...] = ()
light_colors: tuple[int, ...] = ()
dark_colors: tuple[int, ...] = ()
#: :class:`typing.NamedTuple`: A tuple containing the two components of the version number:
@ -162,9 +162,9 @@ BOT_API_VERSION: Final[str] = str(BOT_API_VERSION_INFO)
# constants above this line are tested
#: List[:obj:`int`]: Ports supported by
#: list[:obj:`int`]: Ports supported by
#: :paramref:`telegram.Bot.set_webhook.url`.
SUPPORTED_WEBHOOK_PORTS: Final[List[int]] = [443, 80, 88, 8443]
SUPPORTED_WEBHOOK_PORTS: Final[list[int]] = [443, 80, 88, 8443]
#: :obj:`datetime.datetime`, value of unix 0.
#: This date literal is used in :class:`telegram.InaccessibleMessage`
@ -180,9 +180,9 @@ class AccentColor(Enum):
- ``identifier`` (:obj:`int`): The identifier of the accent color.
- ``name`` (:obj:`str`): Optional. The name of the accent color.
- ``light_colors`` (Tuple[:obj:`str`]): Optional. The light colors of the accent color as HEX
- ``light_colors`` (tuple[:obj:`str`]): Optional. The light colors of the accent color as HEX
value.
- ``dark_colors`` (Tuple[:obj:`str`]): Optional. The dark colors of the accent color as HEX
- ``dark_colors`` (tuple[:obj:`str`]): Optional. The dark colors of the accent color as HEX
value.
Since Telegram gives no exact specification for the accent colors, future accent colors might
@ -2083,9 +2083,9 @@ class ProfileAccentColor(Enum):
- ``identifier`` (:obj:`int`): The identifier of the accent color.
- ``name`` (:obj:`str`): Optional. The name of the accent color.
- ``light_colors`` (Tuple[:obj:`str`]): Optional. The light colors of the accent color as HEX
- ``light_colors`` (tuple[:obj:`str`]): Optional. The light colors of the accent color as HEX
value.
- ``dark_colors`` (Tuple[:obj:`str`]): Optional. The dark colors of the accent color as HEX
- ``dark_colors`` (tuple[:obj:`str`]): Optional. The dark colors of the accent color as HEX
value.
Since Telegram gives no exact specification for the accent colors, future accent colors might

View file

@ -36,20 +36,7 @@ __all__ = (
"TimedOut",
)
from typing import Optional, Tuple, Union
def _lstrip_str(in_s: str, lstr: str) -> str:
"""
Args:
in_s (:obj:`str`): in string
lstr (:obj:`str`): substr to strip from left side
Returns:
:obj:`str`: The stripped string.
"""
return in_s[len(lstr) :] if in_s.startswith(lstr) else in_s
from typing import Optional, Union
class TelegramError(Exception):
@ -70,9 +57,9 @@ class TelegramError(Exception):
def __init__(self, message: str):
super().__init__()
msg = _lstrip_str(message, "Error: ")
msg = _lstrip_str(msg, "[Error]: ")
msg = _lstrip_str(msg, "Bad Request: ")
msg = message.removeprefix("Error: ")
msg = msg.removeprefix("[Error]: ")
msg = msg.removeprefix("Bad Request: ")
if msg != message:
# api_error - capitalize the msg...
msg = msg.capitalize()
@ -94,7 +81,7 @@ class TelegramError(Exception):
"""
return f"{self.__class__.__name__}('{self.message}')"
def __reduce__(self) -> Tuple[type, Tuple[str]]:
def __reduce__(self) -> tuple[type, tuple[str]]:
"""Defines how to serialize the exception for pickle.
.. seealso::
@ -209,7 +196,7 @@ class ChatMigrated(TelegramError):
super().__init__(f"Group migrated to supergroup. New chat id: {new_chat_id}")
self.new_chat_id: int = new_chat_id
def __reduce__(self) -> Tuple[type, Tuple[int]]: # type: ignore[override]
def __reduce__(self) -> tuple[type, tuple[int]]: # type: ignore[override]
return self.__class__, (self.new_chat_id,)
@ -234,7 +221,7 @@ class RetryAfter(TelegramError):
super().__init__(f"Flood control exceeded. Retry in {retry_after} seconds")
self.retry_after: int = retry_after
def __reduce__(self) -> Tuple[type, Tuple[float]]: # type: ignore[override]
def __reduce__(self) -> tuple[type, tuple[float]]: # type: ignore[override]
return self.__class__, (self.retry_after,)
@ -243,7 +230,7 @@ class Conflict(TelegramError):
__slots__ = ()
def __reduce__(self) -> Tuple[type, Tuple[str]]:
def __reduce__(self) -> tuple[type, tuple[str]]:
return self.__class__, (self.message,)
@ -261,5 +248,5 @@ class PassportDecryptionError(TelegramError):
super().__init__(f"PassportDecryptionError: {message}")
self._msg = str(message)
def __reduce__(self) -> Tuple[type, Tuple[str]]:
def __reduce__(self) -> tuple[type, tuple[str]]:
return self.__class__, (self._msg,)

View file

@ -22,7 +22,8 @@ library.
import asyncio
import contextlib
import sys
from typing import Any, AsyncIterator, Callable, Coroutine, Dict, List, Optional, Union
from collections.abc import AsyncIterator, Coroutine
from typing import Any, Callable, Optional, Union
try:
from aiolimiter import AsyncLimiter
@ -152,7 +153,7 @@ class AIORateLimiter(BaseRateLimiter[int]):
self._group_max_rate = 0
self._group_time_period = 0
self._group_limiters: Dict[Union[str, int], AsyncLimiter] = {}
self._group_limiters: dict[Union[str, int], AsyncLimiter] = {}
self._max_retries: int = max_retries
self._retry_after_event = asyncio.Event()
self._retry_after_event.set()
@ -187,10 +188,10 @@ class AIORateLimiter(BaseRateLimiter[int]):
self,
chat: bool,
group: Union[str, int, bool],
callback: Callable[..., Coroutine[Any, Any, Union[bool, JSONDict, List[JSONDict]]]],
callback: Callable[..., Coroutine[Any, Any, Union[bool, JSONDict, list[JSONDict]]]],
args: Any,
kwargs: Dict[str, Any],
) -> Union[bool, JSONDict, List[JSONDict]]:
kwargs: dict[str, Any],
) -> Union[bool, JSONDict, list[JSONDict]]:
base_context = self._base_limiter if (chat and self._base_limiter) else null_context()
group_context = (
self._get_group_limiter(group) if group and self._group_max_rate else null_context()
@ -205,13 +206,13 @@ class AIORateLimiter(BaseRateLimiter[int]):
# mypy doesn't understand that the last run of the for loop raises an exception
async def process_request(
self,
callback: Callable[..., Coroutine[Any, Any, Union[bool, JSONDict, List[JSONDict]]]],
callback: Callable[..., Coroutine[Any, Any, Union[bool, JSONDict, list[JSONDict]]]],
args: Any,
kwargs: Dict[str, Any],
kwargs: dict[str, Any],
endpoint: str, # noqa: ARG002
data: Dict[str, Any],
data: dict[str, Any],
rate_limit_args: Optional[int],
) -> Union[bool, JSONDict, List[JSONDict]]:
) -> Union[bool, JSONDict, list[JSONDict]]:
"""
Processes a request by applying rate limiting.

View file

@ -26,30 +26,11 @@ import platform
import signal
import sys
from collections import defaultdict
from collections.abc import Awaitable, Coroutine, Generator, Mapping, Sequence
from copy import deepcopy
from pathlib import Path
from types import MappingProxyType, TracebackType
from typing import (
TYPE_CHECKING,
Any,
AsyncContextManager,
Awaitable,
Callable,
Coroutine,
DefaultDict,
Dict,
Generator,
Generic,
List,
Mapping,
NoReturn,
Optional,
Sequence,
Set,
Type,
TypeVar,
Union,
)
from typing import TYPE_CHECKING, Any, Callable, Generic, NoReturn, Optional, TypeVar, Union
from telegram._update import Update
from telegram._utils.defaultvalue import (
@ -132,7 +113,10 @@ class ApplicationHandlerStop(Exception):
self.state: Optional[object] = state
class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Application"]):
class Application(
Generic[BT, CCT, UD, CD, BD, JQ],
contextlib.AbstractAsyncContextManager["Application"],
):
"""This class dispatches all kinds of updates to its registered handlers, and is the entry
point to a PTB application.
@ -224,12 +208,12 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
bot_data (:obj:`dict`): A dictionary handlers can use to store data for the bot.
persistence (:class:`telegram.ext.BasePersistence`): The persistence class to
store data that should be persistent over restarts.
handlers (Dict[:obj:`int`, List[:class:`telegram.ext.BaseHandler`]]): A dictionary mapping
handlers (dict[:obj:`int`, list[:class:`telegram.ext.BaseHandler`]]): A dictionary mapping
each handler group to the list of handlers registered to that group.
.. seealso::
:meth:`add_handler`, :meth:`add_handlers`.
error_handlers (Dict[:term:`coroutine function`, :obj:`bool`]): A dictionary where the keys
error_handlers (dict[:term:`coroutine function`, :obj:`bool`]): A dictionary where the keys
are error handlers and the values indicate whether they are to be run blocking.
.. seealso::
@ -323,8 +307,8 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
self.update_queue: asyncio.Queue[object] = update_queue
self.context_types: ContextTypes[CCT, UD, CD, BD] = context_types
self.updater: Optional[Updater] = updater
self.handlers: Dict[int, List[BaseHandler[Any, CCT, Any]]] = {}
self.error_handlers: Dict[
self.handlers: dict[int, list[BaseHandler[Any, CCT, Any]]] = {}
self.error_handlers: dict[
HandlerCallback[object, CCT, None], Union[bool, DefaultValue[bool]]
] = {}
self.post_init: Optional[
@ -338,8 +322,8 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
] = post_stop
self._update_processor = update_processor
self.bot_data: BD = self.context_types.bot_data()
self._user_data: DefaultDict[int, UD] = defaultdict(self.context_types.user_data)
self._chat_data: DefaultDict[int, CD] = defaultdict(self.context_types.chat_data)
self._user_data: defaultdict[int, UD] = defaultdict(self.context_types.user_data)
self._chat_data: defaultdict[int, CD] = defaultdict(self.context_types.chat_data)
# Read only mapping
self.user_data: Mapping[int, UD] = MappingProxyType(self._user_data)
self.chat_data: Mapping[int, CD] = MappingProxyType(self._chat_data)
@ -350,14 +334,14 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
self.persistence = persistence
# Some bookkeeping for persistence logic
self._chat_ids_to_be_updated_in_persistence: Set[int] = set()
self._user_ids_to_be_updated_in_persistence: Set[int] = set()
self._chat_ids_to_be_deleted_in_persistence: Set[int] = set()
self._user_ids_to_be_deleted_in_persistence: Set[int] = set()
self._chat_ids_to_be_updated_in_persistence: set[int] = set()
self._user_ids_to_be_updated_in_persistence: set[int] = set()
self._chat_ids_to_be_deleted_in_persistence: set[int] = set()
self._user_ids_to_be_deleted_in_persistence: set[int] = set()
# This attribute will hold references to the conversation dicts of all conversation
# handlers so that we can extract the changed states during `update_persistence`
self._conversation_handler_conversations: Dict[
self._conversation_handler_conversations: dict[
str, TrackingDict[ConversationKey, object]
] = {}
@ -369,7 +353,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
self.__update_persistence_task: Optional[asyncio.Task] = None
self.__update_persistence_event = asyncio.Event()
self.__update_persistence_lock = asyncio.Lock()
self.__create_task_tasks: Set[asyncio.Task] = set() # Used for awaiting tasks upon exit
self.__create_task_tasks: set[asyncio.Task] = set() # Used for awaiting tasks upon exit
self.__stop_running_marker = asyncio.Event()
async def __aenter__(self: _AppType) -> _AppType: # noqa: PYI019
@ -391,7 +375,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
async def __aexit__(
self,
exc_type: Optional[Type[BaseException]],
exc_type: Optional[type[BaseException]],
exc_val: Optional[BaseException],
exc_tb: Optional[TracebackType],
) -> None:
@ -762,7 +746,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
allowed_updates: Optional[List[str]] = None,
allowed_updates: Optional[list[str]] = None,
drop_pending_updates: Optional[bool] = None,
close_loop: bool = True,
stop_signals: ODVInput[Sequence[int]] = DEFAULT_NONE,
@ -839,7 +823,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
:meth:`telegram.ext.ApplicationBuilder.get_updates_pool_timeout`.
drop_pending_updates (:obj:`bool`, optional): Whether to clean any pending updates on
Telegram servers before actually starting to poll. Default is :obj:`False`.
allowed_updates (List[:obj:`str`], optional): Passed to
allowed_updates (list[:obj:`str`], optional): Passed to
:meth:`telegram.Bot.get_updates`.
close_loop (:obj:`bool`, optional): If :obj:`True`, the current event loop will be
closed upon shutdown. Defaults to :obj:`True`.
@ -904,7 +888,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
key: Optional[Union[str, Path]] = None,
bootstrap_retries: int = 0,
webhook_url: Optional[str] = None,
allowed_updates: Optional[List[str]] = None,
allowed_updates: Optional[list[str]] = None,
drop_pending_updates: Optional[bool] = None,
ip_address: Optional[str] = None,
max_connections: int = 40,
@ -970,7 +954,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
webhook_url (:obj:`str`, optional): Explicitly specify the webhook url. Useful behind
NAT, reverse proxy, etc. Default is derived from :paramref:`listen`,
:paramref:`port`, :paramref:`url_path`, :paramref:`cert`, and :paramref:`key`.
allowed_updates (List[:obj:`str`], optional): Passed to
allowed_updates (list[:obj:`str`], optional): Passed to
:meth:`telegram.Bot.set_webhook`.
drop_pending_updates (:obj:`bool`, optional): Whether to clean any pending updates on
Telegram servers before actually starting to poll. Default is :obj:`False`.
@ -1421,7 +1405,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
self,
handlers: Union[
Sequence[BaseHandler[Any, CCT, Any]],
Dict[int, Sequence[BaseHandler[Any, CCT, Any]]],
dict[int, Sequence[BaseHandler[Any, CCT, Any]]],
],
group: Union[int, DefaultValue[int]] = _DEFAULT_0,
) -> None:
@ -1432,7 +1416,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
Args:
handlers (Sequence[:class:`telegram.ext.BaseHandler`] | \
Dict[int, Sequence[:class:`telegram.ext.BaseHandler`]]):
dict[int, Sequence[:class:`telegram.ext.BaseHandler`]]):
Specify a sequence of handlers *or* a dictionary where the keys are groups and
values are handlers.
@ -1693,7 +1677,7 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
_LOGGER.debug("Starting next run of updating the persistence.")
coroutines: Set[Coroutine] = set()
coroutines: set[Coroutine] = set()
# Mypy doesn't know that persistence.set_bot (see above) already checks that
# self.bot is an instance of ExtBot if callback_data should be stored ...

View file

@ -18,20 +18,9 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the Builder classes for the telegram.ext module."""
from asyncio import Queue
from collections.abc import Collection, Coroutine
from pathlib import Path
from typing import (
TYPE_CHECKING,
Any,
Callable,
Collection,
Coroutine,
Dict,
Generic,
Optional,
Type,
TypeVar,
Union,
)
from typing import TYPE_CHECKING, Any, Callable, Generic, Optional, TypeVar, Union
import httpx
@ -212,8 +201,8 @@ class ApplicationBuilder(Generic[BT, CCT, UD, CD, BD, JQ]):
self._persistence: ODVInput[BasePersistence] = DEFAULT_NONE
self._context_types: DVType[ContextTypes] = DefaultValue(ContextTypes())
self._application_class: DVType[Type[Application]] = DefaultValue(Application)
self._application_kwargs: Dict[str, object] = {}
self._application_class: DVType[type[Application]] = DefaultValue(Application)
self._application_kwargs: dict[str, object] = {}
self._update_processor: BaseUpdateProcessor = SimpleUpdateProcessor(
max_concurrent_updates=1
)
@ -350,8 +339,8 @@ class ApplicationBuilder(Generic[BT, CCT, UD, CD, BD, JQ]):
def application_class(
self: BuilderType,
application_class: Type[Application[Any, Any, Any, Any, Any, Any]],
kwargs: Optional[Dict[str, object]] = None,
application_class: type[Application[Any, Any, Any, Any, Any, Any]],
kwargs: Optional[dict[str, object]] = None,
) -> BuilderType:
"""Sets a custom subclass instead of :class:`telegram.ext.Application`. The
subclass's ``__init__`` should look like this
@ -365,7 +354,7 @@ class ApplicationBuilder(Generic[BT, CCT, UD, CD, BD, JQ]):
Args:
application_class (:obj:`type`): A subclass of :class:`telegram.ext.Application`
kwargs (Dict[:obj:`str`, :obj:`object`], optional): Keyword arguments for the
kwargs (dict[:obj:`str`, :obj:`object`], optional): Keyword arguments for the
initialization. Defaults to an empty dict.
Returns:
@ -1397,9 +1386,9 @@ InitApplicationBuilder = ( # This is defined all the way down here so that its
ApplicationBuilder[ # by Pylance correctly.
ExtBot[None],
ContextTypes.DEFAULT_TYPE,
Dict[Any, Any],
Dict[Any, Any],
Dict[Any, Any],
dict[Any, Any],
dict[Any, Any],
dict[Any, Any],
JobQueue[ContextTypes.DEFAULT_TYPE],
]
)

View file

@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the BasePersistence class."""
from abc import ABC, abstractmethod
from typing import Dict, Generic, NamedTuple, NoReturn, Optional
from typing import Generic, NamedTuple, NoReturn, Optional
from telegram._bot import Bot
from telegram.ext._extbot import ExtBot
@ -184,7 +184,7 @@ class BasePersistence(Generic[UD, CD, BD], ABC):
self.bot = bot
@abstractmethod
async def get_user_data(self) -> Dict[int, UD]:
async def get_user_data(self) -> dict[int, UD]:
"""Will be called by :class:`telegram.ext.Application` upon creation with a
persistence object. It should return the ``user_data`` if stored, or an empty
:obj:`dict`. In the latter case, the dictionary should produce values
@ -198,12 +198,12 @@ class BasePersistence(Generic[UD, CD, BD], ABC):
This method may now return a :obj:`dict` instead of a :obj:`collections.defaultdict`
Returns:
Dict[:obj:`int`, :obj:`dict` | :attr:`telegram.ext.ContextTypes.user_data`]:
dict[:obj:`int`, :obj:`dict` | :attr:`telegram.ext.ContextTypes.user_data`]:
The restored user data.
"""
@abstractmethod
async def get_chat_data(self) -> Dict[int, CD]:
async def get_chat_data(self) -> dict[int, CD]:
"""Will be called by :class:`telegram.ext.Application` upon creation with a
persistence object. It should return the ``chat_data`` if stored, or an empty
:obj:`dict`. In the latter case, the dictionary should produce values
@ -217,7 +217,7 @@ class BasePersistence(Generic[UD, CD, BD], ABC):
This method may now return a :obj:`dict` instead of a :obj:`collections.defaultdict`
Returns:
Dict[:obj:`int`, :obj:`dict` | :attr:`telegram.ext.ContextTypes.chat_data`]:
dict[:obj:`int`, :obj:`dict` | :attr:`telegram.ext.ContextTypes.chat_data`]:
The restored chat data.
"""
@ -233,7 +233,7 @@ class BasePersistence(Generic[UD, CD, BD], ABC):
if :class:`telegram.ext.ContextTypes` are used.
Returns:
Dict[:obj:`int`, :obj:`dict` | :attr:`telegram.ext.ContextTypes.bot_data`]:
dict[:obj:`int`, :obj:`dict` | :attr:`telegram.ext.ContextTypes.bot_data`]:
The restored bot data.
"""
@ -248,8 +248,8 @@ class BasePersistence(Generic[UD, CD, BD], ABC):
Changed this method into an :external:func:`~abc.abstractmethod`.
Returns:
Tuple[List[Tuple[:obj:`str`, :obj:`float`, Dict[:obj:`str`, :class:`object`]]],
Dict[:obj:`str`, :obj:`str`]] | :obj:`None`: The restored metadata or :obj:`None`,
tuple[list[tuple[:obj:`str`, :obj:`float`, dict[:obj:`str`, :class:`object`]]],
dict[:obj:`str`, :obj:`str`]] | :obj:`None`: The restored metadata or :obj:`None`,
if no data was stored.
"""
@ -324,8 +324,8 @@ class BasePersistence(Generic[UD, CD, BD], ABC):
Changed this method into an :external:func:`~abc.abstractmethod`.
Args:
data (Tuple[List[Tuple[:obj:`str`, :obj:`float`, \
Dict[:obj:`str`, :obj:`Any`]]], Dict[:obj:`str`, :obj:`str`]] | :obj:`None`):
data (tuple[list[tuple[:obj:`str`, :obj:`float`, \
dict[:obj:`str`, :obj:`Any`]]], dict[:obj:`str`, :obj:`str`]] | :obj:`None`):
The relevant data to restore :class:`telegram.ext.CallbackDataCache`.
"""

View file

@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains a class that allows to rate limit requests to the Bot API."""
from abc import ABC, abstractmethod
from typing import Any, Callable, Coroutine, Dict, Generic, List, Optional, Union
from collections.abc import Coroutine
from typing import Any, Callable, Generic, Optional, Union
from telegram._utils.types import JSONDict
from telegram.ext._utils.types import RLARGS
@ -56,13 +57,13 @@ class BaseRateLimiter(ABC, Generic[RLARGS]):
@abstractmethod
async def process_request(
self,
callback: Callable[..., Coroutine[Any, Any, Union[bool, JSONDict, List[JSONDict]]]],
callback: Callable[..., Coroutine[Any, Any, Union[bool, JSONDict, list[JSONDict]]]],
args: Any,
kwargs: Dict[str, Any],
kwargs: dict[str, Any],
endpoint: str,
data: Dict[str, Any],
data: dict[str, Any],
rate_limit_args: Optional[RLARGS],
) -> Union[bool, JSONDict, List[JSONDict]]:
) -> Union[bool, JSONDict, list[JSONDict]]:
"""
Process a request. Must be implemented by a subclass.
@ -107,13 +108,13 @@ class BaseRateLimiter(ABC, Generic[RLARGS]):
Args:
callback (Callable[..., :term:`coroutine`]): The coroutine function that must be called
to make the request.
args (Tuple[:obj:`object`]): The positional arguments for the :paramref:`callback`
args (tuple[:obj:`object`]): The positional arguments for the :paramref:`callback`
function.
kwargs (Dict[:obj:`str`, :obj:`object`]): The keyword arguments for the
kwargs (dict[:obj:`str`, :obj:`object`]): The keyword arguments for the
:paramref:`callback` function.
endpoint (:obj:`str`): The endpoint that the request is made for, e.g.
``"sendMessage"``.
data (Dict[:obj:`str`, :obj:`object`]): The parameters that were passed to the method
data (dict[:obj:`str`, :obj:`object`]): The parameters that were passed to the method
of :class:`~telegram.ext.ExtBot`. Any ``api_kwargs`` are included in this and
any :paramref:`~telegram.ext.ExtBot.defaults` are already applied.
@ -136,6 +137,6 @@ class BaseRateLimiter(ABC, Generic[RLARGS]):
the request.
Returns:
:obj:`bool` | Dict[:obj:`str`, :obj:`object`] | :obj:`None`: The result of the
:obj:`bool` | dict[:obj:`str`, :obj:`object`] | :obj:`None`: The result of the
callback function.
"""

View file

@ -19,13 +19,17 @@
"""This module contains the BaseProcessor class."""
from abc import ABC, abstractmethod
from asyncio import BoundedSemaphore
from contextlib import AbstractAsyncContextManager
from types import TracebackType
from typing import Any, AsyncContextManager, Awaitable, Optional, Type, TypeVar, final
from typing import TYPE_CHECKING, Any, Optional, TypeVar, final
if TYPE_CHECKING:
from collections.abc import Awaitable
_BUPT = TypeVar("_BUPT", bound="BaseUpdateProcessor")
class BaseUpdateProcessor(AsyncContextManager["BaseUpdateProcessor"], ABC):
class BaseUpdateProcessor(AbstractAsyncContextManager["BaseUpdateProcessor"], ABC):
"""An abstract base class for update processors. You can use this class to implement
your own update processor.
@ -88,7 +92,7 @@ class BaseUpdateProcessor(AsyncContextManager["BaseUpdateProcessor"], ABC):
async def __aexit__(
self,
exc_type: Optional[Type[BaseException]],
exc_type: Optional[type[BaseException]],
exc_val: Optional[BaseException],
exc_tb: Optional[TracebackType],
) -> None:

View file

@ -17,21 +17,10 @@
# 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 the CallbackContext class."""
from typing import (
TYPE_CHECKING,
Any,
Awaitable,
Dict,
Generator,
Generic,
List,
Match,
NoReturn,
Optional,
Type,
TypeVar,
Union,
)
from collections.abc import Awaitable, Generator
from re import Match
from typing import TYPE_CHECKING, Any, Generic, NoReturn, Optional, TypeVar, Union
from telegram._callbackquery import CallbackQuery
from telegram._update import Update
@ -105,11 +94,11 @@ class CallbackContext(Generic[BT, UD, CD, BD]):
coroutine (:term:`awaitable`): Optional. Only present in error handlers if the
error was caused by an awaitable run with :meth:`Application.create_task` or a handler
callback with :attr:`block=False <BaseHandler.block>`.
matches (List[:meth:`re.Match <re.Match.expand>`]): Optional. If the associated update
matches (list[:meth:`re.Match <re.Match.expand>`]): Optional. If the associated update
originated from a :class:`filters.Regex`, this will contain a list of match objects for
every pattern where ``re.search(pattern, string)`` returned a match. Note that filters
short circuit, so combined regex filters will not always be evaluated.
args (List[:obj:`str`]): Optional. Arguments passed to a command if the associated update
args (list[:obj:`str`]): Optional. Arguments passed to a command if the associated update
is handled by :class:`telegram.ext.CommandHandler`, :class:`telegram.ext.PrefixHandler`
or :class:`telegram.ext.StringCommandHandler`. It contains a list of the words in the
text after the command, using any whitespace string as a delimiter.
@ -145,8 +134,8 @@ class CallbackContext(Generic[BT, UD, CD, BD]):
self._application: Application[BT, ST, UD, CD, BD, Any] = application
self._chat_id: Optional[int] = chat_id
self._user_id: Optional[int] = user_id
self.args: Optional[List[str]] = None
self.matches: Optional[List[Match[str]]] = None
self.args: Optional[list[str]] = None
self.matches: Optional[list[Match[str]]] = None
self.error: Optional[Exception] = None
self.job: Optional[Job[Any]] = None
self.coroutine: Optional[
@ -282,7 +271,7 @@ class CallbackContext(Generic[BT, UD, CD, BD]):
@classmethod
def from_error(
cls: Type["CCT"],
cls: type["CCT"],
update: object,
error: Exception,
application: "Application[BT, CCT, UD, CD, BD, Any]",
@ -335,7 +324,7 @@ class CallbackContext(Generic[BT, UD, CD, BD]):
@classmethod
def from_update(
cls: Type["CCT"],
cls: type["CCT"],
update: object,
application: "Application[Any, CCT, Any, Any, Any, Any]",
) -> "CCT":
@ -365,7 +354,7 @@ class CallbackContext(Generic[BT, UD, CD, BD]):
@classmethod
def from_job(
cls: Type["CCT"],
cls: type["CCT"],
job: "Job[CCT]",
application: "Application[Any, CCT, Any, Any, Any, Any]",
) -> "CCT":
@ -387,11 +376,11 @@ class CallbackContext(Generic[BT, UD, CD, BD]):
self.job = job
return self
def update(self, data: Dict[str, object]) -> None:
def update(self, data: dict[str, object]) -> None:
"""Updates ``self.__slots__`` with the passed data.
Args:
data (Dict[:obj:`str`, :obj:`object`]): The data.
data (dict[:obj:`str`, :obj:`object`]): The data.
"""
for key, value in data.items():
setattr(self, key, value)

View file

@ -18,8 +18,9 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the CallbackDataCache class."""
import time
from collections.abc import MutableMapping
from datetime import datetime
from typing import TYPE_CHECKING, Any, Dict, MutableMapping, Optional, Tuple, Union, cast
from typing import TYPE_CHECKING, Any, Optional, Union, cast
from uuid import uuid4
try:
@ -70,7 +71,7 @@ class InvalidCallbackData(TelegramError):
)
self.callback_data: Optional[str] = callback_data
def __reduce__(self) -> Tuple[type, Tuple[Optional[str]]]: # type: ignore[override]
def __reduce__(self) -> tuple[type, tuple[Optional[str]]]: # type: ignore[override]
"""Defines how to serialize the exception for pickle. See
:py:meth:`object.__reduce__` for more info.
@ -87,7 +88,7 @@ class _KeyboardData:
self,
keyboard_uuid: str,
access_time: Optional[float] = None,
button_data: Optional[Dict[str, object]] = None,
button_data: Optional[dict[str, object]] = None,
):
self.keyboard_uuid = keyboard_uuid
self.button_data = button_data or {}
@ -97,7 +98,7 @@ class _KeyboardData:
"""Updates the access time with the current time."""
self.access_time = time.time()
def to_tuple(self) -> Tuple[str, float, Dict[str, object]]:
def to_tuple(self) -> tuple[str, float, dict[str, object]]:
"""Gives a tuple representation consisting of the keyboard uuid, the access time and the
button data.
"""
@ -140,8 +141,8 @@ class CallbackDataCache:
maxsize (:obj:`int`, optional): Maximum number of items in each of the internal mappings.
Defaults to ``1024``.
persistent_data (Tuple[List[Tuple[:obj:`str`, :obj:`float`, \
Dict[:obj:`str`, :class:`object`]]], Dict[:obj:`str`, :obj:`str`]], optional): \
persistent_data (tuple[list[tuple[:obj:`str`, :obj:`float`, \
dict[:obj:`str`, :class:`object`]]], dict[:obj:`str`, :obj:`str`]], optional): \
Data to initialize the cache with, as returned by \
:meth:`telegram.ext.BasePersistence.get_callback_data`.
@ -181,8 +182,8 @@ class CallbackDataCache:
.. versionadded:: 20.0
Args:
persistent_data (Tuple[List[Tuple[:obj:`str`, :obj:`float`, \
Dict[:obj:`str`, :class:`object`]]], Dict[:obj:`str`, :obj:`str`]], optional): \
persistent_data (tuple[list[tuple[:obj:`str`, :obj:`float`, \
dict[:obj:`str`, :class:`object`]]], dict[:obj:`str`, :obj:`str`]], optional): \
Data to load, as returned by \
:meth:`telegram.ext.BasePersistence.get_callback_data`.
"""
@ -205,8 +206,8 @@ class CallbackDataCache:
@property
def persistence_data(self) -> CDCData:
"""Tuple[List[Tuple[:obj:`str`, :obj:`float`, Dict[:obj:`str`, :class:`object`]]],
Dict[:obj:`str`, :obj:`str`]]: The data that needs to be persisted to allow
"""tuple[list[tuple[:obj:`str`, :obj:`float`, dict[:obj:`str`, :class:`object`]]],
dict[:obj:`str`, :obj:`str`]]: The data that needs to be persisted to allow
caching callback data across bot reboots.
"""
# While building a list/dict from the LRUCaches has linear runtime (in the number of
@ -269,7 +270,7 @@ class CallbackDataCache:
def __get_keyboard_uuid_and_button_data(
self, callback_data: str
) -> Union[Tuple[str, object], Tuple[None, InvalidCallbackData]]:
) -> Union[tuple[str, object], tuple[None, InvalidCallbackData]]:
keyboard, button = self.extract_uuids(callback_data)
try:
# we get the values before calling update() in case KeyErrors are raised
@ -283,7 +284,7 @@ class CallbackDataCache:
return keyboard, button_data
@staticmethod
def extract_uuids(callback_data: str) -> Tuple[str, str]:
def extract_uuids(callback_data: str) -> tuple[str, str]:
"""Extracts the keyboard uuid and the button uuid from the given :paramref:`callback_data`.
Args:

View file

@ -17,13 +17,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/].
"""This module contains the auxiliary class ContextTypes."""
from typing import Any, Dict, Generic, Type, overload
from typing import Any, Generic, overload
from telegram.ext._callbackcontext import CallbackContext
from telegram.ext._extbot import ExtBot
from telegram.ext._utils.types import BD, CCT, CD, UD
ADict = Dict[Any, Any]
ADict = dict[Any, Any]
class ContextTypes(Generic[CCT, UD, CD, BD]):
@ -83,109 +83,109 @@ class ContextTypes(Generic[CCT, UD, CD, BD]):
): ...
@overload
def __init__(self: "ContextTypes[CCT, ADict, ADict, ADict]", context: Type[CCT]): ...
def __init__(self: "ContextTypes[CCT, ADict, ADict, ADict]", context: type[CCT]): ...
@overload
def __init__(
self: "ContextTypes[CallbackContext[ExtBot[Any], UD, ADict, ADict], UD, ADict, ADict]",
user_data: Type[UD],
user_data: type[UD],
): ...
@overload
def __init__(
self: "ContextTypes[CallbackContext[ExtBot[Any], ADict, CD, ADict], ADict, CD, ADict]",
chat_data: Type[CD],
chat_data: type[CD],
): ...
@overload
def __init__(
self: "ContextTypes[CallbackContext[ExtBot[Any], ADict, ADict, BD], ADict, ADict, BD]",
bot_data: Type[BD],
bot_data: type[BD],
): ...
@overload
def __init__(
self: "ContextTypes[CCT, UD, ADict, ADict]", context: Type[CCT], user_data: Type[UD]
self: "ContextTypes[CCT, UD, ADict, ADict]", context: type[CCT], user_data: type[UD]
): ...
@overload
def __init__(
self: "ContextTypes[CCT, ADict, CD, ADict]", context: Type[CCT], chat_data: Type[CD]
self: "ContextTypes[CCT, ADict, CD, ADict]", context: type[CCT], chat_data: type[CD]
): ...
@overload
def __init__(
self: "ContextTypes[CCT, ADict, ADict, BD]", context: Type[CCT], bot_data: Type[BD]
self: "ContextTypes[CCT, ADict, ADict, BD]", context: type[CCT], bot_data: type[BD]
): ...
@overload
def __init__(
self: "ContextTypes[CallbackContext[ExtBot[Any], UD, CD, ADict], UD, CD, ADict]",
user_data: Type[UD],
chat_data: Type[CD],
user_data: type[UD],
chat_data: type[CD],
): ...
@overload
def __init__(
self: "ContextTypes[CallbackContext[ExtBot[Any], UD, ADict, BD], UD, ADict, BD]",
user_data: Type[UD],
bot_data: Type[BD],
user_data: type[UD],
bot_data: type[BD],
): ...
@overload
def __init__(
self: "ContextTypes[CallbackContext[ExtBot[Any], ADict, CD, BD], ADict, CD, BD]",
chat_data: Type[CD],
bot_data: Type[BD],
chat_data: type[CD],
bot_data: type[BD],
): ...
@overload
def __init__(
self: "ContextTypes[CCT, UD, CD, ADict]",
context: Type[CCT],
user_data: Type[UD],
chat_data: Type[CD],
context: type[CCT],
user_data: type[UD],
chat_data: type[CD],
): ...
@overload
def __init__(
self: "ContextTypes[CCT, UD, ADict, BD]",
context: Type[CCT],
user_data: Type[UD],
bot_data: Type[BD],
context: type[CCT],
user_data: type[UD],
bot_data: type[BD],
): ...
@overload
def __init__(
self: "ContextTypes[CCT, ADict, CD, BD]",
context: Type[CCT],
chat_data: Type[CD],
bot_data: Type[BD],
context: type[CCT],
chat_data: type[CD],
bot_data: type[BD],
): ...
@overload
def __init__(
self: "ContextTypes[CallbackContext[ExtBot[Any], UD, CD, BD], UD, CD, BD]",
user_data: Type[UD],
chat_data: Type[CD],
bot_data: Type[BD],
user_data: type[UD],
chat_data: type[CD],
bot_data: type[BD],
): ...
@overload
def __init__(
self: "ContextTypes[CCT, UD, CD, BD]",
context: Type[CCT],
user_data: Type[UD],
chat_data: Type[CD],
bot_data: Type[BD],
context: type[CCT],
user_data: type[UD],
chat_data: type[CD],
bot_data: type[BD],
): ...
def __init__( # type: ignore[misc]
self,
context: "Type[CallbackContext[ExtBot[Any], ADict, ADict, ADict]]" = CallbackContext,
bot_data: Type[ADict] = dict,
chat_data: Type[ADict] = dict,
user_data: Type[ADict] = dict,
context: "type[CallbackContext[ExtBot[Any], ADict, ADict, ADict]]" = CallbackContext,
bot_data: type[ADict] = dict,
chat_data: type[ADict] = dict,
user_data: type[ADict] = dict,
):
if not issubclass(context, CallbackContext):
raise TypeError("context must be a subclass of CallbackContext.")
@ -198,28 +198,28 @@ class ContextTypes(Generic[CCT, UD, CD, BD]):
self._user_data = user_data
@property
def context(self) -> Type[CCT]:
def context(self) -> type[CCT]:
"""The type of the ``context`` argument of all (error-)handler callbacks and job
callbacks.
"""
return self._context # type: ignore[return-value]
@property
def bot_data(self) -> Type[BD]:
def bot_data(self) -> type[BD]:
"""The type of :attr:`context.bot_data <CallbackContext.bot_data>` of all (error-)handler
callbacks and job callbacks.
"""
return self._bot_data # type: ignore[return-value]
@property
def chat_data(self) -> Type[CD]:
def chat_data(self) -> type[CD]:
"""The type of :attr:`context.chat_data <CallbackContext.chat_data>` of all (error-)handler
callbacks and job callbacks.
"""
return self._chat_data # type: ignore[return-value]
@property
def user_data(self) -> Type[UD]:
def user_data(self) -> type[UD]:
"""The type of :attr:`context.user_data <CallbackContext.user_data>` of all (error-)handler
callbacks and job callbacks.
"""

View file

@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the class Defaults, which allows passing default values to Application."""
import datetime
from typing import Any, Dict, NoReturn, Optional, final
from typing import Any, NoReturn, Optional, final
from telegram import LinkPreviewOptions
from telegram._utils.datetime import UTC
@ -228,7 +228,7 @@ class Defaults:
return False
@property
def api_defaults(self) -> Dict[str, Any]: # skip-cq: PY-D0003
def api_defaults(self) -> dict[str, Any]: # skip-cq: PY-D0003
return self._api_defaults
@property

View file

@ -19,7 +19,7 @@
"""This module contains the DictPersistence class."""
import json
from copy import deepcopy
from typing import TYPE_CHECKING, Any, Dict, Optional, cast
from typing import TYPE_CHECKING, Any, Optional, cast
from telegram.ext import BasePersistence, PersistenceInput
from telegram.ext._utils.types import CDCData, ConversationDict, ConversationKey
@ -28,7 +28,7 @@ if TYPE_CHECKING:
from telegram._utils.types import JSONDict
class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any, Any]]):
class DictPersistence(BasePersistence[dict[Any, Any], dict[Any, Any], dict[Any, Any]]):
"""Using Python's :obj:`dict` and :mod:`json` for making your bot persistent.
Attention:
@ -170,7 +170,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
) from exc
@property
def user_data(self) -> Optional[Dict[int, Dict[Any, Any]]]:
def user_data(self) -> Optional[dict[int, dict[Any, Any]]]:
""":obj:`dict`: The user_data as a dict."""
return self._user_data
@ -182,7 +182,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
return json.dumps(self.user_data)
@property
def chat_data(self) -> Optional[Dict[int, Dict[Any, Any]]]:
def chat_data(self) -> Optional[dict[int, dict[Any, Any]]]:
""":obj:`dict`: The chat_data as a dict."""
return self._chat_data
@ -194,7 +194,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
return json.dumps(self.chat_data)
@property
def bot_data(self) -> Optional[Dict[Any, Any]]:
def bot_data(self) -> Optional[dict[Any, Any]]:
""":obj:`dict`: The bot_data as a dict."""
return self._bot_data
@ -207,8 +207,8 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
@property
def callback_data(self) -> Optional[CDCData]:
"""Tuple[List[Tuple[:obj:`str`, :obj:`float`, Dict[:obj:`str`, :class:`object`]]], \
Dict[:obj:`str`, :obj:`str`]]: The metadata on the stored callback data.
"""tuple[list[tuple[:obj:`str`, :obj:`float`, dict[:obj:`str`, :class:`object`]]], \
dict[:obj:`str`, :obj:`str`]]: The metadata on the stored callback data.
.. versionadded:: 13.6
"""
@ -225,7 +225,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
return json.dumps(self.callback_data)
@property
def conversations(self) -> Optional[Dict[str, ConversationDict]]:
def conversations(self) -> Optional[dict[str, ConversationDict]]:
""":obj:`dict`: The conversations as a dict."""
return self._conversations
@ -238,7 +238,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
return self._encode_conversations_to_json(self.conversations)
return json.dumps(self.conversations)
async def get_user_data(self) -> Dict[int, Dict[object, object]]:
async def get_user_data(self) -> dict[int, dict[object, object]]:
"""Returns the user_data created from the ``user_data_json`` or an empty :obj:`dict`.
Returns:
@ -248,7 +248,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
self._user_data = {}
return deepcopy(self.user_data) # type: ignore[arg-type]
async def get_chat_data(self) -> Dict[int, Dict[object, object]]:
async def get_chat_data(self) -> dict[int, dict[object, object]]:
"""Returns the chat_data created from the ``chat_data_json`` or an empty :obj:`dict`.
Returns:
@ -258,7 +258,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
self._chat_data = {}
return deepcopy(self.chat_data) # type: ignore[arg-type]
async def get_bot_data(self) -> Dict[object, object]:
async def get_bot_data(self) -> dict[object, object]:
"""Returns the bot_data created from the ``bot_data_json`` or an empty :obj:`dict`.
Returns:
@ -274,8 +274,8 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
.. versionadded:: 13.6
Returns:
Tuple[List[Tuple[:obj:`str`, :obj:`float`, Dict[:obj:`str`, :class:`object`]]], \
Dict[:obj:`str`, :obj:`str`]]: The restored metadata or :obj:`None`, \
tuple[list[tuple[:obj:`str`, :obj:`float`, dict[:obj:`str`, :class:`object`]]], \
dict[:obj:`str`, :obj:`str`]]: The restored metadata or :obj:`None`, \
if no data was stored.
"""
if self.callback_data is None:
@ -311,7 +311,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
self._conversations[name][key] = new_state
self._conversations_json = None
async def update_user_data(self, user_id: int, data: Dict[Any, Any]) -> None:
async def update_user_data(self, user_id: int, data: dict[Any, Any]) -> None:
"""Will update the user_data (if changed).
Args:
@ -325,7 +325,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
self._user_data[user_id] = data
self._user_data_json = None
async def update_chat_data(self, chat_id: int, data: Dict[Any, Any]) -> None:
async def update_chat_data(self, chat_id: int, data: dict[Any, Any]) -> None:
"""Will update the chat_data (if changed).
Args:
@ -339,7 +339,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
self._chat_data[chat_id] = data
self._chat_data_json = None
async def update_bot_data(self, data: Dict[Any, Any]) -> None:
async def update_bot_data(self, data: dict[Any, Any]) -> None:
"""Will update the bot_data (if changed).
Args:
@ -356,8 +356,8 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
.. versionadded:: 13.6
Args:
data (Tuple[List[Tuple[:obj:`str`, :obj:`float`, Dict[:obj:`str`, :class:`object`]]], \
Dict[:obj:`str`, :obj:`str`]]): The relevant data to restore
data (tuple[list[tuple[:obj:`str`, :obj:`float`, dict[:obj:`str`, :class:`object`]]], \
dict[:obj:`str`, :obj:`str`]]): The relevant data to restore
:class:`telegram.ext.CallbackDataCache`.
"""
if self._callback_data == data:
@ -391,21 +391,21 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
self._user_data.pop(user_id, None)
self._user_data_json = None
async def refresh_user_data(self, user_id: int, user_data: Dict[Any, Any]) -> None:
async def refresh_user_data(self, user_id: int, user_data: dict[Any, Any]) -> None:
"""Does nothing.
.. versionadded:: 13.6
.. seealso:: :meth:`telegram.ext.BasePersistence.refresh_user_data`
"""
async def refresh_chat_data(self, chat_id: int, chat_data: Dict[Any, Any]) -> None:
async def refresh_chat_data(self, chat_id: int, chat_data: dict[Any, Any]) -> None:
"""Does nothing.
.. versionadded:: 13.6
.. seealso:: :meth:`telegram.ext.BasePersistence.refresh_chat_data`
"""
async def refresh_bot_data(self, bot_data: Dict[Any, Any]) -> None:
async def refresh_bot_data(self, bot_data: dict[Any, Any]) -> None:
"""Does nothing.
.. versionadded:: 13.6
@ -420,7 +420,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
"""
@staticmethod
def _encode_conversations_to_json(conversations: Dict[str, ConversationDict]) -> str:
def _encode_conversations_to_json(conversations: dict[str, ConversationDict]) -> str:
"""Helper method to encode a conversations dict (that uses tuples as keys) to a
JSON-serializable way. Use :meth:`self._decode_conversations_from_json` to decode.
@ -430,7 +430,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
Returns:
:obj:`str`: The JSON-serialized conversations dict
"""
tmp: Dict[str, JSONDict] = {}
tmp: dict[str, JSONDict] = {}
for handler, states in conversations.items():
tmp[handler] = {}
for key, state in states.items():
@ -438,7 +438,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
return json.dumps(tmp)
@staticmethod
def _decode_conversations_from_json(json_string: str) -> Dict[str, ConversationDict]:
def _decode_conversations_from_json(json_string: str) -> dict[str, ConversationDict]:
"""Helper method to decode a conversations dict (that uses tuples as keys) from a
JSON-string created with :meth:`self._encode_conversations_to_json`.
@ -449,7 +449,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
:obj:`dict`: The conversations dict after decoding
"""
tmp = json.loads(json_string)
conversations: Dict[str, ConversationDict] = {}
conversations: dict[str, ConversationDict] = {}
for handler, states in tmp.items():
conversations[handler] = {}
for key, state in states.items():
@ -457,7 +457,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
return conversations
@staticmethod
def _decode_user_chat_data_from_json(data: str) -> Dict[int, Dict[object, object]]:
def _decode_user_chat_data_from_json(data: str) -> dict[int, dict[object, object]]:
"""Helper method to decode chat or user data (that uses ints as keys) from a
JSON-string.
@ -467,7 +467,7 @@ class DictPersistence(BasePersistence[Dict[Any, Any], Dict[Any, Any], Dict[Any,
Returns:
:obj:`dict`: The user/chat_data defaultdict after decoding
"""
tmp: Dict[int, Dict[object, object]] = {}
tmp: dict[int, dict[object, object]] = {}
decoded_data = json.loads(data)
for user, user_data in decoded_data.items():
int_user_id = int(user)

View file

@ -18,19 +18,15 @@
# 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 Bot with convenience extensions."""
from collections.abc import Sequence
from copy import copy
from datetime import datetime
from typing import (
TYPE_CHECKING,
Any,
Callable,
Dict,
Generic,
List,
Optional,
Sequence,
Tuple,
Type,
TypeVar,
Union,
cast,
@ -267,7 +263,7 @@ class ExtBot(Bot, Generic[RLARGS]):
def _warn(
cls,
message: Union[str, PTBUserWarning],
category: Type[Warning] = PTBUserWarning,
category: type[Warning] = PTBUserWarning,
stacklevel: int = 0,
) -> None:
"""We override this method to add one more level to the stacklevel, so that the warning
@ -340,7 +336,7 @@ class ExtBot(Bot, Generic[RLARGS]):
write_timeout: ODVInput[float] = DEFAULT_NONE,
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
) -> Union[bool, JSONDict, List[JSONDict]]:
) -> Union[bool, JSONDict, list[JSONDict]]:
"""Order of method calls is: Bot.some_method -> Bot._post -> Bot._do_post.
So we can override Bot._do_post to add rate limiting.
"""
@ -421,7 +417,7 @@ class ExtBot(Bot, Generic[RLARGS]):
}
)
def _insert_defaults(self, data: Dict[str, object]) -> None:
def _insert_defaults(self, data: dict[str, object]) -> None:
"""Inserts the defaults values for optional kwargs for which tg.ext.Defaults provides
convenience functionality, i.e. the kwargs with a tg.utils.helpers.DefaultValue default
@ -645,7 +641,7 @@ class ExtBot(Bot, Generic[RLARGS]):
connect_timeout: ODVInput[float] = DEFAULT_NONE,
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
) -> Tuple[Update, ...]:
) -> tuple[Update, ...]:
updates = await super().get_updates(
offset=offset,
limit=limit,
@ -670,7 +666,7 @@ class ExtBot(Bot, Generic[RLARGS]):
],
next_offset: Optional[str] = None,
current_offset: Optional[str] = None,
) -> Tuple[Sequence["InlineQueryResult"], Optional[str]]:
) -> tuple[Sequence["InlineQueryResult"], Optional[str]]:
"""This method is called by Bot.answer_inline_query to build the actual results list.
Overriding this to call self._replace_keyboard suffices
"""
@ -746,7 +742,7 @@ class ExtBot(Bot, Generic[RLARGS]):
self,
endpoint: str,
api_kwargs: Optional[JSONDict] = None,
return_type: Optional[Type[TelegramObject]] = None,
return_type: Optional[type[TelegramObject]] = None,
*,
read_timeout: ODVInput[float] = DEFAULT_NONE,
write_timeout: ODVInput[float] = DEFAULT_NONE,
@ -854,7 +850,7 @@ class ExtBot(Bot, Generic[RLARGS]):
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
rate_limit_args: Optional[RLARGS] = None,
) -> Tuple["MessageId", ...]:
) -> tuple["MessageId", ...]:
# We override this method to call self._replace_keyboard
return await super().copy_messages(
chat_id=chat_id,
@ -1744,7 +1740,7 @@ class ExtBot(Bot, Generic[RLARGS]):
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
rate_limit_args: Optional[RLARGS] = None,
) -> Tuple[MessageId, ...]:
) -> tuple[MessageId, ...]:
return await super().forward_messages(
chat_id=chat_id,
from_chat_id=from_chat_id,
@ -1769,7 +1765,7 @@ class ExtBot(Bot, Generic[RLARGS]):
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
rate_limit_args: Optional[RLARGS] = None,
) -> Tuple[ChatMember, ...]:
) -> tuple[ChatMember, ...]:
return await super().get_chat_administrators(
chat_id=chat_id,
read_timeout=read_timeout,
@ -1872,7 +1868,7 @@ class ExtBot(Bot, Generic[RLARGS]):
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
rate_limit_args: Optional[RLARGS] = None,
) -> Tuple[Sticker, ...]:
) -> tuple[Sticker, ...]:
return await super().get_forum_topic_icon_stickers(
read_timeout=read_timeout,
write_timeout=write_timeout,
@ -1894,7 +1890,7 @@ class ExtBot(Bot, Generic[RLARGS]):
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
rate_limit_args: Optional[RLARGS] = None,
) -> Tuple[GameHighScore, ...]:
) -> tuple[GameHighScore, ...]:
return await super().get_game_high_scores(
user_id=user_id,
chat_id=chat_id,
@ -1936,7 +1932,7 @@ class ExtBot(Bot, Generic[RLARGS]):
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
rate_limit_args: Optional[RLARGS] = None,
) -> Tuple[BotCommand, ...]:
) -> tuple[BotCommand, ...]:
return await super().get_my_commands(
scope=scope,
language_code=language_code,
@ -1997,7 +1993,7 @@ class ExtBot(Bot, Generic[RLARGS]):
pool_timeout: ODVInput[float] = DEFAULT_NONE,
api_kwargs: Optional[JSONDict] = None,
rate_limit_args: Optional[RLARGS] = None,
) -> Tuple[Sticker, ...]:
) -> tuple[Sticker, ...]:
return await super().get_custom_emoji_stickers(
custom_emoji_ids=custom_emoji_ids,
read_timeout=read_timeout,
@ -2859,7 +2855,7 @@ class ExtBot(Bot, Generic[RLARGS]):
caption: Optional[str] = None,
parse_mode: ODVInput[str] = DEFAULT_NONE,
caption_entities: Optional[Sequence["MessageEntity"]] = None,
) -> Tuple[Message, ...]:
) -> tuple[Message, ...]:
return await super().send_media_group(
chat_id=chat_id,
media=media,
@ -3497,7 +3493,7 @@ class ExtBot(Bot, Generic[RLARGS]):
async def set_my_commands(
self,
commands: Sequence[Union[BotCommand, Tuple[str, str]]],
commands: Sequence[Union[BotCommand, tuple[str, str]]],
scope: Optional[BotCommandScope] = None,
language_code: Optional[str] = None,
*,

View file

@ -19,7 +19,8 @@
"""This module contains the CallbackQueryHandler class."""
import asyncio
import re
from typing import TYPE_CHECKING, Any, Callable, Match, Optional, Pattern, TypeVar, Union, cast
from re import Match, Pattern
from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union, cast
from telegram import Update
from telegram._utils.defaultvalue import DEFAULT_TRUE

View file

@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the ChosenInlineResultHandler class."""
import re
from typing import TYPE_CHECKING, Any, Match, Optional, Pattern, TypeVar, Union, cast
from re import Match, Pattern
from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union, cast
from telegram import Update
from telegram._utils.defaultvalue import DEFAULT_TRUE

View file

@ -18,7 +18,7 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the CommandHandler class."""
import re
from typing import TYPE_CHECKING, Any, FrozenSet, List, Optional, Tuple, TypeVar, Union
from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union
from telegram import MessageEntity, Update
from telegram._utils.defaultvalue import DEFAULT_TRUE
@ -101,7 +101,7 @@ class CommandHandler(BaseHandler[Update, CCT, RT]):
:exc:`ValueError`: When the command is too long or has illegal chars.
Attributes:
commands (FrozenSet[:obj:`str`]): The set of commands this handler should listen for.
commands (frozenset[:obj:`str`]): The set of commands this handler should listen for.
callback (:term:`coroutine function`): The callback function for this handler.
filters (:class:`telegram.ext.filters.BaseFilter`): Optional. Only allow updates with these
filters.
@ -134,7 +134,7 @@ class CommandHandler(BaseHandler[Update, CCT, RT]):
for comm in commands:
if not re.match(r"^[\da-z_]{1,32}$", comm):
raise ValueError(f"Command `{comm}` is not a valid bot command")
self.commands: FrozenSet[str] = commands
self.commands: frozenset[str] = commands
self.filters: filters_module.BaseFilter = (
filters if filters is not None else filters_module.UpdateType.MESSAGES
@ -145,7 +145,7 @@ class CommandHandler(BaseHandler[Update, CCT, RT]):
if (isinstance(self.has_args, int)) and (self.has_args < 0):
raise ValueError("CommandHandler argument has_args cannot be a negative integer")
def _check_correct_args(self, args: List[str]) -> Optional[bool]:
def _check_correct_args(self, args: list[str]) -> Optional[bool]:
"""Determines whether the args are correct for this handler. Implemented in check_update().
Args:
args (:obj:`list`): The args for the handler.
@ -161,7 +161,7 @@ class CommandHandler(BaseHandler[Update, CCT, RT]):
def check_update(
self, update: object
) -> Optional[Union[bool, Tuple[List[str], Optional[Union[bool, FilterDataDict]]]]]:
) -> Optional[Union[bool, tuple[list[str], Optional[Union[bool, FilterDataDict]]]]]:
"""Determines whether an update should be passed to this handler's :attr:`callback`.
Args:
@ -206,7 +206,7 @@ class CommandHandler(BaseHandler[Update, CCT, RT]):
context: CCT,
update: Update, # noqa: ARG002
application: "Application[Any, CCT, Any, Any, Any, Any]", # noqa: ARG002
check_result: Optional[Union[bool, Tuple[List[str], Optional[bool]]]],
check_result: Optional[Union[bool, tuple[list[str], Optional[bool]]]],
) -> None:
"""Add text after the command to :attr:`CallbackContext.args` as list, split on single
whitespaces and add output of data filters to :attr:`CallbackContext` as well.

View file

@ -20,20 +20,7 @@
import asyncio
import datetime
from dataclasses import dataclass
from typing import (
TYPE_CHECKING,
Any,
Dict,
Final,
Generic,
List,
NoReturn,
Optional,
Set,
Tuple,
Union,
cast,
)
from typing import TYPE_CHECKING, Any, Final, Generic, NoReturn, Optional, Union, cast
from telegram import Update
from telegram._utils.defaultvalue import DEFAULT_TRUE, DefaultValue
@ -55,7 +42,7 @@ from telegram.ext._utils.types import CCT, ConversationDict, ConversationKey
if TYPE_CHECKING:
from telegram.ext import Application, Job, JobQueue
_CheckUpdateType = Tuple[object, ConversationKey, BaseHandler[Update, CCT, object], object]
_CheckUpdateType = tuple[object, ConversationKey, BaseHandler[Update, CCT, object], object]
_LOGGER = get_logger(__name__, class_name="ConversationHandler")
@ -192,16 +179,16 @@ class ConversationHandler(BaseHandler[Update, CCT, object]):
* :any:`Persistent Conversation Bot <examples.persistentconversationbot>`
Args:
entry_points (List[:class:`telegram.ext.BaseHandler`]): A list of :obj:`BaseHandler`
entry_points (list[:class:`telegram.ext.BaseHandler`]): A list of :obj:`BaseHandler`
objects that
can trigger the start of the conversation. The first handler whose :meth:`check_update`
method returns :obj:`True` will be used. If all return :obj:`False`, the update is not
handled.
states (Dict[:obj:`object`, List[:class:`telegram.ext.BaseHandler`]]): A :obj:`dict` that
states (dict[:obj:`object`, list[:class:`telegram.ext.BaseHandler`]]): A :obj:`dict` that
defines the different states of conversation a user can be in and one or more
associated :obj:`BaseHandler` objects that should be used in that state. The first
handler whose :meth:`check_update` method returns :obj:`True` will be used.
fallbacks (List[:class:`telegram.ext.BaseHandler`]): A list of handlers that might be used
fallbacks (list[:class:`telegram.ext.BaseHandler`]): A list of handlers that might be used
if the user is in a conversation, but every handler for their current state returned
:obj:`False` on :meth:`check_update`. The first handler which :meth:`check_update`
method returns :obj:`True` will be used. If all return :obj:`False`, the update is not
@ -238,7 +225,7 @@ class ConversationHandler(BaseHandler[Update, CCT, object]):
.. versionchanged:: 20.0
Was previously named as ``persistence``.
map_to_parent (Dict[:obj:`object`, :obj:`object`], optional): A :obj:`dict` that can be
map_to_parent (dict[:obj:`object`, :obj:`object`], optional): A :obj:`dict` that can be
used to instruct a child conversation handler to transition into a mapped state on
its parent conversation handler in place of a specified nested state.
block (:obj:`bool`, optional): Pass :obj:`False` or :obj:`True` to set a default value for
@ -297,9 +284,9 @@ class ConversationHandler(BaseHandler[Update, CCT, object]):
# pylint: disable=super-init-not-called
def __init__(
self: "ConversationHandler[CCT]",
entry_points: List[BaseHandler[Update, CCT, object]],
states: Dict[object, List[BaseHandler[Update, CCT, object]]],
fallbacks: List[BaseHandler[Update, CCT, object]],
entry_points: list[BaseHandler[Update, CCT, object]],
states: dict[object, list[BaseHandler[Update, CCT, object]]],
fallbacks: list[BaseHandler[Update, CCT, object]],
allow_reentry: bool = False,
per_chat: bool = True,
per_user: bool = True,
@ -307,7 +294,7 @@ class ConversationHandler(BaseHandler[Update, CCT, object]):
conversation_timeout: Optional[Union[float, datetime.timedelta]] = None,
name: Optional[str] = None,
persistent: bool = False,
map_to_parent: Optional[Dict[object, object]] = None,
map_to_parent: Optional[dict[object, object]] = None,
block: DVType[bool] = DEFAULT_TRUE,
):
# these imports need to be here because of circular import error otherwise
@ -324,9 +311,9 @@ class ConversationHandler(BaseHandler[Update, CCT, object]):
# Store the actual setting in a protected variable instead
self._block: DVType[bool] = block
self._entry_points: List[BaseHandler[Update, CCT, object]] = entry_points
self._states: Dict[object, List[BaseHandler[Update, CCT, object]]] = states
self._fallbacks: List[BaseHandler[Update, CCT, object]] = fallbacks
self._entry_points: list[BaseHandler[Update, CCT, object]] = entry_points
self._states: dict[object, list[BaseHandler[Update, CCT, object]]] = states
self._fallbacks: list[BaseHandler[Update, CCT, object]] = fallbacks
self._allow_reentry: bool = allow_reentry
self._per_user: bool = per_user
@ -336,14 +323,14 @@ class ConversationHandler(BaseHandler[Update, CCT, object]):
conversation_timeout
)
self._name: Optional[str] = name
self._map_to_parent: Optional[Dict[object, object]] = map_to_parent
self._map_to_parent: Optional[dict[object, object]] = map_to_parent
# if conversation_timeout is used, this dict is used to schedule a job which runs when the
# conv has timed out.
self.timeout_jobs: Dict[ConversationKey, Job[Any]] = {}
self.timeout_jobs: dict[ConversationKey, Job[Any]] = {}
self._timeout_jobs_lock = asyncio.Lock()
self._conversations: ConversationDict = {}
self._child_conversations: Set[ConversationHandler] = set()
self._child_conversations: set[ConversationHandler] = set()
if persistent and not self.name:
raise ValueError("Conversations can't be persistent when handler is unnamed.")
@ -359,7 +346,7 @@ class ConversationHandler(BaseHandler[Update, CCT, object]):
stacklevel=2,
)
all_handlers: List[BaseHandler[Update, CCT, object]] = []
all_handlers: list[BaseHandler[Update, CCT, object]] = []
all_handlers.extend(entry_points)
all_handlers.extend(fallbacks)
@ -466,8 +453,8 @@ class ConversationHandler(BaseHandler[Update, CCT, object]):
)
@property
def entry_points(self) -> List[BaseHandler[Update, CCT, object]]:
"""List[:class:`telegram.ext.BaseHandler`]: A list of :obj:`BaseHandler` objects that can
def entry_points(self) -> list[BaseHandler[Update, CCT, object]]:
"""list[:class:`telegram.ext.BaseHandler`]: A list of :obj:`BaseHandler` objects that can
trigger the start of the conversation.
"""
return self._entry_points
@ -479,8 +466,8 @@ class ConversationHandler(BaseHandler[Update, CCT, object]):
)
@property
def states(self) -> Dict[object, List[BaseHandler[Update, CCT, object]]]:
"""Dict[:obj:`object`, List[:class:`telegram.ext.BaseHandler`]]: A :obj:`dict` that
def states(self) -> dict[object, list[BaseHandler[Update, CCT, object]]]:
"""dict[:obj:`object`, list[:class:`telegram.ext.BaseHandler`]]: A :obj:`dict` that
defines the different states of conversation a user can be in and one or more
associated :obj:`BaseHandler` objects that should be used in that state.
"""
@ -491,8 +478,8 @@ class ConversationHandler(BaseHandler[Update, CCT, object]):
raise AttributeError("You can not assign a new value to states after initialization.")
@property
def fallbacks(self) -> List[BaseHandler[Update, CCT, object]]:
"""List[:class:`telegram.ext.BaseHandler`]: A list of handlers that might be used if
def fallbacks(self) -> list[BaseHandler[Update, CCT, object]]:
"""list[:class:`telegram.ext.BaseHandler`]: A list of handlers that might be used if
the user is in a conversation, but every handler for their current state returned
:obj:`False` on :meth:`check_update`.
"""
@ -578,8 +565,8 @@ class ConversationHandler(BaseHandler[Update, CCT, object]):
raise AttributeError("You can not assign a new value to persistent after initialization.")
@property
def map_to_parent(self) -> Optional[Dict[object, object]]:
"""Dict[:obj:`object`, :obj:`object`]: Optional. A :obj:`dict` that can be
def map_to_parent(self) -> Optional[dict[object, object]]:
"""dict[:obj:`object`, :obj:`object`]: Optional. A :obj:`dict` that can be
used to instruct a nested :class:`ConversationHandler` to transition into a mapped state on
its parent :class:`ConversationHandler` in place of a specified nested state.
"""
@ -593,7 +580,7 @@ class ConversationHandler(BaseHandler[Update, CCT, object]):
async def _initialize_persistence(
self, application: "Application"
) -> Dict[str, TrackingDict[ConversationKey, object]]:
) -> dict[str, TrackingDict[ConversationKey, object]]:
"""Initializes the persistence for this handler and its child conversations.
While this method is marked as protected, we expect it to be called by the
Application/parent conversations. It's just protected to hide it from users.
@ -648,7 +635,7 @@ class ConversationHandler(BaseHandler[Update, CCT, object]):
chat = update.effective_chat
user = update.effective_user
key: List[Union[int, str]] = []
key: list[Union[int, str]] = []
if self.per_chat:
if chat is None:

View file

@ -18,7 +18,8 @@
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the InlineQueryHandler class."""
import re
from typing import TYPE_CHECKING, Any, List, Match, Optional, Pattern, TypeVar, Union, cast
from re import Match, Pattern
from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union, cast
from telegram import Update
from telegram._utils.defaultvalue import DEFAULT_TRUE
@ -67,7 +68,7 @@ class InlineQueryHandler(BaseHandler[Update, CCT, RT]):
:meth:`telegram.ext.Application.process_update`. Defaults to :obj:`True`.
.. seealso:: :wiki:`Concurrency`
chat_types (List[:obj:`str`], optional): List of allowed chat types. If passed, will only
chat_types (list[:obj:`str`], optional): List of allowed chat types. If passed, will only
handle inline queries with the appropriate :attr:`telegram.InlineQuery.chat_type`.
.. versionadded:: 13.5
@ -75,7 +76,7 @@ class InlineQueryHandler(BaseHandler[Update, CCT, RT]):
callback (:term:`coroutine function`): The callback function for this handler.
pattern (:obj:`str` | :func:`re.Pattern <re.compile>`): Optional. Regex pattern to test
:attr:`telegram.InlineQuery.query` against.
chat_types (List[:obj:`str`]): Optional. List of allowed chat types.
chat_types (list[:obj:`str`]): Optional. List of allowed chat types.
.. versionadded:: 13.5
block (:obj:`bool`): Determines whether the return value of the callback should be
@ -91,7 +92,7 @@ class InlineQueryHandler(BaseHandler[Update, CCT, RT]):
callback: HandlerCallback[Update, CCT, RT],
pattern: Optional[Union[str, Pattern[str]]] = None,
block: DVType[bool] = DEFAULT_TRUE,
chat_types: Optional[List[str]] = None,
chat_types: Optional[list[str]] = None,
):
super().__init__(callback, block=block)
@ -99,7 +100,7 @@ class InlineQueryHandler(BaseHandler[Update, CCT, RT]):
pattern = re.compile(pattern)
self.pattern: Optional[Union[str, Pattern[str]]] = pattern
self.chat_types: Optional[List[str]] = chat_types
self.chat_types: Optional[list[str]] = chat_types
def check_update(self, update: object) -> Optional[Union[bool, Match[str]]]:
"""

Some files were not shown because too many files have changed in this diff Show more