mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2026-06-25 18:55:14 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2877bc068b | |||
| 430bde6e0e | |||
| 6775884282 | |||
| 8504e323b6 |
@@ -1,6 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: 'v0.15.15'
|
||||
rev: 'v0.15.16'
|
||||
hooks:
|
||||
# Run the linter:
|
||||
- id: ruff-check
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
dependencies = "Update dependency tornado to v6.5.6 [SECURITY]"
|
||||
[[pull_requests]]
|
||||
uid = "5264"
|
||||
author_uids = ["renovate[bot]"]
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,5 @@
|
||||
internal = "Update Ruff to v0.15.16"
|
||||
[[pull_requests]]
|
||||
uid = "5265"
|
||||
author_uids = ["renovate[bot]"]
|
||||
closes_threads = []
|
||||
@@ -0,0 +1,6 @@
|
||||
breaking = "Remove functionality deprecated in Bot API 10.0"
|
||||
features = "Remove functionality deprecated in Bot API 10.0"
|
||||
[[pull_requests]]
|
||||
uid = "5271"
|
||||
author_uids = ["harshil21"]
|
||||
closes_threads = []
|
||||
+1
-1
@@ -134,7 +134,7 @@ docs = [
|
||||
]
|
||||
linting = [
|
||||
"prek",
|
||||
"ruff==0.15.15",
|
||||
"ruff==0.15.16",
|
||||
"mypy==1.20.2",
|
||||
"pylint==4.0.5"
|
||||
]
|
||||
|
||||
+2
-24
@@ -106,7 +106,6 @@ from telegram._utils.repr import build_repr_with_selected_attrs
|
||||
from telegram._utils.strings import to_camel_case
|
||||
from telegram._utils.types import (
|
||||
BaseUrl,
|
||||
CorrectOptionID,
|
||||
CorrectOptionIds,
|
||||
FileInput,
|
||||
JSONDict,
|
||||
@@ -120,7 +119,7 @@ from telegram.error import EndPointNotFound, InvalidToken
|
||||
from telegram.request import BaseRequest, RequestData
|
||||
from telegram.request._httpxrequest import HTTPXRequest
|
||||
from telegram.request._requestparameter import RequestParameter
|
||||
from telegram.warnings import PTBDeprecationWarning, PTBUserWarning
|
||||
from telegram.warnings import PTBUserWarning
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from telegram import (
|
||||
@@ -7376,9 +7375,6 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||
is_anonymous: bool | None = None,
|
||||
type: str | None = None, # pylint: disable=redefined-builtin
|
||||
allows_multiple_answers: bool | None = None,
|
||||
# tags: deprecated in 22.8, to be removed
|
||||
# replaced by `correct_option_ids`
|
||||
correct_option_id: CorrectOptionID | None = None,
|
||||
is_closed: bool | None = None,
|
||||
disable_notification: ODVInput[bool] = DEFAULT_NONE,
|
||||
reply_markup: "ReplyMarkup | None" = None,
|
||||
@@ -7443,12 +7439,6 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||
:tg-const:`telegram.Poll.REGULAR`, defaults to :tg-const:`telegram.Poll.REGULAR`.
|
||||
allows_multiple_answers (:obj:`bool`, optional): :obj:`True`, if the poll allows
|
||||
multiple answers, defaults to :obj:`False`.
|
||||
correct_option_id (:obj:`int`, optional): 0-based identifier of the correct answer
|
||||
option, required for polls in quiz mode.
|
||||
|
||||
.. deprecated:: 22.8
|
||||
Bot API 9.6 replaces this with :paramref:`correct_option_ids` instead.
|
||||
|
||||
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 with at most
|
||||
@@ -7596,18 +7586,6 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||
:class:`telegram.Message`: On success, the sent Message is returned.
|
||||
"""
|
||||
|
||||
if correct_option_id is not None:
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
version="22.8",
|
||||
message="Bot API 9.6 deprecated `correct_option_id` in favour of "
|
||||
"`correct_option_ids`, please use that.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
if correct_option_ids is None:
|
||||
correct_option_ids = [correct_option_id]
|
||||
|
||||
data: JSONDict = {
|
||||
"chat_id": chat_id,
|
||||
"question": question,
|
||||
@@ -8414,7 +8392,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified.
|
||||
found or copied, they are skipped. Service messages, paid media messages, giveaway
|
||||
messages, giveaway winners messages, and invoice messages can't be copied. A quiz poll can
|
||||
be copied only if the value
|
||||
of the field :attr:`telegram.Poll.correct_option_id` is known to the bot. The method is
|
||||
of the field :attr:`telegram.Poll.correct_option_ids` is known to the bot. The method is
|
||||
analogous to the method :meth:`forward_messages`, but the copied messages don't have a
|
||||
link to the original message. Album grouping is kept for copied messages.
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ from telegram._telegramobject import TelegramObject
|
||||
from telegram._utils import enum
|
||||
from telegram._utils.defaultvalue import DEFAULT_NONE
|
||||
from telegram._utils.types import (
|
||||
CorrectOptionID,
|
||||
CorrectOptionIds,
|
||||
FileInput,
|
||||
JSONDict,
|
||||
@@ -2358,7 +2357,6 @@ class _ChatBase(TelegramObject):
|
||||
is_anonymous: bool | None = None,
|
||||
type: str | None = None,
|
||||
allows_multiple_answers: bool | None = None,
|
||||
correct_option_id: CorrectOptionID | None = None,
|
||||
is_closed: bool | None = None,
|
||||
disable_notification: ODVInput[bool] = DEFAULT_NONE,
|
||||
reply_markup: "ReplyMarkup | None" = None,
|
||||
@@ -2413,7 +2411,6 @@ class _ChatBase(TelegramObject):
|
||||
is_anonymous=is_anonymous,
|
||||
type=type, # pylint=pylint,
|
||||
allows_multiple_answers=allows_multiple_answers,
|
||||
correct_option_id=correct_option_id,
|
||||
allows_revoting=allows_revoting,
|
||||
shuffle_options=shuffle_options,
|
||||
correct_option_ids=correct_option_ids,
|
||||
|
||||
@@ -631,18 +631,13 @@ class ChatMemberRestricted(ChatMember):
|
||||
can_send_video_notes: bool,
|
||||
can_send_voice_notes: bool,
|
||||
can_edit_tag: bool,
|
||||
can_react_to_messages: bool,
|
||||
tag: str | None = None,
|
||||
# tags: 22.8
|
||||
# temporarily optional to make it not breaking
|
||||
can_react_to_messages: bool | None = None,
|
||||
*,
|
||||
api_kwargs: JSONDict | None = None,
|
||||
):
|
||||
super().__init__(status=ChatMember.RESTRICTED, user=user, api_kwargs=api_kwargs)
|
||||
|
||||
if can_react_to_messages is None:
|
||||
raise TypeError("`can_react_to_messages` is required and cannot be None")
|
||||
|
||||
with self._unfrozen():
|
||||
self.is_member: bool = is_member
|
||||
self.can_change_info: bool = can_change_info
|
||||
|
||||
@@ -81,7 +81,6 @@ from telegram._utils.defaultvalue import DEFAULT_NONE, DefaultValue
|
||||
from telegram._utils.entities import parse_message_entities, parse_message_entity
|
||||
from telegram._utils.strings import TextEncoding
|
||||
from telegram._utils.types import (
|
||||
CorrectOptionID,
|
||||
CorrectOptionIds,
|
||||
JSONDict,
|
||||
MarkdownVersion,
|
||||
@@ -3663,7 +3662,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
is_anonymous: bool | None = None,
|
||||
type: str | None = None, # pylint: disable=redefined-builtin
|
||||
allows_multiple_answers: bool | None = None,
|
||||
correct_option_id: CorrectOptionID | None = None,
|
||||
is_closed: bool | None = None,
|
||||
disable_notification: ODVInput[bool] = DEFAULT_NONE,
|
||||
reply_markup: "ReplyMarkup | None" = None,
|
||||
@@ -3739,7 +3737,6 @@ class Message(MaybeInaccessibleMessage):
|
||||
is_anonymous=is_anonymous,
|
||||
type=type,
|
||||
allows_multiple_answers=allows_multiple_answers,
|
||||
correct_option_id=correct_option_id,
|
||||
allows_revoting=allows_revoting,
|
||||
shuffle_options=shuffle_options,
|
||||
correct_option_ids=correct_option_ids,
|
||||
|
||||
+12
-99
@@ -51,8 +51,6 @@ from telegram._utils.datetime import (
|
||||
from telegram._utils.defaultvalue import DEFAULT_NONE
|
||||
from telegram._utils.entities import parse_message_entities, parse_message_entity
|
||||
from telegram._utils.types import JSONDict, ODVInput, TimePeriod
|
||||
from telegram._utils.warnings import warn
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from telegram import Bot, InputPollOptionMedia, MaybeInaccessibleMessage
|
||||
@@ -234,30 +232,6 @@ class InputPollOption(TelegramObject):
|
||||
|
||||
self._freeze()
|
||||
|
||||
# tags: deprecated 22.8
|
||||
@classmethod
|
||||
def de_json(cls, data: JSONDict, bot: "Bot | None" = None) -> "InputPollOption":
|
||||
"""See :meth:`telegram.TelegramObject.de_json`. The :paramref:`media` field will
|
||||
not be included for deserialization.
|
||||
|
||||
.. deprecated:: 22.8
|
||||
This class is input only and will be removed in the next version.
|
||||
"""
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
"22.8",
|
||||
"`InputPollOption.de_json` is deprecated. This class is input only and will be "
|
||||
"removed in the next version. The `media` field will not be included for "
|
||||
"deserialization.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
data = cls._parse_data(data)
|
||||
|
||||
data["text_entities"] = de_list_optional(data.get("text_entities"), MessageEntity, bot)
|
||||
|
||||
return super().de_json(data=data, bot=bot)
|
||||
|
||||
|
||||
class PollOption(TelegramObject):
|
||||
"""
|
||||
@@ -348,20 +322,15 @@ class PollOption(TelegramObject):
|
||||
self,
|
||||
text: str,
|
||||
voter_count: int,
|
||||
persistent_id: str,
|
||||
text_entities: Sequence[MessageEntity] | None = None,
|
||||
added_by_user: User | None = None,
|
||||
added_by_chat: Chat | None = None,
|
||||
addition_date: dtm.datetime | None = None,
|
||||
media: PollMedia | None = None,
|
||||
# tags: required in 22.8, bot api 9.6
|
||||
# temporarily optional to avoid breaking changes
|
||||
persistent_id: str | None = None,
|
||||
*,
|
||||
api_kwargs: JSONDict | None = None,
|
||||
):
|
||||
if persistent_id is None:
|
||||
raise TypeError("`persistent_id` is a required argument since Bot API 9.6")
|
||||
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.text: str = text
|
||||
self.voter_count: int = voter_count
|
||||
@@ -515,17 +484,12 @@ class PollAnswer(TelegramObject):
|
||||
self,
|
||||
poll_id: str,
|
||||
option_ids: Sequence[int],
|
||||
option_persistent_ids: Sequence[str],
|
||||
user: User | None = None,
|
||||
voter_chat: Chat | None = None,
|
||||
# tags: required in 22.8, bot api 9.6
|
||||
# temporarily optional to avoid breaking changes
|
||||
option_persistent_ids: Sequence[str] | None = None,
|
||||
*,
|
||||
api_kwargs: JSONDict | None = None,
|
||||
):
|
||||
if option_persistent_ids is None:
|
||||
raise TypeError("`option_persistent_ids` is a required argument since Bot API 9.6")
|
||||
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.poll_id: str = poll_id
|
||||
self.voter_chat: Chat | None = voter_chat
|
||||
@@ -805,17 +769,15 @@ class Poll(TelegramObject):
|
||||
is_anonymous (:obj:`bool`): :obj:`True`, if the poll is anonymous.
|
||||
type (:obj:`str`): Poll type, currently can be :attr:`REGULAR` or :attr:`QUIZ`.
|
||||
allows_multiple_answers (:obj:`bool`): :obj:`True`, if the poll allows multiple answers.
|
||||
allows_revoting (:obj:`bool`): :obj:`True`, if the poll allows to
|
||||
change the chosen answer options.
|
||||
|
||||
.. versionadded:: 22.8
|
||||
members_only (:obj:`bool`): :obj:`True`, if voting is limited to users who have been
|
||||
members of the chat where the poll was originally sent for more than
|
||||
:tg-const:`telegram.Poll.MIN_MEMBERSHIP_HOURS` hours.
|
||||
|
||||
.. versionadded:: 22.8
|
||||
correct_option_id (:obj:`int`, optional): A zero based identifier of the correct answer
|
||||
option. Available only for closed polls in the quiz mode, which were sent
|
||||
(not forwarded), by the bot or to a private chat with the bot.
|
||||
|
||||
.. deprecated:: 22.8
|
||||
Use :paramref:`correct_option_ids` instead.
|
||||
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.
|
||||
@@ -847,10 +809,6 @@ class Poll(TelegramObject):
|
||||
in poll questions.
|
||||
|
||||
.. versionadded:: 21.2
|
||||
allows_revoting (:obj:`bool`, optional): :obj:`True`, if the poll allows to
|
||||
change the chosenanswer options.
|
||||
|
||||
.. versionadded:: 22.8
|
||||
correct_option_ids (Sequence[:class:`int`], optional): Array of 0-based identifiers of
|
||||
the correct answer options. Available only for polls in quiz mode which are closed or
|
||||
were sent (not forwarded) by the bot or to the private chat with the bot.
|
||||
@@ -888,6 +846,10 @@ class Poll(TelegramObject):
|
||||
is_anonymous (:obj:`bool`): :obj:`True`, if the poll is anonymous.
|
||||
type (:obj:`str`): Poll type, currently can be :attr:`REGULAR` or :attr:`QUIZ`.
|
||||
allows_multiple_answers (:obj:`bool`): :obj:`True`, if the poll allows multiple answers.
|
||||
allows_revoting (:obj:`bool`): :obj:`True`, if the poll
|
||||
allows to change the chosen answer options
|
||||
|
||||
.. versionadded:: 22.8
|
||||
members_only (:obj:`bool`): :obj:`True`, if voting is limited to users who have been
|
||||
members of the chat where the poll was originally sent for more than
|
||||
:tg-const:`telegram.Poll.MIN_MEMBERSHIP_HOURS` hours.
|
||||
@@ -925,10 +887,6 @@ class Poll(TelegramObject):
|
||||
This list is empty if the question does not contain entities.
|
||||
|
||||
.. versionadded:: 21.2
|
||||
allows_revoting (:obj:`bool`): :obj:`True`, if the poll
|
||||
allows to change the chosenanswer options
|
||||
|
||||
.. versionadded:: 22.8
|
||||
correct_option_ids (tuple[:class:`int`]): Array of 0-based identifiers of the
|
||||
correct answer options. Available only for polls in quiz mode which are closed or were
|
||||
sent (not forwarded) by the bot or to the private chat with the bot.
|
||||
@@ -989,20 +947,13 @@ class Poll(TelegramObject):
|
||||
is_anonymous: bool,
|
||||
type: str, # pylint: disable=redefined-builtin
|
||||
allows_multiple_answers: bool,
|
||||
# tags: deprecated 22.8
|
||||
# Removed in bot api 9.6:
|
||||
correct_option_id: int | None = None,
|
||||
# ---
|
||||
allows_revoting: bool,
|
||||
members_only: bool,
|
||||
explanation: str | None = None,
|
||||
explanation_entities: Sequence[MessageEntity] | None = None,
|
||||
open_period: TimePeriod | None = None,
|
||||
close_date: dtm.datetime | None = None,
|
||||
question_entities: Sequence[MessageEntity] | None = None,
|
||||
# tags: required in 22.8
|
||||
# temporarily optional to avoid breaking changes
|
||||
allows_revoting: bool | None = None,
|
||||
members_only: bool | None = None,
|
||||
# ---
|
||||
correct_option_ids: Sequence[int] | None = None,
|
||||
description: str | None = None,
|
||||
description_entities: Sequence[MessageEntity] | None = None,
|
||||
@@ -1012,12 +963,6 @@ class Poll(TelegramObject):
|
||||
*,
|
||||
api_kwargs: JSONDict | None = None,
|
||||
):
|
||||
if allows_revoting is None:
|
||||
raise TypeError("`allows_revoting` is a required argument since Bot API 9.6")
|
||||
|
||||
if members_only is None:
|
||||
raise TypeError("`members_only` is a required argument since Bot API 10.0")
|
||||
|
||||
super().__init__(api_kwargs=api_kwargs)
|
||||
self.id: str = id
|
||||
self.question: str = question
|
||||
@@ -1030,19 +975,6 @@ class Poll(TelegramObject):
|
||||
self.allows_revoting: bool = allows_revoting
|
||||
self.members_only: bool = members_only
|
||||
|
||||
# tag: deprecated 22.8
|
||||
if correct_option_id is not None:
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
"22.8",
|
||||
"The parameter `correct_option_id` is deprecated. "
|
||||
"Use `correct_option_ids` instead.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
if correct_option_ids is None:
|
||||
correct_option_ids = [correct_option_id]
|
||||
|
||||
self.correct_option_ids: tuple[int, ...] = parse_sequence_arg(correct_option_ids)
|
||||
self.description: str | None = description
|
||||
self.description_entities: tuple[MessageEntity, ...] = parse_sequence_arg(
|
||||
@@ -1249,25 +1181,6 @@ class Poll(TelegramObject):
|
||||
|
||||
return parse_message_entities(self.description, self.description_entities, types)
|
||||
|
||||
@property
|
||||
def correct_option_id(self) -> int | None:
|
||||
"""A zero based identifier of the correct answer
|
||||
option. Available only for closed polls in the quiz mode, which were sent
|
||||
(not forwarded), by the bot or to a private chat with the bot.
|
||||
|
||||
.. deprecated:: 22.8
|
||||
Use :attr:`correct_option_ids` instead.
|
||||
"""
|
||||
warn(
|
||||
PTBDeprecationWarning(
|
||||
"22.8",
|
||||
"The attribute `correct_option_id` is deprecated. "
|
||||
"Use `correct_option_ids` instead.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.correct_option_ids[0] if self.correct_option_ids else None
|
||||
|
||||
REGULAR: Final[str] = constants.PollType.REGULAR
|
||||
""":const:`telegram.constants.PollType.REGULAR`"""
|
||||
QUIZ: Final[str] = constants.PollType.QUIZ
|
||||
|
||||
@@ -28,7 +28,6 @@ from telegram._menubutton import MenuButton
|
||||
from telegram._telegramobject import TelegramObject
|
||||
from telegram._utils.defaultvalue import DEFAULT_NONE
|
||||
from telegram._utils.types import (
|
||||
CorrectOptionID,
|
||||
CorrectOptionIds,
|
||||
JSONDict,
|
||||
ODVInput,
|
||||
@@ -1818,7 +1817,6 @@ class User(TelegramObject):
|
||||
is_anonymous: bool | None = None,
|
||||
type: str | None = None,
|
||||
allows_multiple_answers: bool | None = None,
|
||||
correct_option_id: CorrectOptionID | None = None,
|
||||
is_closed: bool | None = None,
|
||||
disable_notification: ODVInput[bool] = DEFAULT_NONE,
|
||||
reply_markup: "ReplyMarkup | None" = None,
|
||||
@@ -1876,7 +1874,6 @@ class User(TelegramObject):
|
||||
is_anonymous=is_anonymous,
|
||||
type=type, # pylint=pylint,
|
||||
allows_multiple_answers=allows_multiple_answers,
|
||||
correct_option_id=correct_option_id,
|
||||
allows_revoting=allows_revoting,
|
||||
shuffle_options=shuffle_options,
|
||||
correct_option_ids=correct_option_ids,
|
||||
|
||||
@@ -91,8 +91,6 @@ HTTPVersion: TypeAlias = Literal["1.1", "2.0", "2"]
|
||||
|
||||
.. versionadded:: 20.4"""
|
||||
|
||||
CorrectOptionID: TypeAlias = Literal[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # pylint: disable=invalid-name
|
||||
|
||||
CorrectOptionIds: TypeAlias = Sequence[Literal[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]]
|
||||
"""
|
||||
.. versionadded:: 22.8
|
||||
|
||||
@@ -101,7 +101,6 @@ from telegram._utils.logging import get_logger
|
||||
from telegram._utils.repr import build_repr_with_selected_attrs
|
||||
from telegram._utils.types import (
|
||||
BaseUrl,
|
||||
CorrectOptionID,
|
||||
CorrectOptionIds,
|
||||
FileInput,
|
||||
JSONDict,
|
||||
@@ -3269,7 +3268,6 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||
is_anonymous: bool | None = None,
|
||||
type: str | None = None, # pylint: disable=redefined-builtin
|
||||
allows_multiple_answers: bool | None = None,
|
||||
correct_option_id: CorrectOptionID | None = None,
|
||||
is_closed: bool | None = None,
|
||||
disable_notification: ODVInput[bool] = DEFAULT_NONE,
|
||||
reply_markup: "ReplyMarkup | None" = None,
|
||||
@@ -3315,7 +3313,6 @@ class ExtBot(Bot, Generic[RLARGS]):
|
||||
is_anonymous=is_anonymous,
|
||||
type=type,
|
||||
allows_multiple_answers=allows_multiple_answers,
|
||||
correct_option_id=correct_option_id,
|
||||
is_closed=is_closed,
|
||||
disable_notification=disable_notification,
|
||||
reply_to_message_id=reply_to_message_id,
|
||||
|
||||
+5
-39
@@ -105,7 +105,7 @@ from telegram.error import BadRequest, EndPointNotFound, InvalidToken, TimedOut
|
||||
from telegram.ext import ExtBot, InvalidCallbackData
|
||||
from telegram.helpers import escape_markdown
|
||||
from telegram.request import BaseRequest, HTTPXRequest, RequestData
|
||||
from telegram.warnings import PTBDeprecationWarning, PTBUserWarning
|
||||
from telegram.warnings import PTBUserWarning
|
||||
from tests.auxil.bot_method_checks import check_defaults_handling
|
||||
from tests.auxil.ci_bots import FALLBACKS
|
||||
from tests.auxil.envvars import GITHUB_ACTIONS
|
||||
@@ -3003,40 +3003,6 @@ class TestBotWithoutRequest:
|
||||
|
||||
await offline_bot.set_chat_member_tag(1234, 5678, "This is a tag")
|
||||
|
||||
async def test_send_poll_warn_correct_option_id(self, offline_bot, monkeypatch, recwarn):
|
||||
async def make_first_assert(url, request_data: RequestData, *args, **kwargs):
|
||||
assert request_data.parameters.get("correct_option_ids") == [1]
|
||||
assert request_data.parameters.get("correct_option_id") is None
|
||||
return make_message("dummy reply").to_dict()
|
||||
|
||||
async def make_second_assert(url, request_data: RequestData, *args, **kwargs):
|
||||
assert request_data.parameters.get("correct_option_ids") == [1, 2]
|
||||
assert request_data.parameters.get("correct_option_id") is None
|
||||
return make_message("dummy reply").to_dict()
|
||||
|
||||
monkeypatch.setattr(offline_bot.request, "post", make_first_assert)
|
||||
|
||||
await offline_bot.send_poll(
|
||||
1,
|
||||
question="question",
|
||||
options=["option1", "option2"],
|
||||
correct_option_id=1,
|
||||
)
|
||||
|
||||
w = recwarn.pop()
|
||||
assert issubclass(w.category, PTBDeprecationWarning)
|
||||
assert "correct_option_id" in str(w.message)
|
||||
|
||||
# Test that correct_option_ids takes priority when both correct_option_id(s) are given
|
||||
monkeypatch.setattr(offline_bot.request, "post", make_second_assert)
|
||||
assert await offline_bot.send_poll(
|
||||
1,
|
||||
question="question",
|
||||
options=["option1", "option2"],
|
||||
correct_option_id=1,
|
||||
correct_option_ids=[1, 2],
|
||||
)
|
||||
|
||||
# TODO: If we create a managed bot, we could test this for real
|
||||
async def test_get_managed_bot_token(self, offline_bot, monkeypatch):
|
||||
|
||||
@@ -3349,7 +3315,7 @@ class TestBotWithRequest:
|
||||
question=question,
|
||||
options=answers,
|
||||
type=Poll.QUIZ,
|
||||
correct_option_id=2,
|
||||
correct_option_ids=[2],
|
||||
is_closed=True,
|
||||
explanation=explanation,
|
||||
explanation_parse_mode=ParseMode.MARKDOWN_V2,
|
||||
@@ -3388,7 +3354,7 @@ class TestBotWithRequest:
|
||||
assert poll.total_voter_count == 0
|
||||
|
||||
message_quiz = await quiz_task
|
||||
assert message_quiz.poll.correct_option_id == 2
|
||||
assert message_quiz.poll.correct_option_ids == (2,)
|
||||
assert message_quiz.poll.type == Poll.QUIZ
|
||||
assert message_quiz.poll.is_closed
|
||||
assert message_quiz.poll.explanation == "Here is a link"
|
||||
@@ -3475,7 +3441,7 @@ class TestBotWithRequest:
|
||||
chat_id,
|
||||
"question",
|
||||
options=["a", "b"],
|
||||
correct_option_id=0,
|
||||
correct_option_ids=[0],
|
||||
type=Poll.QUIZ,
|
||||
explanation=test_string,
|
||||
explanation_entities=entities,
|
||||
@@ -3526,7 +3492,7 @@ class TestBotWithRequest:
|
||||
question=question,
|
||||
options=answers,
|
||||
type=Poll.QUIZ,
|
||||
correct_option_id=2,
|
||||
correct_option_ids=[2],
|
||||
is_closed=True,
|
||||
explanation=explanation_markdown,
|
||||
**i,
|
||||
|
||||
@@ -684,18 +684,6 @@ class TestChatMemberRestrictedWithoutRequest(ChatMemberTestBase):
|
||||
"tag": chat_member_restricted.tag,
|
||||
}
|
||||
|
||||
def test_can_react_to_messages_raises(self, chat_member_restricted):
|
||||
with pytest.raises(
|
||||
TypeError, match="`can_react_to_messages` is required and cannot be None"
|
||||
):
|
||||
ChatMemberRestricted(
|
||||
*[
|
||||
getattr(chat_member_restricted, k)
|
||||
for k in chat_member_restricted.__slots__
|
||||
if k != "can_react_to_messages"
|
||||
]
|
||||
)
|
||||
|
||||
def test_equality(self, chat_member_restricted):
|
||||
a = chat_member_restricted
|
||||
b = deepcopy(chat_member_restricted)
|
||||
|
||||
@@ -86,10 +86,7 @@ class ParamTypeCheckingExceptions:
|
||||
# too complex to compare/predict with official API
|
||||
# structure: class/method_name: {param_name: reduced form of annotation}
|
||||
COMPLEX_TYPES = {
|
||||
"send_poll": {
|
||||
# "correct_option_id": int,
|
||||
"correct_option_ids": Sequence[int]
|
||||
},
|
||||
"send_poll": {"correct_option_ids": Sequence[int]},
|
||||
"get_file": {
|
||||
"file_id": str, # actual: Union[str, objs_with_file_id_attr]
|
||||
},
|
||||
@@ -185,10 +182,6 @@ PTB_EXTRA_PARAMS = {
|
||||
"InputProfilePhoto": {"type"}, # attributes common to all subclasses
|
||||
"InputPollOptionMedia": {"args", "kwargs"}, # UnionType's __init__ signature
|
||||
"InputPollMedia": {"args", "kwargs"}, # UnionType's __init__ signature
|
||||
# backwards compatibility for api 10.0 changes
|
||||
# tags: deprecated NEXT.VERSION, bot api 10.0
|
||||
"Poll": {"correct_option_id"},
|
||||
"send_poll": {"correct_option_id"},
|
||||
}
|
||||
|
||||
|
||||
@@ -244,13 +237,7 @@ def ignored_param_requirements(object_name: str) -> set[str]:
|
||||
|
||||
|
||||
# Arguments that are optional arguments for now for backwards compatibility
|
||||
BACKWARDS_COMPAT_KWARGS: dict[str, set[str]] = {
|
||||
"PollOption": {"persistent_id"},
|
||||
"PollAnswer": {"option_persistent_ids"},
|
||||
"Poll": {"allows_revoting", "members_only"},
|
||||
"ChatMemberRestricted": {"can_react_to_messages"},
|
||||
"send_poll": {"correct_option_id"},
|
||||
}
|
||||
BACKWARDS_COMPAT_KWARGS: dict[str, set[str]] = {}
|
||||
|
||||
|
||||
def backwards_compat_kwargs(object_name: str) -> set[str]:
|
||||
|
||||
+6
-94
@@ -78,30 +78,6 @@ class TestInputPollOptionWithoutRequest(InputPollOptionTestBase):
|
||||
"duplicate slot"
|
||||
)
|
||||
|
||||
# tags: deprecated NEXT.VERSION
|
||||
def test_de_json(self):
|
||||
json_dict = {
|
||||
"text": self.text,
|
||||
"text_parse_mode": self.text_parse_mode,
|
||||
"text_entities": [e.to_dict() for e in self.text_entities],
|
||||
}
|
||||
input_poll_option = InputPollOption.de_json(json_dict, None)
|
||||
assert input_poll_option.api_kwargs == {}
|
||||
|
||||
assert input_poll_option.text == self.text
|
||||
assert input_poll_option.text_parse_mode == self.text_parse_mode
|
||||
assert input_poll_option.text_entities == tuple(self.text_entities)
|
||||
|
||||
def test_de_json_deprecated(self, recwarn):
|
||||
InputPollOption.de_json({"text": self.text}, None)
|
||||
|
||||
assert len(recwarn) == 1
|
||||
assert "`InputPollOption.de_json` is deprecated" in str(recwarn[0].message)
|
||||
assert "The `media` field will not be included for deserialization" in str(
|
||||
recwarn[0].message
|
||||
)
|
||||
assert recwarn[0].category is PTBDeprecationWarning
|
||||
|
||||
def test_to_dict(self, input_poll_option):
|
||||
input_poll_option_dict = input_poll_option.to_dict()
|
||||
|
||||
@@ -343,11 +319,6 @@ class TestPollOptionWithoutRequest(PollOptionTestBase):
|
||||
assert poll_option.parse_entities(MessageEntity.BOLD) == {entity: "test"}
|
||||
assert poll_option.parse_entities() == {entity: "test", entity_2: "option"}
|
||||
|
||||
def test_persistent_id_required_workaround(self):
|
||||
# tags: deprecated NEXT.VERSION, bot api 9.6
|
||||
with pytest.raises(TypeError, match="`persistent_id` is a required"):
|
||||
PollOption(self.text, self.voter_count)
|
||||
|
||||
def test_equality(self):
|
||||
a = PollOption("text", 1, persistent_id="persistent_id")
|
||||
b = PollOption("text", 1, persistent_id="persistent_id")
|
||||
@@ -388,9 +359,9 @@ def poll_answer():
|
||||
return PollAnswer(
|
||||
PollAnswerTestBase.poll_id,
|
||||
PollAnswerTestBase.option_ids,
|
||||
PollAnswerTestBase.option_persistent_ids,
|
||||
PollAnswerTestBase.user,
|
||||
PollAnswerTestBase.voter_chat,
|
||||
PollAnswerTestBase.option_persistent_ids,
|
||||
)
|
||||
|
||||
|
||||
@@ -430,19 +401,12 @@ class TestPollAnswerWithoutRequest(PollAnswerTestBase):
|
||||
assert poll_answer_dict["voter_chat"] == poll_answer.voter_chat.to_dict()
|
||||
assert poll_answer_dict["option_persistent_ids"] == list(poll_answer.option_persistent_ids)
|
||||
|
||||
def test_persistent_id_required_workaround(self):
|
||||
# tags: deprecated NEXT.VERSION, bot api 9.6
|
||||
with pytest.raises(TypeError, match="`option_persistent_ids` is a required"):
|
||||
PollAnswer(poll_id=123, option_ids=[2], user=self.user, voter_chat=self.voter_chat)
|
||||
|
||||
def test_equality(self):
|
||||
a = PollAnswer(123, [2], self.user, self.voter_chat, option_persistent_ids=["2"])
|
||||
b = PollAnswer(123, [2], self.user, Chat(1, ""), option_persistent_ids=["2"])
|
||||
c = PollAnswer(
|
||||
123, [2], User(1, "first", False), self.voter_chat, option_persistent_ids=["2"]
|
||||
)
|
||||
d = PollAnswer(123, [1, 2], self.user, self.voter_chat, option_persistent_ids=["1", "2"])
|
||||
e = PollAnswer(456, [2], self.user, self.voter_chat, option_persistent_ids=["2"])
|
||||
a = PollAnswer(123, [2], ["2"], self.user, self.voter_chat)
|
||||
b = PollAnswer(123, [2], ["2"], self.user, Chat(1, ""))
|
||||
c = PollAnswer(123, [2], ["2"], User(1, "first", False), self.voter_chat)
|
||||
d = PollAnswer(123, [1, 2], ["1", "2"], self.user, self.voter_chat)
|
||||
e = PollAnswer(456, [2], ["2"], self.user, self.voter_chat)
|
||||
f = PollOption("Text", 1, persistent_id="persistent_id")
|
||||
|
||||
assert a == b
|
||||
@@ -663,58 +627,6 @@ class TestPollWithoutRequest(PollTestBase):
|
||||
assert "`open_period` will be of type `datetime.timedelta`" in str(recwarn[0].message)
|
||||
assert recwarn[0].category is PTBDeprecationWarning
|
||||
|
||||
def test_correct_option_id_deprecated(self, recwarn, poll):
|
||||
poll.correct_option_id
|
||||
|
||||
assert len(recwarn) == 1
|
||||
assert "The attribute `correct_option_id` is deprecated" in str(recwarn[0].message)
|
||||
assert recwarn[0].category is PTBDeprecationWarning
|
||||
|
||||
poll = Poll(
|
||||
PollTestBase.id_,
|
||||
PollTestBase.question,
|
||||
PollTestBase.options,
|
||||
PollTestBase.total_voter_count,
|
||||
PollTestBase.is_closed,
|
||||
PollTestBase.is_anonymous,
|
||||
PollTestBase.type,
|
||||
PollTestBase.allows_multiple_answers,
|
||||
correct_option_id=1,
|
||||
allows_revoting=PollTestBase.allows_revoting,
|
||||
members_only=PollTestBase.members_only,
|
||||
)
|
||||
assert poll.correct_option_ids == (1,)
|
||||
|
||||
def test_allows_revoting_required_workaround(self):
|
||||
# tags: deprecated NEXT.VERSION, bot api 9.6
|
||||
with pytest.raises(TypeError, match="`allows_revoting` is a required"):
|
||||
Poll(
|
||||
self.id_,
|
||||
self.question,
|
||||
self.options,
|
||||
self.total_voter_count,
|
||||
self.is_closed,
|
||||
self.is_anonymous,
|
||||
self.type,
|
||||
self.allows_multiple_answers,
|
||||
members_only=self.members_only,
|
||||
)
|
||||
|
||||
def test_members_only_required_workaround(self):
|
||||
# tags: deprecated NEXT.VERSION, bot api 10.0
|
||||
with pytest.raises(TypeError, match="`members_only` is a required"):
|
||||
Poll(
|
||||
self.id_,
|
||||
self.question,
|
||||
self.options,
|
||||
self.total_voter_count,
|
||||
self.is_closed,
|
||||
self.is_anonymous,
|
||||
self.type,
|
||||
self.allows_multiple_answers,
|
||||
allows_revoting=self.allows_revoting,
|
||||
)
|
||||
|
||||
def test_equality(self):
|
||||
a = Poll(
|
||||
123,
|
||||
|
||||
@@ -1651,7 +1651,7 @@ all = [
|
||||
{ name = "pytest-cov" },
|
||||
{ name = "pytest-xdist", specifier = "==3.8.0" },
|
||||
{ name = "pytz" },
|
||||
{ name = "ruff", specifier = "==0.15.15" },
|
||||
{ name = "ruff", specifier = "==0.15.16" },
|
||||
{ name = "sphinx", marker = "python_full_version >= '3.12'", specifier = "==9.1.0" },
|
||||
{ name = "sphinx-build-compatibility", git = "https://github.com/readthedocs/sphinx-build-compatibility.git?rev=58aabc5f207c6c2421f23d3578adc0b14af57047" },
|
||||
{ name = "sphinx-copybutton", specifier = "==0.5.2" },
|
||||
@@ -1675,7 +1675,7 @@ linting = [
|
||||
{ name = "mypy", specifier = "==1.20.2" },
|
||||
{ name = "prek" },
|
||||
{ name = "pylint", specifier = "==4.0.5" },
|
||||
{ name = "ruff", specifier = "==0.15.15" },
|
||||
{ name = "ruff", specifier = "==0.15.16" },
|
||||
]
|
||||
tests = [
|
||||
{ name = "beautifulsoup4" },
|
||||
@@ -1801,27 +1801,27 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.15.15"
|
||||
version = "0.15.16"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/84/6f/a76f7d96e5c962f5b69cee865e49c15c1116897c01990faa8a57edb62e7f/ruff-0.15.15.tar.gz", hash = "sha256:b8dff018130b46d8e5bf0f926ef6b60cf871d6d5ae45fc9334e09632daa741d6", size = 4706985, upload-time = "2026-05-28T14:16:57.784Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a6/bd/5f7ec371001337d8fa61701c186ff8b613ecac1651848c5950f4c4d5f2e9/ruff-0.15.16.tar.gz", hash = "sha256:d05e78d38c78caf020b03789e25106c93017db5a0cb6e2819885018c61343b78", size = 4714267, upload-time = "2026-06-04T16:33:09.974Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/9d/3a45c05b8ab04b4705989de70a79008e27c8003296a0feaee9edc18dd7e9/ruff-0.15.15-py3-none-linux_armv6l.whl", hash = "sha256:cf93e5388f412e1b108b1f8b34a6e036b70fe8aff89393befad96fe48670311b", size = 10710652, upload-time = "2026-05-28T14:16:06.701Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/66/da974431624bf3b49f6ee1f9543c02d929ff1cba78b0d5a79c38cf21f744/ruff-0.15.15-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ac5a646d1f6a7dadd5d50842dae2c1f9862ac887ef5d1b1375e02def791fde6e", size = 11096615, upload-time = "2026-05-28T14:16:23.313Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/09/7443452e5d290230a712103f2fdceeef7184f3ec99a2bd01c8be78aaceb5/ruff-0.15.15-py3-none-macosx_11_0_arm64.whl", hash = "sha256:77d955a431430c66f72dd94e379ad38a16daea3d25094872ac4edf9e797be530", size = 10436683, upload-time = "2026-05-28T14:16:40.974Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/01/d330c26a57fa4f3943a14424904027428315b700fe4d14a84bb123a649e5/ruff-0.15.15-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7614ee79c69788cf6cedd568069ade9cecc22a1ad20494efe8d0c9ebb4b622d4", size = 10769064, upload-time = "2026-05-28T14:16:28.905Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/85/cc8770f8bdff541b1da8392d1634141fe4a0e3f4ee596605959b7906c27f/ruff-0.15.15-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3cdb1679e06a1f6b47bc384714ae96f6e2fb65ca441eb78c43d2ca554176ce1f", size = 10511987, upload-time = "2026-05-28T14:16:43.732Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/29/8c190c1472b63013583ba391f3342036e02010544c1270455ed8e519bdf3/ruff-0.15.15-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2728b93d7b23a603ea2c0ac6eb73d760bd38ec9de35f35fb41e18f7a3fee7622", size = 11275100, upload-time = "2026-05-28T14:16:55.244Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/6b/7e145ce2cc8e63d6834eca03d83a0e18d121def5c69f91b4cf4011ed4879/ruff-0.15.15-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be582fcc0db438902c7792b08d6ddf6c9b9e21addaa10092c2c741cfb09e5a45", size = 12176903, upload-time = "2026-05-28T14:16:14.368Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/a3/d5974637f68e451f7fadf015cf3101d1cd7d8ba5027cffe0b9e3826ebe6b/ruff-0.15.15-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7aa77465b8ecaf1a27bea098d696f7fed5e1eccbd10b321b682d6de586ae5627", size = 11404550, upload-time = "2026-05-28T14:16:20.138Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/1c/e6e5e568f22be4fb05d6244234aba384c06b451252453b821e1a529263cf/ruff-0.15.15-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48decfa11d740de4889de623be1463308346312f2409a56e24aa280c86162dc4", size = 11382027, upload-time = "2026-05-28T14:16:46.615Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/01/170921b49fcd2e8858825593f91cf7146c3e40a5c3e6df763e4bb0484dde/ruff-0.15.15-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a5015088452ca0081387063649ec67f06d3d1d6b8b936a1f836b5e9657ecd48c", size = 11366041, upload-time = "2026-05-28T14:16:26.247Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/54/a7bad711d7de93254e15e06a4c375b89a03d18de45d3e5dcc86a4472fb1a/ruff-0.15.15-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f5294aab6356c81600fcdea3a62bb1b924dfd5e91767c12318d3f68f86af57cd", size = 10741795, upload-time = "2026-05-28T14:16:17.11Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/31/38c075963668f8b41c6914ee0f6f318727fbe30ab9145cb29e6df464c5fa/ruff-0.15.15-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:db5bd4d802415cca656dc1616070b725952d6ae95eb5d4831e49fbd94a38f75f", size = 10511117, upload-time = "2026-05-28T14:16:31.767Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/96/6ff689e1f7e375d1d97075eca022f74c2bab59554a432fe4d2e6f091986a/ruff-0.15.15-py3-none-musllinux_1_2_i686.whl", hash = "sha256:587a6278ed42059191c1a466e490bd7930fb50bd2e255398bc29616c895a61cb", size = 10994867, upload-time = "2026-05-28T14:16:35.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/c2/5dce0ab9f92a8d534fa62b9bf9caca3eddb8c1a81b616f5e195ada4f0d6e/ruff-0.15.15-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:df0c1c084f5f4be9812f61518a45c440d3c30d69ce4bf6c5270e66d38338f02a", size = 11482101, upload-time = "2026-05-28T14:16:49.598Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/c0/1003b60edd697c649faf61f1a34094b1abb38fb3d1181e3f895781250a08/ruff-0.15.15-py3-none-win32.whl", hash = "sha256:29428ea79694afbe756d45fd59b36f22b6b020dc0443cf7de0173046236964b9", size = 10716774, upload-time = "2026-05-28T14:16:52.337Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/a8/1269eddd6945a06c23f055ef7848886e37cf9d6a8bebb386a3115f01470c/ruff-0.15.15-py3-none-win_amd64.whl", hash = "sha256:8df0323902e15e24bc4bf246da830573d3cf3352bd0b9a164eab335d111ff4a4", size = 11868463, upload-time = "2026-05-28T14:16:11.333Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/b2/920464c907b191e37469d477a1aa8bc048b8f36c4c1610dfa4ab87b39e18/ruff-0.15.15-py3-none-win_arm64.whl", hash = "sha256:3c8ceca6792f38196b8f589bc92eccd03eef286602da92e5dc05cc42ef6441b7", size = 11138498, upload-time = "2026-05-28T14:16:38.425Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/42/53ef1c3953f157956db9bf7861e3bc50b9b887ce93300aa48cdba8336fe6/ruff-0.15.16-py3-none-linux_armv6l.whl", hash = "sha256:6ac3c0b3969cc6cf6b158c4e2f8f682acb58e7d700d8a44b65ecdc72d66ab0b2", size = 10709025, upload-time = "2026-06-04T16:32:51.935Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/9a/a79159346f19134a956607754e57d8d128f7a4c00f4ad2f7514d224c172c/ruff-0.15.16-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:197c207ed75ffba54a0dec23db4aa939a27a3053073e085e0042433cbdc58e4a", size = 11063550, upload-time = "2026-06-04T16:32:42.24Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/72/3ce2ac000a5299ec238e01f51397b3b653c93b077d9b1bfe8715bb895f20/ruff-0.15.16-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3a39fec45ab316cc23e7558f23fea4a70403ddb5648ea9a4a3854a16973d0071", size = 10421345, upload-time = "2026-06-04T16:32:37.251Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/c2/cc7fad3ec9169373f5b6a18f1917b91080feec40c3f9658334a1d28e2f03/ruff-0.15.16-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba93191d79003116b95128c9d306e045200fdbd0bccb782b110f3cd1d4abc5cf", size = 10757217, upload-time = "2026-06-04T16:32:54.722Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/d2/3474009eaa0a65b31fa7152a2fad5e2f050c640ceb1e6b02ee6922e94c82/ruff-0.15.16-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c6ee4b90520630120ef032aa5cc10db483852dff950e78b1d717e2993a61ac8d", size = 10507035, upload-time = "2026-06-04T16:33:05.343Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/81/b7ae6ccbd11f0c8dc3d5d67fc4be9b57ff57ca86ba56152021378e1277f2/ruff-0.15.16-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e4215bc938bc3c8215c1472c1aa437e310fee20cd427335fec9d7e609563628", size = 11255291, upload-time = "2026-06-04T16:32:49.49Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/e1/46e526f1a7cc90857ce6ddf25fbb77eb6568651ac38d71b033af07076dd5/ruff-0.15.16-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c8d26be963b090f10e29abc8b3e74a2a321f6fa34e02424e30b5af89350ecbb", size = 12124922, upload-time = "2026-06-04T16:33:07.821Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/da/5c791b088b596b24d0deb967fa28ae02ad751a140c0b9ea81c5ab915d6c0/ruff-0.15.16-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f198cf4123602a2280ed46c307bcbafe41758d6fee5b456b6b6058ca1514b3b4", size = 11332186, upload-time = "2026-06-04T16:33:02.971Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/11/5da87abe20047c8962361473923ebb2f62b595250126aadfad8c20649c1e/ruff-0.15.16-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb27515fa6240fb586ae82b901a59e67d24acff86f2190b433dc542fe0435aeb", size = 11373541, upload-time = "2026-06-04T16:32:47.007Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/2a/8554754c23a854ae3fd6b507e36ad61ddb121e298c6d5d617dec94ed0f14/ruff-0.15.16-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a267c46ba1593fc26b8eecbea050b39d40c0b6bb7781ee11c90a02cd10032951", size = 11353014, upload-time = "2026-06-04T16:32:34.795Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/25/62ea41529ec89f742ea3fed9cb1059c72877ec7cf9b9e99ac9cf3294d1d9/ruff-0.15.16-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:528c68f39a91498a8d50e91ff5985df3d105782bab49cc378e73ac26bff083e8", size = 10737467, upload-time = "2026-06-04T16:32:26.348Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/90/17/334d3ad9de4d40f9dd58fdd09e35ce64553bb501e2f19a839e2fb6be14fc/ruff-0.15.16-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7ed55c58950df60589a9a7a5d2f8fa5f54ebd287163be805adfe6ee95a9de123", size = 10521910, upload-time = "2026-06-04T16:32:32.54Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/bd/3ac7c6ae77a885c1004b3dda2446ea401768d24f851c14b4ad4b24f6639c/ruff-0.15.16-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d482feaf51512b50f9790ceb417a56a61dd1e9d9bf967662b9ed27c01b34f53a", size = 10979190, upload-time = "2026-06-04T16:32:57.492Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/d7/609546e6a413c3f216fbf2a50c928f97c80939154f6a0503114094a86191/ruff-0.15.16-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1e15bc8c94513dae2a40cc9ef07c94fdd4ecc9e29dabebeebe170f952322c9e3", size = 11477014, upload-time = "2026-06-04T16:32:44.687Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/0d/f2cd247ad32633a5c36e97141a2c21b11c6279f7957bc2ff360b1e08fddd/ruff-0.15.16-py3-none-win32.whl", hash = "sha256:580378f7bd4aa25f72e74aa54948a9622f142b1e509521dd10902e886681cc1e", size = 10735541, upload-time = "2026-06-04T16:32:30.145Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/9e/02e845ef151b1dee585e55c4739f8e1734ae1d9f1221dff65761c162208b/ruff-0.15.16-py3-none-win_amd64.whl", hash = "sha256:408256017284eddf98fff77b29aa4fb30f586042d535b2d9befc6512f400aaec", size = 11843403, upload-time = "2026-06-04T16:32:39.76Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/19/016553f86f207450aebebc2b2b5088d086b901cc8186c02ac4284db3bd88/ruff-0.15.16-py3-none-win_arm64.whl", hash = "sha256:8cd61783afb39638a7133ef0d2dfb1e91277593962f81b5a8423eb0b888a6121", size = 11134555, upload-time = "2026-06-04T16:33:00.136Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2166,19 +2166,19 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "tornado"
|
||||
version = "6.5.5"
|
||||
version = "6.5.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f8/f1/3173dfa4a18db4a9b03e5d55325559dab51ee653763bb8745a75af491286/tornado-6.5.5.tar.gz", hash = "sha256:192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9", size = 516006, upload-time = "2026-03-10T21:31:02.067Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/50/57/6d7303a77ae439d9189108f76c0c4fd89ee5e2cc8387bffb55232565c4ed/tornado-6.5.6.tar.gz", hash = "sha256:9a365179fe8ff6b8766f602c0f67c185d778193e9bdd828b19f0b6ed7764177d", size = 518139, upload-time = "2026-05-27T15:35:54.646Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/59/8c/77f5097695f4dd8255ecbd08b2a1ed8ba8b953d337804dd7080f199e12bf/tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa", size = 445983, upload-time = "2026-03-10T21:30:44.28Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ab/5e/7625b76cd10f98f1516c36ce0346de62061156352353ef2da44e5c21523c/tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521", size = 444246, upload-time = "2026-03-10T21:30:46.571Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/04/7b5705d5b3c0fab088f434f9c83edac1573830ca49ccf29fb83bf7178eec/tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5", size = 447229, upload-time = "2026-03-10T21:30:48.273Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/01/74e034a30ef59afb4097ef8659515e96a39d910b712a89af76f5e4e1f93c/tornado-6.5.5-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:435319e9e340276428bbdb4e7fa732c2d399386d1de5686cb331ec8eee754f07", size = 448192, upload-time = "2026-03-10T21:30:51.22Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/00/fe9e02c5a96429fce1a1d15a517f5d8444f9c412e0bb9eadfbe3b0fc55bf/tornado-6.5.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3f54aa540bdbfee7b9eb268ead60e7d199de5021facd276819c193c0fb28ea4e", size = 448039, upload-time = "2026-03-10T21:30:53.52Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/9e/656ee4cec0398b1d18d0f1eb6372c41c6b889722641d84948351ae19556d/tornado-6.5.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:36abed1754faeb80fbd6e64db2758091e1320f6bba74a4cf8c09cd18ccce8aca", size = 447445, upload-time = "2026-03-10T21:30:55.541Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/76/4921c00511f88af86a33de770d64141170f1cfd9c00311aea689949e274e/tornado-6.5.5-cp39-abi3-win32.whl", hash = "sha256:dd3eafaaeec1c7f2f8fdcd5f964e8907ad788fe8a5a32c4426fbbdda621223b7", size = 448582, upload-time = "2026-03-10T21:30:57.142Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/23/f6c6112a04d28eed765e374435fb1a9198f73e1ec4b4024184f21faeb1ad/tornado-6.5.5-cp39-abi3-win_amd64.whl", hash = "sha256:6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b", size = 448990, upload-time = "2026-03-10T21:30:58.857Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/c8/876602cbc96469911f0939f703453c1157b0c826ecb05bdd32e023397d4e/tornado-6.5.5-cp39-abi3-win_arm64.whl", hash = "sha256:2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6", size = 448016, upload-time = "2026-03-10T21:31:00.43Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/0d/b4f481e18c5a51864e6d12b9a05ecf72919696680b747c958c3fc1f4fbae/tornado-6.5.6-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:65fcfaafb079435c2c19dc9e07c0f1cf0fa9051759ed0a7d0a3ba7ea7f64919c", size = 447737, upload-time = "2026-05-27T15:35:38.122Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/9c/5430c39fcab1144d35860f457b15e9c08b4bc7ac86764354204e983d6183/tornado-6.5.6-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:38bc01b4acacded2de63ae78023548e41ebe6fbed3ec05a796d7ae3ad893887e", size = 445899, upload-time = "2026-05-27T15:35:40.519Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/79/fa7e14a2f939c807a8d30619b4eb604eab219601b78792516ebe22d40cf9/tornado-6.5.6-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b942e6a137fda31ff54bf8e6e2c8d1c37f1f50583f3ed53fb840b53b9601d104", size = 448964, upload-time = "2026-05-27T15:35:42.106Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/71/bd67d5f5199f937dafe03a49a37989f60f600ff6fef34c79412a829d97bd/tornado-6.5.6-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8666946e70171b8c3f1fc9b7876fac492e84822c4c7f3746f4e8f8bc9ac92a79", size = 449935, upload-time = "2026-05-27T15:35:43.906Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/a4/c24388c9cf5b3c3a513b56a158af9f23092c9a2810d789e294310797df21/tornado-6.5.6-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1c34cfab7ad6d104f052f55de06d39bbafc5885cfeb4da688803308dbcfa90b7", size = 449767, upload-time = "2026-05-27T15:35:45.793Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/eb/6a07ad550c3f7b37244bd0becdf293ec3d3e961783d8b720a97df50de1b2/tornado-6.5.6-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:385f35e4e22fb52551dfcda4cdc8c30c61c2c001aef5ddad99cdfe116952efd3", size = 449174, upload-time = "2026-05-27T15:35:47.485Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/84/3469e098dccdb6763130e06aacd786bb4363fca7b590a55c101ddf34ed30/tornado-6.5.6-cp39-abi3-win32.whl", hash = "sha256:db475f1b67b2809b10bb16264829087724ca8d24fe4ed47f7b8675cae453ef86", size = 450230, upload-time = "2026-05-27T15:35:49.322Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/3c/273a04e0b9dd9016f1685cca0c1c8795a71ac88a34a8c889a0b443483226/tornado-6.5.6-cp39-abi3-win_amd64.whl", hash = "sha256:6739bf1e8eb09230f1280ddbd3236f0309db70f2c551a8dbc40f62babdf82f79", size = 450667, upload-time = "2026-05-27T15:35:51.194Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/98/0cffe22a224f60c5fb1e3aa0b76f9da2e1ca78b0e9545e3d077c68ce60a7/tornado-6.5.6-cp39-abi3-win_arm64.whl", hash = "sha256:2543597b24a695d72338a9a77818362d72387c03ae173f1f169eadc5c91466ac", size = 449690, upload-time = "2026-05-27T15:35:52.902Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
Reference in New Issue
Block a user