mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2024-11-23 07:38:58 +01:00
Add Version to PTBDeprecationWarning
(#4262)
This commit is contained in:
parent
7d952d8707
commit
512a0b7417
16 changed files with 150 additions and 70 deletions
|
@ -524,7 +524,10 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|
|||
|
||||
@classmethod
|
||||
def _warn(
|
||||
cls, message: str, category: Type[Warning] = PTBUserWarning, stacklevel: int = 0
|
||||
cls,
|
||||
message: Union[str, PTBUserWarning],
|
||||
category: Type[Warning] = PTBUserWarning,
|
||||
stacklevel: int = 0,
|
||||
) -> None:
|
||||
"""Convenience method to issue a warning. This method is here mostly to make it easier
|
||||
for ExtBot to add 1 level to all warning calls.
|
||||
|
@ -837,7 +840,6 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|
|||
f"Please use 'Bot.{endpoint}' instead of "
|
||||
f"'Bot.do_api_request(\"{endpoint}\", ...)'"
|
||||
),
|
||||
PTBDeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
|
@ -4209,10 +4211,12 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]):
|
|||
except NotImplementedError:
|
||||
arg_read_timeout = 2
|
||||
self._warn(
|
||||
f"The class {self._request[0].__class__.__name__} does not override "
|
||||
"the property `read_timeout`. Overriding this property will be mandatory in "
|
||||
"future versions. Using 2 seconds as fallback.",
|
||||
PTBDeprecationWarning,
|
||||
PTBDeprecationWarning(
|
||||
"20.7",
|
||||
f"The class {self._request[0].__class__.__name__} does not override "
|
||||
"the property `read_timeout`. Overriding this property will be mandatory "
|
||||
"in future versions. Using 2 seconds as fallback.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
|
|
|
@ -910,10 +910,12 @@ class Chat(TelegramObject):
|
|||
for arg in _deprecated_attrs:
|
||||
if (val := object.__getattribute__(self, arg)) is not None and val != ():
|
||||
warn(
|
||||
f"The argument `{arg}` is deprecated and will only be available via "
|
||||
"`ChatFullInfo` in the future.",
|
||||
PTBDeprecationWarning(
|
||||
"NEXT.VERSION",
|
||||
f"The argument `{arg}` is deprecated and will only be available via "
|
||||
"`ChatFullInfo` in the future.",
|
||||
),
|
||||
stacklevel=2,
|
||||
category=PTBDeprecationWarning,
|
||||
)
|
||||
|
||||
self._id_attrs = (self.id,)
|
||||
|
@ -923,10 +925,12 @@ class Chat(TelegramObject):
|
|||
def __getattribute__(self, name: str) -> Any:
|
||||
if name in _deprecated_attrs and self.__class__ is Chat:
|
||||
warn(
|
||||
f"The attribute `{name}` is deprecated and will only be accessible via "
|
||||
"`ChatFullInfo` in the future.",
|
||||
PTBDeprecationWarning(
|
||||
"NEXT.VERSION",
|
||||
f"The attribute `{name}` is deprecated and will only be accessible via "
|
||||
"`ChatFullInfo` in the future.",
|
||||
),
|
||||
stacklevel=2,
|
||||
category=PTBDeprecationWarning,
|
||||
)
|
||||
return super().__getattribute__(name)
|
||||
|
||||
|
|
|
@ -1579,9 +1579,11 @@ class Message(MaybeInaccessibleMessage):
|
|||
|
||||
if quote is not None:
|
||||
warn(
|
||||
"The `quote` parameter is deprecated in favor of the `do_quote` parameter. Please "
|
||||
"update your code to use `do_quote` instead.",
|
||||
PTBDeprecationWarning,
|
||||
PTBDeprecationWarning(
|
||||
"20.8",
|
||||
"The `quote` parameter is deprecated in favor of the `do_quote` parameter. "
|
||||
"Please update your code to use `do_quote` instead.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
|
|
|
@ -210,9 +210,11 @@ class PassportElementErrorFiles(PassportElementError):
|
|||
This attribute will return a tuple instead of a list in future major versions.
|
||||
"""
|
||||
warn(
|
||||
"The attribute `file_hashes` will return a tuple instead of a list in future major"
|
||||
" versions.",
|
||||
PTBDeprecationWarning,
|
||||
PTBDeprecationWarning(
|
||||
"20.6",
|
||||
"The attribute `file_hashes` will return a tuple instead of a list in future major"
|
||||
" versions.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
return self._file_hashes
|
||||
|
@ -427,10 +429,12 @@ class PassportElementErrorTranslationFiles(PassportElementError):
|
|||
This attribute will return a tuple instead of a list in future major versions.
|
||||
"""
|
||||
warn(
|
||||
"The attribute `file_hashes` will return a tuple instead of a list in future major"
|
||||
" versions. See the stability policy:"
|
||||
" https://docs.python-telegram-bot.org/en/stable/stability_policy.html",
|
||||
PTBDeprecationWarning,
|
||||
PTBDeprecationWarning(
|
||||
"20.6",
|
||||
"The attribute `file_hashes` will return a tuple instead of a list in future major"
|
||||
" versions. See the stability policy:"
|
||||
" https://docs.python-telegram-bot.org/en/stable/stability_policy.html",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
return self._file_hashes
|
||||
|
|
|
@ -107,9 +107,11 @@ class PassportFile(TelegramObject):
|
|||
This attribute will return a datetime instead of a integer in future major versions.
|
||||
"""
|
||||
warn(
|
||||
"The attribute `file_date` will return a datetime instead of an integer in future"
|
||||
" major versions.",
|
||||
PTBDeprecationWarning,
|
||||
PTBDeprecationWarning(
|
||||
"20.6",
|
||||
"The attribute `file_date` will return a datetime instead of an integer in future"
|
||||
" major versions.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
return self._file_date
|
||||
|
|
|
@ -26,19 +26,28 @@ Warning:
|
|||
the changelog.
|
||||
"""
|
||||
import warnings
|
||||
from typing import Type
|
||||
from typing import Type, Union
|
||||
|
||||
from telegram.warnings import PTBUserWarning
|
||||
|
||||
|
||||
def warn(message: str, category: Type[Warning] = PTBUserWarning, stacklevel: int = 0) -> None:
|
||||
def warn(
|
||||
message: Union[str, PTBUserWarning],
|
||||
category: Type[Warning] = PTBUserWarning,
|
||||
stacklevel: int = 0,
|
||||
) -> None:
|
||||
"""
|
||||
Helper function used as a shortcut for warning with default values.
|
||||
|
||||
.. versionadded:: 20.0
|
||||
|
||||
Args:
|
||||
message (:obj:`str`): Specify the warnings message to pass to ``warnings.warn()``.
|
||||
message (:obj:`str` | :obj:`PTBUserWarning`): Specify the warnings message to pass to
|
||||
``warnings.warn()``.
|
||||
|
||||
.. versionchanged:: NEXT.VERSION
|
||||
Now also accepts a :obj:`PTBUserWarning` instance.
|
||||
|
||||
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()``.
|
||||
|
|
|
@ -23,10 +23,10 @@ inside warnings.py.
|
|||
|
||||
.. versionadded:: 20.2
|
||||
"""
|
||||
from typing import Any, Callable, Type
|
||||
from typing import Any, Callable, Type, Union
|
||||
|
||||
from telegram._utils.warnings import warn
|
||||
from telegram.warnings import PTBDeprecationWarning
|
||||
from telegram.warnings import PTBDeprecationWarning, PTBUserWarning
|
||||
|
||||
|
||||
def build_deprecation_warning_message(
|
||||
|
@ -54,8 +54,9 @@ def warn_about_deprecated_arg_return_new_arg(
|
|||
deprecated_arg_name: str,
|
||||
new_arg_name: str,
|
||||
bot_api_version: str,
|
||||
ptb_version: str,
|
||||
stacklevel: int = 2,
|
||||
warn_callback: Callable[[str, 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.
|
||||
|
||||
|
@ -80,10 +81,12 @@ def warn_about_deprecated_arg_return_new_arg(
|
|||
|
||||
if deprecated_arg:
|
||||
warn_callback(
|
||||
f"Bot API {bot_api_version} renamed the argument '{deprecated_arg_name}' to "
|
||||
f"'{new_arg_name}'.",
|
||||
PTBDeprecationWarning,
|
||||
stacklevel + 1,
|
||||
PTBDeprecationWarning(
|
||||
ptb_version,
|
||||
f"Bot API {bot_api_version} renamed the argument '{deprecated_arg_name}' to "
|
||||
f"'{new_arg_name}'.",
|
||||
),
|
||||
stacklevel=stacklevel + 1, # type: ignore[call-arg]
|
||||
)
|
||||
return deprecated_arg
|
||||
|
||||
|
@ -94,6 +97,7 @@ def warn_about_deprecated_attr_in_property(
|
|||
deprecated_attr_name: str,
|
||||
new_attr_name: str,
|
||||
bot_api_version: str,
|
||||
ptb_version: str,
|
||||
stacklevel: int = 2,
|
||||
) -> None:
|
||||
"""A helper function for the transition in API when attribute is renamed. Call from properties.
|
||||
|
@ -101,8 +105,10 @@ def warn_about_deprecated_attr_in_property(
|
|||
The properties replace deprecated attributes in classes and issue these deprecation warnings.
|
||||
"""
|
||||
warn(
|
||||
f"Bot API {bot_api_version} renamed the attribute '{deprecated_attr_name}' to "
|
||||
f"'{new_attr_name}'.",
|
||||
PTBDeprecationWarning,
|
||||
PTBDeprecationWarning(
|
||||
ptb_version,
|
||||
f"Bot API {bot_api_version} renamed the attribute '{deprecated_attr_name}' to "
|
||||
f"'{new_attr_name}'.",
|
||||
),
|
||||
stacklevel=stacklevel + 1,
|
||||
)
|
||||
|
|
|
@ -857,9 +857,11 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
|
|||
|
||||
if (read_timeout, write_timeout, connect_timeout, pool_timeout) != ((DEFAULT_NONE,) * 4):
|
||||
warn(
|
||||
"Setting timeouts via `Application.run_polling` is deprecated. "
|
||||
"Please use `ApplicationBuilder.get_updates_*_timeout` instead.",
|
||||
PTBDeprecationWarning,
|
||||
PTBDeprecationWarning(
|
||||
"20.6",
|
||||
"Setting timeouts via `Application.run_polling` is deprecated. "
|
||||
"Please use `ApplicationBuilder.get_updates_*_timeout` instead.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
|
@ -1183,9 +1185,11 @@ class Application(Generic[BT, CCT, UD, CD, BD, JQ], AsyncContextManager["Applica
|
|||
# Generator-based coroutines are not supported in Python 3.12+
|
||||
if sys.version_info < (3, 12) and isinstance(coroutine, Generator):
|
||||
warn(
|
||||
"Generator-based coroutines are deprecated in create_task and will not work"
|
||||
" in Python 3.12+",
|
||||
category=PTBDeprecationWarning,
|
||||
PTBDeprecationWarning(
|
||||
"20.4",
|
||||
"Generator-based coroutines are deprecated in create_task and will not"
|
||||
" work in Python 3.12+",
|
||||
),
|
||||
)
|
||||
return await asyncio.create_task(coroutine)
|
||||
# If user uses generator in python 3.12+, Exception will happen and we cannot do
|
||||
|
|
|
@ -528,9 +528,11 @@ class ApplicationBuilder(Generic[BT, CCT, UD, CD, BD, JQ]):
|
|||
:class:`ApplicationBuilder`: The same builder with the updated argument.
|
||||
"""
|
||||
warn(
|
||||
"`ApplicationBuilder.proxy_url` is deprecated since version "
|
||||
"20.7. Use `ApplicationBuilder.proxy` instead.",
|
||||
PTBDeprecationWarning,
|
||||
PTBDeprecationWarning(
|
||||
"20.7",
|
||||
"`ApplicationBuilder.proxy_url` is deprecated. Use `ApplicationBuilder.proxy` "
|
||||
"instead.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.proxy(proxy_url)
|
||||
|
@ -760,9 +762,11 @@ class ApplicationBuilder(Generic[BT, CCT, UD, CD, BD, JQ]):
|
|||
:class:`ApplicationBuilder`: The same builder with the updated argument.
|
||||
"""
|
||||
warn(
|
||||
"`ApplicationBuilder.get_updates_proxy_url` is deprecated since version "
|
||||
"20.7. Use `ApplicationBuilder.get_updates_proxy` instead.",
|
||||
PTBDeprecationWarning,
|
||||
PTBDeprecationWarning(
|
||||
"20.7",
|
||||
"`ApplicationBuilder.get_updates_proxy_url` is deprecated. Use "
|
||||
"`ApplicationBuilder.get_updates_proxy` instead.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.get_updates_proxy(get_updates_proxy_url)
|
||||
|
|
|
@ -156,9 +156,11 @@ class Defaults:
|
|||
raise ValueError("`quote` and `do_quote` are mutually exclusive")
|
||||
if disable_web_page_preview is not None:
|
||||
warn(
|
||||
"`Defaults.disable_web_page_preview` is deprecated. Use "
|
||||
"`Defaults.link_preview_options` instead.",
|
||||
category=PTBDeprecationWarning,
|
||||
PTBDeprecationWarning(
|
||||
"20.8",
|
||||
"`Defaults.disable_web_page_preview` is deprecated. Use "
|
||||
"`Defaults.link_preview_options` instead.",
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
self._link_preview_options: Optional[LinkPreviewOptions] = LinkPreviewOptions(
|
||||
|
@ -169,8 +171,9 @@ class Defaults:
|
|||
|
||||
if quote is not None:
|
||||
warn(
|
||||
"`Defaults.quote` is deprecated. Use `Defaults.do_quote` instead.",
|
||||
category=PTBDeprecationWarning,
|
||||
PTBDeprecationWarning(
|
||||
"20.8", "`Defaults.quote` is deprecated. Use `Defaults.do_quote` instead."
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
self._do_quote: Optional[bool] = quote
|
||||
|
|
|
@ -263,7 +263,10 @@ class ExtBot(Bot, Generic[RLARGS]):
|
|||
|
||||
@classmethod
|
||||
def _warn(
|
||||
cls, message: str, category: Type[Warning] = PTBUserWarning, stacklevel: int = 0
|
||||
cls,
|
||||
message: Union[str, 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
|
||||
points to the user's code, not to the PTB code.
|
||||
|
|
|
@ -318,10 +318,12 @@ class BaseRequest(
|
|||
and isinstance(write_timeout, DefaultValue)
|
||||
):
|
||||
warn(
|
||||
f"The `write_timeout` parameter passed to {self.__class__.__name__}.do_request "
|
||||
"will default to `BaseRequest.DEFAULT_NONE` instead of 20 in future versions "
|
||||
"for *all* methods of the `Bot` class, including methods sending media.",
|
||||
PTBDeprecationWarning,
|
||||
PTBDeprecationWarning(
|
||||
"20.7",
|
||||
f"The `write_timeout` parameter passed to {self.__class__.__name__}.do_request"
|
||||
" will default to `BaseRequest.DEFAULT_NONE` instead of 20 in future versions "
|
||||
"for *all* methods of the `Bot` class, including methods sending media.",
|
||||
),
|
||||
stacklevel=3,
|
||||
)
|
||||
write_timeout = 20
|
||||
|
|
|
@ -146,9 +146,9 @@ class HTTPXRequest(BaseRequest):
|
|||
if proxy_url is not None:
|
||||
proxy = proxy_url
|
||||
warn(
|
||||
"The parameter `proxy_url` is deprecated since version 20.7. Use `proxy` "
|
||||
"instead.",
|
||||
PTBDeprecationWarning,
|
||||
PTBDeprecationWarning(
|
||||
"20.7", "The parameter `proxy_url` is deprecated. Use `proxy` instead."
|
||||
),
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
|
|
|
@ -54,6 +54,34 @@ class PTBDeprecationWarning(PTBUserWarning, DeprecationWarning):
|
|||
|
||||
.. versionchanged:: 20.0
|
||||
Renamed TelegramDeprecationWarning to PTBDeprecationWarning.
|
||||
|
||||
Args:
|
||||
version (:obj:`str`): The version in which the feature was deprecated.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
message (:obj:`str`): The message to display.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
|
||||
Attributes:
|
||||
version (:obj:`str`): The version in which the feature was deprecated.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
message (:obj:`str`): The message to display.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
__slots__ = ("message", "version")
|
||||
|
||||
def __init__(self, version: str, message: str) -> None:
|
||||
self.version: str = version
|
||||
self.message: str = message
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""Returns a string representation of the warning, using :attr:`message` and
|
||||
:attr:`version`.
|
||||
|
||||
.. versionadded:: NEXT.VERSION
|
||||
"""
|
||||
return f"Deprecated since version {self.version}: {self.message}"
|
||||
|
|
|
@ -2105,6 +2105,7 @@ class TestBotWithoutRequest:
|
|||
monkeypatch.setattr(bot.request, "post", make_assertion)
|
||||
assert await bot.do_api_request("camel_case")
|
||||
|
||||
@pytest.mark.filterwarnings("ignore::telegram.warnings.PTBUserWarning")
|
||||
async def test_do_api_request_media_write_timeout(self, bot, chat_id, monkeypatch):
|
||||
test_flag = None
|
||||
|
||||
|
@ -2143,6 +2144,7 @@ class TestBotWithoutRequest:
|
|||
DEFAULT_NONE,
|
||||
)
|
||||
|
||||
@pytest.mark.filterwarnings("ignore::telegram.warnings.PTBUserWarning")
|
||||
async def test_do_api_request_default_timezone(self, tz_bot, monkeypatch):
|
||||
until = dtm.datetime(2020, 1, 11, 16, 13)
|
||||
until_timestamp = to_timestamp(until, tzinfo=tz_bot.defaults.tzinfo)
|
||||
|
@ -4090,7 +4092,7 @@ class TestBotWithRequest:
|
|||
|
||||
@pytest.mark.parametrize("bot_class", [Bot, ExtBot])
|
||||
async def test_do_api_request_warning_known_method(self, bot, bot_class):
|
||||
with pytest.warns(PTBDeprecationWarning, match="Please use 'Bot.get_me'") as record:
|
||||
with pytest.warns(PTBUserWarning, match="Please use 'Bot.get_me'") as record:
|
||||
await bot_class(bot.token).do_api_request("get_me")
|
||||
|
||||
assert record[0].filename == __file__, "Wrong stack level!"
|
||||
|
@ -4099,6 +4101,7 @@ class TestBotWithRequest:
|
|||
with pytest.raises(EndPointNotFound, match="'unknownEndpoint' not found"):
|
||||
await bot.do_api_request("unknown_endpoint")
|
||||
|
||||
@pytest.mark.filterwarnings("ignore::telegram.warnings.PTBUserWarning")
|
||||
async def test_do_api_request_invalid_token(self, bot):
|
||||
# we do not initialize the bot here on purpose b/c that's the case were we actually
|
||||
# do not know for sure if the token is invalid or the method was not found
|
||||
|
@ -4113,6 +4116,7 @@ class TestBotWithRequest:
|
|||
):
|
||||
await Bot(bot.token).do_api_request("unknown_endpoint")
|
||||
|
||||
@pytest.mark.filterwarnings("ignore::telegram.warnings.PTBUserWarning")
|
||||
@pytest.mark.parametrize("return_type", [Message, None])
|
||||
async def test_do_api_request_basic_and_files(self, bot, chat_id, return_type):
|
||||
result = await bot.do_api_request(
|
||||
|
@ -4137,6 +4141,7 @@ class TestBotWithRequest:
|
|||
assert out.read() == data_file("telegram.png").open("rb").read()
|
||||
assert result.document.file_name == "telegram.png"
|
||||
|
||||
@pytest.mark.filterwarnings("ignore::telegram.warnings.PTBUserWarning")
|
||||
@pytest.mark.parametrize("return_type", [Message, None])
|
||||
async def test_do_api_request_list_return_type(self, bot, chat_id, return_type):
|
||||
result = await bot.do_api_request(
|
||||
|
@ -4175,6 +4180,7 @@ class TestBotWithRequest:
|
|||
assert out.read() == data_file(file_name).open("rb").read()
|
||||
assert message.document.file_name == file_name
|
||||
|
||||
@pytest.mark.filterwarnings("ignore::telegram.warnings.PTBUserWarning")
|
||||
@pytest.mark.parametrize("return_type", [Message, None])
|
||||
async def test_do_api_request_bool_return_type(self, bot, chat_id, return_type):
|
||||
assert await bot.do_api_request("delete_my_commands", return_type=return_type) is True
|
||||
|
|
|
@ -33,7 +33,7 @@ class TestWarnings:
|
|||
[
|
||||
(PTBUserWarning("test message")),
|
||||
(PTBRuntimeWarning("test message")),
|
||||
(PTBDeprecationWarning()),
|
||||
(PTBDeprecationWarning("20.6", "test message")),
|
||||
],
|
||||
)
|
||||
def test_slots_behavior(self, inst):
|
||||
|
@ -80,9 +80,8 @@ class TestWarnings:
|
|||
assert str(recwarn[1].message) == "test message 2"
|
||||
assert Path(recwarn[1].filename) == expected_file, "incorrect stacklevel!"
|
||||
|
||||
warn("test message 3", stacklevel=1, category=PTBDeprecationWarning)
|
||||
expected_file = Path(__file__)
|
||||
warn(PTBDeprecationWarning("20.6", "test message 3"), stacklevel=1)
|
||||
assert len(recwarn) == 3
|
||||
assert recwarn[2].category is PTBDeprecationWarning
|
||||
assert str(recwarn[2].message) == "test message 3"
|
||||
assert Path(recwarn[2].filename) == expected_file, "incorrect stacklevel!"
|
||||
assert str(recwarn[2].message) == "Deprecated since version 20.6: test message 3"
|
||||
assert Path(recwarn[2].filename) == Path(__file__), "incorrect stacklevel!"
|
||||
|
|
Loading…
Reference in a new issue