Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 76 additions & 22 deletions telegram/ext/_applicationbuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,12 @@
Union,
)

import httpx

from telegram._bot import Bot
from telegram._utils.defaultvalue import DEFAULT_FALSE, DEFAULT_NONE, DefaultValue
from telegram._utils.types import DVInput, DVType, FilePathInput, HTTPVersion, ODVInput
from telegram._utils.warnings import warn
from telegram.ext._application import Application
from telegram.ext._baseupdateprocessor import BaseUpdateProcessor, SimpleUpdateProcessor
from telegram.ext._contexttypes import ContextTypes
Expand All @@ -44,6 +47,7 @@
from telegram.ext._utils.types import BD, BT, CCT, CD, JQ, UD
from telegram.request import BaseRequest
from telegram.request._httpxrequest import HTTPXRequest
from telegram.warnings import PTBDeprecationWarning

if TYPE_CHECKING:
from telegram.ext import BasePersistence, BaseRateLimiter, CallbackContext, Defaults
Expand All @@ -66,14 +70,14 @@
("request", "request instance"),
("get_updates_request", "get_updates_request instance"),
("connection_pool_size", "connection_pool_size"),
("proxy_url", "proxy_url"),
("proxy", "proxy"),
("pool_timeout", "pool_timeout"),
("connect_timeout", "connect_timeout"),
("read_timeout", "read_timeout"),
("write_timeout", "write_timeout"),
("http_version", "http_version"),
("get_updates_connection_pool_size", "get_updates_connection_pool_size"),
("get_updates_proxy_url", "get_updates_proxy_url"),
("get_updates_proxy", "get_updates_proxy"),
("get_updates_pool_timeout", "get_updates_pool_timeout"),
("get_updates_connect_timeout", "get_updates_connect_timeout"),
("get_updates_read_timeout", "get_updates_read_timeout"),
Expand Down Expand Up @@ -136,7 +140,7 @@ class ApplicationBuilder(Generic[BT, CCT, UD, CD, BD, JQ]):
"_get_updates_connect_timeout",
"_get_updates_connection_pool_size",
"_get_updates_pool_timeout",
"_get_updates_proxy_url",
"_get_updates_proxy",
"_get_updates_read_timeout",
"_get_updates_request",
"_get_updates_write_timeout",
Expand All @@ -149,7 +153,7 @@ class ApplicationBuilder(Generic[BT, CCT, UD, CD, BD, JQ]):
"_post_stop",
"_private_key",
"_private_key_password",
"_proxy_url",
"_proxy",
"_rate_limiter",
"_read_timeout",
"_request",
Expand All @@ -166,14 +170,14 @@ def __init__(self: "InitApplicationBuilder"):
self._base_url: DVType[str] = DefaultValue("https://api.telegram.org/bot")
self._base_file_url: DVType[str] = DefaultValue("https://api.telegram.org/file/bot")
self._connection_pool_size: DVInput[int] = DEFAULT_NONE
self._proxy_url: DVInput[str] = DEFAULT_NONE
self._proxy: DVInput[Union[str, httpx.Proxy, httpx.URL]] = DEFAULT_NONE
self._connect_timeout: ODVInput[float] = DEFAULT_NONE
self._read_timeout: ODVInput[float] = DEFAULT_NONE
self._write_timeout: ODVInput[float] = DEFAULT_NONE
self._pool_timeout: ODVInput[float] = DEFAULT_NONE
self._request: DVInput[BaseRequest] = DEFAULT_NONE
self._get_updates_connection_pool_size: DVInput[int] = DEFAULT_NONE
self._get_updates_proxy_url: DVInput[str] = DEFAULT_NONE
self._get_updates_proxy: DVInput[Union[str, httpx.Proxy, httpx.URL]] = DEFAULT_NONE
self._get_updates_connect_timeout: ODVInput[float] = DEFAULT_NONE
self._get_updates_read_timeout: ODVInput[float] = DEFAULT_NONE
self._get_updates_write_timeout: ODVInput[float] = DEFAULT_NONE
Expand Down Expand Up @@ -214,7 +218,7 @@ def _build_request(self, get_updates: bool) -> BaseRequest:
if not isinstance(getattr(self, f"{prefix}request"), DefaultValue):
return getattr(self, f"{prefix}request")

proxy_url = DefaultValue.get_value(getattr(self, f"{prefix}proxy_url"))
proxy = DefaultValue.get_value(getattr(self, f"{prefix}proxy"))
if get_updates:
connection_pool_size = (
DefaultValue.get_value(getattr(self, f"{prefix}connection_pool_size")) or 1
Expand All @@ -239,7 +243,7 @@ def _build_request(self, get_updates: bool) -> BaseRequest:

return HTTPXRequest(
connection_pool_size=connection_pool_size,
proxy_url=proxy_url,
proxy=proxy,
http_version=http_version, # type: ignore[arg-type]
**effective_timeouts,
)
Expand Down Expand Up @@ -419,8 +423,8 @@ def _request_check(self, get_updates: bool) -> None:
if not isinstance(getattr(self, f"_{prefix}connection_pool_size"), DefaultValue):
raise RuntimeError(_TWO_ARGS_REQ.format(name, "connection_pool_size"))

if not isinstance(getattr(self, f"_{prefix}proxy_url"), DefaultValue):
raise RuntimeError(_TWO_ARGS_REQ.format(name, "proxy_url"))
if not isinstance(getattr(self, f"_{prefix}proxy"), DefaultValue):
raise RuntimeError(_TWO_ARGS_REQ.format(name, "proxy"))

if not isinstance(getattr(self, f"_{prefix}http_version"), DefaultValue):
raise RuntimeError(_TWO_ARGS_REQ.format(name, "http_version"))
Expand Down Expand Up @@ -486,21 +490,45 @@ def connection_pool_size(self: BuilderType, connection_pool_size: int) -> Builde
return self

def proxy_url(self: BuilderType, proxy_url: str) -> BuilderType:
"""Sets the proxy for the :paramref:`~telegram.request.HTTPXRequest.proxy_url`
"""Legacy name for :meth:`proxy`, kept for backward compatibility.

.. seealso:: :meth:`get_updates_proxy`

.. deprecated:: NEXT.VERSION

Args:
proxy_url (:obj:`str` | ``httpx.Proxy`` | ``httpx.URL``): See
:paramref:`telegram.ext.ApplicationBuilder.proxy.proxy`.

Returns:
:class:`ApplicationBuilder`: The same builder with the updated argument.
"""
warn(
"`ApplicationBuilder.proxy_url` is deprecated since version "
"NEXT.VERSION. Use `ApplicationBuilder.proxy` instead.",
PTBDeprecationWarning,
stacklevel=2,
)
return self.proxy(proxy_url)

def proxy(self: BuilderType, proxy: Union[str, httpx.Proxy, httpx.URL]) -> BuilderType:
"""Sets the proxy for the :paramref:`~telegram.request.HTTPXRequest.proxy`
parameter of :attr:`telegram.Bot.request`. Defaults to :obj:`None`.

.. seealso:: :meth:`get_updates_proxy`

.. seealso:: :meth:`get_updates_proxy_url`
.. versionadded:: NEXT.VERSION

Args:
proxy_url (:obj:`str`): The URL to the proxy server. See
:paramref:`telegram.request.HTTPXRequest.proxy_url` for more information.
proxy (:obj:`str` | ``httpx.Proxy`` | ``httpx.URL``): The URL to a proxy
server, a ``httpx.Proxy`` object or a ``httpx.URL`` object. See
:paramref:`telegram.request.HTTPXRequest.proxy` for more information.

Returns:
:class:`ApplicationBuilder`: The same builder with the updated argument.
"""
self._request_param_check(name="proxy_url", get_updates=False)
self._proxy_url = proxy_url
self._request_param_check(name="proxy", get_updates=False)
self._proxy = proxy
return self

def connect_timeout(self: BuilderType, connect_timeout: Optional[float]) -> BuilderType:
Expand Down Expand Up @@ -655,21 +683,47 @@ def get_updates_connection_pool_size(
return self

def get_updates_proxy_url(self: BuilderType, get_updates_proxy_url: str) -> BuilderType:
"""Sets the proxy for the :paramref:`telegram.request.HTTPXRequest.proxy_url`
"""Legacy name for :meth:`get_updates_proxy`, kept for backward compatibility.

.. seealso:: :meth:`proxy`

.. deprecated:: NEXT.VERSION

Args:
get_updates_proxy_url (:obj:`str` | ``httpx.Proxy`` | ``httpx.URL``): See
:paramref:`telegram.ext.ApplicationBuilder.get_updates_proxy.get_updates_proxy`.

Returns:
:class:`ApplicationBuilder`: The same builder with the updated argument.
"""
warn(
"`ApplicationBuilder.get_updates_proxy_url` is deprecated since version "
"NEXT.VERSION. Use `ApplicationBuilder.get_updates_proxy` instead.",
PTBDeprecationWarning,
stacklevel=2,
)
return self.get_updates_proxy(get_updates_proxy_url)

def get_updates_proxy(
self: BuilderType, get_updates_proxy: Union[str, httpx.Proxy, httpx.URL]
) -> BuilderType:
"""Sets the proxy for the :paramref:`telegram.request.HTTPXRequest.proxy`
parameter which is used for :meth:`telegram.Bot.get_updates`. Defaults to :obj:`None`.

.. seealso:: :meth:`proxy`

.. seealso:: :meth:`proxy_url`
.. versionadded:: NEXT.VERSION

Args:
get_updates_proxy_url (:obj:`str`): The URL to the proxy server. See
:paramref:`telegram.request.HTTPXRequest.proxy_url` for more information.
proxy (:obj:`str` | ``httpx.Proxy`` | ``httpx.URL``): The URL to a proxy server,
a ``httpx.Proxy`` object or a ``httpx.URL`` object. See
:paramref:`telegram.request.HTTPXRequest.proxy` for more information.

Returns:
:class:`ApplicationBuilder`: The same builder with the updated argument.
"""
self._request_param_check(name="proxy_url", get_updates=True)
self._get_updates_proxy_url = get_updates_proxy_url
self._request_param_check(name="proxy", get_updates=True)
self._get_updates_proxy = get_updates_proxy
return self

def get_updates_connect_timeout(
Expand Down
48 changes: 36 additions & 12 deletions telegram/request/_httpxrequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@
from telegram._utils.defaultvalue import DefaultValue
from telegram._utils.logging import get_logger
from telegram._utils.types import HTTPVersion, ODVInput
from telegram._utils.warnings import warn
from telegram.error import NetworkError, TimedOut
from telegram.request._baserequest import BaseRequest
from telegram.request._requestdata import RequestData
from telegram.warnings import PTBDeprecationWarning

# Note to future devs:
# Proxies are currently only tested manually. The httpx development docs have a nice guide on that:
Expand Down Expand Up @@ -55,17 +57,10 @@ class HTTPXRequest(BaseRequest):
Note:
Independent of the value, one additional connection will be reserved for
:meth:`telegram.Bot.get_updates`.
proxy_url (:obj:`str`, optional): The URL to the proxy server. For example
``'http://127.0.0.1:3128'`` or ``'socks5://127.0.0.1:3128'``. Defaults to :obj:`None`.

Note:
* The proxy URL can also be set via the environment variables ``HTTPS_PROXY`` or
``ALL_PROXY``. See `the docs of httpx`_ for more info.
* For Socks5 support, additional dependencies are required. Make sure to install
PTB via :command:`pip install "python-telegram-bot[socks]"` in this case.
* Socks5 proxies can not be set via environment variables.
proxy_url (:obj:`str`, optional): Legacy name for :paramref:`proxy`, kept for backward
compatibility. Defaults to :obj:`None`.

.. _the docs of httpx: https://www.python-httpx.org/environment_variables/#proxies
.. deprecated:: NEXT.VERSION
read_timeout (:obj:`float` | :obj:`None`, optional): If passed, specifies the maximum
amount of time (in seconds) to wait for a response from Telegram's server.
This value is used unless a different value is passed to :meth:`do_request`.
Expand Down Expand Up @@ -107,6 +102,22 @@ class HTTPXRequest(BaseRequest):
these concepts.

.. versionadded:: NEXT.VERSION
proxy (:obj:`str` | ``httpx.Proxy`` | ``httpx.URL``, optional): The URL to a proxy server,
a ``httpx.Proxy`` object or a ``httpx.URL`` object. For example
``'http://127.0.0.1:3128'`` or ``'socks5://127.0.0.1:3128'``. Defaults to :obj:`None`.

Note:
* The proxy URL can also be set via the environment variables ``HTTPS_PROXY`` or
``ALL_PROXY``. See `the docs of httpx`_ for more info.
* HTTPS proxies can be configured by passing a ``httpx.Proxy`` object with
a corresponding ``ssl_context``.
* For Socks5 support, additional dependencies are required. Make sure to install
PTB via :command:`pip install "python-telegram-bot[socks]"` in this case.
Comment on lines +114 to +115

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* For Socks5 support, additional dependencies are required. Make sure to install
PTB via :command:`pip install "python-telegram-bot[socks]"` in this case.
* For Socks5 support, additional dependencies are required. They can be installed using the
command :command:`pip install "python-telegram-bot[socks]"`.

* Socks5 proxies can not be set via environment variables.
Comment thread
harshil21 marked this conversation as resolved.

.. _the docs of httpx: https://www.python-httpx.org/environment_variables/#proxies

.. versionadded:: NEXT.VERSION

"""

Expand All @@ -115,14 +126,27 @@ class HTTPXRequest(BaseRequest):
def __init__(
self,
connection_pool_size: int = 1,
proxy_url: Optional[str] = None,
proxy_url: Optional[Union[str, httpx.Proxy, httpx.URL]] = None,
read_timeout: Optional[float] = 5.0,
write_timeout: Optional[float] = 5.0,
connect_timeout: Optional[float] = 5.0,
pool_timeout: Optional[float] = 1.0,
http_version: HTTPVersion = "1.1",
socket_options: Optional[Collection[_SocketOpt]] = None,
proxy: Optional[Union[str, httpx.Proxy, httpx.URL]] = None,
):
if proxy_url is not None and proxy is not None:
raise ValueError("The parameters `proxy_url` and `proxy` are mutually exclusive.")

if proxy_url is not None:
proxy = proxy_url
warn(
"The parameter `proxy_url` is deprecated since version NEXT.VERSION. Use `proxy` "
"instead.",
PTBDeprecationWarning,
stacklevel=2,
)

self._http_version = http_version
timeout = httpx.Timeout(
connect=connect_timeout,
Expand All @@ -149,7 +173,7 @@ def __init__(
)
self._client_kwargs = {
"timeout": timeout,
"proxies": proxy_url,
"proxies": proxy,
"limits": limits,
"transport": transport,
**http_kwargs,
Expand Down
Loading