From 1223e851c36809055b27edd9ccf00ce29d2a65c4 Mon Sep 17 00:00:00 2001 From: Bibo-Joshi <22366557+Bibo-Joshi@users.noreply.github.com> Date: Wed, 11 Sep 2024 22:34:18 +0200 Subject: [PATCH] Add Parameter `httpx_kwargs` to `HTTPXRequest` (#4451) --- telegram/request/_httpxrequest.py | 20 ++++++++++++++++-- tests/ext/test_applicationbuilder.py | 2 +- tests/request/test_request.py | 31 ++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/telegram/request/_httpxrequest.py b/telegram/request/_httpxrequest.py index 3dc6cf05f..d74ed00d8 100644 --- a/telegram/request/_httpxrequest.py +++ b/telegram/request/_httpxrequest.py @@ -17,7 +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/]. """This module contains methods to make POST and GET requests using the httpx library.""" -from typing import Collection, Optional, Tuple, Union +from typing import Any, Collection, Dict, Optional, Tuple, Union import httpx @@ -122,6 +122,20 @@ class HTTPXRequest(BaseRequest): :meth:`do_request`. Defaults to ``20`` seconds. .. versionadded:: 21.0 + httpx_kwargs (Dict[:obj:`str`, Any], optional): Additional keyword arguments to be passed + to the `httpx.AsyncClient `_ + constructor. + + Warning: + This parameter is intended for advanced users that want to fine-tune the behavior + of the underlying ``httpx`` client. The values passed here will override all the + defaults set by ``python-telegram-bot`` and all other parameters passed to + :class:`HTTPXRequest`. The only exception is the :paramref:`media_write_timeout` + parameter, which is not passed to the client constructor. + No runtime warnings will be issued about parameters that are overridden in this + way. + + .. versionadded:: NEXT.VERSION """ @@ -139,6 +153,7 @@ class HTTPXRequest(BaseRequest): socket_options: Optional[Collection[SocketOpt]] = None, proxy: Optional[Union[str, httpx.Proxy, httpx.URL]] = None, media_write_timeout: Optional[float] = 20.0, + httpx_kwargs: Optional[Dict[str, Any]] = None, ): if proxy_url is not None and proxy is not None: raise ValueError("The parameters `proxy_url` and `proxy` are mutually exclusive.") @@ -183,6 +198,7 @@ class HTTPXRequest(BaseRequest): "limits": limits, "transport": transport, **http_kwargs, + **(httpx_kwargs or {}), } try: @@ -221,7 +237,7 @@ class HTTPXRequest(BaseRequest): return self._client.timeout.read def _build_client(self) -> httpx.AsyncClient: - return httpx.AsyncClient(**self._client_kwargs) # type: ignore[arg-type] + return httpx.AsyncClient(**self._client_kwargs) async def initialize(self) -> None: """See :meth:`BaseRequest.initialize`.""" diff --git a/tests/ext/test_applicationbuilder.py b/tests/ext/test_applicationbuilder.py index 189164d1b..235a80f68 100644 --- a/tests/ext/test_applicationbuilder.py +++ b/tests/ext/test_applicationbuilder.py @@ -74,7 +74,7 @@ class TestApplicationBuilder: arguments = inspect.signature(HTTPXRequest.__init__).parameters.keys() prefix = "get_updates_" if get_updates else "" for argument in arguments: - if argument == "self": + if argument in ("self", "httpx_kwargs"): continue if argument == "media_write_timeout" and get_updates: # get_updates never makes media requests diff --git a/tests/request/test_request.py b/tests/request/test_request.py index 6adcdf7c0..2bbfcf52d 100644 --- a/tests/request/test_request.py +++ b/tests/request/test_request.py @@ -134,6 +134,37 @@ class TestRequestWithoutRequest: assert getattr(inst, at, "err") != "err", f"got extra slot '{at}'" assert len(mro_slots(inst)) == len(set(mro_slots(inst))), "duplicate slot" + def test_httpx_kwargs(self, monkeypatch): + self.test_flag = {} + + orig_init = httpx.AsyncClient.__init__ + + class Client(httpx.AsyncClient): + def __init__(*args, **kwargs): + orig_init(*args, **kwargs) + self.test_flag["args"] = args + self.test_flag["kwargs"] = kwargs + + monkeypatch.setattr(httpx, "AsyncClient", Client) + + HTTPXRequest( + connect_timeout=1, + connection_pool_size=42, + http_version="2", + httpx_kwargs={ + "timeout": httpx.Timeout(7), + "limits": httpx.Limits(max_connections=7), + "http1": True, + "verify": False, + }, + ) + kwargs = self.test_flag["kwargs"] + + assert kwargs["timeout"].connect == 7 + assert kwargs["limits"].max_connections == 7 + assert kwargs["http1"] is True + assert kwargs["verify"] is False + async def test_context_manager(self, monkeypatch): async def initialize(): self.test_flag = ["initialize"]