Add Parameter socket_options to HTTPXRequest (#3935)

This commit is contained in:
Bibo-Joshi 2023-10-22 12:42:22 +02:00 committed by GitHub
parent f67e8c0804
commit ea7e5a69aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 19 deletions

View file

@ -28,7 +28,7 @@ repos:
- --jobs=0
additional_dependencies:
- httpx~=0.24.1
- httpx~=0.25.0
- tornado~=6.3.3
- APScheduler~=3.10.4
- cachetools~=5.3.1
@ -44,7 +44,7 @@ repos:
- types-pytz
- types-cryptography
- types-cachetools
- httpx~=0.24.1
- httpx~=0.25.0
- tornado~=6.3.3
- APScheduler~=3.10.4
- cachetools~=5.3.1
@ -83,7 +83,7 @@ repos:
name: ruff
files: ^(telegram|examples|tests)/.*\.py$
additional_dependencies:
- httpx~=0.24.1
- httpx~=0.25.0
- tornado~=6.3.3
- APScheduler~=3.10.4
- cachetools~=5.3.1

View file

@ -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 Optional, Tuple
from typing import Collection, Optional, Tuple, Union
import httpx
@ -35,6 +35,12 @@ from telegram.request._requestdata import RequestData
_LOGGER = get_logger(__name__, "HTTPXRequest")
_SocketOpt = Union[
Tuple[int, int, int],
Tuple[int, int, Union[bytes, bytearray]],
Tuple[int, int, None, int],
]
class HTTPXRequest(BaseRequest):
"""Implementation of :class:`~telegram.request.BaseRequest` using the library
@ -91,6 +97,16 @@ class HTTPXRequest(BaseRequest):
.. versionchanged:: 20.5
Accept ``"2"`` as a valid value.
socket_options (Collection[:obj:`tuple`], optional): Socket options to be passed to the
underlying `library \
<https://www.encode.io/httpcore/async/#httpcore.AsyncConnectionPool.__init__>`_.
Note:
The values accepted by this parameter depend on the operating system.
This is a low-level parameter and should only be used if you are familiar with
these concepts.
.. versionadded:: NEXT.VERSION
"""
@ -105,6 +121,7 @@ class HTTPXRequest(BaseRequest):
connect_timeout: Optional[float] = 5.0,
pool_timeout: Optional[float] = 1.0,
http_version: HTTPVersion = "1.1",
socket_options: Optional[Collection[_SocketOpt]] = None,
):
self._http_version = http_version
timeout = httpx.Timeout(
@ -122,16 +139,21 @@ class HTTPXRequest(BaseRequest):
raise ValueError("`http_version` must be either '1.1', '2.0' or '2'.")
http1 = http_version == "1.1"
# See https://github.com/python-telegram-bot/python-telegram-bot/pull/3542
# for why we need to use `dict()` here.
self._client_kwargs = dict( # pylint: disable=use-dict-literal # noqa: C408
timeout=timeout,
proxies=proxy_url,
limits=limits,
http1=http1,
http2=not http1,
http_kwargs = {"http1": http1, "http2": not http1}
transport = (
httpx.AsyncHTTPTransport(
socket_options=socket_options,
)
if socket_options
else None
)
self._client_kwargs = {
"timeout": timeout,
"proxies": proxy_url,
"limits": limits,
"transport": transport,
**http_kwargs,
}
try:
self._client = self._build_client()
@ -206,12 +228,6 @@ class HTTPXRequest(BaseRequest):
pool=pool_timeout,
)
# TODO p0: On Linux, use setsockopt to properly set socket level keepalive.
# (socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 120)
# (socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 30)
# (socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 8)
# TODO p4: Support setsockopt on lesser platforms than Linux.
files = request_data.multipart_data if request_data else None
data = request_data.json_parameters if request_data else None

View file

@ -91,6 +91,7 @@ class TestApplicationBuilder:
limits: object
http1: object
http2: object
transport: object = None
monkeypatch.setattr(httpx, "AsyncClient", Client)
@ -322,6 +323,7 @@ class TestApplicationBuilder:
limits: object
http1: object
http2: object
transport: object = None
monkeypatch.setattr(httpx, "AsyncClient", Client)

View file

@ -28,6 +28,7 @@ from typing import Any, Callable, Coroutine, Tuple
import httpx
import pytest
from httpx import AsyncHTTPTransport
from telegram._utils.defaultvalue import DEFAULT_NONE
from telegram.error import (
@ -366,6 +367,7 @@ class TestHTTPXRequestWithoutRequest:
limits: object
http1: object
http2: object
transport: object = None
monkeypatch.setattr(httpx, "AsyncClient", Client)
@ -618,6 +620,24 @@ class TestHTTPXRequestWithoutRequest:
assert exc_info.value.__cause__ is pool_timeout
async def test_socket_opts(self, monkeypatch):
transport_kwargs = {}
transport_init = AsyncHTTPTransport.__init__
def init_transport(*args, **kwargs):
nonlocal transport_kwargs
transport_kwargs = kwargs.copy()
transport_init(*args, **kwargs)
monkeypatch.setattr(AsyncHTTPTransport, "__init__", init_transport)
HTTPXRequest()
assert "socket_options" not in transport_kwargs
transport_kwargs = {}
HTTPXRequest(socket_options=((1, 2, 3),))
assert transport_kwargs["socket_options"] == ((1, 2, 3),)
@pytest.mark.skipif(not TEST_WITH_OPT_DEPS, reason="No need to run this twice")
class TestHTTPXRequestWithRequest: