We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[FEATURE] Set SocketOpts
To improve the networking backend, we would like to set socketopts if possible. Before the `asyncio` switch, we did something like

https://github.com/python-telegram-bot/python-telegram-bot/blob/ad5a1fb1f6a01f5f662e9e610ddb77fb57558e44/telegram/request/_httpxrequest.py#L164-L168

It would be nice if we could do that for httpx as well at some point.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `telegram/request/_httpxrequest.py`
Content:
```
1 #!/usr/bin/env python
2 #
3 # A library that provides a Python interface to the Telegram Bot API
4 # Copyright (C) 2015-2023
5 # Leandro Toledo de Souza <devs@python-telegram-bot.org>
6 #
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Lesser Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU Lesser Public License for more details.
16 #
17 # You should have received a copy of the GNU Lesser Public License
18 # along with this program.  If not, see [http://www.gnu.org/licenses/].
19 """This module contains methods to make POST and GET requests using the httpx library."""
20 from typing import Optional, Tuple
21 
22 import httpx
23 
24 from telegram._utils.defaultvalue import DefaultValue
25 from telegram._utils.logging import get_logger
26 from telegram._utils.types import HTTPVersion, ODVInput
27 from telegram.error import NetworkError, TimedOut
28 from telegram.request._baserequest import BaseRequest
29 from telegram.request._requestdata import RequestData
30 
31 # Note to future devs:
32 # Proxies are currently only tested manually. The httpx development docs have a nice guide on that:
33 # https://www.python-httpx.org/contributing/#development-proxy-setup (also saved on archive.org)
34 # That also works with socks5. Just pass `--mode socks5` to mitmproxy
35 
36 _LOGGER = get_logger(__name__, "HTTPXRequest")
37 
38 
39 class HTTPXRequest(BaseRequest):
40     """Implementation of :class:`~telegram.request.BaseRequest` using the library
41     `httpx <https://www.python-httpx.org>`_.
42 
43     .. versionadded:: 20.0
44 
45     Args:
46         connection_pool_size (:obj:`int`, optional): Number of connections to keep in the
47             connection pool. Defaults to ``1``.
48 
49             Note:
50                 Independent of the value, one additional connection will be reserved for
51                 :meth:`telegram.Bot.get_updates`.
52         proxy_url (:obj:`str`, optional): The URL to the proxy server. For example
53             ``'http://127.0.0.1:3128'`` or ``'socks5://127.0.0.1:3128'``. Defaults to :obj:`None`.
54 
55             Note:
56                 * The proxy URL can also be set via the environment variables ``HTTPS_PROXY`` or
57                   ``ALL_PROXY``. See `the docs of httpx`_ for more info.
58                 * For Socks5 support, additional dependencies are required. Make sure to install
59                   PTB via :command:`pip install "python-telegram-bot[socks]"` in this case.
60                 * Socks5 proxies can not be set via environment variables.
61 
62             .. _the docs of httpx: https://www.python-httpx.org/environment_variables/#proxies
63         read_timeout (:obj:`float` | :obj:`None`, optional): If passed, specifies the maximum
64             amount of time (in seconds) to wait for a response from Telegram's server.
65             This value is used unless a different value is passed to :meth:`do_request`.
66             Defaults to ``5``.
67         write_timeout (:obj:`float` | :obj:`None`, optional): If passed, specifies the maximum
68             amount of time (in seconds) to wait for a write operation to complete (in terms of
69             a network socket; i.e. POSTing a request or uploading a file).
70             This value is used unless a different value is passed to :meth:`do_request`.
71             Defaults to ``5``.
72         connect_timeout (:obj:`float` | :obj:`None`, optional): If passed, specifies the
73             maximum amount of time (in seconds) to wait for a connection attempt to a server
74             to succeed. This value is used unless a different value is passed to
75             :meth:`do_request`. Defaults to ``5``.
76         pool_timeout (:obj:`float` | :obj:`None`, optional): If passed, specifies the maximum
77             amount of time (in seconds) to wait for a connection to become available.
78             This value is used unless a different value is passed to :meth:`do_request`.
79             Defaults to ``1``.
80 
81             Warning:
82                 With a finite pool timeout, you must expect :exc:`telegram.error.TimedOut`
83                 exceptions to be thrown when more requests are made simultaneously than there are
84                 connections in the connection pool!
85         http_version (:obj:`str`, optional): If ``"2"`` or ``"2.0"``, HTTP/2 will be used instead
86             of HTTP/1.1. Defaults to ``"1.1"``.
87 
88             .. versionadded:: 20.1
89             .. versionchanged:: 20.2
90                 Reset the default version to 1.1.
91 
92             .. versionchanged:: 20.5
93                 Accept ``"2"`` as a valid value.
94 
95     """
96 
97     __slots__ = ("_client", "_client_kwargs", "_http_version")
98 
99     def __init__(
100         self,
101         connection_pool_size: int = 1,
102         proxy_url: Optional[str] = None,
103         read_timeout: Optional[float] = 5.0,
104         write_timeout: Optional[float] = 5.0,
105         connect_timeout: Optional[float] = 5.0,
106         pool_timeout: Optional[float] = 1.0,
107         http_version: HTTPVersion = "1.1",
108     ):
109         self._http_version = http_version
110         timeout = httpx.Timeout(
111             connect=connect_timeout,
112             read=read_timeout,
113             write=write_timeout,
114             pool=pool_timeout,
115         )
116         limits = httpx.Limits(
117             max_connections=connection_pool_size,
118             max_keepalive_connections=connection_pool_size,
119         )
120 
121         if http_version not in ("1.1", "2", "2.0"):
122             raise ValueError("`http_version` must be either '1.1', '2.0' or '2'.")
123 
124         http1 = http_version == "1.1"
125 
126         # See https://github.com/python-telegram-bot/python-telegram-bot/pull/3542
127         # for why we need to use `dict()` here.
128         self._client_kwargs = dict(  # pylint: disable=use-dict-literal  # noqa: C408
129             timeout=timeout,
130             proxies=proxy_url,
131             limits=limits,
132             http1=http1,
133             http2=not http1,
134         )
135 
136         try:
137             self._client = self._build_client()
138         except ImportError as exc:
139             if "httpx[http2]" not in str(exc) and "httpx[socks]" not in str(exc):
140                 raise exc
141 
142             if "httpx[socks]" in str(exc):
143                 raise RuntimeError(
144                     "To use Socks5 proxies, PTB must be installed via `pip install "
145                     '"python-telegram-bot[socks]"`.'
146                 ) from exc
147             raise RuntimeError(
148                 "To use HTTP/2, PTB must be installed via `pip install "
149                 '"python-telegram-bot[http2]"`.'
150             ) from exc
151 
152     @property
153     def http_version(self) -> str:
154         """
155         :obj:`str`: Used HTTP version, see :paramref:`http_version`.
156 
157         .. versionadded:: 20.2
158         """
159         return self._http_version
160 
161     def _build_client(self) -> httpx.AsyncClient:
162         return httpx.AsyncClient(**self._client_kwargs)  # type: ignore[arg-type]
163 
164     async def initialize(self) -> None:
165         """See :meth:`BaseRequest.initialize`."""
166         if self._client.is_closed:
167             self._client = self._build_client()
168 
169     async def shutdown(self) -> None:
170         """See :meth:`BaseRequest.shutdown`."""
171         if self._client.is_closed:
172             _LOGGER.debug("This HTTPXRequest is already shut down. Returning.")
173             return
174 
175         await self._client.aclose()
176 
177     async def do_request(
178         self,
179         url: str,
180         method: str,
181         request_data: Optional[RequestData] = None,
182         read_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
183         write_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
184         connect_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
185         pool_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,
186     ) -> Tuple[int, bytes]:
187         """See :meth:`BaseRequest.do_request`."""
188         if self._client.is_closed:
189             raise RuntimeError("This HTTPXRequest is not initialized!")
190 
191         # If user did not specify timeouts (for e.g. in a bot method), use the default ones when we
192         # created this instance.
193         if isinstance(read_timeout, DefaultValue):
194             read_timeout = self._client.timeout.read
195         if isinstance(write_timeout, DefaultValue):
196             write_timeout = self._client.timeout.write
197         if isinstance(connect_timeout, DefaultValue):
198             connect_timeout = self._client.timeout.connect
199         if isinstance(pool_timeout, DefaultValue):
200             pool_timeout = self._client.timeout.pool
201 
202         timeout = httpx.Timeout(
203             connect=connect_timeout,
204             read=read_timeout,
205             write=write_timeout,
206             pool=pool_timeout,
207         )
208 
209         # TODO p0: On Linux, use setsockopt to properly set socket level keepalive.
210         #          (socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 120)
211         #          (socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 30)
212         #          (socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 8)
213         # TODO p4: Support setsockopt on lesser platforms than Linux.
214 
215         files = request_data.multipart_data if request_data else None
216         data = request_data.json_parameters if request_data else None
217 
218         try:
219             res = await self._client.request(
220                 method=method,
221                 url=url,
222                 headers={"User-Agent": self.USER_AGENT},
223                 timeout=timeout,
224                 files=files,
225                 data=data,
226             )
227         except httpx.TimeoutException as err:
228             if isinstance(err, httpx.PoolTimeout):
229                 raise TimedOut(
230                     message=(
231                         "Pool timeout: All connections in the connection pool are occupied. "
232                         "Request was *not* sent to Telegram. Consider adjusting the connection "
233                         "pool size or the pool timeout."
234                     )
235                 ) from err
236             raise TimedOut from err
237         except httpx.HTTPError as err:
238             # HTTPError must come last as its the base httpx exception class
239             # TODO p4: do something smart here; for now just raise NetworkError
240 
241             # We include the class name for easier debugging. Especially useful if the error
242             # message of `err` is empty.
243             raise NetworkError(f"httpx.{err.__class__.__name__}: {err}") from err
244 
245         return res.status_code, res.content
246
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/telegram/request/_httpxrequest.py b/telegram/request/_httpxrequest.py
--- 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 Optional, Tuple
+from typing import Collection, Optional, Tuple, Union
 
 import httpx
 
@@ -35,6 +35,12 @@
 
 _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 @@
 
             .. 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 @@
         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 @@
             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 @@
             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

{"golden_diff": "diff --git a/telegram/request/_httpxrequest.py b/telegram/request/_httpxrequest.py\n--- a/telegram/request/_httpxrequest.py\n+++ b/telegram/request/_httpxrequest.py\n@@ -17,7 +17,7 @@\n # You should have received a copy of the GNU Lesser Public License\n # along with this program.  If not, see [http://www.gnu.org/licenses/].\n \"\"\"This module contains methods to make POST and GET requests using the httpx library.\"\"\"\n-from typing import Optional, Tuple\n+from typing import Collection, Optional, Tuple, Union\n \n import httpx\n \n@@ -35,6 +35,12 @@\n \n _LOGGER = get_logger(__name__, \"HTTPXRequest\")\n \n+_SocketOpt = Union[\n+    Tuple[int, int, int],\n+    Tuple[int, int, Union[bytes, bytearray]],\n+    Tuple[int, int, None, int],\n+]\n+\n \n class HTTPXRequest(BaseRequest):\n     \"\"\"Implementation of :class:`~telegram.request.BaseRequest` using the library\n@@ -91,6 +97,16 @@\n \n             .. versionchanged:: 20.5\n                 Accept ``\"2\"`` as a valid value.\n+        socket_options (Collection[:obj:`tuple`], optional): Socket options to be passed to the\n+            underlying `library \\\n+            <https://www.encode.io/httpcore/async/#httpcore.AsyncConnectionPool.__init__>`_.\n+\n+            Note:\n+                The values accepted by this parameter depend on the operating system.\n+                This is a low-level parameter and should only be used if you are familiar with\n+                these concepts.\n+\n+            .. versionadded:: NEXT.VERSION\n \n     \"\"\"\n \n@@ -105,6 +121,7 @@\n         connect_timeout: Optional[float] = 5.0,\n         pool_timeout: Optional[float] = 1.0,\n         http_version: HTTPVersion = \"1.1\",\n+        socket_options: Optional[Collection[_SocketOpt]] = None,\n     ):\n         self._http_version = http_version\n         timeout = httpx.Timeout(\n@@ -122,16 +139,21 @@\n             raise ValueError(\"`http_version` must be either '1.1', '2.0' or '2'.\")\n \n         http1 = http_version == \"1.1\"\n-\n-        # See https://github.com/python-telegram-bot/python-telegram-bot/pull/3542\n-        # for why we need to use `dict()` here.\n-        self._client_kwargs = dict(  # pylint: disable=use-dict-literal  # noqa: C408\n-            timeout=timeout,\n-            proxies=proxy_url,\n-            limits=limits,\n-            http1=http1,\n-            http2=not http1,\n+        http_kwargs = {\"http1\": http1, \"http2\": not http1}\n+        transport = (\n+            httpx.AsyncHTTPTransport(\n+                socket_options=socket_options,\n+            )\n+            if socket_options\n+            else None\n         )\n+        self._client_kwargs = {\n+            \"timeout\": timeout,\n+            \"proxies\": proxy_url,\n+            \"limits\": limits,\n+            \"transport\": transport,\n+            **http_kwargs,\n+        }\n \n         try:\n             self._client = self._build_client()\n@@ -206,12 +228,6 @@\n             pool=pool_timeout,\n         )\n \n-        # TODO p0: On Linux, use setsockopt to properly set socket level keepalive.\n-        #          (socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 120)\n-        #          (socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 30)\n-        #          (socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 8)\n-        # TODO p4: Support setsockopt on lesser platforms than Linux.\n-\n         files = request_data.multipart_data if request_data else None\n         data = request_data.json_parameters if request_data else None\n", "issue": "[FEATURE] Set SocketOpts\nTo improve the networking backend, we would like to set socketopts if possible. Before the `asyncio` switch, we did something like\r\n\r\nhttps://github.com/python-telegram-bot/python-telegram-bot/blob/ad5a1fb1f6a01f5f662e9e610ddb77fb57558e44/telegram/request/_httpxrequest.py#L164-L168\r\n\r\nIt would be nice if we could do that for httpx as well at some point.\n", "before_files": [{"content": "#!/usr/bin/env python\n#\n# A library that provides a Python interface to the Telegram Bot API\n# Copyright (C) 2015-2023\n# Leandro Toledo de Souza <devs@python-telegram-bot.org>\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser Public License for more details.\n#\n# You should have received a copy of the GNU Lesser Public License\n# along with this program.  If not, see [http://www.gnu.org/licenses/].\n\"\"\"This module contains methods to make POST and GET requests using the httpx library.\"\"\"\nfrom typing import Optional, Tuple\n\nimport httpx\n\nfrom telegram._utils.defaultvalue import DefaultValue\nfrom telegram._utils.logging import get_logger\nfrom telegram._utils.types import HTTPVersion, ODVInput\nfrom telegram.error import NetworkError, TimedOut\nfrom telegram.request._baserequest import BaseRequest\nfrom telegram.request._requestdata import RequestData\n\n# Note to future devs:\n# Proxies are currently only tested manually. The httpx development docs have a nice guide on that:\n# https://www.python-httpx.org/contributing/#development-proxy-setup (also saved on archive.org)\n# That also works with socks5. Just pass `--mode socks5` to mitmproxy\n\n_LOGGER = get_logger(__name__, \"HTTPXRequest\")\n\n\nclass HTTPXRequest(BaseRequest):\n    \"\"\"Implementation of :class:`~telegram.request.BaseRequest` using the library\n    `httpx <https://www.python-httpx.org>`_.\n\n    .. versionadded:: 20.0\n\n    Args:\n        connection_pool_size (:obj:`int`, optional): Number of connections to keep in the\n            connection pool. Defaults to ``1``.\n\n            Note:\n                Independent of the value, one additional connection will be reserved for\n                :meth:`telegram.Bot.get_updates`.\n        proxy_url (:obj:`str`, optional): The URL to the proxy server. For example\n            ``'http://127.0.0.1:3128'`` or ``'socks5://127.0.0.1:3128'``. Defaults to :obj:`None`.\n\n            Note:\n                * The proxy URL can also be set via the environment variables ``HTTPS_PROXY`` or\n                  ``ALL_PROXY``. See `the docs of httpx`_ for more info.\n                * For Socks5 support, additional dependencies are required. Make sure to install\n                  PTB via :command:`pip install \"python-telegram-bot[socks]\"` in this case.\n                * Socks5 proxies can not be set via environment variables.\n\n            .. _the docs of httpx: https://www.python-httpx.org/environment_variables/#proxies\n        read_timeout (:obj:`float` | :obj:`None`, optional): If passed, specifies the maximum\n            amount of time (in seconds) to wait for a response from Telegram's server.\n            This value is used unless a different value is passed to :meth:`do_request`.\n            Defaults to ``5``.\n        write_timeout (:obj:`float` | :obj:`None`, optional): If passed, specifies the maximum\n            amount of time (in seconds) to wait for a write operation to complete (in terms of\n            a network socket; i.e. POSTing a request or uploading a file).\n            This value is used unless a different value is passed to :meth:`do_request`.\n            Defaults to ``5``.\n        connect_timeout (:obj:`float` | :obj:`None`, optional): If passed, specifies the\n            maximum amount of time (in seconds) to wait for a connection attempt to a server\n            to succeed. This value is used unless a different value is passed to\n            :meth:`do_request`. Defaults to ``5``.\n        pool_timeout (:obj:`float` | :obj:`None`, optional): If passed, specifies the maximum\n            amount of time (in seconds) to wait for a connection to become available.\n            This value is used unless a different value is passed to :meth:`do_request`.\n            Defaults to ``1``.\n\n            Warning:\n                With a finite pool timeout, you must expect :exc:`telegram.error.TimedOut`\n                exceptions to be thrown when more requests are made simultaneously than there are\n                connections in the connection pool!\n        http_version (:obj:`str`, optional): If ``\"2\"`` or ``\"2.0\"``, HTTP/2 will be used instead\n            of HTTP/1.1. Defaults to ``\"1.1\"``.\n\n            .. versionadded:: 20.1\n            .. versionchanged:: 20.2\n                Reset the default version to 1.1.\n\n            .. versionchanged:: 20.5\n                Accept ``\"2\"`` as a valid value.\n\n    \"\"\"\n\n    __slots__ = (\"_client\", \"_client_kwargs\", \"_http_version\")\n\n    def __init__(\n        self,\n        connection_pool_size: int = 1,\n        proxy_url: Optional[str] = None,\n        read_timeout: Optional[float] = 5.0,\n        write_timeout: Optional[float] = 5.0,\n        connect_timeout: Optional[float] = 5.0,\n        pool_timeout: Optional[float] = 1.0,\n        http_version: HTTPVersion = \"1.1\",\n    ):\n        self._http_version = http_version\n        timeout = httpx.Timeout(\n            connect=connect_timeout,\n            read=read_timeout,\n            write=write_timeout,\n            pool=pool_timeout,\n        )\n        limits = httpx.Limits(\n            max_connections=connection_pool_size,\n            max_keepalive_connections=connection_pool_size,\n        )\n\n        if http_version not in (\"1.1\", \"2\", \"2.0\"):\n            raise ValueError(\"`http_version` must be either '1.1', '2.0' or '2'.\")\n\n        http1 = http_version == \"1.1\"\n\n        # See https://github.com/python-telegram-bot/python-telegram-bot/pull/3542\n        # for why we need to use `dict()` here.\n        self._client_kwargs = dict(  # pylint: disable=use-dict-literal  # noqa: C408\n            timeout=timeout,\n            proxies=proxy_url,\n            limits=limits,\n            http1=http1,\n            http2=not http1,\n        )\n\n        try:\n            self._client = self._build_client()\n        except ImportError as exc:\n            if \"httpx[http2]\" not in str(exc) and \"httpx[socks]\" not in str(exc):\n                raise exc\n\n            if \"httpx[socks]\" in str(exc):\n                raise RuntimeError(\n                    \"To use Socks5 proxies, PTB must be installed via `pip install \"\n                    '\"python-telegram-bot[socks]\"`.'\n                ) from exc\n            raise RuntimeError(\n                \"To use HTTP/2, PTB must be installed via `pip install \"\n                '\"python-telegram-bot[http2]\"`.'\n            ) from exc\n\n    @property\n    def http_version(self) -> str:\n        \"\"\"\n        :obj:`str`: Used HTTP version, see :paramref:`http_version`.\n\n        .. versionadded:: 20.2\n        \"\"\"\n        return self._http_version\n\n    def _build_client(self) -> httpx.AsyncClient:\n        return httpx.AsyncClient(**self._client_kwargs)  # type: ignore[arg-type]\n\n    async def initialize(self) -> None:\n        \"\"\"See :meth:`BaseRequest.initialize`.\"\"\"\n        if self._client.is_closed:\n            self._client = self._build_client()\n\n    async def shutdown(self) -> None:\n        \"\"\"See :meth:`BaseRequest.shutdown`.\"\"\"\n        if self._client.is_closed:\n            _LOGGER.debug(\"This HTTPXRequest is already shut down. Returning.\")\n            return\n\n        await self._client.aclose()\n\n    async def do_request(\n        self,\n        url: str,\n        method: str,\n        request_data: Optional[RequestData] = None,\n        read_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,\n        write_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,\n        connect_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,\n        pool_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,\n    ) -> Tuple[int, bytes]:\n        \"\"\"See :meth:`BaseRequest.do_request`.\"\"\"\n        if self._client.is_closed:\n            raise RuntimeError(\"This HTTPXRequest is not initialized!\")\n\n        # If user did not specify timeouts (for e.g. in a bot method), use the default ones when we\n        # created this instance.\n        if isinstance(read_timeout, DefaultValue):\n            read_timeout = self._client.timeout.read\n        if isinstance(write_timeout, DefaultValue):\n            write_timeout = self._client.timeout.write\n        if isinstance(connect_timeout, DefaultValue):\n            connect_timeout = self._client.timeout.connect\n        if isinstance(pool_timeout, DefaultValue):\n            pool_timeout = self._client.timeout.pool\n\n        timeout = httpx.Timeout(\n            connect=connect_timeout,\n            read=read_timeout,\n            write=write_timeout,\n            pool=pool_timeout,\n        )\n\n        # TODO p0: On Linux, use setsockopt to properly set socket level keepalive.\n        #          (socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 120)\n        #          (socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 30)\n        #          (socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 8)\n        # TODO p4: Support setsockopt on lesser platforms than Linux.\n\n        files = request_data.multipart_data if request_data else None\n        data = request_data.json_parameters if request_data else None\n\n        try:\n            res = await self._client.request(\n                method=method,\n                url=url,\n                headers={\"User-Agent\": self.USER_AGENT},\n                timeout=timeout,\n                files=files,\n                data=data,\n            )\n        except httpx.TimeoutException as err:\n            if isinstance(err, httpx.PoolTimeout):\n                raise TimedOut(\n                    message=(\n                        \"Pool timeout: All connections in the connection pool are occupied. \"\n                        \"Request was *not* sent to Telegram. Consider adjusting the connection \"\n                        \"pool size or the pool timeout.\"\n                    )\n                ) from err\n            raise TimedOut from err\n        except httpx.HTTPError as err:\n            # HTTPError must come last as its the base httpx exception class\n            # TODO p4: do something smart here; for now just raise NetworkError\n\n            # We include the class name for easier debugging. Especially useful if the error\n            # message of `err` is empty.\n            raise NetworkError(f\"httpx.{err.__class__.__name__}: {err}\") from err\n\n        return res.status_code, res.content\n", "path": "telegram/request/_httpxrequest.py"}], "after_files": [{"content": "#!/usr/bin/env python\n#\n# A library that provides a Python interface to the Telegram Bot API\n# Copyright (C) 2015-2023\n# Leandro Toledo de Souza <devs@python-telegram-bot.org>\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser Public License for more details.\n#\n# You should have received a copy of the GNU Lesser Public License\n# along with this program.  If not, see [http://www.gnu.org/licenses/].\n\"\"\"This module contains methods to make POST and GET requests using the httpx library.\"\"\"\nfrom typing import Collection, Optional, Tuple, Union\n\nimport httpx\n\nfrom telegram._utils.defaultvalue import DefaultValue\nfrom telegram._utils.logging import get_logger\nfrom telegram._utils.types import HTTPVersion, ODVInput\nfrom telegram.error import NetworkError, TimedOut\nfrom telegram.request._baserequest import BaseRequest\nfrom telegram.request._requestdata import RequestData\n\n# Note to future devs:\n# Proxies are currently only tested manually. The httpx development docs have a nice guide on that:\n# https://www.python-httpx.org/contributing/#development-proxy-setup (also saved on archive.org)\n# That also works with socks5. Just pass `--mode socks5` to mitmproxy\n\n_LOGGER = get_logger(__name__, \"HTTPXRequest\")\n\n_SocketOpt = Union[\n    Tuple[int, int, int],\n    Tuple[int, int, Union[bytes, bytearray]],\n    Tuple[int, int, None, int],\n]\n\n\nclass HTTPXRequest(BaseRequest):\n    \"\"\"Implementation of :class:`~telegram.request.BaseRequest` using the library\n    `httpx <https://www.python-httpx.org>`_.\n\n    .. versionadded:: 20.0\n\n    Args:\n        connection_pool_size (:obj:`int`, optional): Number of connections to keep in the\n            connection pool. Defaults to ``1``.\n\n            Note:\n                Independent of the value, one additional connection will be reserved for\n                :meth:`telegram.Bot.get_updates`.\n        proxy_url (:obj:`str`, optional): The URL to the proxy server. For example\n            ``'http://127.0.0.1:3128'`` or ``'socks5://127.0.0.1:3128'``. Defaults to :obj:`None`.\n\n            Note:\n                * The proxy URL can also be set via the environment variables ``HTTPS_PROXY`` or\n                  ``ALL_PROXY``. See `the docs of httpx`_ for more info.\n                * For Socks5 support, additional dependencies are required. Make sure to install\n                  PTB via :command:`pip install \"python-telegram-bot[socks]\"` in this case.\n                * Socks5 proxies can not be set via environment variables.\n\n            .. _the docs of httpx: https://www.python-httpx.org/environment_variables/#proxies\n        read_timeout (:obj:`float` | :obj:`None`, optional): If passed, specifies the maximum\n            amount of time (in seconds) to wait for a response from Telegram's server.\n            This value is used unless a different value is passed to :meth:`do_request`.\n            Defaults to ``5``.\n        write_timeout (:obj:`float` | :obj:`None`, optional): If passed, specifies the maximum\n            amount of time (in seconds) to wait for a write operation to complete (in terms of\n            a network socket; i.e. POSTing a request or uploading a file).\n            This value is used unless a different value is passed to :meth:`do_request`.\n            Defaults to ``5``.\n        connect_timeout (:obj:`float` | :obj:`None`, optional): If passed, specifies the\n            maximum amount of time (in seconds) to wait for a connection attempt to a server\n            to succeed. This value is used unless a different value is passed to\n            :meth:`do_request`. Defaults to ``5``.\n        pool_timeout (:obj:`float` | :obj:`None`, optional): If passed, specifies the maximum\n            amount of time (in seconds) to wait for a connection to become available.\n            This value is used unless a different value is passed to :meth:`do_request`.\n            Defaults to ``1``.\n\n            Warning:\n                With a finite pool timeout, you must expect :exc:`telegram.error.TimedOut`\n                exceptions to be thrown when more requests are made simultaneously than there are\n                connections in the connection pool!\n        http_version (:obj:`str`, optional): If ``\"2\"`` or ``\"2.0\"``, HTTP/2 will be used instead\n            of HTTP/1.1. Defaults to ``\"1.1\"``.\n\n            .. versionadded:: 20.1\n            .. versionchanged:: 20.2\n                Reset the default version to 1.1.\n\n            .. versionchanged:: 20.5\n                Accept ``\"2\"`` as a valid value.\n        socket_options (Collection[:obj:`tuple`], optional): Socket options to be passed to the\n            underlying `library \\\n            <https://www.encode.io/httpcore/async/#httpcore.AsyncConnectionPool.__init__>`_.\n\n            Note:\n                The values accepted by this parameter depend on the operating system.\n                This is a low-level parameter and should only be used if you are familiar with\n                these concepts.\n\n            .. versionadded:: NEXT.VERSION\n\n    \"\"\"\n\n    __slots__ = (\"_client\", \"_client_kwargs\", \"_http_version\")\n\n    def __init__(\n        self,\n        connection_pool_size: int = 1,\n        proxy_url: Optional[str] = None,\n        read_timeout: Optional[float] = 5.0,\n        write_timeout: Optional[float] = 5.0,\n        connect_timeout: Optional[float] = 5.0,\n        pool_timeout: Optional[float] = 1.0,\n        http_version: HTTPVersion = \"1.1\",\n        socket_options: Optional[Collection[_SocketOpt]] = None,\n    ):\n        self._http_version = http_version\n        timeout = httpx.Timeout(\n            connect=connect_timeout,\n            read=read_timeout,\n            write=write_timeout,\n            pool=pool_timeout,\n        )\n        limits = httpx.Limits(\n            max_connections=connection_pool_size,\n            max_keepalive_connections=connection_pool_size,\n        )\n\n        if http_version not in (\"1.1\", \"2\", \"2.0\"):\n            raise ValueError(\"`http_version` must be either '1.1', '2.0' or '2'.\")\n\n        http1 = http_version == \"1.1\"\n        http_kwargs = {\"http1\": http1, \"http2\": not http1}\n        transport = (\n            httpx.AsyncHTTPTransport(\n                socket_options=socket_options,\n            )\n            if socket_options\n            else None\n        )\n        self._client_kwargs = {\n            \"timeout\": timeout,\n            \"proxies\": proxy_url,\n            \"limits\": limits,\n            \"transport\": transport,\n            **http_kwargs,\n        }\n\n        try:\n            self._client = self._build_client()\n        except ImportError as exc:\n            if \"httpx[http2]\" not in str(exc) and \"httpx[socks]\" not in str(exc):\n                raise exc\n\n            if \"httpx[socks]\" in str(exc):\n                raise RuntimeError(\n                    \"To use Socks5 proxies, PTB must be installed via `pip install \"\n                    '\"python-telegram-bot[socks]\"`.'\n                ) from exc\n            raise RuntimeError(\n                \"To use HTTP/2, PTB must be installed via `pip install \"\n                '\"python-telegram-bot[http2]\"`.'\n            ) from exc\n\n    @property\n    def http_version(self) -> str:\n        \"\"\"\n        :obj:`str`: Used HTTP version, see :paramref:`http_version`.\n\n        .. versionadded:: 20.2\n        \"\"\"\n        return self._http_version\n\n    def _build_client(self) -> httpx.AsyncClient:\n        return httpx.AsyncClient(**self._client_kwargs)  # type: ignore[arg-type]\n\n    async def initialize(self) -> None:\n        \"\"\"See :meth:`BaseRequest.initialize`.\"\"\"\n        if self._client.is_closed:\n            self._client = self._build_client()\n\n    async def shutdown(self) -> None:\n        \"\"\"See :meth:`BaseRequest.shutdown`.\"\"\"\n        if self._client.is_closed:\n            _LOGGER.debug(\"This HTTPXRequest is already shut down. Returning.\")\n            return\n\n        await self._client.aclose()\n\n    async def do_request(\n        self,\n        url: str,\n        method: str,\n        request_data: Optional[RequestData] = None,\n        read_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,\n        write_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,\n        connect_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,\n        pool_timeout: ODVInput[float] = BaseRequest.DEFAULT_NONE,\n    ) -> Tuple[int, bytes]:\n        \"\"\"See :meth:`BaseRequest.do_request`.\"\"\"\n        if self._client.is_closed:\n            raise RuntimeError(\"This HTTPXRequest is not initialized!\")\n\n        # If user did not specify timeouts (for e.g. in a bot method), use the default ones when we\n        # created this instance.\n        if isinstance(read_timeout, DefaultValue):\n            read_timeout = self._client.timeout.read\n        if isinstance(write_timeout, DefaultValue):\n            write_timeout = self._client.timeout.write\n        if isinstance(connect_timeout, DefaultValue):\n            connect_timeout = self._client.timeout.connect\n        if isinstance(pool_timeout, DefaultValue):\n            pool_timeout = self._client.timeout.pool\n\n        timeout = httpx.Timeout(\n            connect=connect_timeout,\n            read=read_timeout,\n            write=write_timeout,\n            pool=pool_timeout,\n        )\n\n        files = request_data.multipart_data if request_data else None\n        data = request_data.json_parameters if request_data else None\n\n        try:\n            res = await self._client.request(\n                method=method,\n                url=url,\n                headers={\"User-Agent\": self.USER_AGENT},\n                timeout=timeout,\n                files=files,\n                data=data,\n            )\n        except httpx.TimeoutException as err:\n            if isinstance(err, httpx.PoolTimeout):\n                raise TimedOut(\n                    message=(\n                        \"Pool timeout: All connections in the connection pool are occupied. \"\n                        \"Request was *not* sent to Telegram. Consider adjusting the connection \"\n                        \"pool size or the pool timeout.\"\n                    )\n                ) from err\n            raise TimedOut from err\n        except httpx.HTTPError as err:\n            # HTTPError must come last as its the base httpx exception class\n            # TODO p4: do something smart here; for now just raise NetworkError\n\n            # We include the class name for easier debugging. Especially useful if the error\n            # message of `err` is empty.\n            raise NetworkError(f\"httpx.{err.__class__.__name__}: {err}\") from err\n\n        return res.status_code, res.content\n", "path": "telegram/request/_httpxrequest.py"}]}