diff --git a/docs/auxil/kwargs_insertion.py b/docs/auxil/kwargs_insertion.py index 95e1c8bdc..4235f9e0a 100644 --- a/docs/auxil/kwargs_insertion.py +++ b/docs/auxil/kwargs_insertion.py @@ -27,7 +27,7 @@ keyword_args = [ ( " write_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to " " :paramref:`telegram.request.BaseRequest.post.write_timeout`. Defaults to " - " {write_timeout}." + " :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`." ), ( " connect_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to " @@ -45,7 +45,34 @@ keyword_args = [ ), "", ] -write_timeout_sub = [":attr:`~telegram.request.BaseRequest.DEFAULT_NONE`", "``20``"] + +media_write_timeout_deprecation_methods = [ + "send_photo", + "send_audio", + "send_document", + "send_sticker", + "send_video", + "send_video_note", + "send_animation", + "send_voice", + "send_media_group", + "set_chat_photo", + "upload_sticker_file", + "add_sticker_to_set", + "create_new_sticker_set", +] +media_write_timeout_deprecation = [ + " write_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to " + " :paramref:`telegram.request.BaseRequest.post.write_timeout`. By default, ``20`` " + " seconds are used as write timeout." + "", + "", + " .. deprecated:: NEXT.VERSION", + " In future versions, the default value will be changed to " + " :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`.", + "", + "", +] read_timeout_sub = [ ":attr:`~telegram.request.BaseRequest.DEFAULT_NONE`", "``2``. :paramref:`timeout` will be added to this value", @@ -62,12 +89,6 @@ def find_insert_pos_for_kwargs(lines: list[str]) -> int: return False -def is_write_timeout_20(obj: object) -> int: - """inspects the default value of write_timeout parameter of the bot method.""" - sig = inspect.signature(obj) - return 1 if (sig.parameters["write_timeout"].default == 20) else 0 - - def check_timeout_and_api_kwargs_presence(obj: object) -> int: """Checks if the method has timeout and api_kwargs keyword only parameters.""" sig = inspect.signature(obj) diff --git a/docs/auxil/sphinx_hooks.py b/docs/auxil/sphinx_hooks.py index dd93651ee..f8b4c04d2 100644 --- a/docs/auxil/sphinx_hooks.py +++ b/docs/auxil/sphinx_hooks.py @@ -29,11 +29,11 @@ from docs.auxil.admonition_inserter import AdmonitionInserter from docs.auxil.kwargs_insertion import ( check_timeout_and_api_kwargs_presence, find_insert_pos_for_kwargs, - is_write_timeout_20, keyword_args, + media_write_timeout_deprecation, + media_write_timeout_deprecation_methods, read_timeout_sub, read_timeout_type, - write_timeout_sub, ) from docs.auxil.link_code import LINE_NUMBERS @@ -107,19 +107,31 @@ def autodoc_process_docstring( f"Couldn't find the correct position to insert the keyword args for {obj}." ) - long_write_timeout = is_write_timeout_20(obj) get_updates_sub = 1 if (method_name == "get_updates") else 0 # The below can be done in 1 line with itertools.chain, but this must be modified in-place + insert_idx = insert_index for i in range(insert_index, insert_index + len(keyword_args)): - lines.insert( - i, - keyword_args[i - insert_index].format( + to_insert = keyword_args[i - insert_index] + + if ( + "post.write_timeout`. Defaults to" in to_insert + and method_name in media_write_timeout_deprecation_methods + ): + effective_insert: list[str] = media_write_timeout_deprecation + else: + effective_insert = [to_insert] + + effective_insert = [ + entry.format( method=method_name, - write_timeout=write_timeout_sub[long_write_timeout], read_timeout=read_timeout_sub[get_updates_sub], read_timeout_type=read_timeout_type[get_updates_sub], - ), - ) + ) + for entry in effective_insert + ] + + lines[insert_idx:insert_idx] = effective_insert + insert_idx += len(effective_insert) ADMONITION_INSERTER.insert_admonitions( obj=typing.cast(collections.abc.Callable, obj), diff --git a/telegram/_bot.py b/telegram/_bot.py index fb080e42d..d269196b7 100644 --- a/telegram/_bot.py +++ b/telegram/_bot.py @@ -1004,7 +1004,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1118,7 +1118,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1243,7 +1243,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1358,7 +1358,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]): emoji: Optional[str] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1453,7 +1453,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1586,7 +1586,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1703,7 +1703,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1830,7 +1830,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1942,7 +1942,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]): message_thread_id: Optional[int] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -5147,7 +5147,7 @@ class Bot(TelegramObject, AsyncContextManager["Bot"]): photo: FileInput, *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -5527,7 +5527,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. sticker_format: Optional[str], *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -5587,7 +5587,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. sticker: Optional["InputSticker"], *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -5689,7 +5689,7 @@ CUSTOM_EMOJI_IDENTIFIER_LIMIT` custom emoji identifiers can be specified. needs_repainting: Optional[bool] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, diff --git a/telegram/_chat.py b/telegram/_chat.py index 38f93234b..99de4a4e8 100644 --- a/telegram/_chat.py +++ b/telegram/_chat.py @@ -1088,7 +1088,7 @@ class Chat(TelegramObject): photo: FileInput, *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1374,7 +1374,7 @@ class Chat(TelegramObject): message_thread_id: Optional[int] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1462,7 +1462,7 @@ class Chat(TelegramObject): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1567,7 +1567,7 @@ class Chat(TelegramObject): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1623,7 +1623,7 @@ class Chat(TelegramObject): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1910,7 +1910,7 @@ class Chat(TelegramObject): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1962,7 +1962,7 @@ class Chat(TelegramObject): emoji: Optional[str] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -2073,7 +2073,7 @@ class Chat(TelegramObject): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -2129,7 +2129,7 @@ class Chat(TelegramObject): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -2180,7 +2180,7 @@ class Chat(TelegramObject): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, diff --git a/telegram/_message.py b/telegram/_message.py index f12282259..3598952c1 100644 --- a/telegram/_message.py +++ b/telegram/_message.py @@ -1307,7 +1307,7 @@ class Message(TelegramObject): *, quote: Optional[bool] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1369,7 +1369,7 @@ class Message(TelegramObject): filename: Optional[str] = None, quote: Optional[bool] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1431,7 +1431,7 @@ class Message(TelegramObject): filename: Optional[str] = None, quote: Optional[bool] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1494,7 +1494,7 @@ class Message(TelegramObject): filename: Optional[str] = None, quote: Optional[bool] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1558,7 +1558,7 @@ class Message(TelegramObject): filename: Optional[str] = None, quote: Optional[bool] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1618,7 +1618,7 @@ class Message(TelegramObject): *, quote: Optional[bool] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1678,7 +1678,7 @@ class Message(TelegramObject): filename: Optional[str] = None, quote: Optional[bool] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1741,7 +1741,7 @@ class Message(TelegramObject): filename: Optional[str] = None, quote: Optional[bool] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1800,7 +1800,7 @@ class Message(TelegramObject): filename: Optional[str] = None, quote: Optional[bool] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, diff --git a/telegram/_user.py b/telegram/_user.py index 0a24b6abe..e0b60361e 100644 --- a/telegram/_user.py +++ b/telegram/_user.py @@ -446,7 +446,7 @@ class User(TelegramObject): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -497,7 +497,7 @@ class User(TelegramObject): message_thread_id: Optional[int] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -556,7 +556,7 @@ class User(TelegramObject): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -751,7 +751,7 @@ class User(TelegramObject): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1008,7 +1008,7 @@ class User(TelegramObject): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1063,7 +1063,7 @@ class User(TelegramObject): emoji: Optional[str] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1119,7 +1119,7 @@ class User(TelegramObject): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1239,7 +1239,7 @@ class User(TelegramObject): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1293,7 +1293,7 @@ class User(TelegramObject): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, diff --git a/telegram/ext/_extbot.py b/telegram/ext/_extbot.py index cb12a089e..d5e094feb 100644 --- a/telegram/ext/_extbot.py +++ b/telegram/ext/_extbot.py @@ -743,7 +743,7 @@ class ExtBot(Bot, Generic[RLARGS]): sticker: Optional["InputSticker"], *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -1061,7 +1061,7 @@ class ExtBot(Bot, Generic[RLARGS]): needs_repainting: Optional[bool] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -2179,7 +2179,7 @@ class ExtBot(Bot, Generic[RLARGS]): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -2230,7 +2230,7 @@ class ExtBot(Bot, Generic[RLARGS]): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -2378,7 +2378,7 @@ class ExtBot(Bot, Generic[RLARGS]): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -2573,7 +2573,7 @@ class ExtBot(Bot, Generic[RLARGS]): message_thread_id: Optional[int] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -2657,7 +2657,7 @@ class ExtBot(Bot, Generic[RLARGS]): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -2753,7 +2753,7 @@ class ExtBot(Bot, Generic[RLARGS]): emoji: Optional[str] = None, *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -2848,7 +2848,7 @@ class ExtBot(Bot, Generic[RLARGS]): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -2896,7 +2896,7 @@ class ExtBot(Bot, Generic[RLARGS]): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -2939,7 +2939,7 @@ class ExtBot(Bot, Generic[RLARGS]): *, filename: Optional[str] = None, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -3064,7 +3064,7 @@ class ExtBot(Bot, Generic[RLARGS]): photo: FileInput, *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, @@ -3465,7 +3465,7 @@ class ExtBot(Bot, Generic[RLARGS]): sticker_format: Optional[str], *, read_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = 20, + write_timeout: ODVInput[float] = DEFAULT_NONE, connect_timeout: ODVInput[float] = DEFAULT_NONE, pool_timeout: ODVInput[float] = DEFAULT_NONE, api_kwargs: Optional[JSONDict] = None, diff --git a/telegram/request/_baserequest.py b/telegram/request/_baserequest.py index 39214c820..2ae2a7519 100644 --- a/telegram/request/_baserequest.py +++ b/telegram/request/_baserequest.py @@ -27,6 +27,7 @@ from telegram._utils.defaultvalue import DEFAULT_NONE as _DEFAULT_NONE from telegram._utils.defaultvalue import DefaultValue from telegram._utils.logging import get_logger from telegram._utils.types import JSONDict, ODVInput +from telegram._utils.warnings import warn from telegram._version import __version__ as ptb_ver from telegram.error import ( BadRequest, @@ -39,6 +40,7 @@ from telegram.error import ( TelegramError, ) from telegram.request._requestdata import RequestData +from telegram.warnings import PTBDeprecationWarning RT = TypeVar("RT", bound="BaseRequest") @@ -283,8 +285,28 @@ class BaseRequest( TelegramError """ - # TGs response also has the fields 'ok' and 'error_code'. - # However, we rather rely on the HTTP status code for now. + # Import needs to be here since HTTPXRequest is a subclass of BaseRequest + from telegram.request import HTTPXRequest # pylint: disable=import-outside-toplevel + + # 20 is the documented default value for all the media related bot methods and custom + # implementations of BaseRequest may explicitly rely on that. Hence, we follow the + # standard deprecation policy and deprecate starting with version NEXT.VERSION. + # For our own implementation HTTPXRequest, we can handle that ourselves, so we skip the + # warning in that case. + has_files = request_data and request_data.multipart_data + if ( + has_files + and not isinstance(self, HTTPXRequest) + 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, + stacklevel=3, + ) + write_timeout = 20 try: code, payload = await self.do_request( @@ -313,6 +335,8 @@ class BaseRequest( # In some special cases, we can raise more informative exceptions: # see https://core.telegram.org/bots/api#responseparameters and # https://core.telegram.org/bots/api#making-requests + # TGs response also has the fields 'ok' and 'error_code'. + # However, we rather rely on the HTTP status code for now. parameters = response_data.get("parameters") if parameters: migrate_to_chat_id = parameters.get("migrate_to_chat_id") diff --git a/telegram/request/_httpxrequest.py b/telegram/request/_httpxrequest.py index b4f7fd50d..f1e298624 100644 --- a/telegram/request/_httpxrequest.py +++ b/telegram/request/_httpxrequest.py @@ -228,17 +228,25 @@ class HTTPXRequest(BaseRequest): if self._client.is_closed: raise RuntimeError("This HTTPXRequest is not initialized!") + files = request_data.multipart_data if request_data else None + data = request_data.json_parameters if request_data else None + # If user did not specify timeouts (for e.g. in a bot method), use the default ones when we # created this instance. if isinstance(read_timeout, DefaultValue): read_timeout = self._client.timeout.read - if isinstance(write_timeout, DefaultValue): - write_timeout = self._client.timeout.write if isinstance(connect_timeout, DefaultValue): connect_timeout = self._client.timeout.connect if isinstance(pool_timeout, DefaultValue): pool_timeout = self._client.timeout.pool + if isinstance(write_timeout, DefaultValue): + # Making the networking backend decide on the proper timeout values instead of doing + # it via the default values of the Bot methods was introduced in version NEXT.VERSION. + # We hard-code the value here for now until we add additional parameters to this + # class to control the media_write_timeout separately. + write_timeout = self._client.timeout.write if not files else 20 + timeout = httpx.Timeout( connect=connect_timeout, read=read_timeout, @@ -246,9 +254,6 @@ class HTTPXRequest(BaseRequest): pool=pool_timeout, ) - files = request_data.multipart_data if request_data else None - data = request_data.json_parameters if request_data else None - try: res = await self._client.request( method=method, diff --git a/tests/request/test_request.py b/tests/request/test_request.py index 0d6d2f6e5..ea9587070 100644 --- a/tests/request/test_request.py +++ b/tests/request/test_request.py @@ -42,7 +42,9 @@ from telegram.error import ( TelegramError, TimedOut, ) +from telegram.request import BaseRequest, RequestData from telegram.request._httpxrequest import HTTPXRequest +from telegram.request._requestparameter import RequestParameter from telegram.warnings import PTBDeprecationWarning from tests.auxil.envvars import TEST_WITH_OPT_DEPS from tests.auxil.slots import mro_slots @@ -331,7 +333,7 @@ class TestRequestWithoutRequest: assert await httpx_request.retrieve(None, None) == server_response - async def test_timeout_propagation(self, monkeypatch, httpx_request): + async def test_timeout_propagation_to_do_request(self, monkeypatch, httpx_request): async def make_assertion(*args, **kwargs): self.test_flag = ( kwargs.get("read_timeout"), @@ -343,7 +345,7 @@ class TestRequestWithoutRequest: monkeypatch.setattr(httpx_request, "do_request", make_assertion) - await httpx_request.post("url", "method") + await httpx_request.post("url", None) assert self.test_flag == (DEFAULT_NONE, DEFAULT_NONE, DEFAULT_NONE, DEFAULT_NONE) await httpx_request.post( @@ -351,6 +353,59 @@ class TestRequestWithoutRequest: ) assert self.test_flag == (1, 2, 3, 4) + @pytest.mark.parametrize("media", [True, False]) + async def test_timeout_propagation_write_timeout( + self, monkeypatch, media, input_media_photo, recwarn # noqa: F811 + ): + class CustomRequest(BaseRequest): + async def initialize(self_) -> None: + pass + + async def shutdown(self_) -> None: + pass + + async def do_request(self_, *args, **kwargs) -> Tuple[int, bytes]: + self.test_flag = ( + kwargs.get("read_timeout"), + kwargs.get("connect_timeout"), + kwargs.get("write_timeout"), + kwargs.get("pool_timeout"), + ) + return HTTPStatus.OK, b'{"ok": "True", "result": {}}' + + custom_request = CustomRequest() + data = {"string": "string", "int": 1, "float": 1.0} + if media: + data["media"] = input_media_photo + request_data = RequestData( + parameters=[RequestParameter.from_input(key, value) for key, value in data.items()], + ) + + # First make sure that custom timeouts are always respected + await custom_request.post( + "url", request_data, read_timeout=1, connect_timeout=2, write_timeout=3, pool_timeout=4 + ) + assert self.test_flag == (1, 2, 3, 4) + + # Now also ensure that the default timeout for media requests is 20 seconds + await custom_request.post("url", request_data) + assert self.test_flag == ( + DEFAULT_NONE, + DEFAULT_NONE, + 20 if media else DEFAULT_NONE, + DEFAULT_NONE, + ) + + if media: + assert len(recwarn) == 1 + assert "will default to `BaseRequest.DEFAULT_NONE` instead of 20" in str( + recwarn[0].message + ) + assert recwarn[0].category is PTBDeprecationWarning + assert recwarn[0].filename == __file__ + else: + assert len(recwarn) == 0 + @pytest.mark.skipif(not TEST_WITH_OPT_DEPS, reason="No need to run this twice") class TestHTTPXRequestWithoutRequest: @@ -635,6 +690,37 @@ class TestHTTPXRequestWithoutRequest: assert exc_info.value.__cause__ is pool_timeout + @pytest.mark.parametrize("media", [True, False]) + async def test_do_request_write_timeout( + self, monkeypatch, media, httpx_request, input_media_photo, recwarn # noqa: F811 + ): + async def request(_, **kwargs): + self.test_flag = kwargs.get("timeout") + return httpx.Response(HTTPStatus.OK, content=b'{"ok": "True", "result": {}}') + + monkeypatch.setattr(httpx.AsyncClient, "request", request) + + data = {"string": "string", "int": 1, "float": 1.0} + if media: + data["media"] = input_media_photo + request_data = RequestData( + parameters=[RequestParameter.from_input(key, value) for key, value in data.items()], + ) + + # First make sure that custom timeouts are always respected + await httpx_request.post( + "url", request_data, read_timeout=1, connect_timeout=2, write_timeout=3, pool_timeout=4 + ) + assert self.test_flag == httpx.Timeout(read=1, connect=2, write=3, pool=4) + + # Now also ensure that the default timeout for media requests is 20 seconds + await httpx_request.post("url", request_data) + assert self.test_flag == httpx.Timeout(read=5, connect=5, write=20 if media else 5, pool=1) + + # Just for double-checking, since warnings are issued for implementations of BaseRequest + # other than HTTPXRequest + assert len(recwarn) == 0 + async def test_socket_opts(self, monkeypatch): transport_kwargs = {} transport_init = AsyncHTTPTransport.__init__ diff --git a/tests/test_bot.py b/tests/test_bot.py index 988034db1..ea90cdd34 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -27,6 +27,7 @@ import socket import time from collections import defaultdict +import httpx import pytest from telegram import ( @@ -1362,14 +1363,14 @@ class TestBotWithoutRequest: class OkException(BaseException): pass - async def do_request(*args, **kwargs): - obj = kwargs.get("write_timeout") - if obj == 20: + async def request(*args, **kwargs): + timeout = kwargs.get("timeout") + if timeout.write == 20: raise OkException return 200, b'{"ok": true, "result": []}' - monkeypatch.setattr(bot.request, "do_request", do_request) + monkeypatch.setattr(httpx.AsyncClient, "request", request) # Test file uploading with pytest.raises(OkException):