From b165dd415dfbeabe47164daa95c94ad1dde85059 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Sun, 3 Aug 2025 10:07:40 +0200 Subject: [PATCH 1/4] Fix Type Annotations in `AiohttpRequest.do_request` --- ptbcontrib/aiohttp_request/aiohttprequest.py | 10 ++++------ requirements-dev.txt | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/ptbcontrib/aiohttp_request/aiohttprequest.py b/ptbcontrib/aiohttp_request/aiohttprequest.py index 860a35b..dee4504 100644 --- a/ptbcontrib/aiohttp_request/aiohttprequest.py +++ b/ptbcontrib/aiohttp_request/aiohttprequest.py @@ -150,12 +150,10 @@ async def do_request( # pylint: disable=too-many-arguments,too-many-positional- url: str, method: str, request_data: Optional[RequestData] = None, - read_timeout: Optional[Union[BaseRequest.DEFAULT_NONE, float]] = BaseRequest.DEFAULT_NONE, - write_timeout: Optional[Union[BaseRequest.DEFAULT_NONE, float]] = BaseRequest.DEFAULT_NONE, - connect_timeout: Optional[ - Union[BaseRequest.DEFAULT_NONE, float] - ] = BaseRequest.DEFAULT_NONE, - pool_timeout: Optional[Union[BaseRequest.DEFAULT_NONE, float]] = BaseRequest.DEFAULT_NONE, + read_timeout: Optional[float] = BaseRequest.DEFAULT_NONE, + write_timeout: Optional[float] = BaseRequest.DEFAULT_NONE, + connect_timeout: Optional[float] = BaseRequest.DEFAULT_NONE, + pool_timeout: Optional[float] = BaseRequest.DEFAULT_NONE, ) -> tuple[int, bytes]: """See :meth:`BaseRequest.do_request`. diff --git a/requirements-dev.txt b/requirements-dev.txt index af91717..801b787 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,6 +1,6 @@ # cryptography is an optional dependency, but running the tests properly requires it cryptography!=3.4,!=3.4.1,!=3.4.2,!=3.4.3 -pygit2==1.9.1 +pygit2~=1.9 pre-commit From f0c85a853e492527672530710fc931880bf0bfd6 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Sun, 3 Aug 2025 10:31:47 +0200 Subject: [PATCH 2/4] try fixing tests on 3.9+ --- tests/test_aiohttp_request.py | 43 ++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/tests/test_aiohttp_request.py b/tests/test_aiohttp_request.py index e106c12..d899e52 100644 --- a/tests/test_aiohttp_request.py +++ b/tests/test_aiohttp_request.py @@ -25,15 +25,12 @@ from collections.abc import Coroutine from http import HTTPStatus from typing import Any, Callable, Optional +from unittest.mock import MagicMock import aiohttp import multidict import pytest import yarl -from telegram import InputFile -from telegram._utils.defaultvalue import DEFAULT_NONE -from telegram._utils.strings import TextEncoding -from telegram._utils.types import ODVInput from telegram.error import ( BadRequest, ChatMigrated, @@ -45,8 +42,7 @@ TelegramError, TimedOut, ) -from telegram.request import RequestData -from telegram.request._requestparameter import RequestParameter +from telegram.request import BaseRequest, RequestData from ptbcontrib.aiohttp_request import AiohttpRequest @@ -70,10 +66,10 @@ async def _request_wrapper( method: str, url: str, request_data: Optional[RequestData] = None, - read_timeout: ODVInput[float] = DEFAULT_NONE, - connect_timeout: ODVInput[float] = DEFAULT_NONE, - write_timeout: ODVInput[float] = DEFAULT_NONE, - pool_timeout: ODVInput[float] = DEFAULT_NONE, + read_timeout: Optional[float] = BaseRequest.DEFAULT_NONE, + connect_timeout: Optional[float] = BaseRequest.DEFAULT_NONE, + write_timeout: Optional[float] = BaseRequest.DEFAULT_NONE, + pool_timeout: Optional[float] = BaseRequest.DEFAULT_NONE, ) -> bytes: try: return await super()._request_wrapper( @@ -222,8 +218,9 @@ async def test_chat_migrated(self, monkeypatch, aiohttp_request: AiohttpRequest) assert exc_info.value.new_chat_id == 123 - async def test_retry_after(self, monkeypatch, aiohttp_request: AiohttpRequest): + async def test_retry_after(self, monkeypatch): server_response = b'{"ok": "False", "parameters": {"retry_after": 42}}' + aiohttp_request = AiohttpRequest() monkeypatch.setattr( aiohttp_request, @@ -231,8 +228,9 @@ async def test_retry_after(self, monkeypatch, aiohttp_request: AiohttpRequest): mocker_factory(response=server_response, return_code=HTTPStatus.BAD_REQUEST), ) - with pytest.raises(RetryAfter, match="Retry in 42") as exc_info: - await aiohttp_request.post(None, None, None) + async with aiohttp_request: + with pytest.raises(RetryAfter, match="Retry in 42") as exc_info: + await aiohttp_request.post(None, None, None) assert exc_info.value.retry_after == 42 @@ -262,7 +260,7 @@ async def test_error_description( else: match = "Unknown HTTPError" - server_response = json.dumps(response_data).encode(TextEncoding.UTF_8) + server_response = json.dumps(response_data).encode("utf-8") monkeypatch.setattr( aiohttp_request, @@ -364,7 +362,12 @@ async def make_assertion(*args, **kwargs): monkeypatch.setattr(aiohttp_request, "do_request", make_assertion) await aiohttp_request.post("url", None) - assert self.test_flag == (DEFAULT_NONE, DEFAULT_NONE, DEFAULT_NONE, DEFAULT_NONE) + assert self.test_flag == ( + BaseRequest.DEFAULT_NONE, + BaseRequest.DEFAULT_NONE, + BaseRequest.DEFAULT_NONE, + BaseRequest.DEFAULT_NONE, + ) await aiohttp_request.post( "url", None, read_timeout=1, connect_timeout=2, write_timeout=3, pool_timeout=4 @@ -527,12 +530,10 @@ async def make_assertion(self, **kwargs): assert code == HTTPStatus.OK async def test_do_request_params_with_data(self, monkeypatch, aiohttp_request): - mixed_rqs = RequestData( - [ - RequestParameter("name", "value", [InputFile(obj="data", attach=True)]), - RequestParameter("second_name", "second_value", []), - ] - ) + mixed_rqs = MagicMock() + mixed_rqs.contains_files = True + mixed_rqs.json_parameters = {"name": "value", "second_name": "second_value"} + mixed_rqs.multipart_data = {"attachment": ("data", b"content", "application/octet-stream")} async def make_assertion(self, **kwargs): method_assertion = kwargs.get("method") == "method" From 3c9b1d1ea7ee9d5a9083e64cfa016224c1807ae2 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Sun, 3 Aug 2025 10:46:05 +0200 Subject: [PATCH 3/4] try harder --- ptbcontrib/aiohttp_request/aiohttprequest.py | 3 ++- tests/test_aiohttp_request.py | 13 +++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ptbcontrib/aiohttp_request/aiohttprequest.py b/ptbcontrib/aiohttp_request/aiohttprequest.py index dee4504..ace99bc 100644 --- a/ptbcontrib/aiohttp_request/aiohttprequest.py +++ b/ptbcontrib/aiohttp_request/aiohttprequest.py @@ -213,7 +213,8 @@ async def do_request( # pylint: disable=too-many-arguments,too-many-positional- timeout=timeout, data=data, ) - except TimeoutError as err: + # asyncio.TimeoutError is an alias of TimeoutError only starting with Python 3.11. + except asyncio.TimeoutError as err: if isinstance(err, aiohttp.ConnectionTimeoutError): raise TimedOut( message=( diff --git a/tests/test_aiohttp_request.py b/tests/test_aiohttp_request.py index d899e52..358c631 100644 --- a/tests/test_aiohttp_request.py +++ b/tests/test_aiohttp_request.py @@ -199,10 +199,15 @@ async def test_illegal_json_response( await aiohttp_request.shutdown() - assert len(caplog.records) == 1 - record = caplog.records[0] - assert record.name == "telegram.request.BaseRequest" - assert record.getMessage().endswith(f'invalid JSON data: "{server_response.decode()}"') + assert len(caplog.records) >= 1 + found = False + for record in caplog.records: + if record.name == "telegram.request.BaseRequest": + assert record.getMessage().endswith( + f'invalid JSON data: "{server_response.decode()}"' + ) + found = True + assert found, "Expected log message not found" async def test_chat_migrated(self, monkeypatch, aiohttp_request: AiohttpRequest): server_response = b'{"ok": "False", "parameters": {"migrate_to_chat_id": 123}}' From ca03a4dae25ec50228ed6fe4de73a2dc14d24f46 Mon Sep 17 00:00:00 2001 From: Hinrich Mahler <22366557+Bibo-Joshi@users.noreply.github.com> Date: Sun, 3 Aug 2025 11:04:01 +0200 Subject: [PATCH 4/4] try skipping aiohttp tests on python3.8 --- run_tests.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/run_tests.py b/run_tests.py index a9e69e2..a9d9a52 100644 --- a/run_tests.py +++ b/run_tests.py @@ -75,7 +75,7 @@ def run_tests(changed: bool, names: List[str]) -> int: exit_code = 0 for name in names: try: - subprocess.check_call( # nosec + result = subprocess.run( # pylint: disable=subprocess-run-check # nosec [ sys.executable, "-m", @@ -83,8 +83,20 @@ def run_tests(changed: bool, names: List[str]) -> int: "install", "-r", str(ptbcontrib_path / name / "requirements.txt"), - ] + ], + capture_output=True, + text=True, ) + if ( + result.stderr + and "No matching distribution found for python-telegram-bot" in result.stderr + ): + print( + f"Ignoring contribution {name}, as this PTB version is not " + f"supported on Python {sys.version}. " + ) + continue + result.check_returncode() result = subprocess.run( # nosec [sys.executable, "-m", "telegram"],