From 1878a4b07ee1a60ab5ba7d3afdee96f405058bdb Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Thu, 31 Oct 2024 15:58:17 +0100 Subject: [PATCH 1/7] Improve Exception Handling in `File.download_*` --- telegram/_files/file.py | 14 +++++++++++++- tests/_files/test_file.py | 9 +++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/telegram/_files/file.py b/telegram/_files/file.py index c9b8d22d49a..9171713b089 100644 --- a/telegram/_files/file.py +++ b/telegram/_files/file.py @@ -176,6 +176,9 @@ async def download_to_drive( :class:`pathlib.Path`: Returns the Path object the file was downloaded to. """ + if not self.file_path: + raise RuntimeError("No `file_path` available for this file. Can not download.") + local_file = is_local_file(self.file_path) url = None if local_file else self._get_encoded_url() @@ -254,13 +257,19 @@ async def download_to_memory( pool_timeout (:obj:`float` | :obj:`None`, optional): Value to pass to :paramref:`telegram.request.BaseRequest.post.pool_timeout`. Defaults to :attr:`~telegram.request.BaseRequest.DEFAULT_NONE`. + + Raises: + RuntimeError: If :attr:`file_path` is not set. """ + if not self.file_path: + raise RuntimeError("No `file_path` available for this file. Can not download.") + local_file = is_local_file(self.file_path) url = None if local_file else self._get_encoded_url() path = Path(self.file_path) if local_file else None if local_file: buf = path.read_bytes() - else: + elif url: buf = await self.get_bot().request.retrieve( url, read_timeout=read_timeout, @@ -313,6 +322,9 @@ async def download_as_bytearray( newly allocated :obj:`bytearray`. """ + if not self.file_path: + raise RuntimeError("No `file_path` available for this file. Can not download.") + if buf is None: buf = bytearray() diff --git a/tests/_files/test_file.py b/tests/_files/test_file.py index 70874d5feb8..83032a4d152 100644 --- a/tests/_files/test_file.py +++ b/tests/_files/test_file.py @@ -17,6 +17,7 @@ # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. import os +from io import BytesIO from pathlib import Path from tempfile import TemporaryFile, mkstemp @@ -272,6 +273,14 @@ async def test(*args, **kwargs): assert buf2[len(buf) :] == buf assert buf2[: len(buf)] == buf + async def test_download_no_file_path(self): + with pytest.raises(RuntimeError, match="No `file_path` available"): + await File(self.file_id, self.file_unique_id).download_to_drive() + with pytest.raises(RuntimeError, match="No `file_path` available"): + await File(self.file_id, self.file_unique_id).download_to_memory(BytesIO()) + with pytest.raises(RuntimeError, match="No `file_path` available"): + await File(self.file_id, self.file_unique_id).download_as_bytearray() + class TestFileWithRequest(FileTestBase): async def test_error_get_empty_file_id(self, bot): From 77297da3317406b72b620a3c4f21c69bdeb9bdbb Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Thu, 31 Oct 2024 16:00:24 +0100 Subject: [PATCH 2/7] A bit more documentation --- telegram/_files/file.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/telegram/_files/file.py b/telegram/_files/file.py index 9171713b089..93b4ebe3ff1 100644 --- a/telegram/_files/file.py +++ b/telegram/_files/file.py @@ -152,6 +152,9 @@ async def download_to_drive( * This method was previously called ``download``. It was split into :meth:`download_to_drive` and :meth:`download_to_memory`. + .. versionchanged:: NEXT.VERSION + Raises :exc:`RuntimeError` if :attr:`file_path` is not set. + Args: custom_path (:class:`pathlib.Path` | :obj:`str` , optional): The path where the file will be saved to. If not specified, will be saved in the current working directory @@ -175,6 +178,9 @@ async def download_to_drive( Returns: :class:`pathlib.Path`: Returns the Path object the file was downloaded to. + Raises: + RuntimeError: If :attr:`file_path` is not set. + """ if not self.file_path: raise RuntimeError("No `file_path` available for this file. Can not download.") @@ -240,6 +246,9 @@ async def download_to_memory( .. versionadded:: 20.0 + .. versionchanged:: NEXT.VERSION + Raises :exc:`RuntimeError` if :attr:`file_path` is not set. + Args: out (:obj:`io.BufferedIOBase`): A file-like object. Must be opened for writing in binary mode. @@ -292,6 +301,9 @@ async def download_as_bytearray( ) -> bytearray: """Download this file and return it as a bytearray. + .. versionchanged:: NEXT.VERSION + Raises :exc:`RuntimeError` if :attr:`file_path` is not set. + Args: buf (:obj:`bytearray`, optional): Extend the given bytearray with the downloaded data. @@ -321,6 +333,9 @@ async def download_as_bytearray( :obj:`bytearray`: The same object as :paramref:`buf` if it was specified. Otherwise a newly allocated :obj:`bytearray`. + Raises: + RuntimeError: If :attr:`file_path` is not set. + """ if not self.file_path: raise RuntimeError("No `file_path` available for this file. Can not download.") From bf883a5cf62a1256b4e523278f9161d8fbacf1b0 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Sat, 2 Nov 2024 18:53:24 +0100 Subject: [PATCH 3/7] Remove `file_id` case in `download_to_drive` and add `stable_get_file` to tests as workaround for tdlib/telegram-bot-api#658 --- telegram/_files/file.py | 21 ++++++++++++--------- tests/_files/test_animation.py | 4 ++-- tests/_files/test_audio.py | 4 ++-- tests/_files/test_chatphoto.py | 7 +++++-- tests/_files/test_document.py | 4 ++-- tests/_files/test_file.py | 15 --------------- tests/_files/test_inputfile.py | 6 +++--- tests/_files/test_sticker.py | 4 ++-- tests/_files/test_video.py | 4 ++-- tests/_files/test_videonote.py | 4 ++-- tests/_files/test_voice.py | 4 ++-- tests/auxil/files.py | 21 +++++++++++++++++++++ tests/test_bot.py | 6 +++--- 13 files changed, 58 insertions(+), 46 deletions(-) diff --git a/telegram/_files/file.py b/telegram/_files/file.py index 93b4ebe3ff1..667ae1d6c74 100644 --- a/telegram/_files/file.py +++ b/telegram/_files/file.py @@ -128,9 +128,8 @@ async def download_to_drive( ) -> Path: """ Download this file. By default, the file is saved in the current working directory with - :attr:`file_path` as file name. If the file has no filename, the file ID will be used as - filename. If :paramref:`custom_path` is supplied as a :obj:`str` or :obj:`pathlib.Path`, - it will be saved to that path. + :attr:`file_path` as file name. If :paramref:`custom_path` is supplied as a :obj:`str` or + :obj:`pathlib.Path`, it will be saved to that path. Note: If :paramref:`custom_path` isn't provided and :attr:`file_path` is the path of a @@ -153,7 +152,9 @@ async def download_to_drive( :meth:`download_to_drive` and :meth:`download_to_memory`. .. versionchanged:: NEXT.VERSION - Raises :exc:`RuntimeError` if :attr:`file_path` is not set. + Raises :exc:`RuntimeError` if :attr:`file_path` is not set. Note that files without + a :attr:`file_path` could never be downloaded, as this attribute is mandatory for that + operation. Args: custom_path (:class:`pathlib.Path` | :obj:`str` , optional): The path where the file @@ -207,10 +208,8 @@ async def download_to_drive( filename = Path(custom_path) elif local_file: return Path(self.file_path) - elif self.file_path: - filename = Path(Path(self.file_path).name) else: - filename = Path.cwd() / self.file_id + filename = Path(Path(self.file_path).name) buf = await self.get_bot().request.retrieve( url, @@ -247,7 +246,9 @@ async def download_to_memory( .. versionadded:: 20.0 .. versionchanged:: NEXT.VERSION - Raises :exc:`RuntimeError` if :attr:`file_path` is not set. + Raises :exc:`RuntimeError` if :attr:`file_path` is not set. Note that files without + a :attr:`file_path` could never be downloaded, as this attribute is mandatory for that + operation. Args: out (:obj:`io.BufferedIOBase`): A file-like object. Must be opened for writing in @@ -302,7 +303,9 @@ async def download_as_bytearray( """Download this file and return it as a bytearray. .. versionchanged:: NEXT.VERSION - Raises :exc:`RuntimeError` if :attr:`file_path` is not set. + Raises :exc:`RuntimeError` if :attr:`file_path` is not set. Note that files without + a :attr:`file_path` could never be downloaded, as this attribute is mandatory for that + operation. Args: buf (:obj:`bytearray`, optional): Extend the given bytearray with the downloaded data. diff --git a/tests/_files/test_animation.py b/tests/_files/test_animation.py index 0f581259db9..6face27d667 100644 --- a/tests/_files/test_animation.py +++ b/tests/_files/test_animation.py @@ -33,7 +33,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message -from tests.auxil.files import data_file +from tests.auxil.files import data_file, stable_get_file from tests.auxil.slots import mro_slots @@ -245,7 +245,7 @@ async def test_send_all_args(self, bot, chat_id, animation_file, animation, thum pytest.xfail("This is a bug on Telegram's end") async def test_get_and_download(self, bot, animation, tmp_file): - new_file = await bot.get_file(animation.file_id) + new_file = await stable_get_file(bot, animation.file_id) assert new_file.file_path.startswith("https://") diff --git a/tests/_files/test_audio.py b/tests/_files/test_audio.py index 08e598cb267..358aae57063 100644 --- a/tests/_files/test_audio.py +++ b/tests/_files/test_audio.py @@ -33,7 +33,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message -from tests.auxil.files import data_file +from tests.auxil.files import data_file, stable_get_file from tests.auxil.slots import mro_slots @@ -244,7 +244,7 @@ async def test_send_all_args(self, bot, chat_id, audio_file, thumb_file): assert message.has_protected_content async def test_get_and_download(self, bot, chat_id, audio, tmp_file): - new_file = await bot.get_file(audio.file_id) + new_file = await stable_get_file(bot, audio.file_id) assert new_file.file_size == self.file_size assert new_file.file_unique_id == audio.file_unique_id diff --git a/tests/_files/test_chatphoto.py b/tests/_files/test_chatphoto.py index 5bbb6a8f71e..9b34986369c 100644 --- a/tests/_files/test_chatphoto.py +++ b/tests/_files/test_chatphoto.py @@ -31,7 +31,7 @@ check_shortcut_call, check_shortcut_signature, ) -from tests.auxil.files import data_file +from tests.auxil.files import data_file, stable_get_file from tests.auxil.networking import expect_bad_request from tests.auxil.slots import mro_slots @@ -158,7 +158,10 @@ async def make_assertion(*_, **kwargs): class TestChatPhotoWithRequest: async def test_get_and_download(self, bot, chat_photo, tmp_file): - tasks = {bot.get_file(chat_photo.small_file_id), bot.get_file(chat_photo.big_file_id)} + tasks = { + stable_get_file(bot, chat_photo.small_file_id), + stable_get_file(bot, chat_photo.big_file_id), + } asserts = [] for task in asyncio.as_completed(tasks): diff --git a/tests/_files/test_document.py b/tests/_files/test_document.py index e6037403408..b0456e103cc 100644 --- a/tests/_files/test_document.py +++ b/tests/_files/test_document.py @@ -33,7 +33,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message -from tests.auxil.files import data_file +from tests.auxil.files import data_file, stable_get_file from tests.auxil.slots import mro_slots @@ -216,7 +216,7 @@ async def test_error_send_empty_file_id(self, bot, chat_id): await bot.send_document(chat_id=chat_id, document="") async def test_get_and_download(self, bot, document, chat_id, tmp_file): - new_file = await bot.get_file(document.file_id) + new_file = await stable_get_file(bot, document.file_id) assert new_file.file_size == document.file_size assert new_file.file_unique_id == document.file_unique_id diff --git a/tests/_files/test_file.py b/tests/_files/test_file.py index 83032a4d152..fbf71dc70ba 100644 --- a/tests/_files/test_file.py +++ b/tests/_files/test_file.py @@ -182,21 +182,6 @@ async def test(*args, **kwargs): os.close(file_handle) custom_path.unlink(missing_ok=True) - async def test_download_no_filename(self, monkeypatch, file): - async def test(*args, **kwargs): - return self.file_content - - file.file_path = None - - monkeypatch.setattr(file.get_bot().request, "retrieve", test) - out_file = await file.download_to_drive() - - assert str(out_file)[-len(file.file_id) :] == file.file_id - try: - assert out_file.read_bytes() == self.file_content - finally: - out_file.unlink(missing_ok=True) - async def test_download_file_obj(self, monkeypatch, file): async def test(*args, **kwargs): return self.file_content diff --git a/tests/_files/test_inputfile.py b/tests/_files/test_inputfile.py index b7235497b92..e733b5ca1f7 100644 --- a/tests/_files/test_inputfile.py +++ b/tests/_files/test_inputfile.py @@ -25,7 +25,7 @@ from telegram import InputFile from telegram._utils.strings import TextEncoding -from tests.auxil.files import data_file +from tests.auxil.files import data_file, stable_get_file from tests.auxil.slots import mro_slots @@ -214,7 +214,7 @@ async def test_send_bytes(self, bot, chat_id): message = await bot.send_document(chat_id, data_file("text_file.txt").read_bytes()) out = BytesIO() - await (await message.document.get_file()).download_to_memory(out=out) + await (await stable_get_file(bot, message.document)).download_to_memory(out=out) out.seek(0) assert out.read().decode(TextEncoding.UTF_8) == "PTB Rocks! ⅞" @@ -227,7 +227,7 @@ async def test_send_string(self, bot, chat_id): ) out = BytesIO() - await (await message.document.get_file()).download_to_memory(out=out) + await (await stable_get_file(bot, message.document)).download_to_memory(out=out) out.seek(0) assert out.read().decode(TextEncoding.UTF_8) == "PTB Rocks! ⅞" diff --git a/tests/_files/test_sticker.py b/tests/_files/test_sticker.py index d77f93ac776..5ee8e4c514f 100644 --- a/tests/_files/test_sticker.py +++ b/tests/_files/test_sticker.py @@ -45,7 +45,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message -from tests.auxil.files import data_file +from tests.auxil.files import data_file, stable_get_file from tests.auxil.slots import mro_slots @@ -336,7 +336,7 @@ async def test_send_all_args(self, bot, chat_id, sticker_file, sticker): assert message.sticker.thumbnail.file_size == sticker.thumbnail.file_size async def test_get_and_download(self, bot, sticker, tmp_file): - new_file = await bot.get_file(sticker.file_id) + new_file = await stable_get_file(bot, sticker.file_id) assert new_file.file_size == sticker.file_size assert new_file.file_unique_id == sticker.file_unique_id diff --git a/tests/_files/test_video.py b/tests/_files/test_video.py index 66230389f7e..9594be16c82 100644 --- a/tests/_files/test_video.py +++ b/tests/_files/test_video.py @@ -33,7 +33,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message -from tests.auxil.files import data_file +from tests.auxil.files import data_file, stable_get_file from tests.auxil.slots import mro_slots @@ -257,7 +257,7 @@ async def test_send_all_args(self, bot, chat_id, video_file, video, thumb_file): assert message.show_caption_above_media async def test_get_and_download(self, bot, video, chat_id, tmp_file): - new_file = await bot.get_file(video.file_id) + new_file = await stable_get_file(bot, video.file_id) assert new_file.file_size == self.file_size assert new_file.file_unique_id == video.file_unique_id diff --git a/tests/_files/test_videonote.py b/tests/_files/test_videonote.py index ce69fa8f850..ed16ddd393a 100644 --- a/tests/_files/test_videonote.py +++ b/tests/_files/test_videonote.py @@ -32,7 +32,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message -from tests.auxil.files import data_file +from tests.auxil.files import data_file, stable_get_file from tests.auxil.slots import mro_slots @@ -249,7 +249,7 @@ async def test_send_all_args(self, bot, chat_id, video_note_file, video_note, th assert message.has_protected_content async def test_get_and_download(self, bot, video_note, tmp_file): - new_file = await bot.get_file(video_note.file_id) + new_file = await stable_get_file(bot, video_note.file_id) assert new_file.file_size == self.file_size assert new_file.file_unique_id == video_note.file_unique_id diff --git a/tests/_files/test_voice.py b/tests/_files/test_voice.py index e32bb195c8e..81dfc07dcd8 100644 --- a/tests/_files/test_voice.py +++ b/tests/_files/test_voice.py @@ -33,7 +33,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message -from tests.auxil.files import data_file +from tests.auxil.files import data_file, stable_get_file from tests.auxil.slots import mro_slots @@ -227,7 +227,7 @@ async def test_send_all_args(self, bot, chat_id, voice_file, voice): assert message.has_protected_content async def test_get_and_download(self, bot, voice, chat_id, tmp_file): - new_file = await bot.get_file(voice.file_id) + new_file = await stable_get_file(bot, voice.file_id) assert new_file.file_size == voice.file_size assert new_file.file_unique_id == voice.file_unique_id diff --git a/tests/auxil/files.py b/tests/auxil/files.py index 6b1f87eacff..b2021bea9bb 100644 --- a/tests/auxil/files.py +++ b/tests/auxil/files.py @@ -16,7 +16,11 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. +import logging from pathlib import Path +from typing import Protocol + +from telegram import Bot, File PROJECT_ROOT_PATH = Path(__file__).parent.parent.parent.resolve() TEST_DATA_PATH = PROJECT_ROOT_PATH / "tests" / "data" @@ -24,3 +28,20 @@ def data_file(filename: str) -> Path: return TEST_DATA_PATH / filename + + +class _HasGetFile(Protocol): + async def get_file(self) -> File: ... + + +async def stable_get_file(bot: Bot, obj: _HasGetFile | str) -> File: + """Temporary workaround for Telegram API returning file_path as None on first call to + get_file. This function will attempt to get the file 3 times before raising an error. + Remove this once https://github.com/tdlib/telegram-bot-api/issues/658 as closed.""" + for i in range(3): + file = await bot.get_file(obj) if isinstance(obj, str) else await obj.get_file() + if file.file_path: + logging.debug("File path returned by TG on attempt %s", i + 1) + return file + + raise RuntimeError("File path not found returned by TG after 3 attempts") diff --git a/tests/test_bot.py b/tests/test_bot.py index 7f060fb0992..0fd9482e51c 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -97,7 +97,7 @@ from tests.auxil.bot_method_checks import check_defaults_handling from tests.auxil.ci_bots import FALLBACKS from tests.auxil.envvars import GITHUB_ACTION, TEST_WITH_OPT_DEPS -from tests.auxil.files import data_file +from tests.auxil.files import data_file, stable_get_file from tests.auxil.networking import OfflineRequest, expect_bad_request from tests.auxil.pytest_classes import PytestBot, PytestExtBot, make_bot from tests.auxil.slots import mro_slots @@ -4231,7 +4231,7 @@ async def test_do_api_request_basic_and_files(self, bot, chat_id, return_type): assert result.chat_id == int(chat_id) assert result.caption == "test_caption" out = BytesIO() - await (await result.document.get_file()).download_to_memory(out) + await (await stable_get_file(bot, result.document)).download_to_memory(out) out.seek(0) assert out.read() == data_file("telegram.png").open("rb").read() assert result.document.file_name == "telegram.png" @@ -4270,7 +4270,7 @@ async def test_do_api_request_list_return_type(self, bot, chat_id, return_type): assert isinstance(message, Message) assert message.chat_id == int(chat_id) out = BytesIO() - await (await message.document.get_file()).download_to_memory(out) + await (await stable_get_file(bot, message.document)).download_to_memory(out) out.seek(0) assert out.read() == data_file(file_name).open("rb").read() assert message.document.file_name == file_name From 1e3b147a80bf7d96942d1ad28ff9cd6ebaa0bd4b Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Sat, 2 Nov 2024 18:58:30 +0100 Subject: [PATCH 4/7] Use `Union` instead of `|` --- tests/auxil/files.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auxil/files.py b/tests/auxil/files.py index b2021bea9bb..eead241cfe5 100644 --- a/tests/auxil/files.py +++ b/tests/auxil/files.py @@ -18,7 +18,7 @@ # along with this program. If not, see [http://www.gnu.org/licenses/]. import logging from pathlib import Path -from typing import Protocol +from typing import Protocol, Union from telegram import Bot, File @@ -34,7 +34,7 @@ class _HasGetFile(Protocol): async def get_file(self) -> File: ... -async def stable_get_file(bot: Bot, obj: _HasGetFile | str) -> File: +async def stable_get_file(bot: Bot, obj: Union[_HasGetFile, str]) -> File: """Temporary workaround for Telegram API returning file_path as None on first call to get_file. This function will attempt to get the file 3 times before raising an error. Remove this once https://github.com/tdlib/telegram-bot-api/issues/658 as closed.""" From d36f12c02e1d136fbd0bc5b1574ce6bf9fc319ee Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Sun, 3 Nov 2024 14:45:26 +0100 Subject: [PATCH 5/7] Revert "Use `Union` instead of `|`" This reverts commit 1e3b147a80bf7d96942d1ad28ff9cd6ebaa0bd4b. --- tests/auxil/files.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auxil/files.py b/tests/auxil/files.py index eead241cfe5..b2021bea9bb 100644 --- a/tests/auxil/files.py +++ b/tests/auxil/files.py @@ -18,7 +18,7 @@ # along with this program. If not, see [http://www.gnu.org/licenses/]. import logging from pathlib import Path -from typing import Protocol, Union +from typing import Protocol from telegram import Bot, File @@ -34,7 +34,7 @@ class _HasGetFile(Protocol): async def get_file(self) -> File: ... -async def stable_get_file(bot: Bot, obj: Union[_HasGetFile, str]) -> File: +async def stable_get_file(bot: Bot, obj: _HasGetFile | str) -> File: """Temporary workaround for Telegram API returning file_path as None on first call to get_file. This function will attempt to get the file 3 times before raising an error. Remove this once https://github.com/tdlib/telegram-bot-api/issues/658 as closed.""" From 1ac480c5ee9f2fe41e839011f326e6578d826450 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Sun, 3 Nov 2024 14:50:32 +0100 Subject: [PATCH 6/7] Revert addition of `stable_get_file` --- tests/_files/test_animation.py | 4 ++-- tests/_files/test_audio.py | 4 ++-- tests/_files/test_chatphoto.py | 7 ++----- tests/_files/test_document.py | 4 ++-- tests/_files/test_inputfile.py | 6 +++--- tests/_files/test_sticker.py | 4 ++-- tests/_files/test_video.py | 4 ++-- tests/_files/test_videonote.py | 4 ++-- tests/_files/test_voice.py | 4 ++-- tests/auxil/files.py | 21 --------------------- tests/test_bot.py | 6 +++--- 11 files changed, 22 insertions(+), 46 deletions(-) diff --git a/tests/_files/test_animation.py b/tests/_files/test_animation.py index 6face27d667..0f581259db9 100644 --- a/tests/_files/test_animation.py +++ b/tests/_files/test_animation.py @@ -33,7 +33,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message -from tests.auxil.files import data_file, stable_get_file +from tests.auxil.files import data_file from tests.auxil.slots import mro_slots @@ -245,7 +245,7 @@ async def test_send_all_args(self, bot, chat_id, animation_file, animation, thum pytest.xfail("This is a bug on Telegram's end") async def test_get_and_download(self, bot, animation, tmp_file): - new_file = await stable_get_file(bot, animation.file_id) + new_file = await bot.get_file(animation.file_id) assert new_file.file_path.startswith("https://") diff --git a/tests/_files/test_audio.py b/tests/_files/test_audio.py index 358aae57063..08e598cb267 100644 --- a/tests/_files/test_audio.py +++ b/tests/_files/test_audio.py @@ -33,7 +33,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message -from tests.auxil.files import data_file, stable_get_file +from tests.auxil.files import data_file from tests.auxil.slots import mro_slots @@ -244,7 +244,7 @@ async def test_send_all_args(self, bot, chat_id, audio_file, thumb_file): assert message.has_protected_content async def test_get_and_download(self, bot, chat_id, audio, tmp_file): - new_file = await stable_get_file(bot, audio.file_id) + new_file = await bot.get_file(audio.file_id) assert new_file.file_size == self.file_size assert new_file.file_unique_id == audio.file_unique_id diff --git a/tests/_files/test_chatphoto.py b/tests/_files/test_chatphoto.py index 9b34986369c..5bbb6a8f71e 100644 --- a/tests/_files/test_chatphoto.py +++ b/tests/_files/test_chatphoto.py @@ -31,7 +31,7 @@ check_shortcut_call, check_shortcut_signature, ) -from tests.auxil.files import data_file, stable_get_file +from tests.auxil.files import data_file from tests.auxil.networking import expect_bad_request from tests.auxil.slots import mro_slots @@ -158,10 +158,7 @@ async def make_assertion(*_, **kwargs): class TestChatPhotoWithRequest: async def test_get_and_download(self, bot, chat_photo, tmp_file): - tasks = { - stable_get_file(bot, chat_photo.small_file_id), - stable_get_file(bot, chat_photo.big_file_id), - } + tasks = {bot.get_file(chat_photo.small_file_id), bot.get_file(chat_photo.big_file_id)} asserts = [] for task in asyncio.as_completed(tasks): diff --git a/tests/_files/test_document.py b/tests/_files/test_document.py index b0456e103cc..e6037403408 100644 --- a/tests/_files/test_document.py +++ b/tests/_files/test_document.py @@ -33,7 +33,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message -from tests.auxil.files import data_file, stable_get_file +from tests.auxil.files import data_file from tests.auxil.slots import mro_slots @@ -216,7 +216,7 @@ async def test_error_send_empty_file_id(self, bot, chat_id): await bot.send_document(chat_id=chat_id, document="") async def test_get_and_download(self, bot, document, chat_id, tmp_file): - new_file = await stable_get_file(bot, document.file_id) + new_file = await bot.get_file(document.file_id) assert new_file.file_size == document.file_size assert new_file.file_unique_id == document.file_unique_id diff --git a/tests/_files/test_inputfile.py b/tests/_files/test_inputfile.py index e733b5ca1f7..b7235497b92 100644 --- a/tests/_files/test_inputfile.py +++ b/tests/_files/test_inputfile.py @@ -25,7 +25,7 @@ from telegram import InputFile from telegram._utils.strings import TextEncoding -from tests.auxil.files import data_file, stable_get_file +from tests.auxil.files import data_file from tests.auxil.slots import mro_slots @@ -214,7 +214,7 @@ async def test_send_bytes(self, bot, chat_id): message = await bot.send_document(chat_id, data_file("text_file.txt").read_bytes()) out = BytesIO() - await (await stable_get_file(bot, message.document)).download_to_memory(out=out) + await (await message.document.get_file()).download_to_memory(out=out) out.seek(0) assert out.read().decode(TextEncoding.UTF_8) == "PTB Rocks! ⅞" @@ -227,7 +227,7 @@ async def test_send_string(self, bot, chat_id): ) out = BytesIO() - await (await stable_get_file(bot, message.document)).download_to_memory(out=out) + await (await message.document.get_file()).download_to_memory(out=out) out.seek(0) assert out.read().decode(TextEncoding.UTF_8) == "PTB Rocks! ⅞" diff --git a/tests/_files/test_sticker.py b/tests/_files/test_sticker.py index 5ee8e4c514f..d77f93ac776 100644 --- a/tests/_files/test_sticker.py +++ b/tests/_files/test_sticker.py @@ -45,7 +45,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message -from tests.auxil.files import data_file, stable_get_file +from tests.auxil.files import data_file from tests.auxil.slots import mro_slots @@ -336,7 +336,7 @@ async def test_send_all_args(self, bot, chat_id, sticker_file, sticker): assert message.sticker.thumbnail.file_size == sticker.thumbnail.file_size async def test_get_and_download(self, bot, sticker, tmp_file): - new_file = await stable_get_file(bot, sticker.file_id) + new_file = await bot.get_file(sticker.file_id) assert new_file.file_size == sticker.file_size assert new_file.file_unique_id == sticker.file_unique_id diff --git a/tests/_files/test_video.py b/tests/_files/test_video.py index 9594be16c82..66230389f7e 100644 --- a/tests/_files/test_video.py +++ b/tests/_files/test_video.py @@ -33,7 +33,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message -from tests.auxil.files import data_file, stable_get_file +from tests.auxil.files import data_file from tests.auxil.slots import mro_slots @@ -257,7 +257,7 @@ async def test_send_all_args(self, bot, chat_id, video_file, video, thumb_file): assert message.show_caption_above_media async def test_get_and_download(self, bot, video, chat_id, tmp_file): - new_file = await stable_get_file(bot, video.file_id) + new_file = await bot.get_file(video.file_id) assert new_file.file_size == self.file_size assert new_file.file_unique_id == video.file_unique_id diff --git a/tests/_files/test_videonote.py b/tests/_files/test_videonote.py index ed16ddd393a..ce69fa8f850 100644 --- a/tests/_files/test_videonote.py +++ b/tests/_files/test_videonote.py @@ -32,7 +32,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message -from tests.auxil.files import data_file, stable_get_file +from tests.auxil.files import data_file from tests.auxil.slots import mro_slots @@ -249,7 +249,7 @@ async def test_send_all_args(self, bot, chat_id, video_note_file, video_note, th assert message.has_protected_content async def test_get_and_download(self, bot, video_note, tmp_file): - new_file = await stable_get_file(bot, video_note.file_id) + new_file = await bot.get_file(video_note.file_id) assert new_file.file_size == self.file_size assert new_file.file_unique_id == video_note.file_unique_id diff --git a/tests/_files/test_voice.py b/tests/_files/test_voice.py index 81dfc07dcd8..e32bb195c8e 100644 --- a/tests/_files/test_voice.py +++ b/tests/_files/test_voice.py @@ -33,7 +33,7 @@ check_shortcut_signature, ) from tests.auxil.build_messages import make_message -from tests.auxil.files import data_file, stable_get_file +from tests.auxil.files import data_file from tests.auxil.slots import mro_slots @@ -227,7 +227,7 @@ async def test_send_all_args(self, bot, chat_id, voice_file, voice): assert message.has_protected_content async def test_get_and_download(self, bot, voice, chat_id, tmp_file): - new_file = await stable_get_file(bot, voice.file_id) + new_file = await bot.get_file(voice.file_id) assert new_file.file_size == voice.file_size assert new_file.file_unique_id == voice.file_unique_id diff --git a/tests/auxil/files.py b/tests/auxil/files.py index b2021bea9bb..6b1f87eacff 100644 --- a/tests/auxil/files.py +++ b/tests/auxil/files.py @@ -16,11 +16,7 @@ # # You should have received a copy of the GNU Lesser Public License # along with this program. If not, see [http://www.gnu.org/licenses/]. -import logging from pathlib import Path -from typing import Protocol - -from telegram import Bot, File PROJECT_ROOT_PATH = Path(__file__).parent.parent.parent.resolve() TEST_DATA_PATH = PROJECT_ROOT_PATH / "tests" / "data" @@ -28,20 +24,3 @@ def data_file(filename: str) -> Path: return TEST_DATA_PATH / filename - - -class _HasGetFile(Protocol): - async def get_file(self) -> File: ... - - -async def stable_get_file(bot: Bot, obj: _HasGetFile | str) -> File: - """Temporary workaround for Telegram API returning file_path as None on first call to - get_file. This function will attempt to get the file 3 times before raising an error. - Remove this once https://github.com/tdlib/telegram-bot-api/issues/658 as closed.""" - for i in range(3): - file = await bot.get_file(obj) if isinstance(obj, str) else await obj.get_file() - if file.file_path: - logging.debug("File path returned by TG on attempt %s", i + 1) - return file - - raise RuntimeError("File path not found returned by TG after 3 attempts") diff --git a/tests/test_bot.py b/tests/test_bot.py index 0fd9482e51c..7f060fb0992 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -97,7 +97,7 @@ from tests.auxil.bot_method_checks import check_defaults_handling from tests.auxil.ci_bots import FALLBACKS from tests.auxil.envvars import GITHUB_ACTION, TEST_WITH_OPT_DEPS -from tests.auxil.files import data_file, stable_get_file +from tests.auxil.files import data_file from tests.auxil.networking import OfflineRequest, expect_bad_request from tests.auxil.pytest_classes import PytestBot, PytestExtBot, make_bot from tests.auxil.slots import mro_slots @@ -4231,7 +4231,7 @@ async def test_do_api_request_basic_and_files(self, bot, chat_id, return_type): assert result.chat_id == int(chat_id) assert result.caption == "test_caption" out = BytesIO() - await (await stable_get_file(bot, result.document)).download_to_memory(out) + await (await result.document.get_file()).download_to_memory(out) out.seek(0) assert out.read() == data_file("telegram.png").open("rb").read() assert result.document.file_name == "telegram.png" @@ -4270,7 +4270,7 @@ async def test_do_api_request_list_return_type(self, bot, chat_id, return_type): assert isinstance(message, Message) assert message.chat_id == int(chat_id) out = BytesIO() - await (await stable_get_file(bot, message.document)).download_to_memory(out) + await (await message.document.get_file()).download_to_memory(out) out.seek(0) assert out.read() == data_file(file_name).open("rb").read() assert message.document.file_name == file_name From fe586174aadbefcda46c1589406f079b7941eac9 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Sun, 3 Nov 2024 14:57:42 +0100 Subject: [PATCH 7/7] Coverage problem --- telegram/_files/file.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telegram/_files/file.py b/telegram/_files/file.py index 667ae1d6c74..640dfc96884 100644 --- a/telegram/_files/file.py +++ b/telegram/_files/file.py @@ -279,7 +279,7 @@ async def download_to_memory( path = Path(self.file_path) if local_file else None if local_file: buf = path.read_bytes() - elif url: + else: buf = await self.get_bot().request.retrieve( url, read_timeout=read_timeout, pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy